diff --git a/AUTHORS b/AUTHORS
index 4b63c63..a3be090 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -465,6 +465,7 @@
 Nitish Mehrotra <nitish.m@samsung.com>
 Noj Vek <nojvek@gmail.com>
 Nolan Cao <nolan.robin.cao@gmail.com>
+Omar Sandoval <osandov@osandov.com>
 Pan Deng <pan.deng@intel.com>
 Parag Radke <nrqv63@motorola.com>
 Paritosh Kumar <paritosh.in@samsung.com>
diff --git a/BUILD.gn b/BUILD.gn
index ed2dcdd..48ed85c 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -661,10 +661,6 @@
     deps += [ "//chromecast:cast_shell" ]
   }
 
-  if (is_mac) {  # TODO(GYP) || is_ios
-    deps += [ "//media/cast:cast_h264_vt_encoder_unittests" ]
-  }
-
   if (is_mac || is_win) {
     deps += [
       "//third_party/crashpad/crashpad/handler:crashpad_handler",
diff --git a/DEPS b/DEPS
index 1f7e9024..87ef606 100644
--- a/DEPS
+++ b/DEPS
@@ -36,11 +36,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': 'f119796f95f336d5b29f06f369b15b48a6a0df45',
+  'skia_revision': 'ba3880fa6d47d467bfcf4db80c553f051336e406',
   # 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': '909f0b27d3baff1005248545e3f47246a59c0159',
+  'v8_revision': 'fe6d66c4a7cce492a7a2d8437d034d957b4d6f4c',
   # 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.
@@ -52,7 +52,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
-  'buildtools_revision': 'aa47d9773d8f4d6254a587a1240b3dc023d54f06',
+  'buildtools_revision': '924d50ecaeb08f1baf52aa9e032895cedcd3238a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # 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 BoringSSL
   # and whatever else without interference from each other.
-  'boringssl_revision': '95c69563dc5422c3b3cd3a0bf435944a7530a12d',
+  'boringssl_revision': '10f97f3bfcecc3fbe8e9f02e7c426f7e340f7f54',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling google-toolbox-for-mac
   # and whatever else without interference from each other.
@@ -88,7 +88,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': '4160831d2082e3e07cc9b2a957dca49391ba7edf',
+  'catapult_revision': '65c2d9df0d06ab117a006589275e2ec04647d8eb',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -148,7 +148,7 @@
     Var('chromium_git') + '/external/snappy.git' + '@' + '762bb32f0c9d2f31ba4958c7c0933d22e80c20bf',
 
   'src/tools/gyp':
-    Var('chromium_git') + '/external/gyp.git' + '@' + 'bac4680ec9a5c55ab692490b6732999648ecf1e9',
+    Var('chromium_git') + '/external/gyp.git' + '@' + 'e7079f0e0e14108ab0dba58728ff219637458563',
 
   'src/tools/swarming_client':
    Var('chromium_git') + '/external/swarming.client.git' + '@' +  Var('swarming_revision'),
@@ -178,7 +178,7 @@
     Var('chromium_git') + '/external/bidichecker/lib.git' + '@' + '97f2aa645b74c28c57eca56992235c79850fa9e0',
 
   'src/third_party/webgl/src':
-   Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '443264a6dadf61e92a6569b5ec90777009160b94',
+   Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '50c670170b1a7c9566e389962ec0e2bfb70a7eec',
 
   'src/third_party/webdriver/pylib':
     Var('chromium_git') + '/external/selenium/py.git' + '@' + '5fd78261a75fe08d27ca4835fb6c5ce4b42275bd',
diff --git a/android_webview/browser/browser_view_renderer.cc b/android_webview/browser/browser_view_renderer.cc
index ef2418d0..7ba66c5e 100644
--- a/android_webview/browser/browser_view_renderer.cc
+++ b/android_webview/browser/browser_view_renderer.cc
@@ -343,7 +343,10 @@
     {
       // Reset scroll back to the origin, will go back to the old
       // value when scroll_reset is out of scope.
-      compositor_->DidChangeRootLayerScrollOffset(gfx::ScrollOffset());
+      base::AutoReset<gfx::Vector2dF> scroll_reset(&scroll_offset_dip_,
+                                                   gfx::Vector2dF());
+      compositor_->DidChangeRootLayerScrollOffset(
+          gfx::ScrollOffset(scroll_offset_dip_));
       CompositeSW(rec_canvas);
     }
     compositor_->DidChangeRootLayerScrollOffset(
diff --git a/android_webview/browser/hardware_renderer.cc b/android_webview/browser/hardware_renderer.cc
index 33b1eaec..b1405bef 100644
--- a/android_webview/browser/hardware_renderer.cc
+++ b/android_webview/browser/hardware_renderer.cc
@@ -32,7 +32,7 @@
       last_submitted_output_surface_id_(0u) {
   DCHECK(last_egl_context_);
   surfaces_->GetSurfaceManager()->RegisterSurfaceFactoryClient(
-      surface_id_allocator_->id_namespace(), this);
+      surface_id_allocator_->client_id(), this);
 }
 
 HardwareRenderer::~HardwareRenderer() {
@@ -42,7 +42,7 @@
     DestroySurface();
   surface_factory_.reset();
   surfaces_->GetSurfaceManager()->UnregisterSurfaceFactoryClient(
-      surface_id_allocator_->id_namespace());
+      surface_id_allocator_->client_id());
 
   // Reset draw constraints.
   render_thread_manager_->PostExternalDrawConstraintsToChildCompositorOnRT(
diff --git a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc
index 71df045..7f4cf31 100644
--- a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc
+++ b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc
@@ -327,8 +327,7 @@
 void AwResourceDispatcherHostDelegate::OnResponseStarted(
     net::URLRequest* request,
     content::ResourceContext* resource_context,
-    content::ResourceResponse* response,
-    IPC::Sender* sender) {
+    content::ResourceResponse* response) {
   const content::ResourceRequestInfo* request_info =
       content::ResourceRequestInfo::ForRequest(request);
   if (!request_info) {
diff --git a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h
index d5af23f9..0528e56b 100644
--- a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h
+++ b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h
@@ -18,10 +18,6 @@
 struct ResourceResponse;
 }  // namespace content
 
-namespace IPC {
-class Sender;
-}  // namespace IPC
-
 namespace android_webview {
 
 class IoThreadClientThrottle;
@@ -60,8 +56,7 @@
       content::ResourceContext* resource_context) override;
   void OnResponseStarted(net::URLRequest* request,
                          content::ResourceContext* resource_context,
-                         content::ResourceResponse* response,
-                         IPC::Sender* sender) override;
+                         content::ResourceResponse* response) override;
 
   void OnRequestRedirected(const GURL& redirect_url,
                            net::URLRequest* request,
diff --git a/android_webview/browser/surfaces_instance.cc b/android_webview/browser/surfaces_instance.cc
index b418075..b796730 100644
--- a/android_webview/browser/surfaces_instance.cc
+++ b/android_webview/browser/surfaces_instance.cc
@@ -39,8 +39,7 @@
 }
 
 SurfacesInstance::SurfacesInstance()
-  : next_surface_id_namespace_(1u),
-    gl_surface_(new AwGLSurface) {
+    : next_surface_client_id_(1u), gl_surface_(new AwGLSurface) {
   cc::RendererSettings settings;
 
   // Should be kept in sync with compositor_impl_android.cc.
@@ -52,8 +51,8 @@
 
   surface_manager_.reset(new cc::SurfaceManager);
   surface_id_allocator_.reset(
-      new cc::SurfaceIdAllocator(next_surface_id_namespace_++));
-  surface_id_allocator_->RegisterSurfaceIdNamespace(surface_manager_.get());
+      new cc::SurfaceIdAllocator(next_surface_client_id_++));
+  surface_id_allocator_->RegisterSurfaceClientId(surface_manager_.get());
 
   std::unique_ptr<cc::BeginFrameSource> begin_frame_source(
       new cc::StubBeginFrameSource);
@@ -69,7 +68,7 @@
   display_.reset(new cc::Display(
       surface_manager_.get(), nullptr /* shared_bitmap_manager */,
       nullptr /* gpu_memory_buffer_manager */, settings,
-      surface_id_allocator_->id_namespace(), std::move(begin_frame_source),
+      surface_id_allocator_->client_id(), std::move(begin_frame_source),
       std::move(output_surface_holder), std::move(scheduler),
       std::move(texture_mailbox_deleter)));
   display_->Initialize(this);
@@ -92,9 +91,9 @@
 
 std::unique_ptr<cc::SurfaceIdAllocator>
 SurfacesInstance::CreateSurfaceIdAllocator() {
-  std::unique_ptr<cc::SurfaceIdAllocator> allocator = base::WrapUnique(
-      new cc::SurfaceIdAllocator(next_surface_id_namespace_++));
-  allocator->RegisterSurfaceIdNamespace(surface_manager_.get());
+  std::unique_ptr<cc::SurfaceIdAllocator> allocator =
+      base::WrapUnique(new cc::SurfaceIdAllocator(next_surface_client_id_++));
+  allocator->RegisterSurfaceClientId(surface_manager_.get());
   return allocator;
 }
 
diff --git a/android_webview/browser/surfaces_instance.h b/android_webview/browser/surfaces_instance.h
index 709b389b..e92f15b 100644
--- a/android_webview/browser/surfaces_instance.h
+++ b/android_webview/browser/surfaces_instance.h
@@ -68,7 +68,7 @@
 
   void SetEmptyRootFrame();
 
-  uint32_t next_surface_id_namespace_;
+  uint32_t next_surface_client_id_;
 
   scoped_refptr<AwGLSurface> gl_surface_;
   std::unique_ptr<cc::SurfaceManager> surface_manager_;
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java
index 0aef4c9c..3089aaf 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java
@@ -838,4 +838,44 @@
                 Math.abs(atomicContentHeight.get() - atomicNewContentHeightApproximation.get())
                         <= 1);
     }
+
+    @SmallTest
+    @Feature("AndroidWebView")
+    public void testScrollOffsetAfterCapturePicture() throws Throwable {
+        final TestAwContentsClient contentsClient = new TestAwContentsClient();
+        final ScrollTestContainerView testContainerView =
+                (ScrollTestContainerView) createAwTestContainerViewOnMainSync(contentsClient);
+        enableJavaScriptOnUiThread(testContainerView.getAwContents());
+
+        final int targetScrollYPix = 322;
+
+        loadTestPageAndWaitForFirstFrame(testContainerView, contentsClient, null, "");
+
+        assertScrollOnMainSync(testContainerView, 0, 0);
+
+        scrollToOnMainSync(testContainerView, 0, targetScrollYPix);
+
+        final int scrolledYPix = runTestOnUiThreadAndGetResult(new Callable<Integer>() {
+            @Override
+            public Integer call() {
+                return testContainerView.getScrollY();
+            }
+        });
+
+        assertTrue(scrolledYPix > 0);
+
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                testContainerView.getAwContents().capturePicture();
+            }
+        });
+
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals(testContainerView.getScrollY(), scrolledYPix);
+            }
+        });
+    }
 }
diff --git a/android_webview/tools/system_webview_shell/test/data/webexposed/global-interface-listing-expected.txt b/android_webview/tools/system_webview_shell/test/data/webexposed/global-interface-listing-expected.txt
index 01fad36..318bb0e 100644
--- a/android_webview/tools/system_webview_shell/test/data/webexposed/global-interface-listing-expected.txt
+++ b/android_webview/tools/system_webview_shell/test/data/webexposed/global-interface-listing-expected.txt
@@ -4377,13 +4377,6 @@
     getter zoomAndPan
     method constructor
     setter zoomAndPan
-interface SVGZoomEvent : UIEvent
-    getter newScale
-    getter newTranslate
-    getter previousScale
-    getter previousTranslate
-    getter zoomRectScreen
-    method constructor
 interface Screen
     getter availHeight
     getter availLeft
diff --git a/ash/ash.gyp b/ash/ash.gyp
index 83fc888e..5165e13 100644
--- a/ash/ash.gyp
+++ b/ash/ash.gyp
@@ -140,6 +140,8 @@
       'common/system/chromeos/keyboard_brightness_controller.cc',
       'common/system/chromeos/keyboard_brightness_controller.h',
       'common/system/chromeos/media_security/media_capture_observer.h',
+      'common/system/chromeos/media_security/multi_profile_media_tray_item.cc',
+      'common/system/chromeos/media_security/multi_profile_media_tray_item.h',
       'common/system/chromeos/network/network_detailed_view.h',
       'common/system/chromeos/network/network_observer.h',
       'common/system/chromeos/network/network_portal_detector_observer.h',
@@ -620,8 +622,6 @@
       'sticky_keys/sticky_keys_overlay.cc',
       'sticky_keys/sticky_keys_overlay.h',
       'sticky_keys/sticky_keys_state.h',
-      'system/chromeos/media_security/multi_profile_media_tray_item.cc',
-      'system/chromeos/media_security/multi_profile_media_tray_item.h',
       'system/chromeos/multi_user/user_switch_util.cc',
       'system/chromeos/multi_user/user_switch_util.h',
       'system/chromeos/power/power_event_observer.cc',
diff --git a/ash/ash_chromeos_strings.grdp b/ash/ash_chromeos_strings.grdp
index 1b3a4e5..1d563d14 100644
--- a/ash/ash_chromeos_strings.grdp
+++ b/ash/ash_chromeos_strings.grdp
@@ -499,6 +499,14 @@
     Take our survey
   </message>
 
+  <!-- Quick Unlock Strings -->
+   <message name="IDS_ASH_QUICK_UNLOCK_NOTIFICATION_TITLE" desc="The title of the notification for Quick Unlock feature notification.">
+    QU Feature notification title here
+  </message>
+  <message name="IDS_ASH_QUICK_UNLOCK_NOTIFICATION_BODY" desc="The body of the notification for Quick Unlock feature notification.">
+    QU Feature notification body goes here. QU Feature notification body goes here. QU Feature notification body goes here. QU Feature notification body goes here. QU Feature notification body goes here.
+  </message>
+
   <!-- Deprecated Accelerators Messages -->
   <!-- Shortcut keys MUST be connected with pluses (e.g. Ctrl+Shift+L). -->
   <message name="IDS_SHORTCUT_LOCK_SCREEN_OLD" desc="the old deprecated shortcut to lock the screen.">
diff --git a/ash/aura/wm_window_aura.cc b/ash/aura/wm_window_aura.cc
index ade5c2c..412772b 100644
--- a/ash/aura/wm_window_aura.cc
+++ b/ash/aura/wm_window_aura.cc
@@ -718,6 +718,12 @@
                     OnWindowVisibilityChanging(this, visible));
 }
 
+void WmWindowAura::OnWindowVisibilityChanged(aura::Window* window,
+                                             bool visible) {
+  FOR_EACH_OBSERVER(WmWindowObserver, observers_,
+                    OnWindowVisibilityChanged(this, visible));
+}
+
 void WmWindowAura::OnWindowTitleChanged(aura::Window* window) {
   FOR_EACH_OBSERVER(WmWindowObserver, observers_, OnWindowTitleChanged(this));
 }
diff --git a/ash/aura/wm_window_aura.h b/ash/aura/wm_window_aura.h
index f33c8d2..32ed9eee 100644
--- a/ash/aura/wm_window_aura.h
+++ b/ash/aura/wm_window_aura.h
@@ -168,6 +168,7 @@
   void OnWindowDestroying(aura::Window* window) override;
   void OnWindowDestroyed(aura::Window* window) override;
   void OnWindowVisibilityChanging(aura::Window* window, bool visible) override;
+  void OnWindowVisibilityChanged(aura::Window* window, bool visible) override;
   void OnWindowTitleChanged(aura::Window* window) override;
 
   aura::Window* window_;
diff --git a/ash/common/metrics/user_metrics_action.h b/ash/common/metrics/user_metrics_action.h
index 38584ab..e989f99 100644
--- a/ash/common/metrics/user_metrics_action.h
+++ b/ash/common/metrics/user_metrics_action.h
@@ -75,6 +75,11 @@
   UMA_STATUS_AREA_DISABLE_SPOKEN_FEEDBACK,
   UMA_STATUS_AREA_DISABLE_WIFI,
   UMA_STATUS_AREA_DISABLE_VIRTUAL_KEYBOARD,
+  UMA_STATUS_AREA_DISPLAY_DEFAULT_SELECTED,
+  UMA_STATUS_AREA_DISPLAY_DEFAULT_SHOW_SETTINGS,
+  UMA_STATUS_AREA_DISPLAY_NOTIFICATION_CREATED,
+  UMA_STATUS_AREA_DISPLAY_NOTIFICATION_SELECTED,
+  UMA_STATUS_AREA_DISPLAY_NOTIFICATION_SHOW_SETTINGS,
   UMA_STATUS_AREA_DRIVE_CANCEL_OPERATION,
   UMA_STATUS_AREA_DRIVE_SETTINGS,
   UMA_STATUS_AREA_ENABLE_AUTO_CLICK,
diff --git a/ash/common/shelf/shelf_alignment_menu.cc b/ash/common/shelf/shelf_alignment_menu.cc
index bf5f052..574317a 100644
--- a/ash/common/shelf/shelf_alignment_menu.cc
+++ b/ash/common/shelf/shelf_alignment_menu.cc
@@ -47,7 +47,7 @@
 
 bool ShelfAlignmentMenu::GetAcceleratorForCommandId(
     int command_id,
-    ui::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) const {
   return false;
 }
 
diff --git a/ash/common/shelf/shelf_alignment_menu.h b/ash/common/shelf/shelf_alignment_menu.h
index c283466e..2686f3e 100644
--- a/ash/common/shelf/shelf_alignment_menu.h
+++ b/ash/common/shelf/shelf_alignment_menu.h
@@ -24,7 +24,7 @@
   bool IsCommandIdChecked(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
 
  private:
diff --git a/ash/system/chromeos/media_security/multi_profile_media_tray_item.cc b/ash/common/system/chromeos/media_security/multi_profile_media_tray_item.cc
similarity index 93%
rename from ash/system/chromeos/media_security/multi_profile_media_tray_item.cc
rename to ash/common/system/chromeos/media_security/multi_profile_media_tray_item.cc
index 4164e8bf..fa32b6a 100644
--- a/ash/system/chromeos/media_security/multi_profile_media_tray_item.cc
+++ b/ash/common/system/chromeos/media_security/multi_profile_media_tray_item.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/system/chromeos/media_security/multi_profile_media_tray_item.h"
+#include "ash/common/system/chromeos/media_security/multi_profile_media_tray_item.h"
 
 #include "ash/common/ash_view_ids.h"
 #include "ash/common/media_delegate.h"
@@ -62,7 +62,7 @@
 }  // namespace tray
 
 MultiProfileMediaTrayItem::MultiProfileMediaTrayItem(SystemTray* system_tray)
-    : SystemTrayItem(system_tray), tray_view_(NULL) {}
+    : SystemTrayItem(system_tray), tray_view_(nullptr) {}
 
 MultiProfileMediaTrayItem::~MultiProfileMediaTrayItem() {}
 
@@ -72,7 +72,7 @@
 }
 
 void MultiProfileMediaTrayItem::DestroyTrayView() {
-  tray_view_ = NULL;
+  tray_view_ = nullptr;
 }
 
 }  // namespace ash
diff --git a/ash/system/chromeos/media_security/multi_profile_media_tray_item.h b/ash/common/system/chromeos/media_security/multi_profile_media_tray_item.h
similarity index 71%
rename from ash/system/chromeos/media_security/multi_profile_media_tray_item.h
rename to ash/common/system/chromeos/media_security/multi_profile_media_tray_item.h
index bbddc63..7d985d1 100644
--- a/ash/system/chromeos/media_security/multi_profile_media_tray_item.h
+++ b/ash/common/system/chromeos/media_security/multi_profile_media_tray_item.h
@@ -2,15 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef ASH_SYSTEM_CHROMEOS_MEDIA_SECURITY_MULTI_PROFILE_MEDIA_TRAY_ITEM_H_
-#define ASH_SYSTEM_CHROMEOS_MEDIA_SECURITY_MULTI_PROFILE_MEDIA_TRAY_ITEM_H_
+#ifndef ASH_COMMON_SYSTEM_CHROMEOS_MEDIA_SECURITY_MULTI_PROFILE_MEDIA_TRAY_ITEM_H_
+#define ASH_COMMON_SYSTEM_CHROMEOS_MEDIA_SECURITY_MULTI_PROFILE_MEDIA_TRAY_ITEM_H_
 
 #include "ash/common/system/tray/system_tray_item.h"
 #include "base/macros.h"
-#include "ui/message_center/notification_delegate.h"
-#include "ui/views/view.h"
 
 namespace ash {
+
 namespace tray {
 class MultiProfileMediaTrayView;
 }
@@ -33,4 +32,4 @@
 
 }  // namespace ash
 
-#endif  // ASH_SYSTEM_CHROMEOS_MEDIA_SECURITY_MULTI_PROFILE_MEDIA_TRAY_ITEM_H_
+#endif  // ASH_COMMON_SYSTEM_CHROMEOS_MEDIA_SECURITY_MULTI_PROFILE_MEDIA_TRAY_ITEM_H_
diff --git a/ash/common/system/system_notifier.cc b/ash/common/system/system_notifier.cc
index 94472e9..b85815e 100644
--- a/ash/common/system/system_notifier.cc
+++ b/ash/common/system/system_notifier.cc
@@ -77,6 +77,7 @@
 const char kNotifierMultiProfileFirstRun[] = "ash.multi-profile.first-run";
 const char kNotifierNetworkPortalDetector[] = "ash.network.portal-detector";
 const char kNotifierPower[] = "ash.power";
+const char kNotifierQuickUnlock[] = "ash.quickunlock";
 const char kNotifierScreenshot[] = "ash.screenshot";
 const char kNotifierScreenCapture[] = "ash.screen-capture";
 const char kNotifierScreenShare[] = "ash.screen-share";
diff --git a/ash/common/system/system_notifier.h b/ash/common/system/system_notifier.h
index dc5dfd1..e8bbb30 100644
--- a/ash/common/system/system_notifier.h
+++ b/ash/common/system/system_notifier.h
@@ -29,6 +29,7 @@
 ASH_EXPORT extern const char kNotifierNetworkError[];
 ASH_EXPORT extern const char kNotifierNetworkPortalDetector[];
 ASH_EXPORT extern const char kNotifierPower[];
+ASH_EXPORT extern const char kNotifierQuickUnlock[];
 ASH_EXPORT extern const char kNotifierScreenshot[];
 ASH_EXPORT extern const char kNotifierScreenCapture[];
 ASH_EXPORT extern const char kNotifierScreenShare[];
diff --git a/ash/common/system/web_notification/web_notification_tray.cc b/ash/common/system/web_notification/web_notification_tray.cc
index 787c46e..6c3a7ad 100644
--- a/ash/common/system/web_notification/web_notification_tray.cc
+++ b/ash/common/system/web_notification/web_notification_tray.cc
@@ -139,7 +139,7 @@
     unread_label_.set_owned_by_client();
     SetupLabelForTray(&unread_label_);
 
-    AddChildView(&unread_label_);
+    AddChildView(&no_unread_icon_);
   }
 
   void SetBubbleVisible(bool visible) {
@@ -450,7 +450,7 @@
 
 bool WebNotificationTray::GetAcceleratorForCommandId(
     int command_id,
-    ui::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) const {
   return false;
 }
 
diff --git a/ash/common/system/web_notification/web_notification_tray.h b/ash/common/system/web_notification/web_notification_tray.h
index b4bd2f4..0527238 100644
--- a/ash/common/system/web_notification/web_notification_tray.h
+++ b/ash/common/system/web_notification/web_notification_tray.h
@@ -123,7 +123,7 @@
   bool IsCommandIdChecked(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
 
   message_center::MessageCenter* message_center() const;
diff --git a/ash/common/wm/overview/scoped_transform_overview_window.cc b/ash/common/wm/overview/scoped_transform_overview_window.cc
index 0816a10c..0a13bf6 100644
--- a/ash/common/wm/overview/scoped_transform_overview_window.cc
+++ b/ash/common/wm/overview/scoped_transform_overview_window.cc
@@ -183,6 +183,7 @@
   explicit OverviewContentMask(float radius);
   ~OverviewContentMask() override;
 
+  void set_radius(float radius) { radius_ = radius; }
   ui::Layer* layer() { return &layer_; }
 
   // Overridden from LayerDelegate.
@@ -405,11 +406,15 @@
 
   if (ash::MaterialDesignController::IsOverviewMaterial() &&
       &transform != &original_transform_) {
+    if (!mask_) {
+      mask_.reset(new OverviewContentMask(radius));
+      mask_->layer()->SetFillsBoundsOpaquely(false);
+      window()->GetLayer()->SetMaskLayer(mask_->layer());
+    }
     gfx::Rect bounds(GetTargetBoundsInScreen().size());
-    mask_.reset(new OverviewContentMask(radius));
-    mask_->layer()->SetFillsBoundsOpaquely(false);
     mask_->layer()->SetBounds(bounds);
-    window()->GetLayer()->SetMaskLayer(mask_->layer());
+    mask_->set_radius(radius);
+    window()->GetLayer()->SchedulePaint(bounds);
 
     SkRegion* window_shape = window()->GetLayer()->alpha_shape();
     if (!original_window_shape_ && window_shape)
diff --git a/ash/common/wm_window_observer.h b/ash/common/wm_window_observer.h
index fd7250a..a50b00e 100644
--- a/ash/common/wm_window_observer.h
+++ b/ash/common/wm_window_observer.h
@@ -46,6 +46,7 @@
                                      const gfx::Rect& new_bounds) {}
 
   virtual void OnWindowVisibilityChanging(WmWindow* window, bool visible) {}
+  virtual void OnWindowVisibilityChanged(WmWindow* window, bool visible) {}
 
   virtual void OnWindowTitleChanged(WmWindow* window) {}
 
diff --git a/ash/content/screen_orientation_delegate_chromeos.cc b/ash/content/screen_orientation_delegate_chromeos.cc
index 68777e67..93bc8c6 100644
--- a/ash/content/screen_orientation_delegate_chromeos.cc
+++ b/ash/content/screen_orientation_delegate_chromeos.cc
@@ -4,6 +4,7 @@
 
 #include "ash/content/screen_orientation_delegate_chromeos.h"
 
+#include "ash/aura/wm_window_aura.h"
 #include "ash/display/screen_orientation_controller_chromeos.h"
 #include "ash/shell.h"
 #include "content/public/browser/screen_orientation_provider.h"
@@ -14,6 +15,7 @@
 ScreenOrientationDelegateChromeos::ScreenOrientationDelegateChromeos() {
   content::ScreenOrientationProvider::SetDelegate(this);
 }
+
 ScreenOrientationDelegateChromeos::~ScreenOrientationDelegateChromeos() {
   content::ScreenOrientationProvider::SetDelegate(nullptr);
 }
@@ -28,8 +30,8 @@
     blink::WebScreenOrientationLockType lock_orientation) {
   Shell::GetInstance()
       ->screen_orientation_controller()
-      ->LockOrientationForWindow(web_contents->GetNativeView(),
-                                 lock_orientation);
+      ->LockOrientationForWindow(
+          WmWindowAura::Get(web_contents->GetNativeView()), lock_orientation);
 }
 
 bool ScreenOrientationDelegateChromeos::ScreenOrientationProviderSupported() {
@@ -37,11 +39,13 @@
       ->screen_orientation_controller()
       ->ScreenOrientationProviderSupported();
 }
+
 void ScreenOrientationDelegateChromeos::Unlock(
     content::WebContents* web_contents) {
   Shell::GetInstance()
       ->screen_orientation_controller()
-      ->UnlockOrientationForWindow(web_contents->GetNativeView());
+      ->UnlockOrientationForWindow(
+          WmWindowAura::Get(web_contents->GetNativeView()));
 }
 
 }  // namespace ash
diff --git a/ash/display/screen_orientation_controller_chromeos.cc b/ash/display/screen_orientation_controller_chromeos.cc
index 10afdd43..41fd5aa 100644
--- a/ash/display/screen_orientation_controller_chromeos.cc
+++ b/ash/display/screen_orientation_controller_chromeos.cc
@@ -8,6 +8,7 @@
 #include "ash/common/display/display_info.h"
 #include "ash/common/wm/maximize_mode/maximize_mode_controller.h"
 #include "ash/common/wm_shell.h"
+#include "ash/common/wm_window.h"
 #include "ash/display/display_configuration_controller.h"
 #include "ash/display/display_manager.h"
 #include "ash/shell.h"
@@ -15,12 +16,11 @@
 #include "base/command_line.h"
 #include "chromeos/accelerometer/accelerometer_reader.h"
 #include "chromeos/accelerometer/accelerometer_types.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_observer.h"
 #include "ui/chromeos/accelerometer/accelerometer_util.h"
 #include "ui/display/display.h"
 #include "ui/gfx/geometry/size.h"
-#include "ui/wm/public/activation_client.h"
+
+namespace ash {
 
 namespace {
 
@@ -39,9 +39,8 @@
   if (!display::Display::HasInternalDisplay())
     return blink::WebScreenOrientationLockLandscape;
 
-  ash::DisplayInfo info =
-      ash::Shell::GetInstance()->display_manager()->GetDisplayInfo(
-          display::Display::InternalDisplayId());
+  DisplayInfo info =
+      WmShell::Get()->GetDisplayInfo(display::Display::InternalDisplayId());
   gfx::Size size = info.size_in_pixel();
   switch (info.GetActiveRotation()) {
     case display::Display::ROTATE_0:
@@ -61,8 +60,6 @@
 
 }  // namespace
 
-namespace ash {
-
 ScreenOrientationController::ScreenOrientationController()
     : natural_orientation_(GetDisplayNaturalOrientation()),
       ignore_display_configuration_updates_(false),
@@ -76,8 +73,8 @@
 ScreenOrientationController::~ScreenOrientationController() {
   WmShell::Get()->RemoveShellObserver(this);
   chromeos::AccelerometerReader::GetInstance()->RemoveObserver(this);
-  Shell::GetInstance()->window_tree_host_manager()->RemoveObserver(this);
-  Shell::GetInstance()->activation_client()->RemoveObserver(this);
+  WmShell::Get()->RemoveDisplayObserver(this);
+  WmShell::Get()->RemoveActivationObserver(this);
   for (auto& windows : locking_windows_)
     windows.first->RemoveObserver(this);
 }
@@ -91,10 +88,10 @@
 }
 
 void ScreenOrientationController::LockOrientationForWindow(
-    aura::Window* requesting_window,
+    WmWindow* requesting_window,
     blink::WebScreenOrientationLockType lock_orientation) {
   if (locking_windows_.empty())
-    Shell::GetInstance()->activation_client()->AddObserver(this);
+    WmShell::Get()->AddActivationObserver(this);
 
   if (!requesting_window->HasObserver(this))
     requesting_window->AddObserver(this);
@@ -103,11 +100,10 @@
   ApplyLockForActiveWindow();
 }
 
-void ScreenOrientationController::UnlockOrientationForWindow(
-    aura::Window* window) {
+void ScreenOrientationController::UnlockOrientationForWindow(WmWindow* window) {
   locking_windows_.erase(window);
   if (locking_windows_.empty())
-    Shell::GetInstance()->activation_client()->RemoveObserver(this);
+    WmShell::Get()->RemoveActivationObserver(this);
   window->RemoveObserver(this);
   ApplyLockForActiveWindow();
 }
@@ -116,7 +112,7 @@
   for (auto pair : locking_windows_)
     pair.first->RemoveObserver(this);
   locking_windows_.clear();
-  Shell::GetInstance()->activation_client()->RemoveObserver(this);
+  WmShell::Get()->RemoveActivationObserver(this);
   SetRotationLocked(false);
   if (user_rotation_ != current_rotation_)
     SetDisplayRotation(user_rotation_, display::Display::ROTATION_SOURCE_USER);
@@ -160,13 +156,15 @@
       true /* user_action */);
 }
 
-void ScreenOrientationController::OnWindowActivated(
-    aura::client::ActivationChangeObserver::ActivationReason reason,
-    aura::Window* gained_active,
-    aura::Window* lost_active) {
+void ScreenOrientationController::OnWindowActivated(WmWindow* gained_active,
+                                                    WmWindow* lost_active) {
   ApplyLockForActiveWindow();
 }
 
+void ScreenOrientationController::OnWindowDestroying(WmWindow* window) {
+  UnlockOrientationForWindow(window);
+}
+
 // Currently contents::WebContents will only be able to lock rotation while
 // fullscreen. In this state a user cannot click on the tab strip to change. If
 // this becomes supported for non-fullscreen tabs then the following interferes
@@ -174,18 +172,13 @@
 // down and mouse up. The rotation this triggers leads to a coordinate space
 // change in the middle of an event. Causes the tab to separate from the tab
 // strip.
-void ScreenOrientationController::OnWindowVisibilityChanged(
-    aura::Window* window,
-    bool visible) {
+void ScreenOrientationController::OnWindowVisibilityChanged(WmWindow* window,
+                                                            bool visible) {
   if (locking_windows_.find(window) == locking_windows_.end())
     return;
   ApplyLockForActiveWindow();
 }
 
-void ScreenOrientationController::OnWindowDestroying(aura::Window* window) {
-  UnlockOrientationForWindow(window);
-}
-
 void ScreenOrientationController::OnAccelerometerUpdated(
     scoped_refptr<const chromeos::AccelerometerUpdate> update) {
   if (rotation_locked_ && !CanRotateInLockedState())
@@ -205,9 +198,9 @@
     return;
   if (!display::Display::HasInternalDisplay())
     return;
-  DisplayManager* display_manager = Shell::GetInstance()->display_manager();
   display::Display::Rotation user_rotation =
-      display_manager->GetDisplayInfo(display::Display::InternalDisplayId())
+      WmShell::Get()
+          ->GetDisplayInfo(display::Display::InternalDisplayId())
           .GetActiveRotation();
   if (user_rotation != current_rotation_) {
     // A user may change other display configuration settings. When the user
@@ -224,20 +217,19 @@
   // Always start observing.
   if (display::Display::HasInternalDisplay()) {
     current_rotation_ = user_rotation_ =
-        Shell::GetInstance()
-            ->display_manager()
+        WmShell::Get()
             ->GetDisplayInfo(display::Display::InternalDisplayId())
             .GetActiveRotation();
   }
   if (!rotation_locked_)
     LoadDisplayRotationProperties();
   chromeos::AccelerometerReader::GetInstance()->AddObserver(this);
-  Shell::GetInstance()->window_tree_host_manager()->AddObserver(this);
+  WmShell::Get()->AddDisplayObserver(this);
 }
 
 void ScreenOrientationController::OnMaximizeModeEnded() {
   chromeos::AccelerometerReader::GetInstance()->RemoveObserver(this);
-  Shell::GetInstance()->window_tree_host_manager()->RemoveObserver(this);
+  WmShell::Get()->RemoveDisplayObserver(this);
   if (current_rotation_ != user_rotation_)
     SetDisplayRotation(user_rotation_, display::Display::ROTATION_SOURCE_USER);
 }
@@ -309,9 +301,9 @@
   if (!display::Display::HasInternalDisplay())
     return;
 
-  DisplayManager* display_manager = Shell::GetInstance()->display_manager();
   display::Display::Rotation rotation =
-      display_manager->GetDisplayInfo(display::Display::InternalDisplayId())
+      WmShell::Get()
+          ->GetDisplayInfo(display::Display::InternalDisplayId())
           .GetActiveRotation();
   if (natural_orientation_ == lock_orientation) {
     if (rotation == display::Display::ROTATE_0 ||
@@ -394,11 +386,10 @@
 }
 
 void ScreenOrientationController::ApplyLockForActiveWindow() {
-  aura::Window* active_window =
-      Shell::GetInstance()->activation_client()->GetActiveWindow();
+  WmWindow* active_window = WmShell::Get()->GetActiveWindow();
   if (active_window) {
     for (auto const& windows : locking_windows_) {
-      if (windows.first->TargetVisibility() &&
+      if (windows.first->GetTargetVisibility() &&
           active_window->Contains(windows.first)) {
         LockRotationToOrientation(windows.second);
         return;
diff --git a/ash/display/screen_orientation_controller_chromeos.h b/ash/display/screen_orientation_controller_chromeos.h
index 3b92826..7a09c66 100644
--- a/ash/display/screen_orientation_controller_chromeos.h
+++ b/ash/display/screen_orientation_controller_chromeos.h
@@ -9,28 +9,24 @@
 
 #include "ash/ash_export.h"
 #include "ash/common/shell_observer.h"
-#include "ash/display/window_tree_host_manager.h"
+#include "ash/common/wm_activation_observer.h"
+#include "ash/common/wm_display_observer.h"
+#include "ash/common/wm_window_observer.h"
 #include "base/macros.h"
 #include "base/observer_list.h"
 #include "chromeos/accelerometer/accelerometer_reader.h"
 #include "chromeos/accelerometer/accelerometer_types.h"
 #include "third_party/WebKit/public/platform/modules/screen_orientation/WebScreenOrientationLockType.h"
-#include "ui/aura/window_observer.h"
 #include "ui/display/display.h"
-#include "ui/wm/public/activation_change_observer.h"
-
-namespace aura {
-class Window;
-}
 
 namespace ash {
 
 // Implements ChromeOS specific functionality for ScreenOrientationProvider.
 class ASH_EXPORT ScreenOrientationController
-    : public aura::client::ActivationChangeObserver,
-      public aura::WindowObserver,
+    : public WmActivationObserver,
+      public WmWindowObserver,
       public chromeos::AccelerometerReader::Observer,
-      public WindowTreeHostManager::Observer,
+      public WmDisplayObserver,
       public ShellObserver {
  public:
   // Observer that reports changes to the state of ScreenOrientationProvider's
@@ -53,9 +49,9 @@
 
   // Allows/unallows a window to lock the screen orientation.
   void LockOrientationForWindow(
-      aura::Window* requesting_windowwindow,
+      WmWindow* requesting_window,
       blink::WebScreenOrientationLockType lock_orientation);
-  void UnlockOrientationForWindow(aura::Window* window);
+  void UnlockOrientationForWindow(WmWindow* window);
 
   // Unlock all and set the rotation back to the user specified rotation.
   void UnlockAll();
@@ -80,21 +76,19 @@
   void SetDisplayRotation(display::Display::Rotation rotation,
                           display::Display::RotationSource source);
 
-  // aura::client::ActivationChangeObserver:
-  void OnWindowActivated(
-      aura::client::ActivationChangeObserver::ActivationReason reason,
-      aura::Window* gained_active,
-      aura::Window* lost_active) override;
+  // WmActivationObserver:
+  void OnWindowActivated(WmWindow* gained_active,
+                         WmWindow* lost_active) override;
 
-  // aura::WindowObserver:
-  void OnWindowVisibilityChanged(aura::Window* window, bool visible) override;
-  void OnWindowDestroying(aura::Window* window) override;
+  // WmWindowObserver:
+  void OnWindowDestroying(WmWindow* window) override;
+  void OnWindowVisibilityChanged(WmWindow* window, bool visible) override;
 
   // chromeos::AccelerometerReader::Observer:
   void OnAccelerometerUpdated(
       scoped_refptr<const chromeos::AccelerometerUpdate> update) override;
 
-  // WindowTreeHostManager::Observer:
+  // WmDisplayObserver:
   void OnDisplayConfigurationChanged() override;
 
   // ShellObserver:
@@ -180,7 +174,7 @@
 
   // Tracks all windows that have requested a lock, as well as the requested
   // orientation.
-  std::map<aura::Window*, blink::WebScreenOrientationLockType> locking_windows_;
+  std::map<WmWindow*, blink::WebScreenOrientationLockType> locking_windows_;
 
   DISALLOW_COPY_AND_ASSIGN(ScreenOrientationController);
 };
diff --git a/ash/metrics/user_metrics_recorder.cc b/ash/metrics/user_metrics_recorder.cc
index b9a55499..7fe5858 100644
--- a/ash/metrics/user_metrics_recorder.cc
+++ b/ash/metrics/user_metrics_recorder.cc
@@ -199,427 +199,385 @@
 }
 
 void UserMetricsRecorder::RecordUserMetricsAction(UserMetricsAction action) {
+  using base::RecordAction;
+  using base::UserMetricsAction;
+
   switch (action) {
     case UMA_ACCEL_KEYBOARD_BRIGHTNESS_DOWN_F6:
-      base::RecordAction(
-          base::UserMetricsAction("Accel_KeyboardBrightnessDown_F6"));
+      RecordAction(UserMetricsAction("Accel_KeyboardBrightnessDown_F6"));
       break;
     case UMA_ACCEL_KEYBOARD_BRIGHTNESS_UP_F7:
-      base::RecordAction(
-          base::UserMetricsAction("Accel_KeyboardBrightnessUp_F7"));
+      RecordAction(UserMetricsAction("Accel_KeyboardBrightnessUp_F7"));
       break;
     case UMA_ACCEL_LOCK_SCREEN_LOCK_BUTTON:
-      base::RecordAction(
-          base::UserMetricsAction("Accel_LockScreen_LockButton"));
+      RecordAction(UserMetricsAction("Accel_LockScreen_LockButton"));
       break;
     case UMA_ACCEL_LOCK_SCREEN_POWER_BUTTON:
-      base::RecordAction(
-          base::UserMetricsAction("Accel_LockScreen_PowerButton"));
+      RecordAction(UserMetricsAction("Accel_LockScreen_PowerButton"));
       break;
     case UMA_ACCEL_MAXIMIZE_RESTORE_F4:
-      base::RecordAction(base::UserMetricsAction("Accel_Maximize_Restore_F4"));
+      RecordAction(UserMetricsAction("Accel_Maximize_Restore_F4"));
       break;
     case UMA_ACCEL_PREVWINDOW_F5:
-      base::RecordAction(base::UserMetricsAction("Accel_PrevWindow_F5"));
+      RecordAction(UserMetricsAction("Accel_PrevWindow_F5"));
       break;
     case UMA_ACCEL_EXIT_FIRST_Q:
-      base::RecordAction(base::UserMetricsAction("Accel_Exit_First_Q"));
+      RecordAction(UserMetricsAction("Accel_Exit_First_Q"));
       break;
     case UMA_ACCEL_EXIT_SECOND_Q:
-      base::RecordAction(base::UserMetricsAction("Accel_Exit_Second_Q"));
+      RecordAction(UserMetricsAction("Accel_Exit_Second_Q"));
       break;
     case UMA_ACCEL_RESTART_POWER_BUTTON:
-      base::RecordAction(base::UserMetricsAction("Accel_Restart_PowerButton"));
+      RecordAction(UserMetricsAction("Accel_Restart_PowerButton"));
       break;
     case UMA_ACCEL_SHUT_DOWN_POWER_BUTTON:
-      base::RecordAction(base::UserMetricsAction("Accel_ShutDown_PowerButton"));
+      RecordAction(UserMetricsAction("Accel_ShutDown_PowerButton"));
       break;
     case UMA_CLOSE_THROUGH_CONTEXT_MENU:
-      base::RecordAction(base::UserMetricsAction("CloseFromContextMenu"));
+      RecordAction(UserMetricsAction("CloseFromContextMenu"));
       break;
     case UMA_DESKTOP_SWITCH_TASK:
-      base::RecordAction(base::UserMetricsAction("Desktop_SwitchTask"));
+      RecordAction(UserMetricsAction("Desktop_SwitchTask"));
       task_switch_metrics_recorder_.OnTaskSwitch(
           TaskSwitchMetricsRecorder::DESKTOP);
       break;
     case UMA_DRAG_MAXIMIZE_LEFT:
-      base::RecordAction(base::UserMetricsAction("WindowDrag_MaximizeLeft"));
+      RecordAction(UserMetricsAction("WindowDrag_MaximizeLeft"));
       break;
     case UMA_DRAG_MAXIMIZE_RIGHT:
-      base::RecordAction(base::UserMetricsAction("WindowDrag_MaximizeRight"));
+      RecordAction(UserMetricsAction("WindowDrag_MaximizeRight"));
       break;
     case UMA_LAUNCHER_BUTTON_PRESSED_WITH_MOUSE:
-      base::RecordAction(
-          base::UserMetricsAction("Launcher_ButtonPressed_Mouse"));
+      RecordAction(UserMetricsAction("Launcher_ButtonPressed_Mouse"));
       break;
     case UMA_LAUNCHER_BUTTON_PRESSED_WITH_TOUCH:
-      base::RecordAction(
-          base::UserMetricsAction("Launcher_ButtonPressed_Touch"));
+      RecordAction(UserMetricsAction("Launcher_ButtonPressed_Touch"));
       break;
     case UMA_LAUNCHER_CLICK_ON_APP:
-      base::RecordAction(base::UserMetricsAction("Launcher_ClickOnApp"));
+      RecordAction(UserMetricsAction("Launcher_ClickOnApp"));
       break;
     case UMA_LAUNCHER_CLICK_ON_APPLIST_BUTTON:
-      base::RecordAction(
-          base::UserMetricsAction("Launcher_ClickOnApplistButton"));
+      RecordAction(UserMetricsAction("Launcher_ClickOnApplistButton"));
       break;
     case UMA_LAUNCHER_LAUNCH_TASK:
-      base::RecordAction(base::UserMetricsAction("Launcher_LaunchTask"));
+      RecordAction(UserMetricsAction("Launcher_LaunchTask"));
       task_switch_metrics_recorder_.OnTaskSwitch(
           TaskSwitchMetricsRecorder::SHELF);
       break;
     case UMA_LAUNCHER_MINIMIZE_TASK:
-      base::RecordAction(base::UserMetricsAction("Launcher_MinimizeTask"));
+      RecordAction(UserMetricsAction("Launcher_MinimizeTask"));
       break;
     case UMA_LAUNCHER_SWITCH_TASK:
-      base::RecordAction(base::UserMetricsAction("Launcher_SwitchTask"));
+      RecordAction(UserMetricsAction("Launcher_SwitchTask"));
       task_switch_metrics_recorder_.OnTaskSwitch(
           TaskSwitchMetricsRecorder::SHELF);
       break;
     case UMA_MAXIMIZE_MODE_DISABLED:
-      base::RecordAction(base::UserMetricsAction("Touchview_Disabled"));
+      RecordAction(UserMetricsAction("Touchview_Disabled"));
       break;
     case UMA_MAXIMIZE_MODE_ENABLED:
-      base::RecordAction(base::UserMetricsAction("Touchview_Enabled"));
+      RecordAction(UserMetricsAction("Touchview_Enabled"));
       break;
     case UMA_MAXIMIZE_MODE_INITIALLY_DISABLED:
-      base::RecordAction(
-          base::UserMetricsAction("Touchview_Initially_Disabled"));
+      RecordAction(UserMetricsAction("Touchview_Initially_Disabled"));
       break;
     case UMA_MOUSE_DOWN:
-      base::RecordAction(base::UserMetricsAction("Mouse_Down"));
+      RecordAction(UserMetricsAction("Mouse_Down"));
       break;
     case UMA_PANEL_MINIMIZE_CAPTION_CLICK:
-      base::RecordAction(
-          base::UserMetricsAction("Panel_Minimize_Caption_Click"));
+      RecordAction(UserMetricsAction("Panel_Minimize_Caption_Click"));
       break;
     case UMA_PANEL_MINIMIZE_CAPTION_GESTURE:
-      base::RecordAction(
-          base::UserMetricsAction("Panel_Minimize_Caption_Gesture"));
+      RecordAction(UserMetricsAction("Panel_Minimize_Caption_Gesture"));
       break;
     case UMA_SHELF_ALIGNMENT_SET_BOTTOM:
-      base::RecordAction(base::UserMetricsAction("Shelf_AlignmentSetBottom"));
+      RecordAction(UserMetricsAction("Shelf_AlignmentSetBottom"));
       break;
     case UMA_SHELF_ALIGNMENT_SET_LEFT:
-      base::RecordAction(base::UserMetricsAction("Shelf_AlignmentSetLeft"));
+      RecordAction(UserMetricsAction("Shelf_AlignmentSetLeft"));
       break;
     case UMA_SHELF_ALIGNMENT_SET_RIGHT:
-      base::RecordAction(base::UserMetricsAction("Shelf_AlignmentSetRight"));
+      RecordAction(UserMetricsAction("Shelf_AlignmentSetRight"));
       break;
     case UMA_STATUS_AREA_AUDIO_CURRENT_INPUT_DEVICE:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_Audio_CurrentInputDevice"));
+      RecordAction(UserMetricsAction("StatusArea_Audio_CurrentInputDevice"));
       break;
     case UMA_STATUS_AREA_AUDIO_CURRENT_OUTPUT_DEVICE:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_Audio_CurrentOutputDevice"));
+      RecordAction(UserMetricsAction("StatusArea_Audio_CurrentOutputDevice"));
       break;
     case UMA_STATUS_AREA_AUDIO_SWITCH_INPUT_DEVICE:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_Audio_SwitchInputDevice"));
+      RecordAction(UserMetricsAction("StatusArea_Audio_SwitchInputDevice"));
       break;
     case UMA_STATUS_AREA_AUDIO_SWITCH_OUTPUT_DEVICE:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_Audio_SwitchOutputDevice"));
+      RecordAction(UserMetricsAction("StatusArea_Audio_SwitchOutputDevice"));
       break;
     case UMA_STATUS_AREA_BRIGHTNESS_CHANGED:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_BrightnessChanged"));
+      RecordAction(UserMetricsAction("StatusArea_BrightnessChanged"));
       break;
     case UMA_STATUS_AREA_BLUETOOTH_CONNECT_KNOWN_DEVICE:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_Bluetooth_Connect_Known"));
+      RecordAction(UserMetricsAction("StatusArea_Bluetooth_Connect_Known"));
       break;
     case UMA_STATUS_AREA_BLUETOOTH_CONNECT_UNKNOWN_DEVICE:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_Bluetooth_Connect_Unknown"));
+      RecordAction(UserMetricsAction("StatusArea_Bluetooth_Connect_Unknown"));
       break;
     case UMA_STATUS_AREA_BLUETOOTH_DISABLED:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_Bluetooth_Disabled"));
+      RecordAction(UserMetricsAction("StatusArea_Bluetooth_Disabled"));
       break;
     case UMA_STATUS_AREA_BLUETOOTH_ENABLED:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_Bluetooth_Enabled"));
+      RecordAction(UserMetricsAction("StatusArea_Bluetooth_Enabled"));
       break;
     case UMA_STATUS_AREA_CAPS_LOCK_DETAILED:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_CapsLock_Detailed"));
+      RecordAction(UserMetricsAction("StatusArea_CapsLock_Detailed"));
       break;
     case UMA_STATUS_AREA_CAPS_LOCK_DISABLED_BY_CLICK:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_CapsLock_DisabledByClick"));
+      RecordAction(UserMetricsAction("StatusArea_CapsLock_DisabledByClick"));
       break;
     case UMA_STATUS_AREA_CAPS_LOCK_ENABLED_BY_CLICK:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_CapsLock_EnabledByClick"));
+      RecordAction(UserMetricsAction("StatusArea_CapsLock_EnabledByClick"));
       break;
     case UMA_STATUS_AREA_CAPS_LOCK_POPUP:
-      base::RecordAction(base::UserMetricsAction("StatusArea_CapsLock_Popup"));
+      RecordAction(UserMetricsAction("StatusArea_CapsLock_Popup"));
       break;
     case UMA_STATUS_AREA_CAST_STOP_CAST:
-      base::RecordAction(base::UserMetricsAction("StatusArea_Cast_StopCast"));
+      RecordAction(UserMetricsAction("StatusArea_Cast_StopCast"));
       break;
     case UMA_STATUS_AREA_CONNECT_TO_CONFIGURED_NETWORK:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_Network_ConnectConfigured"));
+      RecordAction(UserMetricsAction("StatusArea_Network_ConnectConfigured"));
       break;
     case UMA_STATUS_AREA_CONNECT_TO_UNCONFIGURED_NETWORK:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_Network_ConnectUnconfigured"));
+      RecordAction(UserMetricsAction("StatusArea_Network_ConnectUnconfigured"));
       break;
     case UMA_STATUS_AREA_CONNECT_TO_VPN:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_VPN_ConnectToNetwork"));
+      RecordAction(UserMetricsAction("StatusArea_VPN_ConnectToNetwork"));
       break;
     case UMA_STATUS_AREA_CHANGED_VOLUME_MENU:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_Volume_ChangedMenu"));
+      RecordAction(UserMetricsAction("StatusArea_Volume_ChangedMenu"));
       break;
     case UMA_STATUS_AREA_CHANGED_VOLUME_POPUP:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_Volume_ChangedPopup"));
+      RecordAction(UserMetricsAction("StatusArea_Volume_ChangedPopup"));
       break;
     case UMA_STATUS_AREA_DETAILED_ACCESSABILITY:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_Accessability_DetailedView"));
+      RecordAction(UserMetricsAction("StatusArea_Accessability_DetailedView"));
       break;
     case UMA_STATUS_AREA_DETAILED_AUDIO_VIEW:
-      base::RecordAction(base::UserMetricsAction("StatusArea_Audio_Detailed"));
+      RecordAction(UserMetricsAction("StatusArea_Audio_Detailed"));
       break;
     case UMA_STATUS_AREA_DETAILED_BLUETOOTH_VIEW:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_Bluetooth_Detailed"));
+      RecordAction(UserMetricsAction("StatusArea_Bluetooth_Detailed"));
       break;
     case UMA_STATUS_AREA_DETAILED_BRIGHTNESS_VIEW:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_Brightness_Detailed"));
+      RecordAction(UserMetricsAction("StatusArea_Brightness_Detailed"));
       break;
     case UMA_STATUS_AREA_DETAILED_CAST_VIEW:
-      base::RecordAction(base::UserMetricsAction("StatusArea_Cast_Detailed"));
+      RecordAction(UserMetricsAction("StatusArea_Cast_Detailed"));
       break;
     case UMA_STATUS_AREA_DETAILED_CAST_VIEW_LAUNCH_CAST:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_Cast_Detailed_Launch_Cast"));
+      RecordAction(UserMetricsAction("StatusArea_Cast_Detailed_Launch_Cast"));
       break;
     case UMA_STATUS_AREA_DETAILED_DRIVE_VIEW:
-      base::RecordAction(base::UserMetricsAction("StatusArea_Drive_Detailed"));
+      RecordAction(UserMetricsAction("StatusArea_Drive_Detailed"));
       break;
     case UMA_STATUS_AREA_DETAILED_NETWORK_VIEW:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_Network_Detailed"));
+      RecordAction(UserMetricsAction("StatusArea_Network_Detailed"));
       break;
     case UMA_STATUS_AREA_DETAILED_SMS_VIEW:
-      base::RecordAction(base::UserMetricsAction("StatusArea_SMS_Detailed"));
+      RecordAction(UserMetricsAction("StatusArea_SMS_Detailed"));
       break;
     case UMA_STATUS_AREA_DETAILED_VPN_VIEW:
-      base::RecordAction(base::UserMetricsAction("StatusArea_VPN_Detailed"));
+      RecordAction(UserMetricsAction("StatusArea_VPN_Detailed"));
       break;
     case UMA_STATUS_AREA_DISABLE_AUTO_CLICK:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_AutoClickDisabled"));
+      RecordAction(UserMetricsAction("StatusArea_AutoClickDisabled"));
       break;
     case UMA_STATUS_AREA_DISABLE_HIGH_CONTRAST:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_HighContrastDisabled"));
+      RecordAction(UserMetricsAction("StatusArea_HighContrastDisabled"));
       break;
     case UMA_STATUS_AREA_DISABLE_LARGE_CURSOR:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_LargeCursorDisabled"));
+      RecordAction(UserMetricsAction("StatusArea_LargeCursorDisabled"));
       break;
     case UMA_STATUS_AREA_DISABLE_MAGNIFIER:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_MagnifierDisabled"));
+      RecordAction(UserMetricsAction("StatusArea_MagnifierDisabled"));
       break;
     case UMA_STATUS_AREA_DISABLE_SPOKEN_FEEDBACK:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_SpokenFeedbackDisabled"));
+      RecordAction(UserMetricsAction("StatusArea_SpokenFeedbackDisabled"));
       break;
     case UMA_STATUS_AREA_DISABLE_VIRTUAL_KEYBOARD:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_VirtualKeyboardDisabled"));
+      RecordAction(UserMetricsAction("StatusArea_VirtualKeyboardDisabled"));
+      break;
+    case UMA_STATUS_AREA_DISPLAY_DEFAULT_SELECTED:
+      RecordAction(UserMetricsAction("StatusArea_Display_Default_Selected"));
+      break;
+    case UMA_STATUS_AREA_DISPLAY_DEFAULT_SHOW_SETTINGS:
+      RecordAction(
+          UserMetricsAction("StatusArea_Display_Default_ShowSettings"));
+      break;
+    case UMA_STATUS_AREA_DISPLAY_NOTIFICATION_CREATED:
+      RecordAction(
+          UserMetricsAction("StatusArea_Display_Notification_Created"));
+      break;
+    case UMA_STATUS_AREA_DISPLAY_NOTIFICATION_SELECTED:
+      RecordAction(
+          UserMetricsAction("StatusArea_Display_Notification_Selected"));
+      break;
+    case UMA_STATUS_AREA_DISPLAY_NOTIFICATION_SHOW_SETTINGS:
+      RecordAction(
+          UserMetricsAction("StatusArea_Display_Notification_Show_Settings"));
       break;
     case UMA_STATUS_AREA_DISABLE_WIFI:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_Network_WifiDisabled"));
+      RecordAction(UserMetricsAction("StatusArea_Network_WifiDisabled"));
       break;
     case UMA_STATUS_AREA_DRIVE_CANCEL_OPERATION:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_Drive_CancelOperation"));
+      RecordAction(UserMetricsAction("StatusArea_Drive_CancelOperation"));
       break;
     case UMA_STATUS_AREA_DRIVE_SETTINGS:
-      base::RecordAction(base::UserMetricsAction("StatusArea_Drive_Settings"));
+      RecordAction(UserMetricsAction("StatusArea_Drive_Settings"));
       break;
     case UMA_STATUS_AREA_ENABLE_AUTO_CLICK:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_AutoClickEnabled"));
+      RecordAction(UserMetricsAction("StatusArea_AutoClickEnabled"));
       break;
     case UMA_STATUS_AREA_ENABLE_HIGH_CONTRAST:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_HighContrastEnabled"));
+      RecordAction(UserMetricsAction("StatusArea_HighContrastEnabled"));
       break;
     case UMA_STATUS_AREA_ENABLE_LARGE_CURSOR:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_LargeCursorEnabled"));
+      RecordAction(UserMetricsAction("StatusArea_LargeCursorEnabled"));
       break;
     case UMA_STATUS_AREA_ENABLE_MAGNIFIER:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_MagnifierEnabled"));
+      RecordAction(UserMetricsAction("StatusArea_MagnifierEnabled"));
       break;
     case UMA_STATUS_AREA_ENABLE_SPOKEN_FEEDBACK:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_SpokenFeedbackEnabled"));
+      RecordAction(UserMetricsAction("StatusArea_SpokenFeedbackEnabled"));
       break;
     case UMA_STATUS_AREA_ENABLE_VIRTUAL_KEYBOARD:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_VirtualKeyboardEnabled"));
+      RecordAction(UserMetricsAction("StatusArea_VirtualKeyboardEnabled"));
       break;
     case UMA_STATUS_AREA_ENABLE_WIFI:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_Network_WifiEnabled"));
+      RecordAction(UserMetricsAction("StatusArea_Network_WifiEnabled"));
       break;
     case UMA_STATUS_AREA_IME_SHOW_DETAILED:
-      base::RecordAction(base::UserMetricsAction("StatusArea_IME_Detailed"));
+      RecordAction(UserMetricsAction("StatusArea_IME_Detailed"));
       break;
     case UMA_STATUS_AREA_IME_SWITCH_MODE:
-      base::RecordAction(base::UserMetricsAction("StatusArea_IME_SwitchMode"));
+      RecordAction(UserMetricsAction("StatusArea_IME_SwitchMode"));
       break;
     case UMA_STATUS_AREA_MENU_OPENED:
-      base::RecordAction(base::UserMetricsAction("StatusArea_MenuOpened"));
+      RecordAction(UserMetricsAction("StatusArea_MenuOpened"));
       break;
     case UMA_STATUS_AREA_NETWORK_JOIN_OTHER_CLICKED:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_Network_JoinOther"));
+      RecordAction(UserMetricsAction("StatusArea_Network_JoinOther"));
       break;
     case UMA_STATUS_AREA_NETWORK_SETTINGS_CLICKED:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_Network_Settings"));
+      RecordAction(UserMetricsAction("StatusArea_Network_Settings"));
     case UMA_STATUS_AREA_OS_UPDATE_DEFAULT_SELECTED:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_OS_Update_Default_Selected"));
+      RecordAction(UserMetricsAction("StatusArea_OS_Update_Default_Selected"));
       break;
     case UMA_STATUS_AREA_SCREEN_CAPTURE_DEFAULT_STOP:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_ScreenCapture_Default_Stop"));
+      RecordAction(UserMetricsAction("StatusArea_ScreenCapture_Default_Stop"));
       break;
     case UMA_STATUS_AREA_SCREEN_CAPTURE_NOTIFICATION_STOP:
-      base::RecordAction(base::UserMetricsAction(
-          "StatusArea_ScreenCapture_Notification_Stop"));
+      RecordAction(
+          UserMetricsAction("StatusArea_ScreenCapture_Notification_Stop"));
       break;
     case UMA_STATUS_AREA_SHOW_NETWORK_CONNECTION_DETAILS:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_Network_ConnectionDetails"));
+      RecordAction(UserMetricsAction("StatusArea_Network_ConnectionDetails"));
       break;
     case UMA_STATUS_AREA_SHOW_VPN_CONNECTION_DETAILS:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_VPN_ConnectionDetails"));
+      RecordAction(UserMetricsAction("StatusArea_VPN_ConnectionDetails"));
       break;
     case UMA_STATUS_AREA_SIGN_OUT:
-      base::RecordAction(base::UserMetricsAction("StatusArea_SignOut"));
+      RecordAction(UserMetricsAction("StatusArea_SignOut"));
       break;
     case UMA_STATUS_AREA_SMS_DETAILED_DISMISS_MSG:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_SMS_Detailed_DismissMsg"));
+      RecordAction(UserMetricsAction("StatusArea_SMS_Detailed_DismissMsg"));
       break;
     case UMA_STATUS_AREA_SMS_NOTIFICATION_DISMISS_MSG:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_SMS_Notification_DismissMsg"));
+      RecordAction(UserMetricsAction("StatusArea_SMS_Notification_DismissMsg"));
       break;
     case UMA_STATUS_AREA_TRACING_DEFAULT_SELECTED:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_Tracing_Default_Selected"));
+      RecordAction(UserMetricsAction("StatusArea_Tracing_Default_Selected"));
       break;
     case UMA_STATUS_AREA_VPN_ADD_BUILT_IN_CLICKED:
-      base::RecordAction(base::UserMetricsAction("StatusArea_VPN_AddBuiltIn"));
+      RecordAction(UserMetricsAction("StatusArea_VPN_AddBuiltIn"));
       break;
     case UMA_STATUS_AREA_VPN_ADD_THIRD_PARTY_CLICKED:
-      base::RecordAction(
-          base::UserMetricsAction("StatusArea_VPN_AddThirdParty"));
+      RecordAction(UserMetricsAction("StatusArea_VPN_AddThirdParty"));
       break;
     case UMA_STATUS_AREA_VPN_DISCONNECT_CLICKED:
-      base::RecordAction(base::UserMetricsAction("StatusArea_VPN_Disconnect"));
+      RecordAction(UserMetricsAction("StatusArea_VPN_Disconnect"));
       break;
     case UMA_STATUS_AREA_VPN_SETTINGS_CLICKED:
-      base::RecordAction(base::UserMetricsAction("StatusArea_VPN_Settings"));
+      RecordAction(UserMetricsAction("StatusArea_VPN_Settings"));
       break;
     case UMA_TOGGLE_MAXIMIZE_CAPTION_CLICK:
-      base::RecordAction(
-          base::UserMetricsAction("Caption_ClickTogglesMaximize"));
+      RecordAction(UserMetricsAction("Caption_ClickTogglesMaximize"));
       break;
     case UMA_TOGGLE_MAXIMIZE_CAPTION_GESTURE:
-      base::RecordAction(
-          base::UserMetricsAction("Caption_GestureTogglesMaximize"));
+      RecordAction(UserMetricsAction("Caption_GestureTogglesMaximize"));
       break;
     case UMA_TOGGLE_SINGLE_AXIS_MAXIMIZE_BORDER_CLICK:
-      base::RecordAction(base::UserMetricsAction(
-          "WindowBorder_ClickTogglesSingleAxisMaximize"));
+      RecordAction(
+          UserMetricsAction("WindowBorder_ClickTogglesSingleAxisMaximize"));
       break;
     case UMA_TOUCHPAD_GESTURE_OVERVIEW:
-      base::RecordAction(base::UserMetricsAction("Touchpad_Gesture_Overview"));
+      RecordAction(UserMetricsAction("Touchpad_Gesture_Overview"));
       break;
     case UMA_TOUCHSCREEN_TAP_DOWN:
-      base::RecordAction(base::UserMetricsAction("Touchscreen_Down"));
+      RecordAction(UserMetricsAction("Touchscreen_Down"));
       break;
     case UMA_TRAY_HELP:
-      base::RecordAction(base::UserMetricsAction("Tray_Help"));
+      RecordAction(UserMetricsAction("Tray_Help"));
       break;
     case UMA_TRAY_LOCK_SCREEN:
-      base::RecordAction(base::UserMetricsAction("Tray_LockScreen"));
+      RecordAction(UserMetricsAction("Tray_LockScreen"));
       break;
     case UMA_TRAY_OVERVIEW:
-      base::RecordAction(base::UserMetricsAction("Tray_Overview"));
+      RecordAction(UserMetricsAction("Tray_Overview"));
       break;
     case UMA_TRAY_SHUT_DOWN:
-      base::RecordAction(base::UserMetricsAction("Tray_ShutDown"));
+      RecordAction(UserMetricsAction("Tray_ShutDown"));
       break;
     case UMA_WINDOW_APP_CLOSE_BUTTON_CLICK:
-      base::RecordAction(base::UserMetricsAction("AppCloseButton_Clk"));
+      RecordAction(UserMetricsAction("AppCloseButton_Clk"));
       break;
     case UMA_WINDOW_CLOSE_BUTTON_CLICK:
-      base::RecordAction(base::UserMetricsAction("CloseButton_Clk"));
+      RecordAction(UserMetricsAction("CloseButton_Clk"));
       break;
     case UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_EXIT_FULLSCREEN:
-      base::RecordAction(base::UserMetricsAction("MaxButton_Clk_ExitFS"));
+      RecordAction(UserMetricsAction("MaxButton_Clk_ExitFS"));
       break;
     case UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_RESTORE:
-      base::RecordAction(base::UserMetricsAction("MaxButton_Clk_Restore"));
+      RecordAction(UserMetricsAction("MaxButton_Clk_Restore"));
       break;
     case UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_MAXIMIZE:
-      base::RecordAction(base::UserMetricsAction("MaxButton_Clk_Maximize"));
+      RecordAction(UserMetricsAction("MaxButton_Clk_Maximize"));
       break;
     case UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_MINIMIZE:
-      base::RecordAction(base::UserMetricsAction("MinButton_Clk"));
+      RecordAction(UserMetricsAction("MinButton_Clk"));
       break;
     case UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE_LEFT:
-      base::RecordAction(base::UserMetricsAction("MaxButton_MaxLeft"));
+      RecordAction(UserMetricsAction("MaxButton_MaxLeft"));
       break;
     case UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE_RIGHT:
-      base::RecordAction(base::UserMetricsAction("MaxButton_MaxRight"));
+      RecordAction(UserMetricsAction("MaxButton_MaxRight"));
       break;
     case UMA_WINDOW_CYCLE:
-      base::RecordAction(
-          base::UserMetricsAction("WindowCycleController_Cycle"));
+      RecordAction(UserMetricsAction("WindowCycleController_Cycle"));
       break;
     case UMA_WINDOW_OVERVIEW:
-      base::RecordAction(base::UserMetricsAction("WindowSelector_Overview"));
+      RecordAction(UserMetricsAction("WindowSelector_Overview"));
       break;
     case UMA_WINDOW_OVERVIEW_ACTIVE_WINDOW_CHANGED:
-      base::RecordAction(
-          base::UserMetricsAction("WindowSelector_ActiveWindowChanged"));
+      RecordAction(UserMetricsAction("WindowSelector_ActiveWindowChanged"));
       task_switch_metrics_recorder_.OnTaskSwitch(
           TaskSwitchMetricsRecorder::OVERVIEW_MODE);
       break;
     case UMA_WINDOW_OVERVIEW_ENTER_KEY:
-      base::RecordAction(
-          base::UserMetricsAction("WindowSelector_OverviewEnterKey"));
+      RecordAction(UserMetricsAction("WindowSelector_OverviewEnterKey"));
       break;
     case UMA_WINDOW_OVERVIEW_CLOSE_BUTTON:
-      base::RecordAction(
-          base::UserMetricsAction("WindowSelector_OverviewCloseButton"));
+      RecordAction(UserMetricsAction("WindowSelector_OverviewCloseButton"));
       break;
     case UMA_WINDOW_OVERVIEW_CLOSE_KEY:
-      base::RecordAction(
-          base::UserMetricsAction("WindowSelector_OverviewCloseKey"));
+      RecordAction(UserMetricsAction("WindowSelector_OverviewCloseKey"));
       break;
   }
 }
diff --git a/ash/mus/bridge/wm_shell_mus.cc b/ash/mus/bridge/wm_shell_mus.cc
index 582e750..b962652 100644
--- a/ash/mus/bridge/wm_shell_mus.cc
+++ b/ash/mus/bridge/wm_shell_mus.cc
@@ -22,9 +22,11 @@
 #include "ash/mus/root_window_controller.h"
 #include "base/memory/ptr_util.h"
 #include "components/user_manager/user_info_impl.h"
+#include "services/shell/public/cpp/connector.h"
 #include "services/ui/common/util.h"
 #include "services/ui/public/cpp/window.h"
 #include "services/ui/public/cpp/window_tree_client.h"
+#include "services/ui/public/interfaces/accessibility_manager.mojom.h"
 
 namespace ash {
 namespace mus {
@@ -90,11 +92,39 @@
   DISALLOW_COPY_AND_ASSIGN(SessionStateDelegateStub);
 };
 
+class AccessibilityDelegateMus : public DefaultAccessibilityDelegate {
+ public:
+  explicit AccessibilityDelegateMus(shell::Connector* connector)
+      : connector_(connector) {}
+  ~AccessibilityDelegateMus() override {}
+
+ private:
+  ui::mojom::AccessibilityManager* GetAccessibilityManager() {
+    if (!accessibility_manager_ptr_.is_bound())
+      connector_->ConnectToInterface("mojo:ui", &accessibility_manager_ptr_);
+    return accessibility_manager_ptr_.get();
+  }
+
+  // DefaultAccessibilityDelegate:
+  void ToggleHighContrast() override {
+    DefaultAccessibilityDelegate::ToggleHighContrast();
+    GetAccessibilityManager()->SetHighContrastMode(IsHighContrastEnabled());
+  }
+
+  ui::mojom::AccessibilityManagerPtr accessibility_manager_ptr_;
+  shell::Connector* connector_;
+
+  DISALLOW_COPY_AND_ASSIGN(AccessibilityDelegateMus);
+};
+
 }  // namespace
 
-WmShellMus::WmShellMus(ShellDelegate* delegate, ::ui::WindowTreeClient* client)
+WmShellMus::WmShellMus(ShellDelegate* delegate,
+                       ::ui::WindowTreeClient* client,
+                       shell::Connector* connector)
     : WmShell(delegate),
       client_(client),
+      connector_(connector),
       session_state_delegate_(new SessionStateDelegateStub) {
   client_->AddObserver(this);
   WmShell::Set(this);
@@ -103,7 +133,7 @@
 
   CreateMruWindowTracker();
 
-  accessibility_delegate_.reset(new DefaultAccessibilityDelegate);
+  accessibility_delegate_.reset(new AccessibilityDelegateMus(connector_));
   SetSystemTrayDelegate(base::WrapUnique(new DefaultSystemTrayDelegate));
 }
 
diff --git a/ash/mus/bridge/wm_shell_mus.h b/ash/mus/bridge/wm_shell_mus.h
index 4ad4d41..c9a4c42a 100644
--- a/ash/mus/bridge/wm_shell_mus.h
+++ b/ash/mus/bridge/wm_shell_mus.h
@@ -14,6 +14,10 @@
 #include "base/observer_list.h"
 #include "services/ui/public/cpp/window_tree_client_observer.h"
 
+namespace shell {
+class Connector;
+}
+
 namespace ui {
 class WindowTreeClient;
 }
@@ -27,7 +31,9 @@
 // WmShell implementation for mus.
 class WmShellMus : public WmShell, public ::ui::WindowTreeClientObserver {
  public:
-  WmShellMus(ShellDelegate* delegate, ::ui::WindowTreeClient* client);
+  WmShellMus(ShellDelegate* delegate,
+             ::ui::WindowTreeClient* client,
+             shell::Connector* connector);
   ~WmShellMus() override;
 
   static WmShellMus* Get();
@@ -91,6 +97,7 @@
   void OnDidDestroyClient(::ui::WindowTreeClient* client) override;
 
   ::ui::WindowTreeClient* client_;
+  shell::Connector* connector_;
 
   std::vector<WmRootWindowControllerMus*> root_window_controllers_;
 
diff --git a/ash/mus/manifest.json b/ash/mus/manifest.json
index d2bfcf6..d7080ef 100644
--- a/ash/mus/manifest.json
+++ b/ash/mus/manifest.json
@@ -7,8 +7,13 @@
       "mus:window_manager" : [ "ui::mojom::AcceleratorRegistrar" ]
     },
     "required": {
-      "*": { "classes": [ "app" ] },
-      "mojo:ui": { "interfaces": [ "ui::mojom::WindowManagerWindowTreeFactory" ] }
+      "*": { "classes": [ "accessibility", "app" ] },
+      "mojo:ui": {
+        "interfaces": [
+          "ui::mojom::AccessibilityManager",
+          "ui::mojom::WindowManagerWindowTreeFactory"
+        ]
+      }
     }
   }
 }
diff --git a/ash/mus/window_manager.cc b/ash/mus/window_manager.cc
index d0755a5..33d8806 100644
--- a/ash/mus/window_manager.cc
+++ b/ash/mus/window_manager.cc
@@ -71,7 +71,7 @@
       std::move(frame_decoration_values));
 
   // TODO(msw): Provide a valid ShellDelegate here; maybe port ShellDelegateMus?
-  shell_.reset(new WmShellMus(nullptr, window_tree_client_));
+  shell_.reset(new WmShellMus(nullptr, window_tree_client_, connector_));
   lookup_.reset(new WmLookupMus);
 }
 
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc
index 43eba9d..90b3488 100644
--- a/ash/shelf/shelf_view_unittest.cc
+++ b/ash/shelf/shelf_view_unittest.cc
@@ -2052,7 +2052,7 @@
     return command_id != 0;
   }
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override {
+                                  ui::Accelerator* accelerator) const override {
     return false;
   }
   void ExecuteCommand(int command_id, int event_flags) override {}
diff --git a/ash/shell/app_list.cc b/ash/shell/app_list.cc
index 6b238a87..e4a066a3 100644
--- a/ash/shell/app_list.cc
+++ b/ash/shell/app_list.cc
@@ -312,10 +312,6 @@
     // Nothing needs to be done.
   }
 
-  void OpenSettings() override {
-    // Nothing needs to be done.
-  }
-
   void OpenHelp() override {
     // Nothing needs to be done.
   }
diff --git a/ash/shell/context_menu.cc b/ash/shell/context_menu.cc
index 0723b1cf..b0677b7 100644
--- a/ash/shell/context_menu.cc
+++ b/ash/shell/context_menu.cc
@@ -35,8 +35,9 @@
   return true;
 }
 
-bool ContextMenu::GetAcceleratorForCommandId(int command_id,
-                                             ui::Accelerator* accelerator) {
+bool ContextMenu::GetAcceleratorForCommandId(
+    int command_id,
+    ui::Accelerator* accelerator) const {
   return false;
 }
 
diff --git a/ash/shell/context_menu.h b/ash/shell/context_menu.h
index c89a406..79cb582 100644
--- a/ash/shell/context_menu.h
+++ b/ash/shell/context_menu.h
@@ -26,7 +26,7 @@
   bool IsCommandIdChecked(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
 
  private:
diff --git a/ash/shell_unittest.cc b/ash/shell_unittest.cc
index 8d659eda..694cc5c 100644
--- a/ash/shell_unittest.cc
+++ b/ash/shell_unittest.cc
@@ -116,7 +116,7 @@
   bool IsCommandIdEnabled(int command_id) const override { return true; }
 
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override {
+                                  ui::Accelerator* accelerator) const override {
     return false;
   }
 
diff --git a/ash/system/chromeos/media_security/multi_profile_media_tray_item_unittest.cc b/ash/system/chromeos/media_security/multi_profile_media_tray_item_unittest.cc
index 15072c7..336c89ca 100644
--- a/ash/system/chromeos/media_security/multi_profile_media_tray_item_unittest.cc
+++ b/ash/system/chromeos/media_security/multi_profile_media_tray_item_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/system/chromeos/media_security/multi_profile_media_tray_item.h"
+#include "ash/common/system/chromeos/media_security/multi_profile_media_tray_item.h"
 
 #include "ash/common/ash_view_ids.h"
 #include "ash/common/system/tray/system_tray_bubble.h"
@@ -18,7 +18,7 @@
 
 namespace ash {
 
-typedef test::AshTestBase MultiProfileMediaTrayItemTest;
+using MultiProfileMediaTrayItemTest = test::AshTestBase;
 
 TEST_F(MultiProfileMediaTrayItemTest, NotifyMediaCaptureChange) {
   TrayItemView::DisableAnimationsForTest();
diff --git a/ash/system/chromeos/tray_display.cc b/ash/system/chromeos/tray_display.cc
index 36790db..5873e54 100644
--- a/ash/system/chromeos/tray_display.cc
+++ b/ash/system/chromeos/tray_display.cc
@@ -8,6 +8,7 @@
 #include <utility>
 #include <vector>
 
+#include "ash/common/metrics/user_metrics_action.h"
 #include "ash/common/system/chromeos/devicetype_utils.h"
 #include "ash/common/system/system_notifier.h"
 #include "ash/common/system/tray/actionable_view.h"
@@ -111,13 +112,14 @@
   return base::JoinString(lines, base::ASCIIToUTF16("\n"));
 }
 
-void OpenSettings() {
+// Attempts to open the display settings, returns true if successful.
+bool OpenSettings() {
   // switch is intentionally introduced without default, to cause an error when
   // a new type of login status is introduced.
   switch (WmShell::Get()->system_tray_delegate()->GetUserLoginStatus()) {
     case LoginStatus::NOT_LOGGED_IN:
     case LoginStatus::LOCKED:
-      return;
+      return false;
 
     case LoginStatus::USER:
     case LoginStatus::OWNER:
@@ -126,8 +128,22 @@
     case LoginStatus::SUPERVISED:
     case LoginStatus::KIOSK_APP:
       SystemTrayDelegate* delegate = WmShell::Get()->system_tray_delegate();
-      if (delegate->ShouldShowSettings())
+      if (delegate->ShouldShowSettings()) {
         delegate->ShowDisplaySettings();
+        return true;
+      }
+  }
+
+  return false;
+}
+
+// Callback to handle a user selecting the notification view.
+void OpenSettingsFromNotification() {
+  WmShell::Get()->RecordUserMetricsAction(
+      UMA_STATUS_AREA_DISPLAY_NOTIFICATION_SELECTED);
+  if (OpenSettings()) {
+    WmShell::Get()->RecordUserMetricsAction(
+        UMA_STATUS_AREA_DISPLAY_NOTIFICATION_SHOW_SETTINGS);
   }
 }
 
@@ -279,7 +295,12 @@
 
   // Overridden from ActionableView.
   bool PerformAction(const ui::Event& event) override {
-    OpenSettings();
+    WmShell::Get()->RecordUserMetricsAction(
+        UMA_STATUS_AREA_DISPLAY_DEFAULT_SELECTED);
+    if (OpenSettings()) {
+      WmShell::Get()->RecordUserMetricsAction(
+          UMA_STATUS_AREA_DISPLAY_DEFAULT_SHOW_SETTINGS);
+    }
     return true;
   }
 
@@ -404,8 +425,10 @@
                                  system_notifier::kNotifierDisplay),
       message_center::RichNotificationData(),
       new message_center::HandleNotificationClickedDelegate(
-          base::Bind(&OpenSettings))));
+          base::Bind(&OpenSettingsFromNotification))));
 
+  WmShell::Get()->RecordUserMetricsAction(
+      UMA_STATUS_AREA_DISPLAY_NOTIFICATION_CREATED);
   message_center::MessageCenter::Get()->AddNotification(
       std::move(notification));
 }
diff --git a/ash/system/tray/system_tray.cc b/ash/system/tray/system_tray.cc
index 7ff990768..b9b8141 100644
--- a/ash/system/tray/system_tray.cc
+++ b/ash/system/tray/system_tray.cc
@@ -48,6 +48,7 @@
 #include "ash/common/system/chromeos/bluetooth/tray_bluetooth.h"
 #include "ash/common/system/chromeos/brightness/tray_brightness.h"
 #include "ash/common/system/chromeos/enterprise/tray_enterprise.h"
+#include "ash/common/system/chromeos/media_security/multi_profile_media_tray_item.h"
 #include "ash/common/system/chromeos/network/tray_network.h"
 #include "ash/common/system/chromeos/network/tray_sms.h"
 #include "ash/common/system/chromeos/network/tray_vpn.h"
@@ -61,7 +62,6 @@
 #include "ash/common/system/chromeos/tray_caps_lock.h"
 #include "ash/common/system/chromeos/tray_tracing.h"
 #include "ash/common/system/ime/tray_ime_chromeos.h"
-#include "ash/system/chromeos/media_security/multi_profile_media_tray_item.h"
 #include "ash/system/chromeos/rotation/tray_rotation_lock.h"
 #include "ash/system/chromeos/tray_display.h"
 #include "ui/message_center/message_center.h"
diff --git a/ash/sysui/context_menu_mus.cc b/ash/sysui/context_menu_mus.cc
index 928de76..52ddd93 100644
--- a/ash/sysui/context_menu_mus.cc
+++ b/ash/sysui/context_menu_mus.cc
@@ -41,8 +41,9 @@
   return true;
 }
 
-bool ContextMenuMus::GetAcceleratorForCommandId(int command_id,
-                                                ui::Accelerator* accelerator) {
+bool ContextMenuMus::GetAcceleratorForCommandId(
+    int command_id,
+    ui::Accelerator* accelerator) const {
   return false;
 }
 
diff --git a/ash/sysui/context_menu_mus.h b/ash/sysui/context_menu_mus.h
index 03776e0..d8592d7 100644
--- a/ash/sysui/context_menu_mus.h
+++ b/ash/sysui/context_menu_mus.h
@@ -25,7 +25,7 @@
   bool IsCommandIdChecked(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
 
  private:
diff --git a/ash/sysui/shelf_delegate_mus.cc b/ash/sysui/shelf_delegate_mus.cc
index 773a9ad..a1c229d 100644
--- a/ash/sysui/shelf_delegate_mus.cc
+++ b/ash/sysui/shelf_delegate_mus.cc
@@ -89,8 +89,9 @@
     bool IsCommandIdEnabled(int command_id) const override {
       return command_id > 0;
     }
-    bool GetAcceleratorForCommandId(int command_id,
-                                    ui::Accelerator* accelerator) override {
+    bool GetAcceleratorForCommandId(
+        int command_id,
+        ui::Accelerator* accelerator) const override {
       return false;
     }
     void ExecuteCommand(int command_id, int event_flags) override {
diff --git a/ash/wm/video_detector.cc b/ash/wm/video_detector.cc
index e4355bc..777f36f6 100644
--- a/ash/wm/video_detector.cc
+++ b/ash/wm/video_detector.cc
@@ -22,6 +22,7 @@
 const int VideoDetector::kMinUpdateHeight = 250;
 const int VideoDetector::kMinFramesPerSecond = 15;
 const int VideoDetector::kVideoTimeoutMs = 1000;
+const int VideoDetector::kMinVideoDurationMs = 3000;
 
 // Stores information about updates to a window and determines whether it's
 // likely that a video is playing in it.
@@ -45,8 +46,18 @@
     update_times_[(buffer_start_ + buffer_size_) % kMinFramesPerSecond] = now;
     buffer_size_++;
 
-    return buffer_size_ == static_cast<size_t>(kMinFramesPerSecond) &&
-           (now - update_times_[buffer_start_]).InSecondsF() <= 1.0;
+    const bool in_video =
+        (buffer_size_ == static_cast<size_t>(kMinFramesPerSecond)) &&
+        ((now - update_times_[buffer_start_]).InSecondsF() <= 1.0);
+
+    if (in_video && video_start_time_.is_null())
+      video_start_time_ = update_times_[buffer_start_];
+    else if (!in_video && !video_start_time_.is_null())
+      video_start_time_ = base::TimeTicks();
+
+    const base::TimeDelta elapsed = now - video_start_time_;
+    return in_video &&
+           elapsed >= base::TimeDelta::FromMilliseconds(kMinVideoDurationMs);
   }
 
  private:
@@ -54,6 +65,10 @@
   // |kMinFramesPerSecond|) video-sized updates to this window.
   base::TimeTicks update_times_[kMinFramesPerSecond];
 
+  // Time at which the current sequence of updates that looks like video
+  // started. Empty if video isn't currently playing.
+  base::TimeTicks video_start_time_;
+
   // Index into |update_times_| of the oldest update.
   size_t buffer_start_;
 
@@ -90,7 +105,7 @@
   if (!video_inactive_timer_.IsRunning())
     return false;
 
-  video_inactive_timer_.Reset();
+  video_inactive_timer_.Stop();
   HandleVideoInactive();
   return true;
 }
diff --git a/ash/wm/video_detector.h b/ash/wm/video_detector.h
index 6672239..5ccad54 100644
--- a/ash/wm/video_detector.h
+++ b/ash/wm/video_detector.h
@@ -72,6 +72,10 @@
   // Timeout after which video is no longer considered to be playing.
   static const int kVideoTimeoutMs;
 
+  // Duration video must be playing in a window before it is reported to
+  // observers.
+  static const int kMinVideoDurationMs;
+
   VideoDetector();
   ~VideoDetector() override;
 
diff --git a/ash/wm/video_detector_unittest.cc b/ash/wm/video_detector_unittest.cc
index 103bda8..e0b384d 100644
--- a/ash/wm/video_detector_unittest.cc
+++ b/ash/wm/video_detector_unittest.cc
@@ -55,7 +55,16 @@
 
 class VideoDetectorTest : public AshTestBase {
  public:
-  VideoDetectorTest() {}
+  VideoDetectorTest()
+      : kMinFps(VideoDetector::kMinFramesPerSecond),
+        kMinRect(gfx::Point(0, 0),
+                 gfx::Size(VideoDetector::kMinUpdateWidth,
+                           VideoDetector::kMinUpdateHeight)),
+        kMinDuration(base::TimeDelta::FromMilliseconds(
+            VideoDetector::kMinVideoDurationMs)),
+        kTimeout(
+            base::TimeDelta::FromMilliseconds(VideoDetector::kVideoTimeoutMs)),
+        next_window_id_(1000) {}
   ~VideoDetectorTest() override {}
 
   void SetUp() override {
@@ -80,204 +89,204 @@
     detector_->set_now_for_test(now_);
   }
 
-  VideoDetector* detector_;  // not owned
+  // Creates and returns a new window with |bounds|.
+  std::unique_ptr<aura::Window> CreateTestWindow(const gfx::Rect& bounds) {
+    return std::unique_ptr<aura::Window>(
+        CreateTestWindowInShell(SK_ColorRED, next_window_id_++, bounds));
+  }
 
+  // Report updates to |window| of area |region| at a rate of
+  // |updates_per_second| over |duration|. The first update will be sent
+  // immediately and |now_| will incremented by |duration| upon returning.
+  void SendUpdates(aura::Window* window,
+                   const gfx::Rect& region,
+                   int updates_per_second,
+                   base::TimeDelta duration) {
+    const base::TimeDelta time_between_updates =
+        base::TimeDelta::FromSecondsD(1.0 / updates_per_second);
+    const base::TimeTicks end_time = now_ + duration;
+    while (now_ < end_time) {
+      detector_->OnDelegatedFrameDamage(window, region);
+      AdvanceTime(time_between_updates);
+    }
+    now_ = end_time;
+    detector_->set_now_for_test(now_);
+  }
+
+  // Constants placed here for convenience.
+  const int kMinFps;
+  const gfx::Rect kMinRect;
+  const base::TimeDelta kMinDuration;
+  const base::TimeDelta kTimeout;
+
+  VideoDetector* detector_;  // not owned
   std::unique_ptr<TestObserver> observer_;
 
+  // The current (fake) time used by |detector_|.
   base::TimeTicks now_;
 
+  // Next ID to be assigned by CreateTestWindow().
+  int next_window_id_;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(VideoDetectorTest);
 };
 
-TEST_F(VideoDetectorTest, Basic) {
-  gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768));
-  std::unique_ptr<aura::Window> window(
-      CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds));
-
-  // Send enough updates, but make them be too small to trigger detection.
-  gfx::Rect update_region(gfx::Point(),
-                          gfx::Size(VideoDetector::kMinUpdateWidth - 1,
-                                    VideoDetector::kMinUpdateHeight));
-  for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
-    detector_->OnDelegatedFrameDamage(window.get(), update_region);
-  EXPECT_TRUE(observer_->empty());
-
-  // The inactivity timer shouldn't be running yet.
-  EXPECT_FALSE(detector_->TriggerTimeoutForTest());
-  EXPECT_TRUE(observer_->empty());
-
-  // Send not-quite-enough adaquately-sized updates.
-  observer_->reset();
-  AdvanceTime(base::TimeDelta::FromSeconds(2));
-  update_region.set_size(gfx::Size(VideoDetector::kMinUpdateWidth,
-                                   VideoDetector::kMinUpdateHeight));
-  for (int i = 0; i < VideoDetector::kMinFramesPerSecond - 1; ++i)
-    detector_->OnDelegatedFrameDamage(window.get(), update_region);
-  EXPECT_TRUE(observer_->empty());
-
-  // We should get notified after the next update, but not in response to
-  // additional updates.
-  detector_->OnDelegatedFrameDamage(window.get(), update_region);
-  EXPECT_EQ(VideoDetector::State::PLAYING_WINDOWED, observer_->PopState());
-  detector_->OnDelegatedFrameDamage(window.get(), update_region);
-  EXPECT_TRUE(observer_->empty());
-
-  // Wait and check that the observer is notified about inactivity.
-  AdvanceTime(base::TimeDelta::FromSeconds(VideoDetector::kVideoTimeoutMs));
-  ASSERT_TRUE(detector_->TriggerTimeoutForTest());
-  EXPECT_EQ(VideoDetector::State::NOT_PLAYING, observer_->PopState());
-
-  // Spread out the frames over a longer period of time, but send enough
-  // over a one-second window that the observer should be notified.
-  observer_->reset();
-  detector_->OnDelegatedFrameDamage(window.get(), update_region);
-  EXPECT_TRUE(observer_->empty());
-
-  AdvanceTime(base::TimeDelta::FromMilliseconds(500));
-  const int kNumFrames = VideoDetector::kMinFramesPerSecond + 1;
-  base::TimeDelta kInterval =
-      base::TimeDelta::FromMilliseconds(1000 / kNumFrames);
-  for (int i = 0; i < kNumFrames; ++i) {
-    AdvanceTime(kInterval);
-    detector_->OnDelegatedFrameDamage(window.get(), update_region);
-  }
-  EXPECT_EQ(VideoDetector::State::PLAYING_WINDOWED, observer_->PopState());
-
-  // Let the activity time out again.
-  AdvanceTime(base::TimeDelta::FromSeconds(VideoDetector::kVideoTimeoutMs));
-  ASSERT_TRUE(detector_->TriggerTimeoutForTest());
-  EXPECT_EQ(VideoDetector::State::NOT_PLAYING, observer_->PopState());
-
-  // Send updates at a slower rate and check that the observer isn't notified.
-  observer_->reset();
-  base::TimeDelta kSlowInterval = base::TimeDelta::FromMilliseconds(
-      1000 / (VideoDetector::kMinFramesPerSecond - 2));
-  for (int i = 0; i < kNumFrames; ++i) {
-    AdvanceTime(kSlowInterval);
-    detector_->OnDelegatedFrameDamage(window.get(), update_region);
-  }
+TEST_F(VideoDetectorTest, DontReportWhenRegionTooSmall) {
+  std::unique_ptr<aura::Window> window =
+      CreateTestWindow(gfx::Rect(0, 0, 1024, 768));
+  gfx::Rect rect = kMinRect;
+  rect.Inset(0, 0, 1, 0);
+  SendUpdates(window.get(), rect, 2 * kMinFps, 2 * kMinDuration);
   EXPECT_TRUE(observer_->empty());
 }
 
-TEST_F(VideoDetectorTest, Shutdown) {
-  gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768));
-  std::unique_ptr<aura::Window> window(
-      CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds));
-  gfx::Rect update_region(gfx::Point(),
-                          gfx::Size(VideoDetector::kMinUpdateWidth,
-                                    VideoDetector::kMinUpdateHeight));
-
-  // It should not detect video during the shutdown.
-  Shell::GetInstance()->OnAppTerminating();
-  for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
-    detector_->OnDelegatedFrameDamage(window.get(), update_region);
+TEST_F(VideoDetectorTest, DontReportWhenFramerateTooLow) {
+  std::unique_ptr<aura::Window> window =
+      CreateTestWindow(gfx::Rect(0, 0, 1024, 768));
+  SendUpdates(window.get(), kMinRect, kMinFps - 5, 2 * kMinDuration);
   EXPECT_TRUE(observer_->empty());
 }
 
-TEST_F(VideoDetectorTest, WindowNotVisible) {
-  gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768));
-  std::unique_ptr<aura::Window> window(
-      CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds));
+TEST_F(VideoDetectorTest, DontReportWhenNotPlayingLongEnough) {
+  std::unique_ptr<aura::Window> window =
+      CreateTestWindow(gfx::Rect(0, 0, 1024, 768));
+  SendUpdates(window.get(), kMinRect, 2 * kMinFps, 0.5 * kMinDuration);
+  EXPECT_TRUE(observer_->empty());
 
+  // Continue playing.
+  SendUpdates(window.get(), kMinRect, 2 * kMinFps, 0.6 * kMinDuration);
+  EXPECT_EQ(VideoDetector::State::PLAYING_WINDOWED, observer_->PopState());
+  EXPECT_TRUE(observer_->empty());
+}
+
+TEST_F(VideoDetectorTest, DontReportWhenWindowOffscreen) {
+  std::unique_ptr<aura::Window> window =
+      CreateTestWindow(gfx::Rect(0, 0, 1024, 768));
+  window->SetBounds(
+      gfx::Rect(gfx::Point(Shell::GetPrimaryRootWindow()->bounds().width(), 0),
+                window->bounds().size()));
+  SendUpdates(window.get(), kMinRect, 2 * kMinFps, 2 * kMinDuration);
+  EXPECT_TRUE(observer_->empty());
+
+  // Move the window onscreen.
+  window->SetBounds(gfx::Rect(gfx::Point(0, 0), window->bounds().size()));
+  SendUpdates(window.get(), kMinRect, 2 * kMinFps, 2 * kMinDuration);
+  EXPECT_EQ(VideoDetector::State::PLAYING_WINDOWED, observer_->PopState());
+  EXPECT_TRUE(observer_->empty());
+}
+
+TEST_F(VideoDetectorTest, DontReportWhenWindowHidden) {
+  std::unique_ptr<aura::Window> window =
+      CreateTestWindow(gfx::Rect(0, 0, 1024, 768));
   // Reparent the window to the root to make sure that visibility changes aren't
   // animated.
   Shell::GetPrimaryRootWindow()->AddChild(window.get());
-
-  // We shouldn't report video that's played in a hidden window.
   window->Hide();
-  gfx::Rect update_region(gfx::Point(),
-                          gfx::Size(VideoDetector::kMinUpdateWidth,
-                                    VideoDetector::kMinUpdateHeight));
-  for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
-    detector_->OnDelegatedFrameDamage(window.get(), update_region);
+  SendUpdates(window.get(), kMinRect, kMinFps + 5, 2 * kMinDuration);
   EXPECT_TRUE(observer_->empty());
 
-  // Make the window visible and send more updates.
+  // Make the window visible.
   observer_->reset();
-  AdvanceTime(base::TimeDelta::FromSeconds(2));
+  AdvanceTime(kTimeout);
   window->Show();
-  for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
-    detector_->OnDelegatedFrameDamage(window.get(), update_region);
+  SendUpdates(window.get(), kMinRect, kMinFps + 5, 2 * kMinDuration);
   EXPECT_EQ(VideoDetector::State::PLAYING_WINDOWED, observer_->PopState());
-
-  AdvanceTime(base::TimeDelta::FromSeconds(VideoDetector::kVideoTimeoutMs));
-  ASSERT_TRUE(detector_->TriggerTimeoutForTest());
-  EXPECT_EQ(VideoDetector::State::NOT_PLAYING, observer_->PopState());
-
-  // We also shouldn't report video in a window that's fully offscreen.
-  observer_->reset();
-  gfx::Rect offscreen_bounds(
-      gfx::Point(Shell::GetPrimaryRootWindow()->bounds().width(), 0),
-      window_bounds.size());
-  window->SetBounds(offscreen_bounds);
-  ASSERT_EQ(offscreen_bounds, window->bounds());
-  for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
-    detector_->OnDelegatedFrameDamage(window.get(), update_region);
   EXPECT_TRUE(observer_->empty());
 }
 
-TEST_F(VideoDetectorTest, MultipleWindows) {
-  // Create two windows.
-  gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768));
-  std::unique_ptr<aura::Window> window1(
-      CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds));
-  std::unique_ptr<aura::Window> window2(
-      CreateTestWindowInShell(SK_ColorBLUE, 23456, window_bounds));
-
-  // Even if there's video playing in both, the observer should only receive a
-  // single notification.
-  gfx::Rect update_region(gfx::Point(),
-                          gfx::Size(VideoDetector::kMinUpdateWidth,
-                                    VideoDetector::kMinUpdateHeight));
-  for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
-    detector_->OnDelegatedFrameDamage(window1.get(), update_region);
-  for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
-    detector_->OnDelegatedFrameDamage(window2.get(), update_region);
-  EXPECT_EQ(VideoDetector::State::PLAYING_WINDOWED, observer_->PopState());
+TEST_F(VideoDetectorTest, DontReportDuringShutdown) {
+  std::unique_ptr<aura::Window> window =
+      CreateTestWindow(gfx::Rect(0, 0, 1024, 768));
+  Shell::GetInstance()->OnAppTerminating();
+  SendUpdates(window.get(), kMinRect, kMinFps + 5, 2 * kMinDuration);
+  EXPECT_TRUE(observer_->empty());
 }
 
-// Test that the observer receives the appropriate notification when the window
-// is fullscreen.
-TEST_F(VideoDetectorTest, FullscreenWindow) {
+TEST_F(VideoDetectorTest, ReportStartAndStop) {
+  const base::TimeDelta kDuration =
+      kMinDuration + base::TimeDelta::FromMilliseconds(100);
+  std::unique_ptr<aura::Window> window =
+      CreateTestWindow(gfx::Rect(0, 0, 1024, 768));
+  SendUpdates(window.get(), kMinRect, kMinFps + 5, kDuration);
+  EXPECT_EQ(VideoDetector::State::PLAYING_WINDOWED, observer_->PopState());
+  EXPECT_TRUE(observer_->empty());
+
+  AdvanceTime(kTimeout);
+  EXPECT_TRUE(detector_->TriggerTimeoutForTest());
+  EXPECT_EQ(VideoDetector::State::NOT_PLAYING, observer_->PopState());
+  EXPECT_TRUE(observer_->empty());
+
+  // The timer shouldn't be running anymore.
+  EXPECT_FALSE(detector_->TriggerTimeoutForTest());
+
+  // Start playing again.
+  SendUpdates(window.get(), kMinRect, kMinFps + 5, kDuration);
+  EXPECT_EQ(VideoDetector::State::PLAYING_WINDOWED, observer_->PopState());
+  EXPECT_TRUE(observer_->empty());
+
+  AdvanceTime(kTimeout);
+  EXPECT_TRUE(detector_->TriggerTimeoutForTest());
+  EXPECT_EQ(VideoDetector::State::NOT_PLAYING, observer_->PopState());
+  EXPECT_TRUE(observer_->empty());
+}
+
+TEST_F(VideoDetectorTest, ReportOnceForMultipleWindows) {
+  gfx::Rect kWindowBounds(gfx::Point(), gfx::Size(1024, 768));
+  std::unique_ptr<aura::Window> window1 = CreateTestWindow(kWindowBounds);
+  std::unique_ptr<aura::Window> window2 = CreateTestWindow(kWindowBounds);
+
+  // Even if there's video playing in both windows, the observer should only
+  // receive a single notification.
+  const int fps = 2 * kMinFps;
+  const base::TimeDelta time_between_updates =
+      base::TimeDelta::FromSecondsD(1.0 / fps);
+  const base::TimeTicks start_time = now_;
+  while (now_ < start_time + 2 * kMinDuration) {
+    detector_->OnDelegatedFrameDamage(window1.get(), kMinRect);
+    detector_->OnDelegatedFrameDamage(window2.get(), kMinRect);
+    AdvanceTime(time_between_updates);
+  }
+  EXPECT_EQ(VideoDetector::State::PLAYING_WINDOWED, observer_->PopState());
+  EXPECT_TRUE(observer_->empty());
+}
+
+TEST_F(VideoDetectorTest, ReportFullscreen) {
   if (!SupportsMultipleDisplays())
     return;
 
   UpdateDisplay("1024x768,1024x768");
 
-  const gfx::Rect kLeftBounds(gfx::Point(), gfx::Size(1024, 768));
-  std::unique_ptr<aura::Window> window(
-      CreateTestWindowInShell(SK_ColorRED, 12345, kLeftBounds));
+  std::unique_ptr<aura::Window> window =
+      CreateTestWindow(gfx::Rect(0, 0, 1024, 768));
   wm::WindowState* window_state = wm::GetWindowState(window.get());
   const wm::WMEvent toggle_fullscreen_event(wm::WM_EVENT_TOGGLE_FULLSCREEN);
   window_state->OnWMEvent(&toggle_fullscreen_event);
   ASSERT_TRUE(window_state->IsFullscreen());
   window->Focus();
-  const gfx::Rect kUpdateRegion(gfx::Point(),
-                                gfx::Size(VideoDetector::kMinUpdateWidth,
-                                          VideoDetector::kMinUpdateHeight));
-  for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
-    detector_->OnDelegatedFrameDamage(window.get(), kUpdateRegion);
+  SendUpdates(window.get(), kMinRect, 2 * kMinFps, 2 * kMinDuration);
   EXPECT_EQ(VideoDetector::State::PLAYING_FULLSCREEN, observer_->PopState());
+  EXPECT_TRUE(observer_->empty());
 
-  // Make the first window non-fullscreen.
+  // Make the window non-fullscreen.
+  observer_->reset();
   window_state->OnWMEvent(&toggle_fullscreen_event);
   ASSERT_FALSE(window_state->IsFullscreen());
   EXPECT_EQ(VideoDetector::State::PLAYING_WINDOWED, observer_->PopState());
+  EXPECT_TRUE(observer_->empty());
 
   // Open a second, fullscreen window. Fullscreen video should still be reported
   // due to the second window being fullscreen. This avoids situations where
   // non-fullscreen video could be reported when multiple videos are playing in
   // fullscreen and non-fullscreen windows.
-  const gfx::Rect kRightBounds(gfx::Point(1024, 0), gfx::Size(1024, 768));
-  std::unique_ptr<aura::Window> other_window(
-      CreateTestWindowInShell(SK_ColorBLUE, 6789, kRightBounds));
+  observer_->reset();
+  std::unique_ptr<aura::Window> other_window =
+      CreateTestWindow(gfx::Rect(1024, 0, 1024, 768));
   wm::WindowState* other_window_state = wm::GetWindowState(other_window.get());
   other_window_state->OnWMEvent(&toggle_fullscreen_event);
   ASSERT_TRUE(other_window_state->IsFullscreen());
-  for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
-    detector_->OnDelegatedFrameDamage(window.get(), kUpdateRegion);
   EXPECT_EQ(VideoDetector::State::PLAYING_FULLSCREEN, observer_->PopState());
+  EXPECT_TRUE(observer_->empty());
 
   // Make the second window non-fullscreen and check that the observer is
   // immediately notified about windowed video.
@@ -285,6 +294,7 @@
   other_window_state->OnWMEvent(&toggle_fullscreen_event);
   ASSERT_FALSE(other_window_state->IsFullscreen());
   EXPECT_EQ(VideoDetector::State::PLAYING_WINDOWED, observer_->PopState());
+  EXPECT_TRUE(observer_->empty());
 }
 
 }  // namespace test
diff --git a/base/BUILD.gn b/base/BUILD.gn
index e44570c..b06028b 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -1979,6 +1979,8 @@
     "win/wrapped_window_proc_unittest.cc",
   ]
 
+  defines = []
+
   deps = [
     ":base",
     ":i18n",
@@ -2009,7 +2011,7 @@
   # Allow more direct string conversions on platforms with native utf8
   # strings
   if (is_mac || is_ios || is_chromeos || is_chromecast) {
-    defines = [ "SYSTEM_NATIVE_UTF8" ]
+    defines += [ "SYSTEM_NATIVE_UTF8" ]
   }
 
   if (is_android) {
@@ -2114,6 +2116,11 @@
       # data += [ "$root_out_dir/base_unittests.dSYM/" ]
     }
   }
+
+  if (use_cfi_cast) {
+    # TODO(krasin): remove CFI_CAST_CHECK, see https://crbug.com/626794.
+    defines += [ "CFI_CAST_CHECK" ]
+  }
 }
 
 action("build_date") {
diff --git a/base/base.gyp b/base/base.gyp
index 0c1ad352..a534d5c 100644
--- a/base/base.gyp
+++ b/base/base.gyp
@@ -639,6 +639,12 @@
         'module_dir': 'base'
       },
       'conditions': [
+        ['cfi_vptr==1 and cfi_cast==1', {
+          'defines': [
+             # TODO(krasin): remove CFI_CAST_CHECK, see https://crbug.com/626794.
+            'CFI_CAST_CHECK',
+          ],
+        }],
         ['OS == "ios" or OS == "mac"', {
           'dependencies': [
             'base_unittests_arc',
diff --git a/base/metrics/histogram_base.h b/base/metrics/histogram_base.h
index 58a9ab2..d240099 100644
--- a/base/metrics/histogram_base.h
+++ b/base/metrics/histogram_base.h
@@ -135,10 +135,6 @@
     COUNT_LOW_ERROR = 0x8,
 
     NEVER_EXCEEDED_VALUE = 0x10,
-
-    // This value is used only in HistogramSnapshotManager for marking
-    // internally when new inconsistencies are found.
-    NEW_INCONSISTENCY_FOUND = 0x8000000
   };
 
   explicit HistogramBase(const std::string& name);
diff --git a/base/metrics/histogram_snapshot_manager.cc b/base/metrics/histogram_snapshot_manager.cc
index dc6cb8a..340505e 100644
--- a/base/metrics/histogram_snapshot_manager.cc
+++ b/base/metrics/histogram_snapshot_manager.cc
@@ -16,91 +16,20 @@
 
 HistogramSnapshotManager::HistogramSnapshotManager(
     HistogramFlattener* histogram_flattener)
-    : preparing_deltas_(false),
-      histogram_flattener_(histogram_flattener) {
+    : histogram_flattener_(histogram_flattener) {
   DCHECK(histogram_flattener_);
 }
 
 HistogramSnapshotManager::~HistogramSnapshotManager() {
 }
 
-void HistogramSnapshotManager::StartDeltas() {
-  // Ensure that start/finish calls do not get nested.
-  DCHECK(!preparing_deltas_);
-  preparing_deltas_ = true;
-
-  DCHECK(owned_histograms_.empty());
-
-#if DCHECK_IS_ON()
-  for (const auto& hash_and_info : known_histograms_) {
-    DCHECK(!hash_and_info.second.histogram);
-    DCHECK(!hash_and_info.second.accumulated_samples);
-    DCHECK(!(hash_and_info.second.inconsistencies &
-             HistogramBase::NEW_INCONSISTENCY_FOUND));
-  }
-#endif
-}
-
 void HistogramSnapshotManager::PrepareDelta(HistogramBase* histogram) {
   PrepareSamples(histogram, histogram->SnapshotDelta());
 }
 
-void HistogramSnapshotManager::PrepareDeltaTakingOwnership(
-    std::unique_ptr<HistogramBase> histogram) {
-  PrepareSamples(histogram.get(), histogram->SnapshotDelta());
-  owned_histograms_.push_back(std::move(histogram));
-}
-
-void HistogramSnapshotManager::PrepareAbsolute(const HistogramBase* histogram) {
-  PrepareSamples(histogram, histogram->SnapshotSamples());
-}
-
-void HistogramSnapshotManager::PrepareAbsoluteTakingOwnership(
-    std::unique_ptr<const HistogramBase> histogram) {
-  PrepareSamples(histogram.get(), histogram->SnapshotSamples());
-  owned_histograms_.push_back(std::move(histogram));
-}
-
-void HistogramSnapshotManager::PrepareFinalDeltaTakingOwnership(
-    std::unique_ptr<const HistogramBase> histogram) {
-  PrepareSamples(histogram.get(), histogram->SnapshotFinalDelta());
-  owned_histograms_.push_back(std::move(histogram));
-}
-
-void HistogramSnapshotManager::FinishDeltas() {
-  DCHECK(preparing_deltas_);
-
-  // Iterate over all known histograms to see what should be recorded.
-  for (auto& hash_and_info : known_histograms_) {
-    SampleInfo* sample_info = &hash_and_info.second;
-
-    // First, record any histograms in which corruption was detected.
-    if (sample_info->inconsistencies & HistogramBase::NEW_INCONSISTENCY_FOUND) {
-      sample_info->inconsistencies &= ~HistogramBase::NEW_INCONSISTENCY_FOUND;
-      histogram_flattener_->UniqueInconsistencyDetected(
-          static_cast<HistogramBase::Inconsistency>(
-              sample_info->inconsistencies));
-    }
-
-    // Second, record actual accumulated deltas.
-    if (sample_info->accumulated_samples) {
-      // TODO(bcwhite): Investigate using redundant_count() below to avoid
-      // additional pass through all the samples to calculate real total.
-      if (sample_info->accumulated_samples->TotalCount() > 0) {
-        histogram_flattener_->RecordDelta(*sample_info->histogram,
-                                          *sample_info->accumulated_samples);
-      }
-      delete sample_info->accumulated_samples;
-      sample_info->accumulated_samples = nullptr;
-    }
-
-    // The Histogram pointer must be cleared at this point because the owner
-    // is only required to keep it alive until FinishDeltas() completes.
-    sample_info->histogram = nullptr;
-  }
-
-  owned_histograms_.clear();
-  preparing_deltas_ = false;
+void HistogramSnapshotManager::PrepareFinalDelta(
+    const HistogramBase* histogram) {
+  PrepareSamples(histogram, histogram->SnapshotFinalDelta());
 }
 
 void HistogramSnapshotManager::PrepareSamples(
@@ -108,28 +37,32 @@
     std::unique_ptr<HistogramSamples> samples) {
   DCHECK(histogram_flattener_);
 
-  // Get information known about this histogram.
+  // Get information known about this histogram. If it did not previously
+  // exist, one will be created and initialized.
   SampleInfo* sample_info = &known_histograms_[histogram->name_hash()];
-  if (sample_info->histogram) {
-    DCHECK_EQ(sample_info->histogram->histogram_name(),
-              histogram->histogram_name()) << "hash collision";
-  } else {
-    // First time this histogram has been seen; datafill.
-    sample_info->histogram = histogram;
-  }
 
   // Crash if we detect that our histograms have been overwritten.  This may be
   // a fair distance from the memory smasher, but we hope to correlate these
   // crashes with other events, such as plugins, or usage patterns, etc.
   uint32_t corruption = histogram->FindCorruption(*samples);
   if (HistogramBase::BUCKET_ORDER_ERROR & corruption) {
+    // Extract fields useful during debug.
+    const BucketRanges* ranges =
+        static_cast<const Histogram*>(histogram)->bucket_ranges();
+    std::vector<HistogramBase::Sample> ranges_copy;
+    for (size_t i = 0; i < ranges->size(); ++i)
+      ranges_copy.push_back(ranges->range(i));
+    HistogramBase::Sample* ranges_ptr = &ranges_copy[0];
+    const char* histogram_name = histogram->histogram_name().c_str();
+    int32_t flags = histogram->flags();
     // The checksum should have caught this, so crash separately if it didn't.
     CHECK_NE(0U, HistogramBase::RANGE_CHECKSUM_ERROR & corruption);
     CHECK(false);  // Crash for the bucket order corruption.
     // Ensure that compiler keeps around pointers to |histogram| and its
     // internal |bucket_ranges_| for any minidumps.
-    base::debug::Alias(
-        static_cast<const Histogram*>(histogram)->bucket_ranges());
+    base::debug::Alias(&ranges_ptr);
+    base::debug::Alias(&histogram_name);
+    base::debug::Alias(&flags);
   }
   // Checksum corruption might not have caused order corruption.
   CHECK_EQ(0U, HistogramBase::RANGE_CHECKSUM_ERROR & corruption);
@@ -146,19 +79,14 @@
     const uint32_t old_corruption = sample_info->inconsistencies;
     if (old_corruption == (corruption | old_corruption))
       return;  // We've already seen this corruption for this histogram.
-    sample_info->inconsistencies |=
-        corruption | HistogramBase::NEW_INCONSISTENCY_FOUND;
-    // TODO(bcwhite): Can we clear the inconsistency for future collection?
+    sample_info->inconsistencies |= corruption;
+    histogram_flattener_->UniqueInconsistencyDetected(
+        static_cast<HistogramBase::Inconsistency>(corruption));
     return;
   }
 
-  if (!sample_info->accumulated_samples) {
-    // This histogram has not been seen before; add it as a new entry.
-    sample_info->accumulated_samples = samples.release();
-  } else {
-    // There are previous values from this histogram; add them together.
-    sample_info->accumulated_samples->Add(*samples);
-  }
+  if (samples->TotalCount() > 0)
+    histogram_flattener_->RecordDelta(*histogram, *samples);
 }
 
 void HistogramSnapshotManager::InspectLoggedSamplesInconsistency(
diff --git a/base/metrics/histogram_snapshot_manager.h b/base/metrics/histogram_snapshot_manager.h
index 83bd5fe..26fb93f 100644
--- a/base/metrics/histogram_snapshot_manager.h
+++ b/base/metrics/histogram_snapshot_manager.h
@@ -37,16 +37,12 @@
   // |required_flags| is used to select histograms to be recorded.
   // Only histograms that have all the flags specified by the argument will be
   // chosen. If all histograms should be recorded, set it to
-  // |Histogram::kNoFlags|. Though any "forward" iterator will work, the
-  // histograms over which it iterates *must* remain valid until this method
-  // returns; the iterator cannot deallocate histograms once it iterates past
-  // them and FinishDeltas() has been called after.  StartDeltas() must be
-  // called before.
+  // |Histogram::kNoFlags|.
   template <class ForwardHistogramIterator>
-  void PrepareDeltasWithoutStartFinish(ForwardHistogramIterator begin,
-                                       ForwardHistogramIterator end,
-                                       HistogramBase::Flags flags_to_set,
-                                       HistogramBase::Flags required_flags) {
+  void PrepareDeltas(ForwardHistogramIterator begin,
+                     ForwardHistogramIterator end,
+                     HistogramBase::Flags flags_to_set,
+                     HistogramBase::Flags required_flags) {
     for (ForwardHistogramIterator it = begin; it != end; ++it) {
       (*it)->SetFlags(flags_to_set);
       if (((*it)->flags() & required_flags) == required_flags)
@@ -54,59 +50,21 @@
     }
   }
 
-  // As above but also calls StartDeltas() and FinishDeltas().
-  template <class ForwardHistogramIterator>
-  void PrepareDeltas(ForwardHistogramIterator begin,
-                     ForwardHistogramIterator end,
-                     HistogramBase::Flags flags_to_set,
-                     HistogramBase::Flags required_flags) {
-    StartDeltas();
-    PrepareDeltasWithoutStartFinish(begin, end, flags_to_set, required_flags);
-    FinishDeltas();
-  }
-
   // When the collection is not so simple as can be done using a single
   // iterator, the steps can be performed separately. Call PerpareDelta()
-  // as many times as necessary with a single StartDeltas() before and
-  // a single FinishDeltas() after. All passed histograms must live
-  // until FinishDeltas() completes. PrepareAbsolute() works the same
-  // but assumes there were no previous logged values and no future deltas
-  // will be created (and thus can work on read-only histograms).
-  // PrepareFinalDelta() works like PrepareDelta() except that it does
-  // not update the previous logged values and can thus be used with
-  // read-only files.
-  // Use Prepare*TakingOwnership() if it is desireable to have this class
-  // automatically delete the histogram once it is "finished".
-  void StartDeltas();
+  // as many times as necessary. PrepareFinalDelta() works like PrepareDelta()
+  // except that it does not update the previous logged values and can thus
+  // be used with read-only files.
   void PrepareDelta(HistogramBase* histogram);
-  void PrepareDeltaTakingOwnership(std::unique_ptr<HistogramBase> histogram);
-  void PrepareAbsolute(const HistogramBase* histogram);
-  void PrepareAbsoluteTakingOwnership(
-      std::unique_ptr<const HistogramBase> histogram);
-  void PrepareFinalDeltaTakingOwnership(
-      std::unique_ptr<const HistogramBase> histogram);
-  void FinishDeltas();
+  void PrepareFinalDelta(const HistogramBase* histogram);
 
  private:
   FRIEND_TEST_ALL_PREFIXES(HistogramSnapshotManagerTest, CheckMerge);
 
   // During a snapshot, samples are acquired and aggregated. This structure
-  // contains all the information collected for a given histogram. Once a
-  // snapshot operation is finished, it is generally emptied except for
-  // information that must persist from one report to the next, such as
-  // the "inconsistencies".
+  // contains all the information for a given histogram that persists between
+  // collections.
   struct SampleInfo {
-    // A histogram associated with this sample; it may be one of many if
-    // several have been aggregated into the same "accumulated" sample set.
-    // Ownership of the histogram remains elsewhere and this pointer is
-    // cleared by FinishDeltas().
-    const HistogramBase* histogram = nullptr;
-
-    // The current snapshot-delta values being accumulated.
-    // TODO(bcwhite): Change this to a scoped_ptr once all build architectures
-    // support such as the value of a std::map.
-    HistogramSamples* accumulated_samples = nullptr;
-
     // The set of inconsistencies (flags) already seen for the histogram.
     // See HistogramBase::Inconsistency for values.
     uint32_t inconsistencies = 0;
@@ -126,13 +84,6 @@
   // by the hash of the histogram name.
   std::map<uint64_t, SampleInfo> known_histograms_;
 
-  // Collection of histograms of which ownership has been passed to this
-  // object. They will be deleted by FinishDeltas().
-  std::vector<std::unique_ptr<const HistogramBase>> owned_histograms_;
-
-  // Indicates if deltas are currently being prepared.
-  bool preparing_deltas_;
-
   // |histogram_flattener_| handles the logistics of recording the histogram
   // deltas.
   HistogramFlattener* histogram_flattener_;  // Weak.
diff --git a/base/metrics/histogram_snapshot_manager_unittest.cc b/base/metrics/histogram_snapshot_manager_unittest.cc
index 6d53c86a..3c13e1a5 100644
--- a/base/metrics/histogram_snapshot_manager_unittest.cc
+++ b/base/metrics/histogram_snapshot_manager_unittest.cc
@@ -24,8 +24,9 @@
   void RecordDelta(const HistogramBase& histogram,
                    const HistogramSamples& snapshot) override {
     recorded_delta_histogram_names_.push_back(histogram.histogram_name());
-    ASSERT_FALSE(ContainsKey(recorded_delta_histogram_sum_,
-                             histogram.histogram_name()));
+    // Use CHECK instead of ASSERT to get full stack-trace and thus origin.
+    CHECK(!ContainsKey(recorded_delta_histogram_sum_,
+                       histogram.histogram_name()));
     // Keep pointer to snapshot for testing. This really isn't ideal but the
     // snapshot-manager keeps the snapshot alive until it's "forgotten".
     recorded_delta_histogram_sum_[histogram.histogram_name()] = snapshot.sum();
@@ -125,35 +126,4 @@
   EXPECT_EQ("UmaStabilityHistogram", histograms[0]);
 }
 
-TEST_F(HistogramSnapshotManagerTest, CheckMerge) {
-  UMA_HISTOGRAM_ENUMERATION("UmaHistogram", 1, 4);
-  UMA_STABILITY_HISTOGRAM_ENUMERATION("UmaStabilityHistogram", 1, 2);
-
-  base::HistogramBase* h1 = base::LinearHistogram::FactoryGet(
-      "UmaHistogram", 1, 4, 5, 0);
-  ASSERT_TRUE(h1);
-  base::HistogramBase* h2 = base::LinearHistogram::FactoryGet(
-      "UmaStabilityHistogram", 1, 2, 3, 0);
-  ASSERT_TRUE(h2);
-
-  histogram_snapshot_manager_.StartDeltas();
-  histogram_snapshot_manager_.PrepareDelta(h1);
-  histogram_snapshot_manager_.PrepareDelta(h1);  // Delta will be zero.
-  histogram_snapshot_manager_.PrepareDelta(h2);
-  h1->Add(2);
-  h2->Add(1);
-  histogram_snapshot_manager_.PrepareDelta(h2);
-  histogram_snapshot_manager_.PrepareDelta(h1);
-  histogram_snapshot_manager_.FinishDeltas();
-  {
-    const std::vector<std::string> histograms =
-        histogram_flattener_delta_recorder_.GetRecordedDeltaHistogramNames();
-    EXPECT_EQ(2U, histograms.size());
-    EXPECT_EQ(3, histogram_flattener_delta_recorder_.
-                     GetRecordedDeltaHistogramSum("UmaHistogram"));
-    EXPECT_EQ(2, histogram_flattener_delta_recorder_.
-                     GetRecordedDeltaHistogramSum("UmaStabilityHistogram"));
-  }
-}
-
 }  // namespace base
diff --git a/base/metrics/user_metrics.h b/base/metrics/user_metrics.h
index c80bac0..93701e8 100644
--- a/base/metrics/user_metrics.h
+++ b/base/metrics/user_metrics.h
@@ -26,9 +26,9 @@
 //   not good: "SSLDialogShown", "PageLoaded", "DiskFull"
 // We use this to gather anonymized information about how users are
 // interacting with the browser.
-// WARNING: In calls to this function, UserMetricsAction and a
-// string literal parameter must be on the same line, e.g.
-//   RecordAction(UserMetricsAction("my extremely long action name"));
+// WARNING: In calls to this function, UserMetricsAction should be followed by a
+// string literal parameter and not a variable e.g.
+//   RecordAction(UserMetricsAction("my action name"));
 // This ensures that our processing scripts can associate this action's hash
 // with its metric name. Therefore, it will be possible to retrieve the metric
 // name from the hash later on.
diff --git a/base/metrics/user_metrics_action.h b/base/metrics/user_metrics_action.h
index 8c195b3..3eca3ddb 100644
--- a/base/metrics/user_metrics_action.h
+++ b/base/metrics/user_metrics_action.h
@@ -10,13 +10,12 @@
 // UserMetricsAction exists purely to standardize on the parameters passed to
 // UserMetrics. That way, our toolset can scan the source code reliable for
 // constructors and extract the associated string constants.
-// WARNING: When using UserMetricsAction, UserMetricsAction and a string literal
-// parameter must be on the same line, e.g.
-//   RecordAction(UserMetricsAction("my extremely long action name"));
-// or
-//   RenderThread::Get()->RecordAction(
-//       UserMetricsAction("my extremely long action name"));
-// because otherwise our processing scripts won't pick up on new actions.
+// WARNING: When using UserMetricsAction you should use a string literal
+// parameter e.g.
+//   RecordAction(UserMetricsAction("my action name"));
+// This ensures that our processing scripts can associate this action's hash
+// with its metric name. Therefore, it will be possible to retrieve the metric
+// name from the hash later on.
 // Please see tools/metrics/actions/extract_actions.py for details.
 struct UserMetricsAction {
   const char* str_;
diff --git a/base/observer_list.h b/base/observer_list.h
index 3156421..afe1f46c 100644
--- a/base/observer_list.h
+++ b/base/observer_list.h
@@ -236,8 +236,8 @@
 #define FOR_EACH_OBSERVER(ObserverType, observer_list, func)             \
   do {                                                                   \
     if ((observer_list).might_have_observers()) {                        \
-      base::ObserverListBase<ObserverType>::Iterator it_inside_observer_macro( \
-          &observer_list);                                               \
+      typename base::ObserverListBase<ObserverType>::Iterator            \
+          it_inside_observer_macro(&observer_list);                      \
       ObserverType* obs;                                                 \
       while ((obs = it_inside_observer_macro.GetNext()) != nullptr)      \
         obs->func;                                                       \
diff --git a/base/test/gtest_xml_util.cc b/base/test/gtest_xml_util.cc
index 5426a24..f5464c0 100644
--- a/base/test/gtest_xml_util.cc
+++ b/base/test/gtest_xml_util.cc
@@ -126,9 +126,8 @@
           result.status = TestResult::TEST_SUCCESS;
 
           if (!results->empty() &&
-              results->at(results->size() - 1).full_name == result.full_name &&
-              results->at(results->size() - 1).status ==
-                  TestResult::TEST_CRASH) {
+              results->back().full_name == result.full_name &&
+              results->back().status == TestResult::TEST_CRASH) {
             // Erase the fail-safe "crashed" result - now we know the test did
             // not crash.
             results->pop_back();
@@ -141,7 +140,7 @@
             return false;
 
           DCHECK(!results->empty());
-          results->at(results->size() - 1).status = TestResult::TEST_FAILURE;
+          results->back().status = TestResult::TEST_FAILURE;
 
           state = STATE_FAILURE;
         } else if (node_name == "testcase" && xml_reader.IsClosingElement()) {
diff --git a/base/tools_sanity_unittest.cc b/base/tools_sanity_unittest.cc
index 8d13837..9075d16 100644
--- a/base/tools_sanity_unittest.cc
+++ b/base/tools_sanity_unittest.cc
@@ -343,6 +343,8 @@
 }
 
 #if defined(CFI_ENFORCEMENT)
+// TODO(krasin): remove CFI_CAST_CHECK, see https://crbug.com/626794.
+#if defined(CFI_CAST_CHECK)
 TEST(ToolsSanityTest, BadCast) {
   class A {
     virtual void f() {}
@@ -355,6 +357,32 @@
   A a;
   EXPECT_DEATH((void)(B*)&a, "ILL_ILLOPN");
 }
-#endif
+#endif // CFI_CAST_CHECK
+
+class A {
+ public:
+  A(): n_(0) {}
+  virtual void f() { n_++; }
+ protected:
+  int n_;
+};
+
+class B: public A {
+ public:
+  void f() override { n_--; }
+};
+
+NOINLINE void KillVptrAndCall(A *obj) {
+  *reinterpret_cast<void **>(obj) = 0;
+  obj->f();
+}
+
+TEST(ToolsSanityTest, BadVirtualCall) {
+  A a;
+  B b;
+  EXPECT_DEATH({ KillVptrAndCall(&a); KillVptrAndCall(&b); }, "ILL_ILLOPN");
+}
+
+#endif // CFI_ENFORCEMENT
 
 }  // namespace base
diff --git a/base/trace_event/trace_config.cc b/base/trace_event/trace_config.cc
index ebdddd3..b343ea00 100644
--- a/base/trace_event/trace_config.cc
+++ b/base/trace_event/trace_config.cc
@@ -69,6 +69,7 @@
   explicit ConvertableTraceConfigToTraceFormat(const TraceConfig& trace_config)
       : trace_config_(trace_config) {}
   ~ConvertableTraceConfigToTraceFormat() override {}
+
   void AppendAsTraceFormat(std::string* out) const override {
     out->append(trace_config_.ToString());
   }
@@ -88,9 +89,8 @@
 
 }  // namespace
 
-
-TraceConfig::MemoryDumpConfig::HeapProfiler::HeapProfiler() :
-    breakdown_threshold_bytes(kDefaultBreakdownThresholdBytes) {};
+TraceConfig::MemoryDumpConfig::HeapProfiler::HeapProfiler()
+    : breakdown_threshold_bytes(kDefaultBreakdownThresholdBytes) {}
 
 void TraceConfig::MemoryDumpConfig::HeapProfiler::Clear() {
   breakdown_threshold_bytes = kDefaultBreakdownThresholdBytes;
@@ -102,12 +102,12 @@
   memory_dump_config_ = memory_dump_config;
 }
 
-TraceConfig::MemoryDumpConfig::MemoryDumpConfig() {};
+TraceConfig::MemoryDumpConfig::MemoryDumpConfig() {}
 
 TraceConfig::MemoryDumpConfig::MemoryDumpConfig(
     const MemoryDumpConfig& other) = default;
 
-TraceConfig::MemoryDumpConfig::~MemoryDumpConfig() {};
+TraceConfig::MemoryDumpConfig::~MemoryDumpConfig() {}
 
 void TraceConfig::MemoryDumpConfig::Clear() {
   allowed_dump_modes.clear();
@@ -119,12 +119,12 @@
   InitializeDefault();
 }
 
-TraceConfig::TraceConfig(const std::string& category_filter_string,
-                         const std::string& trace_options_string) {
+TraceConfig::TraceConfig(StringPiece category_filter_string,
+                         StringPiece trace_options_string) {
   InitializeFromStrings(category_filter_string, trace_options_string);
 }
 
-TraceConfig::TraceConfig(const std::string& category_filter_string,
+TraceConfig::TraceConfig(StringPiece category_filter_string,
                          TraceRecordMode record_mode) {
   std::string trace_options_string;
   switch (record_mode) {
@@ -150,7 +150,7 @@
   InitializeFromConfigDict(config);
 }
 
-TraceConfig::TraceConfig(const std::string& config_string) {
+TraceConfig::TraceConfig(StringPiece config_string) {
   if (!config_string.empty())
     InitializeFromConfigString(config_string);
   else
@@ -192,12 +192,9 @@
 }
 
 std::string TraceConfig::ToString() const {
-  base::DictionaryValue dict;
-  ToDict(dict);
-
+  std::unique_ptr<DictionaryValue> dict = ToDict();
   std::string json;
-  base::JSONWriter::Write(dict, &json);
-
+  JSONWriter::Write(*dict, &json);
   return json;
 }
 
@@ -222,20 +219,18 @@
 
   bool had_enabled_by_default = false;
   DCHECK(category_group_name);
-  CStringTokenizer category_group_tokens(
-      category_group_name, category_group_name + strlen(category_group_name),
-      ",");
+  std::string category_group_name_str = category_group_name;
+  StringTokenizer category_group_tokens(category_group_name_str, ",");
   while (category_group_tokens.GetNext()) {
     std::string category_group_token = category_group_tokens.token();
     // Don't allow empty tokens, nor tokens with leading or trailing space.
     DCHECK(!TraceConfig::IsEmptyOrContainsLeadingOrTrailingWhitespace(
                category_group_token))
         << "Disallowed category string";
-    if (IsCategoryEnabled(category_group_token.c_str())) {
+    if (IsCategoryEnabled(category_group_token.c_str()))
       return true;
-    }
-    if (!base::MatchPattern(category_group_token.c_str(),
-                            TRACE_DISABLED_BY_DEFAULT("*")))
+
+    if (!MatchPattern(category_group_token, TRACE_DISABLED_BY_DEFAULT("*")))
       had_enabled_by_default = true;
   }
   // Do a second pass to check for explicitly disabled categories
@@ -244,10 +239,8 @@
   bool category_group_disabled = false;
   while (category_group_tokens.GetNext()) {
     std::string category_group_token = category_group_tokens.token();
-    for (StringList::const_iterator ci = excluded_categories_.begin();
-         ci != excluded_categories_.end();
-         ++ci) {
-      if (base::MatchPattern(category_group_token.c_str(), ci->c_str())) {
+    for (const std::string& category : excluded_categories_) {
+      if (MatchPattern(category_group_token, category)) {
         // Current token of category_group_name is present in excluded_list.
         // Flag the exclusion and proceed further to check if any of the
         // remaining categories of category_group_name is not present in the
@@ -259,8 +252,7 @@
       // excluded_ list. So, if it's not a disabled-by-default category,
       // it has to be included_ list. Enable the category_group_name
       // for recording.
-      if (!base::MatchPattern(category_group_token.c_str(),
-                              TRACE_DISABLED_BY_DEFAULT("*"))) {
+      if (!MatchPattern(category_group_token, TRACE_DISABLED_BY_DEFAULT("*"))) {
         category_group_disabled = false;
       }
     }
@@ -273,8 +265,8 @@
   // If the category group is not excluded, and there are no included patterns
   // we consider this category group enabled, as long as it had categories
   // other than disabled-by-default.
-  return !category_group_disabled &&
-         included_categories_.empty() && had_enabled_by_default;
+  return !category_group_disabled && had_enabled_by_default &&
+         included_categories_.empty();
 }
 
 void TraceConfig::Merge(const TraceConfig& config) {
@@ -346,25 +338,13 @@
     }
   }
 
-  bool enable_sampling;
-  if (!dict.GetBoolean(kEnableSamplingParam, &enable_sampling))
-    enable_sampling_ = false;
-  else
-    enable_sampling_ = enable_sampling;
+  bool val;
+  enable_sampling_ = dict.GetBoolean(kEnableSamplingParam, &val) ? val : false;
+  enable_systrace_ = dict.GetBoolean(kEnableSystraceParam, &val) ? val : false;
+  enable_argument_filter_ =
+      dict.GetBoolean(kEnableArgumentFilterParam, &val) ? val : false;
 
-  bool enable_systrace;
-  if (!dict.GetBoolean(kEnableSystraceParam, &enable_systrace))
-    enable_systrace_ = false;
-  else
-    enable_systrace_ = enable_systrace;
-
-  bool enable_argument_filter;
-  if (!dict.GetBoolean(kEnableArgumentFilterParam, &enable_argument_filter))
-    enable_argument_filter_ = false;
-  else
-    enable_argument_filter_ = enable_argument_filter;
-
-  const base::ListValue* category_list = nullptr;
+  const ListValue* category_list = nullptr;
   if (dict.GetList(kIncludedCategoriesParam, &category_list))
     SetCategoriesFromIncludedList(*category_list);
   if (dict.GetList(kExcludedCategoriesParam, &category_list))
@@ -375,7 +355,7 @@
   if (IsCategoryEnabled(MemoryDumpManager::kTraceCategory)) {
     // If dump triggers not set, the client is using the legacy with just
     // category enabled. So, use the default periodic dump config.
-    const base::DictionaryValue* memory_dump_config = nullptr;
+    const DictionaryValue* memory_dump_config = nullptr;
     if (dict.GetDictionary(kMemoryDumpConfigParam, &memory_dump_config))
       SetMemoryDumpConfigFromConfigDict(*memory_dump_config);
     else
@@ -383,51 +363,39 @@
   }
 }
 
-void TraceConfig::InitializeFromConfigString(const std::string& config_string) {
-  std::unique_ptr<Value> value(JSONReader::Read(config_string));
-  if (!value)
-    return InitializeDefault();
-
-  const DictionaryValue* dict = nullptr;
-  bool is_dict = value->GetAsDictionary(&dict);
-
-  if (!is_dict)
-    return InitializeDefault();
-
-  DCHECK(dict);
-  InitializeFromConfigDict(*dict);
+void TraceConfig::InitializeFromConfigString(StringPiece config_string) {
+  auto dict = DictionaryValue::From(JSONReader::Read(config_string));
+  if (dict)
+    InitializeFromConfigDict(*dict);
+  else
+    InitializeDefault();
 }
 
-void TraceConfig::InitializeFromStrings(
-    const std::string& category_filter_string,
-    const std::string& trace_options_string) {
+void TraceConfig::InitializeFromStrings(StringPiece category_filter_string,
+                                        StringPiece trace_options_string) {
   if (!category_filter_string.empty()) {
-    std::vector<std::string> split = base::SplitString(
-        category_filter_string, ",", base::TRIM_WHITESPACE,
-        base::SPLIT_WANT_ALL);
-    std::vector<std::string>::iterator iter;
-    for (iter = split.begin(); iter != split.end(); ++iter) {
-      std::string category = *iter;
+    std::vector<std::string> split = SplitString(
+        category_filter_string, ",", TRIM_WHITESPACE, SPLIT_WANT_ALL);
+    for (const std::string& category : split) {
       // Ignore empty categories.
       if (category.empty())
         continue;
       // Synthetic delays are of the form 'DELAY(delay;option;option;...)'.
-      if (base::StartsWith(category, kSyntheticDelayCategoryFilterPrefix,
-                           base::CompareCase::SENSITIVE) &&
-          category.at(category.size() - 1) == ')') {
-        category = category.substr(
+      if (StartsWith(category, kSyntheticDelayCategoryFilterPrefix,
+                     CompareCase::SENSITIVE) &&
+          category.back() == ')') {
+        std::string synthetic_category = category.substr(
             strlen(kSyntheticDelayCategoryFilterPrefix),
             category.size() - strlen(kSyntheticDelayCategoryFilterPrefix) - 1);
-        size_t name_length = category.find(';');
+        size_t name_length = synthetic_category.find(';');
         if (name_length != std::string::npos && name_length > 0 &&
-            name_length != category.size() - 1) {
-          synthetic_delays_.push_back(category);
+            name_length != synthetic_category.size() - 1) {
+          synthetic_delays_.push_back(synthetic_category);
         }
-      } else if (category.at(0) == '-') {
+      } else if (category.front() == '-') {
         // Excluded categories start with '-'.
         // Remove '-' from category string.
-        category = category.substr(1);
-        excluded_categories_.push_back(category);
+        excluded_categories_.push_back(category.substr(1));
       } else if (category.compare(0, strlen(TRACE_DISABLED_BY_DEFAULT("")),
                                   TRACE_DISABLED_BY_DEFAULT("")) == 0) {
         disabled_categories_.push_back(category);
@@ -441,24 +409,23 @@
   enable_sampling_ = false;
   enable_systrace_ = false;
   enable_argument_filter_ = false;
-  if(!trace_options_string.empty()) {
-    std::vector<std::string> split = base::SplitString(
-        trace_options_string, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
-    std::vector<std::string>::iterator iter;
-    for (iter = split.begin(); iter != split.end(); ++iter) {
-      if (*iter == kRecordUntilFull) {
+  if (!trace_options_string.empty()) {
+    std::vector<std::string> split =
+        SplitString(trace_options_string, ",", TRIM_WHITESPACE, SPLIT_WANT_ALL);
+    for (const std::string& token : split) {
+      if (token == kRecordUntilFull) {
         record_mode_ = RECORD_UNTIL_FULL;
-      } else if (*iter == kRecordContinuously) {
+      } else if (token == kRecordContinuously) {
         record_mode_ = RECORD_CONTINUOUSLY;
-      } else if (*iter == kTraceToConsole) {
+      } else if (token == kTraceToConsole) {
         record_mode_ = ECHO_TO_CONSOLE;
-      } else if (*iter == kRecordAsMuchAsPossible) {
+      } else if (token == kRecordAsMuchAsPossible) {
         record_mode_ = RECORD_AS_MUCH_AS_POSSIBLE;
-      } else if (*iter == kEnableSampling) {
+      } else if (token == kEnableSampling) {
         enable_sampling_ = true;
-      } else if (*iter == kEnableSystrace) {
+      } else if (token == kEnableSystrace) {
         enable_systrace_ = true;
-      } else if (*iter == kEnableArgumentFilter) {
+      } else if (token == kEnableArgumentFilter) {
         enable_argument_filter_ = true;
       }
     }
@@ -470,7 +437,7 @@
 }
 
 void TraceConfig::SetCategoriesFromIncludedList(
-    const base::ListValue& included_list) {
+    const ListValue& included_list) {
   included_categories_.clear();
   for (size_t i = 0; i < included_list.GetSize(); ++i) {
     std::string category;
@@ -486,7 +453,7 @@
 }
 
 void TraceConfig::SetCategoriesFromExcludedList(
-    const base::ListValue& excluded_list) {
+    const ListValue& excluded_list) {
   excluded_categories_.clear();
   for (size_t i = 0; i < excluded_list.GetSize(); ++i) {
     std::string category;
@@ -495,7 +462,7 @@
   }
 }
 
-void TraceConfig::SetSyntheticDelaysFromList(const base::ListValue& list) {
+void TraceConfig::SetSyntheticDelaysFromList(const ListValue& list) {
   synthetic_delays_.clear();
   for (size_t i = 0; i < list.GetSize(); ++i) {
     std::string delay;
@@ -510,27 +477,23 @@
   }
 }
 
-void TraceConfig::AddCategoryToDict(base::DictionaryValue& dict,
+void TraceConfig::AddCategoryToDict(DictionaryValue* dict,
                                     const char* param,
                                     const StringList& categories) const {
   if (categories.empty())
     return;
 
-  std::unique_ptr<base::ListValue> list(new base::ListValue());
-  for (StringList::const_iterator ci = categories.begin();
-       ci != categories.end();
-       ++ci) {
-    list->AppendString(*ci);
-  }
-
-  dict.Set(param, std::move(list));
+  auto list = MakeUnique<ListValue>();
+  for (const std::string& category : categories)
+    list->AppendString(category);
+  dict->Set(param, std::move(list));
 }
 
 void TraceConfig::SetMemoryDumpConfigFromConfigDict(
-    const base::DictionaryValue& memory_dump_config) {
+    const DictionaryValue& memory_dump_config) {
   // Set allowed dump modes.
   memory_dump_config_.allowed_dump_modes.clear();
-  const base::ListValue* allowed_modes_list;
+  const ListValue* allowed_modes_list;
   if (memory_dump_config.GetList(kAllowedDumpModesParam, &allowed_modes_list)) {
     for (size_t i = 0; i < allowed_modes_list->GetSize(); ++i) {
       std::string level_of_detail_str;
@@ -545,21 +508,20 @@
 
   // Set triggers
   memory_dump_config_.triggers.clear();
-  const base::ListValue* trigger_list = nullptr;
+  const ListValue* trigger_list = nullptr;
   if (memory_dump_config.GetList(kTriggersParam, &trigger_list) &&
       trigger_list->GetSize() > 0) {
     for (size_t i = 0; i < trigger_list->GetSize(); ++i) {
-      const base::DictionaryValue* trigger = nullptr;
+      const DictionaryValue* trigger = nullptr;
       if (!trigger_list->GetDictionary(i, &trigger))
         continue;
 
-      MemoryDumpConfig::Trigger dump_config;
       int interval = 0;
-
-      if (!trigger->GetInteger(kPeriodicIntervalParam, &interval)) {
+      if (!trigger->GetInteger(kPeriodicIntervalParam, &interval))
         continue;
-      }
+
       DCHECK_GT(interval, 0);
+      MemoryDumpConfig::Trigger dump_config;
       dump_config.periodic_interval_ms = static_cast<uint32_t>(interval);
       std::string level_of_detail_str;
       trigger->GetString(kModeParam, &level_of_detail_str);
@@ -570,7 +532,7 @@
   }
 
   // Set heap profiler options
-  const base::DictionaryValue* heap_profiler_options = nullptr;
+  const DictionaryValue* heap_profiler_options = nullptr;
   if (memory_dump_config.GetDictionary(kHeapProfilerOptions,
                                        &heap_profiler_options)) {
     int min_size_bytes = 0;
@@ -593,64 +555,48 @@
   memory_dump_config_.allowed_dump_modes = GetDefaultAllowedMemoryDumpModes();
 }
 
-void TraceConfig::ToDict(base::DictionaryValue& dict) const {
+std::unique_ptr<DictionaryValue> TraceConfig::ToDict() const {
+  auto dict = MakeUnique<DictionaryValue>();
   switch (record_mode_) {
     case RECORD_UNTIL_FULL:
-      dict.SetString(kRecordModeParam, kRecordUntilFull);
+      dict->SetString(kRecordModeParam, kRecordUntilFull);
       break;
     case RECORD_CONTINUOUSLY:
-      dict.SetString(kRecordModeParam, kRecordContinuously);
+      dict->SetString(kRecordModeParam, kRecordContinuously);
       break;
     case RECORD_AS_MUCH_AS_POSSIBLE:
-      dict.SetString(kRecordModeParam, kRecordAsMuchAsPossible);
+      dict->SetString(kRecordModeParam, kRecordAsMuchAsPossible);
       break;
     case ECHO_TO_CONSOLE:
-      dict.SetString(kRecordModeParam, kTraceToConsole);
+      dict->SetString(kRecordModeParam, kTraceToConsole);
       break;
     default:
       NOTREACHED();
   }
 
-  if (enable_sampling_)
-    dict.SetBoolean(kEnableSamplingParam, true);
-  else
-    dict.SetBoolean(kEnableSamplingParam, false);
-
-  if (enable_systrace_)
-    dict.SetBoolean(kEnableSystraceParam, true);
-  else
-    dict.SetBoolean(kEnableSystraceParam, false);
-
-  if (enable_argument_filter_)
-    dict.SetBoolean(kEnableArgumentFilterParam, true);
-  else
-    dict.SetBoolean(kEnableArgumentFilterParam, false);
+  dict->SetBoolean(kEnableSamplingParam, enable_sampling_);
+  dict->SetBoolean(kEnableSystraceParam, enable_systrace_);
+  dict->SetBoolean(kEnableArgumentFilterParam, enable_argument_filter_);
 
   StringList categories(included_categories_);
   categories.insert(categories.end(),
                     disabled_categories_.begin(),
                     disabled_categories_.end());
-  AddCategoryToDict(dict, kIncludedCategoriesParam, categories);
-  AddCategoryToDict(dict, kExcludedCategoriesParam, excluded_categories_);
-  AddCategoryToDict(dict, kSyntheticDelaysParam, synthetic_delays_);
+  AddCategoryToDict(dict.get(), kIncludedCategoriesParam, categories);
+  AddCategoryToDict(dict.get(), kExcludedCategoriesParam, excluded_categories_);
+  AddCategoryToDict(dict.get(), kSyntheticDelaysParam, synthetic_delays_);
 
   if (IsCategoryEnabled(MemoryDumpManager::kTraceCategory)) {
-    std::unique_ptr<base::DictionaryValue> memory_dump_config(
-        new base::DictionaryValue());
-    std::unique_ptr<base::ListValue> allowed_modes_list(new base::ListValue());
-    for (MemoryDumpLevelOfDetail dump_mode :
-         memory_dump_config_.allowed_dump_modes) {
-      allowed_modes_list->AppendString(
-          MemoryDumpLevelOfDetailToString(dump_mode));
-    }
-    memory_dump_config->Set(kAllowedDumpModesParam,
-                            std::move(allowed_modes_list));
+    auto allowed_modes = MakeUnique<ListValue>();
+    for (auto dump_mode : memory_dump_config_.allowed_dump_modes)
+      allowed_modes->AppendString(MemoryDumpLevelOfDetailToString(dump_mode));
 
-    std::unique_ptr<base::ListValue> triggers_list(new base::ListValue());
-    for (const MemoryDumpConfig::Trigger& config
-        : memory_dump_config_.triggers) {
-      std::unique_ptr<base::DictionaryValue> trigger_dict(
-          new base::DictionaryValue());
+    auto memory_dump_config = MakeUnique<DictionaryValue>();
+    memory_dump_config->Set(kAllowedDumpModesParam, std::move(allowed_modes));
+
+    auto triggers_list = MakeUnique<ListValue>();
+    for (const auto& config : memory_dump_config_.triggers) {
+      auto trigger_dict = MakeUnique<DictionaryValue>();
       trigger_dict->SetInteger(kPeriodicIntervalParam,
                                static_cast<int>(config.periodic_interval_ms));
       trigger_dict->SetString(
@@ -664,16 +610,15 @@
 
     if (memory_dump_config_.heap_profiler_options.breakdown_threshold_bytes !=
         MemoryDumpConfig::HeapProfiler::kDefaultBreakdownThresholdBytes) {
-      std::unique_ptr<base::DictionaryValue> heap_profiler_options(
-          new base::DictionaryValue());
-      heap_profiler_options->SetInteger(
+      auto options = MakeUnique<DictionaryValue>();
+      options->SetInteger(
           kBreakdownThresholdBytes,
           memory_dump_config_.heap_profiler_options.breakdown_threshold_bytes);
-      memory_dump_config->Set(kHeapProfilerOptions,
-                              std::move(heap_profiler_options));
+      memory_dump_config->Set(kHeapProfilerOptions, std::move(options));
     }
-    dict.Set(kMemoryDumpConfigParam, std::move(memory_dump_config));
+    dict->Set(kMemoryDumpConfigParam, std::move(memory_dump_config));
   }
+  return dict;
 }
 
 std::string TraceConfig::ToTraceOptionsString() const {
@@ -708,11 +653,10 @@
                                             bool included) const {
   bool prepend_comma = !out->empty();
   int token_cnt = 0;
-  for (StringList::const_iterator ci = values.begin();
-       ci != values.end(); ++ci) {
+  for (const std::string& category : values) {
     if (token_cnt > 0 || prepend_comma)
       StringAppendF(out, ",");
-    StringAppendF(out, "%s%s", (included ? "" : "-"), ci->c_str());
+    StringAppendF(out, "%s%s", (included ? "" : "-"), category.c_str());
     ++token_cnt;
   }
 }
@@ -721,35 +665,28 @@
                                             std::string* out) const {
   bool prepend_comma = !out->empty();
   int token_cnt = 0;
-  for (StringList::const_iterator ci = delays.begin();
-       ci != delays.end(); ++ci) {
+  for (const std::string& category : delays) {
     if (token_cnt > 0 || prepend_comma)
       StringAppendF(out, ",");
     StringAppendF(out, "%s%s)", kSyntheticDelayCategoryFilterPrefix,
-                  ci->c_str());
+                  category.c_str());
     ++token_cnt;
   }
 }
 
 bool TraceConfig::IsCategoryEnabled(const char* category_name) const {
-  StringList::const_iterator ci;
-
   // Check the disabled- filters and the disabled-* wildcard first so that a
   // "*" filter does not include the disabled.
-  for (ci = disabled_categories_.begin();
-       ci != disabled_categories_.end();
-       ++ci) {
-    if (base::MatchPattern(category_name, ci->c_str()))
+  for (const std::string& category : disabled_categories_) {
+    if (MatchPattern(category_name, category))
       return true;
   }
 
-  if (base::MatchPattern(category_name, TRACE_DISABLED_BY_DEFAULT("*")))
+  if (MatchPattern(category_name, TRACE_DISABLED_BY_DEFAULT("*")))
     return false;
 
-  for (ci = included_categories_.begin();
-       ci != included_categories_.end();
-       ++ci) {
-    if (base::MatchPattern(category_name, ci->c_str()))
+  for (const std::string& category : included_categories_) {
+    if (MatchPattern(category_name, category))
       return true;
   }
 
@@ -757,10 +694,8 @@
 }
 
 bool TraceConfig::IsEmptyOrContainsLeadingOrTrailingWhitespace(
-    const std::string& str) {
-  return  str.empty() ||
-          str.at(0) == ' ' ||
-          str.at(str.length() - 1) == ' ';
+    StringPiece str) {
+  return str.empty() || str.front() == ' ' || str.back() == ' ';
 }
 
 bool TraceConfig::HasIncludedPatterns() const {
diff --git a/base/trace_event/trace_config.h b/base/trace_event/trace_config.h
index c3a940e2..91d6f1f3 100644
--- a/base/trace_event/trace_config.h
+++ b/base/trace_event/trace_config.h
@@ -13,6 +13,7 @@
 
 #include "base/base_export.h"
 #include "base/gtest_prod_util.h"
+#include "base/strings/string_piece.h"
 #include "base/trace_event/memory_dump_request_args.h"
 #include "base/values.h"
 
@@ -39,7 +40,7 @@
 
 class BASE_EXPORT TraceConfig {
  public:
-  typedef std::vector<std::string> StringList;
+  using StringList = std::vector<std::string>;
 
   // Specifies the memory dump config for tracing.
   // Used only when "memory-infra" category is enabled.
@@ -124,11 +125,10 @@
   // Example: TraceConfig("DELAY(gpu.PresentingFrame;16;alternating)", "");
   //          would make swap buffers take at least 16 ms every other time it
   //          is called; and use default options.
-  TraceConfig(const std::string& category_filter_string,
-              const std::string& trace_options_string);
+  TraceConfig(StringPiece category_filter_string,
+              StringPiece trace_options_string);
 
-  TraceConfig(const std::string& category_filter_string,
-              TraceRecordMode record_mode);
+  TraceConfig(StringPiece category_filter_string, TraceRecordMode record_mode);
 
   // Create TraceConfig object from the trace config string.
   //
@@ -158,7 +158,7 @@
   //
   // Note: memory_dump_config can be specified only if
   // disabled-by-default-memory-infra category is enabled.
-  explicit TraceConfig(const std::string& config_string);
+  explicit TraceConfig(StringPiece config_string);
 
   // Functionally identical to the above, but takes a parsed dictionary as input
   // instead of its JSON serialization.
@@ -233,25 +233,24 @@
   void InitializeFromConfigDict(const DictionaryValue& dict);
 
   // Initialize from a config string.
-  void InitializeFromConfigString(const std::string& config_string);
+  void InitializeFromConfigString(StringPiece config_string);
 
   // Initialize from category filter and trace options strings
-  void InitializeFromStrings(const std::string& category_filter_string,
-                             const std::string& trace_options_string);
+  void InitializeFromStrings(StringPiece category_filter_string,
+                             StringPiece trace_options_string);
 
-  void SetCategoriesFromIncludedList(const base::ListValue& included_list);
-  void SetCategoriesFromExcludedList(const base::ListValue& excluded_list);
-  void SetSyntheticDelaysFromList(const base::ListValue& list);
-  void AddCategoryToDict(base::DictionaryValue& dict,
+  void SetCategoriesFromIncludedList(const ListValue& included_list);
+  void SetCategoriesFromExcludedList(const ListValue& excluded_list);
+  void SetSyntheticDelaysFromList(const ListValue& list);
+  void AddCategoryToDict(DictionaryValue* dict,
                          const char* param,
                          const StringList& categories) const;
 
   void SetMemoryDumpConfigFromConfigDict(
-      const base::DictionaryValue& memory_dump_config);
+      const DictionaryValue& memory_dump_config);
   void SetDefaultMemoryDumpConfig();
 
-  // Convert TraceConfig to the dict representation of the TraceConfig.
-  void ToDict(base::DictionaryValue& dict) const;
+  std::unique_ptr<DictionaryValue> ToDict() const;
 
   std::string ToTraceOptionsString() const;
 
@@ -267,8 +266,7 @@
   // category is enabled from the tracing runtime's perspective.
   bool IsCategoryEnabled(const char* category_name) const;
 
-  static bool IsEmptyOrContainsLeadingOrTrailingWhitespace(
-      const std::string& str);
+  static bool IsEmptyOrContainsLeadingOrTrailingWhitespace(StringPiece str);
 
   bool HasIncludedPatterns() const;
 
diff --git a/blimp/client/BUILD.gn b/blimp/client/BUILD.gn
index 1c5725bb..50fcb16 100644
--- a/blimp/client/BUILD.gn
+++ b/blimp/client/BUILD.gn
@@ -423,7 +423,7 @@
       ":blimp_java_resources",
       "//base:base_java",
       "//blimp/client/core:core_java",
-      "//blimp/client/core/public:public_java",
+      "//blimp/client/public:public_java",
 
       # TODO(dtrainor): Remove the ui_java target once no more Android Toast
       # notifications are used.
@@ -462,7 +462,7 @@
       "//base:base_java",
       "//base:base_java_test_support",
       "//blimp/client/core:core_java",
-      "//blimp/client/core/public:public_java",
+      "//blimp/client/public:public_java",
       google_play_services_library,
     ]
 
diff --git a/blimp/client/app/android/java/res/mipmap-hdpi/app_icon.png b/blimp/client/app/android/java/res/mipmap-hdpi/app_icon.png
index 8b3efd3..e1924bf 100644
--- a/blimp/client/app/android/java/res/mipmap-hdpi/app_icon.png
+++ b/blimp/client/app/android/java/res/mipmap-hdpi/app_icon.png
Binary files differ
diff --git a/blimp/client/app/android/java/res/mipmap-mdpi/app_icon.png b/blimp/client/app/android/java/res/mipmap-mdpi/app_icon.png
index b248545..32d78b5 100644
--- a/blimp/client/app/android/java/res/mipmap-mdpi/app_icon.png
+++ b/blimp/client/app/android/java/res/mipmap-mdpi/app_icon.png
Binary files differ
diff --git a/blimp/client/app/android/java/res/mipmap-xhdpi/app_icon.png b/blimp/client/app/android/java/res/mipmap-xhdpi/app_icon.png
index 8040d0b4..91e027d 100644
--- a/blimp/client/app/android/java/res/mipmap-xhdpi/app_icon.png
+++ b/blimp/client/app/android/java/res/mipmap-xhdpi/app_icon.png
Binary files differ
diff --git a/blimp/client/app/android/java/res/mipmap-xxhdpi/app_icon.png b/blimp/client/app/android/java/res/mipmap-xxhdpi/app_icon.png
index 3c723846..7aba520 100644
--- a/blimp/client/app/android/java/res/mipmap-xxhdpi/app_icon.png
+++ b/blimp/client/app/android/java/res/mipmap-xxhdpi/app_icon.png
Binary files differ
diff --git a/blimp/client/app/android/java/res/mipmap-xxxhdpi/app_icon.png b/blimp/client/app/android/java/res/mipmap-xxxhdpi/app_icon.png
index 839b0a7..f8b22ff2 100644
--- a/blimp/client/app/android/java/res/mipmap-xxxhdpi/app_icon.png
+++ b/blimp/client/app/android/java/res/mipmap-xxxhdpi/app_icon.png
Binary files differ
diff --git a/blimp/client/app/android/javatests/src/org/chromium/blimp/core/BlimpContentsTest.java b/blimp/client/app/android/javatests/src/org/chromium/blimp/core/BlimpContentsTest.java
index 0bd541b..f33981e 100644
--- a/blimp/client/app/android/javatests/src/org/chromium/blimp/core/BlimpContentsTest.java
+++ b/blimp/client/app/android/javatests/src/org/chromium/blimp/core/BlimpContentsTest.java
@@ -8,9 +8,9 @@
 
 import org.chromium.base.ThreadUtils;
 import org.chromium.blimp.BlimpNativeInstrumentationTestCase;
-import org.chromium.blimp.core_public.BlimpContents;
-import org.chromium.blimp.core_public.BlimpNavigationController;
-import org.chromium.blimp.core_public.EmptyBlimpContentsObserver;
+import org.chromium.blimp_public.BlimpContents;
+import org.chromium.blimp_public.BlimpNavigationController;
+import org.chromium.blimp_public.EmptyBlimpContentsObserver;
 
 import java.util.concurrent.atomic.AtomicReference;
 
diff --git a/blimp/client/core/BUILD.gn b/blimp/client/core/BUILD.gn
index 54faf01..b98e4eb2 100644
--- a/blimp/client/core/BUILD.gn
+++ b/blimp/client/core/BUILD.gn
@@ -20,7 +20,7 @@
 
   deps = [
     "//base",
-    "//blimp/client/core/public",
+    "//blimp/client/public",
     "//url",
   ]
 
@@ -51,7 +51,7 @@
   deps = [
     "//base",
     "//blimp/client/core",
-    "//blimp/client/core/public",
+    "//blimp/client/public",
     "//testing/gtest",
     "//url",
   ]
@@ -70,7 +70,7 @@
 
     deps = [
       "//base:base_java",
-      "//blimp/client/core/public:public_java",
+      "//blimp/client/public:public_java",
     ]
   }
 
diff --git a/blimp/client/core/android/blimp_contents_observer_proxy.h b/blimp/client/core/android/blimp_contents_observer_proxy.h
index f68a01ff..06d2560 100644
--- a/blimp/client/core/android/blimp_contents_observer_proxy.h
+++ b/blimp/client/core/android/blimp_contents_observer_proxy.h
@@ -10,7 +10,7 @@
 #include "base/macros.h"
 #include "blimp/client/core/android/blimp_contents_impl_android.h"
 #include "blimp/client/core/android/blimp_navigation_controller_impl_android.h"
-#include "blimp/client/core/public/blimp_contents_observer.h"
+#include "blimp/client/public/blimp_contents_observer.h"
 
 namespace blimp {
 namespace client {
diff --git a/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpContentsFactory.java b/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpContentsFactory.java
index df513402..07db1aed 100644
--- a/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpContentsFactory.java
+++ b/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpContentsFactory.java
@@ -5,7 +5,7 @@
 package org.chromium.blimp.core;
 
 import org.chromium.base.annotations.JNINamespace;
-import org.chromium.blimp.core_public.BlimpContents;
+import org.chromium.blimp_public.BlimpContents;
 
 /**
  * This factory creates BlimpContents objects and the associated native counterpart.
diff --git a/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpContentsImpl.java b/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpContentsImpl.java
index 67327081..df2b298 100644
--- a/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpContentsImpl.java
+++ b/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpContentsImpl.java
@@ -6,9 +6,9 @@
 
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
-import org.chromium.blimp.core_public.BlimpContents;
-import org.chromium.blimp.core_public.BlimpContentsObserver;
-import org.chromium.blimp.core_public.BlimpNavigationController;
+import org.chromium.blimp_public.BlimpContents;
+import org.chromium.blimp_public.BlimpContentsObserver;
+import org.chromium.blimp_public.BlimpNavigationController;
 
 /**
  * BlimpContentsImpl is a Java wrapper to allow communicating with the native BlimpContentsImpl
diff --git a/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpContentsObserverProxy.java b/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpContentsObserverProxy.java
index 657c7bb..b000c080 100644
--- a/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpContentsObserverProxy.java
+++ b/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpContentsObserverProxy.java
@@ -7,7 +7,7 @@
 import org.chromium.base.ObserverList;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
-import org.chromium.blimp.core_public.BlimpContentsObserver;
+import org.chromium.blimp_public.BlimpContentsObserver;
 
 /**
  * Serves as a compound observer proxy for dispatching BlimpContentsObserver callbacks,
diff --git a/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpNavigationControllerImpl.java b/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpNavigationControllerImpl.java
index a907ed95..7dc5264 100644
--- a/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpNavigationControllerImpl.java
+++ b/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpNavigationControllerImpl.java
@@ -6,7 +6,7 @@
 
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
-import org.chromium.blimp.core_public.BlimpNavigationController;
+import org.chromium.blimp_public.BlimpNavigationController;
 
 /**
  * BlimpNavigationControllerImpl is a Java wrapper to allow communicating with the native
diff --git a/blimp/client/core/blimp_contents_impl.cc b/blimp/client/core/blimp_contents_impl.cc
index d3c1635..3e93e924 100644
--- a/blimp/client/core/blimp_contents_impl.cc
+++ b/blimp/client/core/blimp_contents_impl.cc
@@ -6,7 +6,7 @@
 
 #include "base/memory/ptr_util.h"
 #include "base/supports_user_data.h"
-#include "blimp/client/core/public/blimp_contents_observer.h"
+#include "blimp/client/public/blimp_contents_observer.h"
 
 #if defined(OS_ANDROID)
 #include "blimp/client/core/android/blimp_contents_impl_android.h"
diff --git a/blimp/client/core/blimp_contents_impl.h b/blimp/client/core/blimp_contents_impl.h
index 077796e..bbe1dd9 100644
--- a/blimp/client/core/blimp_contents_impl.h
+++ b/blimp/client/core/blimp_contents_impl.h
@@ -10,7 +10,7 @@
 #include "base/supports_user_data.h"
 #include "blimp/client/core/blimp_navigation_controller_delegate.h"
 #include "blimp/client/core/blimp_navigation_controller_impl.h"
-#include "blimp/client/core/public/blimp_contents.h"
+#include "blimp/client/public/blimp_contents.h"
 #include "url/gurl.h"
 
 #if defined(OS_ANDROID)
diff --git a/blimp/client/core/blimp_contents_impl_unittest.cc b/blimp/client/core/blimp_contents_impl_unittest.cc
index 3d4a7c0..0c9f846 100644
--- a/blimp/client/core/blimp_contents_impl_unittest.cc
+++ b/blimp/client/core/blimp_contents_impl_unittest.cc
@@ -6,7 +6,7 @@
 
 #include "base/message_loop/message_loop.h"
 #include "blimp/client/core/blimp_contents_impl.h"
-#include "blimp/client/core/public/blimp_contents_observer.h"
+#include "blimp/client/public/blimp_contents_observer.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace blimp {
diff --git a/blimp/client/core/blimp_navigation_controller_impl.h b/blimp/client/core/blimp_navigation_controller_impl.h
index b62ed25a..90c42e0 100644
--- a/blimp/client/core/blimp_navigation_controller_impl.h
+++ b/blimp/client/core/blimp_navigation_controller_impl.h
@@ -7,7 +7,7 @@
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "blimp/client/core/public/blimp_navigation_controller.h"
+#include "blimp/client/public/blimp_navigation_controller.h"
 #include "url/gurl.h"
 
 namespace blimp {
diff --git a/blimp/client/core/public/BUILD.gn b/blimp/client/public/BUILD.gn
similarity index 63%
rename from blimp/client/core/public/BUILD.gn
rename to blimp/client/public/BUILD.gn
index 5e840d0..bd422f4a 100644
--- a/blimp/client/core/public/BUILD.gn
+++ b/blimp/client/public/BUILD.gn
@@ -23,10 +23,10 @@
 if (is_android) {
   android_library("public_java") {
     java_files = [
-      "android/java/src/org/chromium/blimp/core_public/BlimpContents.java",
-      "android/java/src/org/chromium/blimp/core_public/BlimpContentsObserver.java",
-      "android/java/src/org/chromium/blimp/core_public/BlimpNavigationController.java",
-      "android/java/src/org/chromium/blimp/core_public/EmptyBlimpContentsObserver.java",
+      "android/java/src/org/chromium/blimp_public/BlimpContents.java",
+      "android/java/src/org/chromium/blimp_public/BlimpContentsObserver.java",
+      "android/java/src/org/chromium/blimp_public/BlimpNavigationController.java",
+      "android/java/src/org/chromium/blimp_public/EmptyBlimpContentsObserver.java",
     ]
   }
 }
diff --git a/blimp/client/public/DEPS b/blimp/client/public/DEPS
new file mode 100644
index 0000000..12c81a5
--- /dev/null
+++ b/blimp/client/public/DEPS
@@ -0,0 +1,6 @@
+include_rules = [
+  "+base",
+  "-blimp",
+  "-content",
+  "+url",
+]
diff --git a/blimp/client/core/public/android/java/src/org/chromium/blimp/core_public/BlimpContents.java b/blimp/client/public/android/java/src/org/chromium/blimp_public/BlimpContents.java
similarity index 96%
rename from blimp/client/core/public/android/java/src/org/chromium/blimp/core_public/BlimpContents.java
rename to blimp/client/public/android/java/src/org/chromium/blimp_public/BlimpContents.java
index 1760bfc..ae13f41 100644
--- a/blimp/client/core/public/android/java/src/org/chromium/blimp/core_public/BlimpContents.java
+++ b/blimp/client/public/android/java/src/org/chromium/blimp_public/BlimpContents.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.blimp.core_public;
+package org.chromium.blimp_public;
 
 /**
  * BlimpContents is the Java representation of a native BlimpContents object.
diff --git a/blimp/client/core/public/android/java/src/org/chromium/blimp/core_public/BlimpContentsObserver.java b/blimp/client/public/android/java/src/org/chromium/blimp_public/BlimpContentsObserver.java
similarity index 93%
rename from blimp/client/core/public/android/java/src/org/chromium/blimp/core_public/BlimpContentsObserver.java
rename to blimp/client/public/android/java/src/org/chromium/blimp_public/BlimpContentsObserver.java
index ee9fa5a..7d7a8581 100644
--- a/blimp/client/core/public/android/java/src/org/chromium/blimp/core_public/BlimpContentsObserver.java
+++ b/blimp/client/public/android/java/src/org/chromium/blimp_public/BlimpContentsObserver.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.blimp.core_public;
+package org.chromium.blimp_public;
 
 /**
  * BlimpContentsObserver is the Java representation of a native BlimpContentsObserver object.
diff --git a/blimp/client/core/public/android/java/src/org/chromium/blimp/core_public/BlimpNavigationController.java b/blimp/client/public/android/java/src/org/chromium/blimp_public/BlimpNavigationController.java
similarity index 95%
rename from blimp/client/core/public/android/java/src/org/chromium/blimp/core_public/BlimpNavigationController.java
rename to blimp/client/public/android/java/src/org/chromium/blimp_public/BlimpNavigationController.java
index 2e60b97..efc4da2a 100644
--- a/blimp/client/core/public/android/java/src/org/chromium/blimp/core_public/BlimpNavigationController.java
+++ b/blimp/client/public/android/java/src/org/chromium/blimp_public/BlimpNavigationController.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.blimp.core_public;
+package org.chromium.blimp_public;
 
 /**
  * BlimpNavigationController is the Java representation of a native BlimpNavigationController
diff --git a/blimp/client/core/public/android/java/src/org/chromium/blimp/core_public/EmptyBlimpContentsObserver.java b/blimp/client/public/android/java/src/org/chromium/blimp_public/EmptyBlimpContentsObserver.java
similarity index 92%
rename from blimp/client/core/public/android/java/src/org/chromium/blimp/core_public/EmptyBlimpContentsObserver.java
rename to blimp/client/public/android/java/src/org/chromium/blimp_public/EmptyBlimpContentsObserver.java
index 2f4097b2a..8ff0500 100644
--- a/blimp/client/core/public/android/java/src/org/chromium/blimp/core_public/EmptyBlimpContentsObserver.java
+++ b/blimp/client/public/android/java/src/org/chromium/blimp_public/EmptyBlimpContentsObserver.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.blimp.core_public;
+package org.chromium.blimp_public;
 
 /**
  * EmptyBlimpContentsObserver is a helper class that has an empty implementation of all the
diff --git a/blimp/client/core/public/blimp_contents.h b/blimp/client/public/blimp_contents.h
similarity index 87%
rename from blimp/client/core/public/blimp_contents.h
rename to blimp/client/public/blimp_contents.h
index 5da71d27..239d3d93 100644
--- a/blimp/client/core/public/blimp_contents.h
+++ b/blimp/client/public/blimp_contents.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BLIMP_CLIENT_CORE_PUBLIC_BLIMP_CONTENTS_H_
-#define BLIMP_CLIENT_CORE_PUBLIC_BLIMP_CONTENTS_H_
+#ifndef BLIMP_CLIENT_PUBLIC_BLIMP_CONTENTS_H_
+#define BLIMP_CLIENT_PUBLIC_BLIMP_CONTENTS_H_
 
 #include "base/macros.h"
 #include "url/gurl.h"
@@ -40,4 +40,4 @@
 }  // namespace client
 }  // namespace blimp
 
-#endif  // BLIMP_CLIENT_CORE_PUBLIC_BLIMP_CONTENTS_H_
+#endif  // BLIMP_CLIENT_PUBLIC_BLIMP_CONTENTS_H_
diff --git a/blimp/client/core/public/blimp_contents_observer.h b/blimp/client/public/blimp_contents_observer.h
similarity index 79%
rename from blimp/client/core/public/blimp_contents_observer.h
rename to blimp/client/public/blimp_contents_observer.h
index bd3b86a..c980833 100644
--- a/blimp/client/core/public/blimp_contents_observer.h
+++ b/blimp/client/public/blimp_contents_observer.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BLIMP_CLIENT_CORE_PUBLIC_BLIMP_CONTENTS_OBSERVER_H_
-#define BLIMP_CLIENT_CORE_PUBLIC_BLIMP_CONTENTS_OBSERVER_H_
+#ifndef BLIMP_CLIENT_PUBLIC_BLIMP_CONTENTS_OBSERVER_H_
+#define BLIMP_CLIENT_PUBLIC_BLIMP_CONTENTS_OBSERVER_H_
 
 #include "base/macros.h"
 #include "url/gurl.h"
@@ -30,4 +30,4 @@
 }  // namespace client
 }  // namespace blimp
 
-#endif  // BLIMP_CLIENT_CORE_PUBLIC_BLIMP_CONTENTS_OBSERVER_H_
+#endif  // BLIMP_CLIENT_PUBLIC_BLIMP_CONTENTS_OBSERVER_H_
diff --git a/blimp/client/core/public/blimp_navigation_controller.h b/blimp/client/public/blimp_navigation_controller.h
similarity index 84%
rename from blimp/client/core/public/blimp_navigation_controller.h
rename to blimp/client/public/blimp_navigation_controller.h
index fc79b068..87b30a0 100644
--- a/blimp/client/core/public/blimp_navigation_controller.h
+++ b/blimp/client/public/blimp_navigation_controller.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BLIMP_CLIENT_CORE_PUBLIC_BLIMP_NAVIGATION_CONTROLLER_H_
-#define BLIMP_CLIENT_CORE_PUBLIC_BLIMP_NAVIGATION_CONTROLLER_H_
+#ifndef BLIMP_CLIENT_PUBLIC_BLIMP_NAVIGATION_CONTROLLER_H_
+#define BLIMP_CLIENT_PUBLIC_BLIMP_NAVIGATION_CONTROLLER_H_
 
 #include "base/macros.h"
 #include "url/gurl.h"
@@ -39,4 +39,4 @@
 }  // namespace client
 }  // namespace blimp
 
-#endif  // BLIMP_CLIENT_CORE_PUBLIC_BLIMP_NAVIGATION_CONTROLLER_H_
+#endif  // BLIMP_CLIENT_PUBLIC_BLIMP_NAVIGATION_CONTROLLER_H_
diff --git a/build/android/pylib/base/test_instance_factory.py b/build/android/pylib/base/test_instance_factory.py
index 523b4c5..5cc3723 100644
--- a/build/android/pylib/base/test_instance_factory.py
+++ b/build/android/pylib/base/test_instance_factory.py
@@ -4,6 +4,7 @@
 
 from pylib.gtest import gtest_test_instance
 from pylib.instrumentation import instrumentation_test_instance
+from pylib.perf import perf_test_instance
 from pylib.uirobot import uirobot_test_instance
 from pylib.utils import isolator
 
@@ -16,6 +17,8 @@
   elif args.command == 'instrumentation':
     return instrumentation_test_instance.InstrumentationTestInstance(
         args, isolator.Isolator(), error_func)
+  elif args.command == 'perf':
+    return perf_test_instance.PerfTestInstance(args, error_func)
   elif args.command == 'uirobot':
     return uirobot_test_instance.UirobotTestInstance(args, error_func)
 
diff --git a/build/android/pylib/base/test_run_factory.py b/build/android/pylib/base/test_run_factory.py
index 8db9bd63..46c8076 100644
--- a/build/android/pylib/base/test_run_factory.py
+++ b/build/android/pylib/base/test_run_factory.py
@@ -7,6 +7,8 @@
 from pylib.local.device import local_device_environment
 from pylib.local.device import local_device_gtest_run
 from pylib.local.device import local_device_instrumentation_test_run
+from pylib.local.device import local_device_perf_test_run
+from pylib.perf import perf_test_instance
 from pylib.uirobot import uirobot_test_instance
 
 try:
@@ -21,7 +23,18 @@
   remote_device_uirobot_test_run = None
 
 
-def CreateTestRun(_args, env, test_instance, error_func):
+def _CreatePerfTestRun(args, env, test_instance):
+  if args.print_step:
+    return local_device_perf_test_run.PrintStep(
+        env, test_instance)
+  elif args.output_json_list:
+    return local_device_perf_test_run.OutputJsonList(
+        env, test_instance)
+  return local_device_perf_test_run.LocalDevicePerfTestRun(
+      env, test_instance)
+
+
+def CreateTestRun(args, env, test_instance, error_func):
   if isinstance(env, local_device_environment.LocalDeviceEnvironment):
     if isinstance(test_instance, gtest_test_instance.GtestTestInstance):
       return local_device_gtest_run.LocalDeviceGtestRun(env, test_instance)
@@ -29,6 +42,9 @@
                   instrumentation_test_instance.InstrumentationTestInstance):
       return (local_device_instrumentation_test_run
               .LocalDeviceInstrumentationTestRun(env, test_instance))
+    if isinstance(test_instance,
+                  perf_test_instance.PerfTestInstance):
+      return _CreatePerfTestRun(args, env, test_instance)
 
   if (remote_device_environment
       and isinstance(env, remote_device_environment.RemoteDeviceEnvironment)):
diff --git a/build/android/pylib/local/device/local_device_environment.py b/build/android/pylib/local/device/local_device_environment.py
index 178e2f1..f8cd530 100644
--- a/build/android/pylib/local/device/local_device_environment.py
+++ b/build/android/pylib/local/device/local_device_environment.py
@@ -90,6 +90,10 @@
         monitor.Start()
 
   @property
+  def blacklist(self):
+    return self._blacklist
+
+  @property
   def concurrent_adb(self):
     return self._concurrent_adb
 
diff --git a/build/android/pylib/local/device/local_device_perf_test_run.py b/build/android/pylib/local/device/local_device_perf_test_run.py
new file mode 100644
index 0000000..d3bcd0f
--- /dev/null
+++ b/build/android/pylib/local/device/local_device_perf_test_run.py
@@ -0,0 +1,386 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import io
+import json
+import logging
+import os
+import pickle
+import shutil
+import tempfile
+import time
+import zipfile
+
+from devil.android import battery_utils
+from devil.android import device_blacklist
+from devil.android import device_errors
+from devil.android import device_list
+from devil.android import device_utils
+from devil.android import forwarder
+from devil.android.tools import device_recovery
+from devil.android.tools import device_status
+from devil.utils import cmd_helper
+from devil.utils import parallelizer
+from pylib import constants
+from pylib.base import base_test_result
+from pylib.constants import host_paths
+from pylib.local.device import local_device_test_run
+
+
+class TestShard(object):
+  def __init__(
+      self, env, test_instance, device, index, tests, retries=3, timeout=None):
+    logging.info('Create shard %s for device %s to run the following tests:',
+                 index, device)
+    for t in tests:
+      logging.info('  %s', t)
+    self._battery = battery_utils.BatteryUtils(device)
+    self._device = device
+    self._env = env
+    self._index = index
+    self._output_dir = None
+    self._retries = retries
+    self._test_instance = test_instance
+    self._tests = tests
+    self._timeout = timeout
+
+  @local_device_test_run.handle_shard_failures
+  def RunTestsOnShard(self):
+    results = base_test_result.TestRunResults()
+    for test in self._tests:
+      tries_left = self._retries
+      result_type = None
+      while (result_type != base_test_result.ResultType.PASS
+             and tries_left > 0):
+        try:
+          self._TestSetUp(test)
+          result_type = self._RunSingleTest(test)
+        except device_errors.CommandTimeoutError:
+          result_type = base_test_result.ResultType.TIMEOUT
+        except device_errors.CommandFailedError:
+          logging.exception('Exception when executing %s.', test)
+          result_type = base_test_result.ResultType.FAIL
+        finally:
+          self._TestTearDown()
+          if result_type != base_test_result.ResultType.PASS:
+            try:
+              device_recovery.RecoverDevice(self._device, self._env.blacklist)
+            except device_errors.CommandTimeoutError:
+              logging.exception(
+                  'Device failed to recover after failing %s.', test)
+          tries_left = tries_left - 1
+
+      results.AddResult(base_test_result.BaseTestResult(test, result_type))
+    return results
+
+  def _TestSetUp(self, test):
+    if not self._device.IsOnline():
+      msg = 'Device %s is unresponsive.' % str(self._device)
+      raise device_errors.DeviceUnreachableError(msg)
+
+    logging.info('Charge level: %s%%',
+                 str(self._battery.GetBatteryInfo().get('level')))
+    if self._test_instance.min_battery_level:
+      self._battery.ChargeDeviceToLevel(self._test_instance.min_battery_level)
+
+    logging.info('temperature: %s (0.1 C)',
+                 str(self._battery.GetBatteryInfo().get('temperature')))
+    if self._test_instance.max_battery_temp:
+      self._battery.LetBatteryCoolToTemperature(
+          self._test_instance.max_battery_temp)
+
+    if not self._device.IsScreenOn():
+      self._device.SetScreen(True)
+
+    if (self._test_instance.collect_chartjson_data
+        or self._tests[test].get('archive_output_dir')):
+      self._output_dir = tempfile.mkdtemp()
+
+  def _RunSingleTest(self, test):
+    self._test_instance.WriteBuildBotJson(self._output_dir)
+
+    timeout = self._tests[test].get('timeout', self._timeout)
+    cmd = self._CreateCmd(test)
+    cwd = os.path.abspath(host_paths.DIR_SOURCE_ROOT)
+
+    logging.debug("Running %s with command '%s' on shard %d with timeout %d",
+                  test, cmd, self._index, timeout)
+
+    try:
+      start_time = time.time()
+      exit_code, output = cmd_helper.GetCmdStatusAndOutputWithTimeout(
+          cmd, timeout, cwd=cwd, shell=True)
+      end_time = time.time()
+      json_output = self._test_instance.ReadChartjsonOutput(self._output_dir)
+      if exit_code == 0:
+        result_type = base_test_result.ResultType.PASS
+      else:
+        result_type = base_test_result.ResultType.FAIL
+    except cmd_helper.TimeoutError as e:
+      end_time = time.time()
+      exit_code = -1
+      output = e.output
+      json_output = ''
+      result_type = base_test_result.ResultType.TIMEOUT
+
+    return self._ProcessTestResult(test, cmd, start_time, end_time, exit_code,
+                                   output, json_output, result_type)
+
+  def _CreateCmd(self, test):
+    cmd = '%s --device %s' % (self._tests[test]['cmd'], str(self._device))
+    if self._output_dir:
+      cmd = cmd + ' --output-dir=%s' % self._output_dir
+    if self._test_instance.dry_run:
+      cmd = 'echo %s' % cmd
+    return cmd
+
+  def _ProcessTestResult(self, test, cmd, start_time, end_time, exit_code,
+                         output, json_output, result_type):
+    if exit_code is None:
+      exit_code = -1
+    logging.info('%s : exit_code=%d in %d secs on device %s',
+                 test, exit_code, end_time - start_time,
+                 str(self._device))
+
+    actual_exit_code = exit_code
+    if (self._test_instance.flaky_steps
+        and test in self._test_instance.flaky_steps):
+      exit_code = 0
+    archive_bytes = (self._ArchiveOutputDir()
+                     if self._tests[test].get('archive_output_dir')
+                     else None)
+    persisted_result = {
+        'name': test,
+        'output': [output],
+        'chartjson': json_output,
+        'archive_bytes': archive_bytes,
+        'exit_code': exit_code,
+        'actual_exit_code': actual_exit_code,
+        'result_type': result_type,
+        'start_time': start_time,
+        'end_time': end_time,
+        'total_time': end_time - start_time,
+        'device': str(self._device),
+        'cmd': cmd,
+    }
+    self._SaveResult(persisted_result)
+    return result_type
+
+  def _ArchiveOutputDir(self):
+    """Archive all files in the output dir, and return as compressed bytes."""
+    with io.BytesIO() as archive:
+      with zipfile.ZipFile(archive, 'w', zipfile.ZIP_DEFLATED) as contents:
+        num_files = 0
+        for absdir, _, files in os.walk(self._output_dir):
+          reldir = os.path.relpath(absdir, self._output_dir)
+          for filename in files:
+            src_path = os.path.join(absdir, filename)
+            # We use normpath to turn './file.txt' into just 'file.txt'.
+            dst_path = os.path.normpath(os.path.join(reldir, filename))
+            contents.write(src_path, dst_path)
+            num_files += 1
+      if num_files:
+        logging.info('%d files in the output dir were archived.', num_files)
+      else:
+        logging.warning('No files in the output dir. Archive is empty.')
+      return archive.getvalue()
+
+  @staticmethod
+  def _SaveResult(result):
+    pickled = os.path.join(constants.PERF_OUTPUT_DIR, result['name'])
+    if os.path.exists(pickled):
+      with file(pickled, 'r') as f:
+        previous = pickle.loads(f.read())
+        result['output'] = previous['output'] + result['output']
+    with file(pickled, 'w') as f:
+      f.write(pickle.dumps(result))
+
+  def _TestTearDown(self):
+    if self._output_dir:
+      shutil.rmtree(self._output_dir, ignore_errors=True)
+      self._output_dir = None
+    try:
+      logging.info('Unmapping device ports for %s.', self._device)
+      forwarder.Forwarder.UnmapAllDevicePorts(self._device)
+    except Exception: # pylint: disable=broad-except
+      logging.exception('Exception when resetting ports.')
+
+
+class LocalDevicePerfTestRun(local_device_test_run.LocalDeviceTestRun):
+
+  _DEFAULT_TIMEOUT = 60 * 60
+  _CONFIG_VERSION = 1
+
+  def __init__(self, env, test_instance):
+    super(LocalDevicePerfTestRun, self).__init__(env, test_instance)
+    self._devices = None
+    self._env = env
+    self._test_buckets = []
+    self._test_instance = test_instance
+    self._timeout = None if test_instance.no_timeout else self._DEFAULT_TIMEOUT
+
+  def SetUp(self):
+    self._devices = self._GetAllDevices(self._env.devices,
+                                        self._test_instance.known_devices_file)
+
+    if os.path.exists(constants.PERF_OUTPUT_DIR):
+      shutil.rmtree(constants.PERF_OUTPUT_DIR)
+    os.makedirs(constants.PERF_OUTPUT_DIR)
+
+  def TearDown(self):
+    pass
+
+  def _GetStepsFromDict(self):
+    # From where this is called one of these two must be set.
+    if self._test_instance.single_step:
+      return {
+          'version': self._CONFIG_VERSION,
+          'steps': {
+              'single_step': {
+                'device_affinity': 0,
+                'cmd': self._test_instance.single_step
+              },
+          }
+      }
+    if self._test_instance.steps:
+      with file(self._test_instance.steps, 'r') as f:
+        steps = json.load(f)
+        if steps['version'] != self._CONFIG_VERSION:
+          raise TestDictVersionError(
+              'Version is expected to be %d but was %d' % (self._CONFIG_VERSION,
+                                                           steps['version']))
+        return steps
+    raise PerfTestRunGetStepsError(
+        'Neither single_step or steps set in test_instance.')
+
+  def _SplitTestsByAffinity(self):
+    # This splits tests by their device affinity so that the same tests always
+    # run on the same devices. This is important for perf tests since different
+    # devices might yield slightly different performance results.
+    test_dict = self._GetStepsFromDict()
+    for test, test_config in test_dict['steps'].iteritems():
+      try:
+        affinity = test_config['device_affinity']
+        if len(self._test_buckets) < affinity + 1:
+          while len(self._test_buckets) != affinity + 1:
+            self._test_buckets.append({})
+        self._test_buckets[affinity][test] = test_config
+      except KeyError:
+        logging.exception(
+            'Test config for %s is bad.\n Config:%s', test, str(test_config))
+
+  @staticmethod
+  def _GetAllDevices(active_devices, devices_path):
+    try:
+      if devices_path:
+        devices = [device_utils.DeviceUtils(s)
+                   for s in device_list.GetPersistentDeviceList(devices_path)]
+        if not devices and active_devices:
+          logging.warning('%s is empty. Falling back to active devices.',
+                          devices_path)
+          devices = active_devices
+      else:
+        logging.warning('Known devices file path not being passed. For device '
+                        'affinity to work properly, it must be passed.')
+        devices = active_devices
+    except IOError as e:
+      logging.error('Unable to find %s [%s]', devices_path, e)
+      devices = active_devices
+    return sorted(devices)
+
+  #override
+  def RunTests(self):
+    # Affinitize the tests.
+    self._SplitTestsByAffinity()
+    if not self._test_buckets:
+      raise local_device_test_run.NoTestsError()
+
+    blacklist = (device_blacklist.Blacklist(self._env.blacklist)
+                 if self._env.blacklist
+                 else None)
+
+    def run_perf_tests(shard_id):
+      if device_status.IsBlacklisted(str(self._devices[shard_id]), blacklist):
+        logging.warning('Device %s is not active. Will not create shard %s.',
+                        str(self._devices[shard_id]), shard_id)
+        return []
+      s = TestShard(self._env, self._test_instance, self._devices[shard_id],
+                    shard_id, self._test_buckets[shard_id],
+                    retries=self._env.max_tries, timeout=self._timeout)
+      return s.RunTestsOnShard()
+
+    device_indices = range(min(len(self._devices), len(self._test_buckets)))
+    shards = parallelizer.Parallelizer(device_indices).pMap(run_perf_tests)
+    return shards.pGet(self._timeout)
+
+  # override
+  def TestPackage(self):
+    return 'perf'
+
+  # override
+  def _CreateShards(self, _tests):
+    raise NotImplementedError
+
+  # override
+  def _GetTests(self):
+    return self._test_buckets
+
+  # override
+  def _RunTest(self, _device, _test):
+    raise NotImplementedError
+
+  # override
+  def _ShouldShard(self):
+    return False
+
+
+class OutputJsonList(LocalDevicePerfTestRun):
+  # override
+  def SetUp(self):
+    pass
+
+  # override
+  def RunTests(self):
+    result_type = self._test_instance.OutputJsonList()
+    result = base_test_result.TestRunResults()
+    result.AddResult(
+        base_test_result.BaseTestResult('OutputJsonList', result_type))
+    return [result]
+
+  # override
+  def _CreateShards(self, _tests):
+    raise NotImplementedError
+
+  # override
+  def _RunTest(self, _device, _test):
+    raise NotImplementedError
+
+
+class PrintStep(LocalDevicePerfTestRun):
+  # override
+  def SetUp(self):
+    pass
+
+  # override
+  def RunTests(self):
+    result_type = self._test_instance.PrintTestOutput()
+    result = base_test_result.TestRunResults()
+    result.AddResult(
+        base_test_result.BaseTestResult('PrintStep', result_type))
+    return [result]
+
+  # override
+  def _CreateShards(self, _tests):
+    raise NotImplementedError
+
+  # override
+  def _RunTest(self, _device, _test):
+    raise NotImplementedError
+
+
+class TestDictVersionError(Exception):
+  pass
+
+class PerfTestRunGetStepsError(Exception):
+  pass
diff --git a/build/android/pylib/local/device/local_device_test_run.py b/build/android/pylib/local/device/local_device_test_run.py
index bcdb012..74e3d22 100644
--- a/build/android/pylib/local/device/local_device_test_run.py
+++ b/build/android/pylib/local/device/local_device_test_run.py
@@ -222,3 +222,7 @@
 
   def _ShouldShard(self):
     raise NotImplementedError
+
+
+class NoTestsError(Exception):
+  """Error for when no tests are found."""
diff --git a/build/android/pylib/perf/perf_test_instance.py b/build/android/pylib/perf/perf_test_instance.py
new file mode 100644
index 0000000..17f3fd4
--- /dev/null
+++ b/build/android/pylib/perf/perf_test_instance.py
@@ -0,0 +1,237 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+import logging
+import os
+import pickle
+import re
+
+from devil import base_error
+from devil.utils import cmd_helper
+from pylib import constants
+from pylib.base import base_test_result
+from pylib.base import test_instance
+from pylib.constants import host_paths
+
+
+_GIT_CR_POS_RE = re.compile(r'^Cr-Commit-Position: refs/heads/master@{#(\d+)}$')
+
+
+def _GetPersistedResult(test_name):
+  file_name = os.path.join(constants.PERF_OUTPUT_DIR, test_name)
+  if not os.path.exists(file_name):
+    logging.error('File not found %s', file_name)
+    return None
+
+  with file(file_name, 'r') as f:
+    return pickle.loads(f.read())
+
+
+def _GetChromiumRevision():
+  # pylint: disable=line-too-long
+  """Get the git hash and commit position of the chromium master branch.
+
+  See:
+  https://chromium.googlesource.com/chromium/tools/build/+/387e3cf3/scripts/slave/runtest.py#211
+
+  Returns:
+    A dictionary with 'revision' and 'commit_pos' keys.
+  """
+  # pylint: enable=line-too-long
+  status, output = cmd_helper.GetCmdStatusAndOutput(
+      ['git', 'log', '-n', '1', '--pretty=format:%H%n%B', 'HEAD'],
+      cwd=host_paths.DIR_SOURCE_ROOT)
+  revision = None
+  commit_pos = None
+  if not status:
+    lines = output.splitlines()
+    revision = lines[0]
+    for line in reversed(lines):
+      m = _GIT_CR_POS_RE.match(line.strip())
+      if m:
+        commit_pos = int(m.group(1))
+        break
+  return {'revision': revision, 'commit_pos': commit_pos}
+
+
+class PerfTestInstance(test_instance.TestInstance):
+  def __init__(self, args, _):
+    super(PerfTestInstance, self).__init__()
+
+    self._collect_chartjson_data = args.collect_chartjson_data
+    self._dry_run = args.dry_run
+    self._flaky_steps = args.flaky_steps
+    self._output_dir_archive_path = args.output_dir_archive_path
+    self._known_devices_file = args.known_devices_file
+    self._max_battery_temp = args.max_battery_temp
+    self._min_battery_level = args.min_battery_level
+    self._no_timeout = args.no_timeout
+    self._output_chartjson_data = args.output_chartjson_data
+    self._output_json_list = args.output_json_list
+    self._print_step = args.print_step
+    self._single_step = (
+        ' '.join(args.single_step_command) if args.single_step else None)
+    self._steps = args.steps
+    self._test_filter = args.test_filter
+    self._write_buildbot_json = args.write_buildbot_json
+
+  def SetUp(self):
+    pass
+
+  def TearDown(self):
+    pass
+
+  def OutputJsonList(self):
+    try:
+      with file(self._steps, 'r') as i:
+        all_steps = json.load(i)
+
+      step_values = []
+      for k, v in all_steps['steps'].iteritems():
+        data = {'test': k, 'device_affinity': v['device_affinity']}
+
+        persisted_result = _GetPersistedResult(k)
+        if persisted_result:
+          data['start_time'] = persisted_result['start_time']
+          data['end_time'] = persisted_result['end_time']
+          data['total_time'] = persisted_result['total_time']
+          data['has_archive'] = persisted_result['archive_bytes'] is not None
+        step_values.append(data)
+
+      with file(self._output_json_list, 'w') as o:
+        o.write(json.dumps(step_values))
+      return base_test_result.ResultType.PASS
+    except KeyError:
+      logging.exception('Persistent results file missing key.')
+      return base_test_result.ResultType.FAIL
+
+  def PrintTestOutput(self):
+    """Helper method to print the output of previously executed test_name.
+
+    Test_name is passed from the command line as print_step
+
+    Returns:
+      exit code generated by the test step.
+    """
+    persisted_result = _GetPersistedResult(self._print_step)
+    if not persisted_result:
+      raise PersistentDataError('No data for test %s found.' % self._print_step)
+    logging.info('*' * 80)
+    logging.info('Output from:')
+    logging.info(persisted_result['cmd'])
+    logging.info('*' * 80)
+
+    output_formatted = ''
+    persisted_outputs = persisted_result['output']
+    for i in xrange(len(persisted_outputs)):
+      output_formatted += '\n\nOutput from run #%d:\n\n%s' % (
+          i, persisted_outputs[i])
+    print output_formatted
+
+    if self._output_chartjson_data:
+      with file(self._output_chartjson_data, 'w') as f:
+        f.write(persisted_result['chartjson'])
+
+    if self._output_dir_archive_path:
+      if persisted_result['archive_bytes'] is not None:
+        with file(self._output_dir_archive_path, 'wb') as f:
+          f.write(persisted_result['archive_bytes'])
+      else:
+        logging.error('The output dir was not archived.')
+    if persisted_result['exit_code'] == 0:
+      return base_test_result.ResultType.PASS
+    return base_test_result.ResultType.FAIL
+
+  #override
+  def TestType(self):
+    return 'perf'
+
+  @staticmethod
+  def ReadChartjsonOutput(output_dir):
+    if not output_dir:
+      return ''
+    json_output_path = os.path.join(output_dir, 'results-chart.json')
+    try:
+      with open(json_output_path) as f:
+        return f.read()
+    except IOError:
+      logging.exception('Exception when reading chartjson.')
+      logging.error('This usually means that telemetry did not run, so it could'
+                    ' not generate the file. Please check the device running'
+                    ' the test.')
+      return ''
+
+  def WriteBuildBotJson(self, output_dir):
+    """Write metadata about the buildbot environment to the output dir."""
+    if not output_dir or not self._write_buildbot_json:
+      return
+    data = {
+      'chromium': _GetChromiumRevision(),
+      'environment': dict(os.environ)
+    }
+    with open(os.path.join(output_dir, 'buildbot.json'), 'w') as f:
+      json.dump(data, f, sort_keys=True, separators=(',', ': '))
+
+  @property
+  def collect_chartjson_data(self):
+    return self._collect_chartjson_data
+
+  @property
+  def dry_run(self):
+    return self._dry_run
+
+  @property
+  def flaky_steps(self):
+    return self._flaky_steps
+
+  @property
+  def known_devices_file(self):
+    return self._known_devices_file
+
+  @property
+  def max_battery_temp(self):
+    return self._max_battery_temp
+
+  @property
+  def min_battery_level(self):
+    return self._min_battery_level
+
+  @property
+  def no_timeout(self):
+    return self._no_timeout
+
+  @property
+  def output_chartjson_data(self):
+    return self._output_chartjson_data
+
+  @property
+  def output_dir_archive_path(self):
+    return self._output_dir_archive_path
+
+  @property
+  def output_json_list(self):
+    return self._output_json_list
+
+  @property
+  def print_step(self):
+    return self._print_step
+
+  @property
+  def single_step(self):
+    return self._single_step
+
+  @property
+  def steps(self):
+    return self._steps
+
+  @property
+  def test_filter(self):
+    return self._test_filter
+
+
+class PersistentDataError(base_error.BaseError):
+  def __init__(self, message):
+    super(PersistentDataError, self).__init__(message)
+    self._is_infra_error = True
diff --git a/build/android/test_runner.py b/build/android/test_runner.py
index 46889f94..faec492 100755
--- a/build/android/test_runner.py
+++ b/build/android/test_runner.py
@@ -562,9 +562,15 @@
       '--output-chartjson-data',
       default='',
       help='Write out chartjson into the given file.')
+  # TODO(rnephew): Remove this when everything moves to new option in platform
+  # mode.
   group.add_argument(
       '--get-output-dir-archive', metavar='FILENAME',
-      help='Write the chached output directory archived by a step into the'
+      help='Write the cached output directory archived by a step into the'
+      ' given ZIP file.')
+  group.add_argument(
+      '--output-dir-archive-path', metavar='FILENAME',
+      help='Write the cached output directory archived by a step into the'
       ' given ZIP file.')
   group.add_argument(
       '--flaky-steps',
@@ -585,12 +591,23 @@
       '--max-battery-temp', type=int,
       help='Only start tests when the battery is at or below the given '
            'temperature (0.1 C)')
-  group.add_argument('single_step_command', nargs='*', action=SingleStepAction,
-                     help='If --single-step is specified, the command to run.')
-  group.add_argument('--min-battery-level', type=int,
-                     help='Only starts tests when the battery is charged above '
-                          'given level.')
+  group.add_argument(
+      'single_step_command', nargs='*', action=SingleStepAction,
+      help='If --single-step is specified, the command to run.')
+  group.add_argument(
+      '--min-battery-level', type=int,
+      help='Only starts tests when the battery is charged above '
+      'given level.')
   group.add_argument('--known-devices-file', help='Path to known device list.')
+  group.add_argument(
+      '--repeat', dest='repeat', type=int, default=0,
+      help='Number of times to repeat the specified set of tests.')
+  group.add_argument(
+      '--break-on-failure', '--break_on_failure', dest='break_on_failure',
+      action='store_true', help='Whether to break on failure.')
+  group.add_argument(
+      '--write-buildbot-json', action='store_true',
+      help='Whether to output buildbot json.')
   AddCommonOptions(parser)
   AddDeviceOptions(parser)
 
@@ -776,6 +793,10 @@
     return sorted(attached_devices)
 
 
+# TODO(rnephew): Add perf when ready to switch to platform mode as default.
+_DEFAULT_PLATFORM_MODE_TESTS = ['gtest', 'instrumentation']
+
+
 def RunTestsCommand(args): # pylint: disable=too-many-return-statements
   """Checks test type and dispatches to the appropriate function.
 
@@ -793,8 +814,7 @@
 
   ProcessCommonOptions(args)
   logging.info('command: %s', ' '.join(sys.argv))
-
-  if args.enable_platform_mode or command in ('gtest', 'instrumentation'):
+  if args.enable_platform_mode or command in _DEFAULT_PLATFORM_MODE_TESTS:
     return RunTestsInPlatformMode(args)
 
   forwarder.Forwarder.RemoveHostLog()
@@ -823,6 +843,7 @@
   # TODO(jbudorick): Add support for more test types.
   'gtest',
   'instrumentation',
+  'perf',
   'uirobot',
 ]
 
diff --git a/build/android/test_runner.pydeps b/build/android/test_runner.pydeps
index a1a7ed63..a751412 100644
--- a/build/android/test_runner.pydeps
+++ b/build/android/test_runner.pydeps
@@ -46,6 +46,9 @@
 ../../third_party/catapult/devil/devil/android/sdk/keyevent.py
 ../../third_party/catapult/devil/devil/android/sdk/split_select.py
 ../../third_party/catapult/devil/devil/android/sdk/version_codes.py
+../../third_party/catapult/devil/devil/android/tools/__init__.py
+../../third_party/catapult/devil/devil/android/tools/device_recovery.py
+../../third_party/catapult/devil/devil/android/tools/device_status.py
 ../../third_party/catapult/devil/devil/android/valgrind_tools/__init__.py
 ../../third_party/catapult/devil/devil/android/valgrind_tools/base_tool.py
 ../../third_party/catapult/devil/devil/base_error.py
@@ -58,8 +61,10 @@
 ../../third_party/catapult/devil/devil/utils/host_utils.py
 ../../third_party/catapult/devil/devil/utils/lazy/__init__.py
 ../../third_party/catapult/devil/devil/utils/lazy/weak_constant.py
+../../third_party/catapult/devil/devil/utils/lsusb.py
 ../../third_party/catapult/devil/devil/utils/parallelizer.py
 ../../third_party/catapult/devil/devil/utils/reraiser_thread.py
+../../third_party/catapult/devil/devil/utils/reset_usb.py
 ../../third_party/catapult/devil/devil/utils/run_tests_helper.py
 ../../third_party/catapult/devil/devil/utils/signal_handler.py
 ../../third_party/catapult/devil/devil/utils/timeout_retry.py
@@ -102,6 +107,7 @@
 pylib/local/device/local_device_environment.py
 pylib/local/device/local_device_gtest_run.py
 pylib/local/device/local_device_instrumentation_test_run.py
+pylib/local/device/local_device_perf_test_run.py
 pylib/local/device/local_device_test_run.py
 pylib/local/local_test_server_spawner.py
 pylib/monkey/__init__.py
@@ -109,6 +115,7 @@
 pylib/monkey/test_options.py
 pylib/monkey/test_runner.py
 pylib/perf/__init__.py
+pylib/perf/perf_test_instance.py
 pylib/perf/setup.py
 pylib/perf/test_options.py
 pylib/perf/test_runner.py
diff --git a/build/common.gypi b/build/common.gypi
index cdefdd1..7f647fd 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -698,6 +698,8 @@
       # Control Flow Integrity for virtual calls and casts.
       # See http://clang.llvm.org/docs/ControlFlowIntegrity.html
       'cfi_vptr%': 0,
+      # TODO(krasin): remove it. See https://crbug.com/626794.
+      'cfi_cast%': 0,
       'cfi_diag%': 0,
 
       'cfi_blacklist%': '<(PRODUCT_DIR)/../../tools/cfi/blacklist.txt',
@@ -966,17 +968,10 @@
         }],
 
         ['chromeos==1', {
-          'enable_basic_printing%': 0,
+          'enable_basic_printing%': 1,
           'enable_print_preview%': 1,
         }],
 
-        # Do not enable the Settings App on ChromeOS.
-        ['enable_app_list==1 and chromeos==0', {
-          'enable_settings_app%': 1,
-        }, {
-          'enable_settings_app%': 0,
-        }],
-
         # Whether tests targets should be run, archived or just have the
         # dependencies verified. All the tests targets have the '_run' suffix,
         # e.g. base_unittests_run runs the target base_unittests. The test
@@ -1242,7 +1237,6 @@
     'create_standalone_apk%': 1,
     'enable_app_list%': '<(enable_app_list)',
     'use_default_render_theme%': '<(use_default_render_theme)',
-    'enable_settings_app%': '<(enable_settings_app)',
     'google_api_key%': '<(google_api_key)',
     'google_default_client_id%': '<(google_default_client_id)',
     'google_default_client_secret%': '<(google_default_client_secret)',
@@ -1259,6 +1253,7 @@
     'video_hole%': '<(video_hole)',
     'v8_use_external_startup_data%': '<(v8_use_external_startup_data)',
     'cfi_vptr%': '<(cfi_vptr)',
+    'cfi_cast%': '<(cfi_cast)',
     'cfi_diag%': '<(cfi_diag)',
     'cfi_blacklist%': '<(cfi_blacklist)',
     'mac_views_browser%': '<(mac_views_browser)',
@@ -2163,9 +2158,6 @@
       ['enable_app_list==1', {
         'grit_defines': ['-D', 'enable_app_list'],
       }],
-      ['enable_settings_app==1', {
-        'grit_defines': ['-D', 'enable_settings_app'],
-      }],
       ['use_concatenated_impulse_responses==1', {
         'grit_defines': ['-D', 'use_concatenated_impulse_responses'],
       }],
@@ -2947,9 +2939,6 @@
       ['enable_app_list==1', {
         'defines': ['ENABLE_APP_LIST=1'],
       }],
-      ['enable_settings_app==1', {
-        'defines': ['ENABLE_SETTINGS_APP=1'],
-      }],
       ['disable_file_support==1', {
         'defines': ['DISABLE_FILE_SUPPORT=1'],
       }],
@@ -6212,8 +6201,6 @@
           ['_toolset=="target"', {
             'cflags': [
               '-fsanitize=cfi-vcall',
-              '-fsanitize=cfi-derived-cast',
-              '-fsanitize=cfi-unrelated-cast',
               '-fsanitize-blacklist=<(cfi_blacklist)',
             ],
             'ldflags': [
@@ -6224,8 +6211,6 @@
             'xcode_settings': {
               'OTHER_CFLAGS': [
                 '-fsanitize=cfi-vcall',
-                '-fsanitize=cfi-derived-cast',
-                '-fsanitize=cfi-unrelated-cast',
                 '-fsanitize-blacklist=<(cfi_blacklist)',
               ],
             },
@@ -6234,6 +6219,34 @@
             'xcode_settings':  {
               'OTHER_LDFLAGS': [
                 '-fsanitize=cfi-vcall',
+              ],
+            },
+          }],
+        ],
+      },
+    }],
+    ['cfi_vptr==1 and cfi_cast==1', {
+      'target_defaults': {
+        'target_conditions': [
+          ['_toolset=="target"', {
+            'cflags': [
+              '-fsanitize=cfi-derived-cast',
+              '-fsanitize=cfi-unrelated-cast',
+            ],
+            'ldflags': [
+              '-fsanitize=cfi-derived-cast',
+              '-fsanitize=cfi-unrelated-cast',
+            ],
+            'xcode_settings': {
+              'OTHER_CFLAGS': [
+                '-fsanitize=cfi-derived-cast',
+                '-fsanitize=cfi-unrelated-cast',
+              ],
+            },
+          }],
+          ['_toolset=="target" and _type!="static_library"', {
+            'xcode_settings':  {
+              'OTHER_LDFLAGS': [
                 '-fsanitize=cfi-derived-cast',
                 '-fsanitize=cfi-unrelated-cast',
               ],
diff --git a/build/config/BUILD.gn b/build/config/BUILD.gn
index c06f6ab..4934afa 100644
--- a/build/config/BUILD.gn
+++ b/build/config/BUILD.gn
@@ -201,9 +201,6 @@
   if (enable_app_list) {
     defines += [ "ENABLE_APP_LIST=1" ]
   }
-  if (enable_settings_app) {
-    defines += [ "ENABLE_SETTINGS_APP=1" ]
-  }
   if (enable_supervised_users) {
     defines += [ "ENABLE_SUPERVISED_USERS=1" ]
   }
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn
index 4f3a223c..2036b345 100644
--- a/build/config/BUILDCONFIG.gn
+++ b/build/config/BUILDCONFIG.gn
@@ -639,9 +639,14 @@
     assert(invoker.static_component_type == "static_library" ||
            invoker.static_component_type == "source_set")
     _component_mode = invoker.static_component_type
-  } else if (!defined(invoker.sources)) {
+  } else if (is_android || !defined(invoker.sources)) {
     # When there are no sources defined, use a source set to avoid creating
     # an empty static library (which generally don't work).
+    #
+    # TODO(brettw) remove the Android condition or comment why it needs to be
+    # kept after some analysis. Source sets vs. static libraries seem to be
+    # causing some performance differences. As part of the analysis for
+    # http://crbug.com/619593 we're testing source sets for components again.
     _component_mode = "source_set"
   } else {
     _component_mode = "static_library"
diff --git a/build/config/features.gni b/build/config/features.gni
index f0dca909..f2968d7 100644
--- a/build/config/features.gni
+++ b/build/config/features.gni
@@ -110,7 +110,7 @@
   use_gio = is_linux && !is_chromeos && !is_chromecast
 
   # Enable basic printing support and UI.
-  enable_basic_printing = !is_chromeos && !is_chromecast && !is_ios
+  enable_basic_printing = !is_chromecast && !is_ios
 
   # Enable printing with print preview. It does not imply
   # enable_basic_printing. It's possible to build Chrome with preview only.
@@ -155,8 +155,6 @@
 enable_rlz_support = is_win || is_mac || is_ios || is_chromeos
 enable_rlz = is_chrome_branded && enable_rlz_support
 
-enable_settings_app = enable_app_list && !is_chromeos
-
 enable_service_discovery = enable_mdns || is_mac
 
 # Image loader extension is enabled on ChromeOS only.
diff --git a/build/config/ios/ios_sdk.gni b/build/config/ios/ios_sdk.gni
index 31885e77..e3abd7b 100644
--- a/build/config/ios/ios_sdk.gni
+++ b/build/config/ios/ios_sdk.gni
@@ -23,6 +23,43 @@
   # ios_enable_code_signing_flag=<bool> flag to make the invocation clearer.
   ios_enable_code_signing = true
   ios_code_signing_identity = ""
+
+  # If non-empty, this list must contain valid cpu architecture, and the final
+  # build will be a multi-architecture build (aka fat build) supporting the
+  # main $target_cpu architecture and all of $additional_target_cpus.
+  #
+  # For example to build an application that will run on both arm64 and armv7
+  # devices, you would use the following in args.gn file when running "gn args":
+  #
+  #   target_os = "ios"
+  #   target_cpu = "arm64"
+  #   additional_target_cpus = [ "arm" ]
+  #
+  # You can also pass the value via "--args" parameter for "gn gen" command by
+  # using the syntax --args='additional_target_cpus=["arm"] target_cpu="arm64"'.
+  additional_target_cpus = []
+}
+
+assert(custom_toolchain == "" || additional_target_cpus == [],
+       "cannot define both custom_toolchain and additional_target_cpus")
+
+# Initialize additional_toolchains from additional_target_cpus. Assert here
+# that the list does not contains $target_cpu nor duplicates as this would
+# cause weird errors during the build.
+additional_toolchains = []
+if (additional_target_cpus != []) {
+  foreach(_additional_target_cpu, additional_target_cpus) {
+    assert(_additional_target_cpu != target_cpu,
+           "target_cpu must not be listed in additional_target_cpus")
+
+    _toolchain = "//build/toolchain/mac:ios_clang_$_additional_target_cpu"
+    foreach(_additional_toolchain, additional_toolchains) {
+      assert(_toolchain != _additional_toolchain,
+             "additional_target_cpus must not contains duplicate values")
+    }
+
+    additional_toolchains += [ _toolchain ]
+  }
 }
 
 if (ios_sdk_path == "") {
diff --git a/build/config/ios/rules.gni b/build/config/ios/rules.gni
index 219b580b..aec0de5 100644
--- a/build/config/ios/rules.gni
+++ b/build/config/ios/rules.gni
@@ -70,10 +70,6 @@
   }
 }
 
-# TODO(crbug.com/297668): refactor this template to extract common behaviour
-# between OS X and iOS bundle generation, then create a generic "app" template
-# that forward to "executable" on all platform except iOS/OS X.
-
 # Template to build an application bundle for iOS.
 #
 # This should be used instead of "executable" built-in target type on iOS.
@@ -122,155 +118,323 @@
     _output_name = invoker.output_name
   }
 
-  _generate_info_plist = target_name + "_generate_info_plist"
-  _bundle_data_info_plist = target_name + "_bundle_data_info_plist"
+  # This template expands to multiple targets with some differences between
+  # the the different build configuration.
+  #
+  # For a thin build (i.e. when additional_target_cpus is an empty list),
+  # it compiles the final application binary with an "executable" target,
+  # performs variable expansions on the Info.plist, defines some "bundle_data"
+  # target to pack Info.plist and the executable into the .app bundle, and
+  # finally a "create_bundle" target that packs everything the bundle. If the
+  # bundle needs to be signed, then the binary is copied into the bundle by
+  # the "create_bundle" target and the intermediate "bundle_data" target is
+  # not generated.
+  #
+  # For a multi-architecture build (aka fat-build), the template expands to
+  # a simple "executable" target for non-default toolchain. This is because
+  # the real application bundle will contains a single binary that supports
+  # all the architectures and creating a separate .app bundle for every
+  # architecture would be a waste of time.
+  #
+  # The target for the default toolchain of a multi-architecture build will
+  # build the executable for current_cpu in a temporary location. The real
+  # fat binary will be created by "lipo" command from all those "executable"
+  # target (including those of the non-default toolchains). This additional
+  # target has the same role as the "executable" target of a thin build.
+  #
+  # The rest of the build, including the codesigning step, are the same for
+  # thin and fat builds.
 
-  ios_info_plist(_generate_info_plist) {
-    executable_name = _output_name
-    forward_variables_from(invoker,
-                           [
-                             "extra_substitutions",
-                             "info_plist",
-                             "info_plist_target",
-                           ])
+  _is_fat_build = additional_toolchains != []
+  if (_is_fat_build) {
+    _is_fat_build_main_target = current_toolchain == default_toolchain
   }
 
-  bundle_data(_bundle_data_info_plist) {
-    forward_variables_from(invoker, [ "testonly" ])
-    visibility = [ ":$_target_name" ]
-    sources = get_target_outputs(":$_generate_info_plist")
-    outputs = [
-      "{{bundle_root_dir}}/Info.plist",
-    ]
-    public_deps = [
-      ":$_generate_info_plist",
-    ]
-  }
+  if (_is_fat_build && !_is_fat_build_main_target) {
+    # For the non-default toolchain of a fat-build, the template expands to a
+    # single "executable" target that creates "$root_out_dir/$_output_name".
+    executable(_target_name) {
+      forward_variables_from(invoker,
+                             "*",
+                             [
+                               "bundle_extension",
+                               "entitlements_path",
+                               "extra_substitutions",
+                               "info_plist",
+                               "info_plist_target",
+                               "output_name",
+                               "product_type",
+                             ])
 
-  _generate_executable = target_name + "_generate_executable"
-  if (!ios_enable_code_signing) {
-    _bundle_data_executable = target_name + "_bundle_data_executable"
-  }
+      if (defined(visibility)) {
+        visibility += [ ":*($default_toolchain)" ]
+      }
 
-  executable(_generate_executable) {
-    if (ios_enable_code_signing) {
+      output_name = _output_name
+      if (!defined(libs)) {
+        libs = []
+      }
+      libs += [ "UIKit.framework" ]
+      if (!defined(ldflags)) {
+        ldflags = []
+      }
+      ldflags += [ "-ObjC" ]
+    }
+  } else {
+    # This is either a thin build or the default toolchain of a fat-build.
+    # The template will expand in many different target ($target_name is the
+    # create_bundle target) used as input to the create_bundle target.
+    _generate_info_plist = target_name + "_generate_info_plist"
+    _bundle_data_info_plist = target_name + "_bundle_data_info_plist"
+
+    ios_info_plist(_generate_info_plist) {
+      visibility = [ ":$_bundle_data_info_plist" ]
+      executable_name = _output_name
+      forward_variables_from(invoker,
+                             [
+                               "extra_substitutions",
+                               "info_plist",
+                               "info_plist_target",
+                             ])
+    }
+
+    bundle_data(_bundle_data_info_plist) {
       visibility = [ ":$_target_name" ]
-    } else {
-      visibility = [ ":$_bundle_data_executable" ]
-    }
-    forward_variables_from(invoker,
-                           "*",
-                           [
-                             "bundle_extension",
-                             "data_deps",
-                             "entitlements_path",
-                             "info_plist",
-                             "info_plist_target",
-                             "output_name",
-                             "product_type",
-                             "visibility",
-                           ])
-
-    output_name = rebase_path("$target_gen_dir/$_output_name", root_out_dir)
-    output_prefix_override = true
-
-    if (!defined(libs)) {
-      libs = []
-    }
-    libs += [ "UIKit.framework" ]
-    if (!defined(ldflags)) {
-      ldflags = []
-    }
-    ldflags += [ "-ObjC" ]
-  }
-
-  if (!ios_enable_code_signing) {
-    bundle_data(_bundle_data_executable) {
       forward_variables_from(invoker, [ "testonly" ])
-      visibility = [ ":$_target_name" ]
-      sources = [
-        "$target_gen_dir/$_output_name",
-      ]
+      sources = get_target_outputs(":$_generate_info_plist")
       outputs = [
-        "{{bundle_executable_dir}}/$_output_name",
+        "{{bundle_root_dir}}/Info.plist",
       ]
       public_deps = [
-        ":$_generate_executable",
+        ":$_generate_info_plist",
       ]
     }
+
+    _link_executable = _target_name + "_link_executable"
+    _executable_path = "$target_out_dir/$_output_name"
+
+    if (ios_enable_code_signing) {
+      _link_executable_visibility = [ ":$_target_name" ]
+    } else {
+      _bundle_data_executable = target_name + "_bundle_data_executable"
+      _link_executable_visibility = [ ":$_bundle_data_executable" ]
+    }
+
+    # For a fat-build, the different "executable" outputs will be used to
+    # create the final binary using "lipo". As the corresponding target has
+    # the same role as the "executable" target in a thin build, copy the
+    # visibility and redefine some variables.
+    if (_is_fat_build) {
+      _lipo_executable = _target_name + "_lipo_executable"
+      _lipo_executable_visibility = _link_executable_visibility
+
+      _link_executable_visibility = []
+      _link_executable_visibility = [ ":$_lipo_executable" ]
+
+      _arch_executable_path = "$target_out_dir/$current_cpu/$_output_name"
+    }
+
+    executable(_link_executable) {
+      forward_variables_from(invoker,
+                             "*",
+                             [
+                               "bundle_extension",
+                               "data_deps",
+                               "entitlements_path",
+                               "extra_substitutions",
+                               "info_plist",
+                               "info_plist_target",
+                               "output_name",
+                               "product_type",
+                               "visibility",
+                             ])
+
+      visibility = _link_executable_visibility
+
+      output_prefix_override = true
+      if (_is_fat_build) {
+        output_name = rebase_path(_arch_executable_path, root_build_dir)
+      } else {
+        output_name = rebase_path(_executable_path, root_build_dir)
+      }
+
+      if (!defined(libs)) {
+        libs = []
+      }
+      libs += [ "UIKit.framework" ]
+      if (!defined(ldflags)) {
+        ldflags = []
+      }
+      ldflags += [ "-ObjC" ]
+    }
+
+    if (_is_fat_build) {
+      # Create the multi-architecture binary from all the single architecture
+      # binaries using "lipo". This target exists for the default toolchain
+      # of a fat-build only and depends on the expansion of "ios_app_bundle"
+      # for the other toolchains (i.e. a single "executable" target).
+      #
+      # This action only happens once per "ios_app_bundle" template (for the
+      # main toolchain).
+      action(_lipo_executable) {
+        forward_variables_from(invoker, [ "testonly" ])
+        visibility = _lipo_executable_visibility
+        script = "//build/config/mac/xcrun.py"
+        outputs = [
+          _executable_path,
+        ]
+        inputs = [
+          _arch_executable_path,
+        ]
+        deps = [
+          ":$_link_executable",
+        ]
+        foreach(_additional_toolchain, additional_toolchains) {
+          _additional_toolchain_target = "$_target_name($_additional_toolchain)"
+          deps += [ ":$_additional_toolchain_target" ]
+          inputs += [ get_label_info(_additional_toolchain_target,
+                                     "root_out_dir") + "/$_output_name" ]
+        }
+        args = [
+                 "lipo",
+                 "-create",
+                 "-output",
+                 rebase_path(outputs[0], root_build_dir),
+               ] + rebase_path(inputs, root_build_dir)
+      }
+    }
+
+    if (!ios_enable_code_signing) {
+      # If codesigning is enabled, the binary will be copied into the bundle
+      # by the codesigning script (as the binary is updated by the signature).
+      # Otherwise, this "bundle_data" declares the location of the binary in
+      # the .app bundle.
+      bundle_data(_bundle_data_executable) {
+        forward_variables_from(invoker, [ "testonly" ])
+        visibility = [ ":$_target_name" ]
+        outputs = [
+          "{{bundle_executable_dir}}/$_output_name",
+        ]
+        if (_is_fat_build) {
+          public_deps = [
+            ":$_lipo_executable",
+          ]
+        } else {
+          public_deps = [
+            ":$_link_executable",
+          ]
+        }
+        sources = [
+          "$target_out_dir/$_output_name",
+        ]
+      }
+    }
+
+    create_bundle(target_name) {
+      forward_variables_from(invoker,
+                             [
+                               "data_deps",
+                               "deps",
+                               "public_deps",
+                               "testonly",
+                               "visibility",
+                             ])
+
+      if (!defined(deps)) {
+        deps = []
+      }
+      deps += [ ":$_bundle_data_info_plist" ]
+      if (ios_enable_code_signing) {
+        if (_is_fat_build) {
+          deps += [ ":$_lipo_executable" ]
+        } else {
+          deps += [ ":$_link_executable" ]
+        }
+      } else {
+        deps += [ ":$_bundle_data_executable" ]
+      }
+
+      if (use_ios_simulator) {
+        if (!defined(data_deps)) {
+          data_deps = []
+        }
+        data_deps += [ "//testing/iossim" ]
+      }
+
+      if (defined(invoker.product_type)) {
+        product_type = invoker.product_type
+      } else {
+        product_type = "com.apple.product-type.application"
+      }
+
+      if (defined(invoker.bundle_extension)) {
+        _bundle_extension = invoker.bundle_extension
+      } else {
+        _bundle_extension = ".app"
+      }
+
+      bundle_root_dir = "$root_out_dir/$_output_name$_bundle_extension"
+      bundle_resources_dir = bundle_root_dir
+      bundle_executable_dir = bundle_root_dir
+      bundle_plugins_dir = "$bundle_root_dir/PlugIns"
+
+      if (ios_enable_code_signing) {
+        _entitlements_path = "$ios_sdk_path/Entitlements.plist"
+        if (defined(invoker.entitlements_path)) {
+          _entitlements_path = invoker.entitlements_path
+        }
+
+        code_signing_script = "//build/config/ios/codesign.py"
+        code_signing_sources = [
+          _entitlements_path,
+          "$target_out_dir/$_output_name",
+        ]
+        code_signing_outputs = [
+          "$bundle_root_dir/$_output_name",
+          "$bundle_root_dir/_CodeSignature/CodeResources",
+          "$bundle_root_dir/embedded.mobileprovision",
+        ]
+        code_signing_args = [
+          "-i=" + ios_code_signing_identity,
+          "-b=" + rebase_path("$target_out_dir/$_output_name", root_build_dir),
+          "-e=" + rebase_path(_entitlements_path, root_build_dir),
+          rebase_path(bundle_root_dir, root_build_dir),
+        ]
+      }
+    }
   }
 
-  create_bundle(target_name) {
-    forward_variables_from(invoker,
-                           [
-                             "data_deps",
-                             "deps",
-                             "public_deps",
-                             "testonly",
-                             "visibility",
-                           ])
-
-    if (!defined(deps)) {
-      deps = []
-    }
-    deps += [ ":$_bundle_data_info_plist" ]
-    if (ios_enable_code_signing) {
-      deps += [ ":$_generate_executable" ]
-    } else {
-      deps += [ ":$_bundle_data_executable" ]
-    }
-
-    if (use_ios_simulator) {
-      if (!defined(data_deps)) {
-        data_deps = []
-      }
-      data_deps += [ "//testing/iossim" ]
-    }
-
-    if (defined(invoker.product_type)) {
-      product_type = invoker.product_type
-    } else {
-      product_type = "com.apple.product-type.application"
-    }
-
-    if (defined(invoker.bundle_extension)) {
-      _bundle_extension = invoker.bundle_extension
-    } else {
-      _bundle_extension = ".app"
-    }
-
-    bundle_root_dir = "$root_out_dir/$_output_name$_bundle_extension"
-    bundle_resources_dir = bundle_root_dir
-    bundle_executable_dir = bundle_root_dir
-    bundle_plugins_dir = "$bundle_root_dir/PlugIns"
-
-    if (defined(invoker.entitlements_path)) {
-      _entitlements_path = invoker.entitlements_path
-    } else {
-      _entitlements_path = "$ios_sdk_path/Entitlements.plist"
-    }
-
-    if (ios_enable_code_signing) {
-      code_signing_script = "//build/config/ios/codesign.py"
-      code_signing_sources = [
-        _entitlements_path,
-        "$target_gen_dir/$_output_name",
-      ]
-      code_signing_outputs = [
-        "$bundle_root_dir/$_output_name",
-        "$bundle_root_dir/_CodeSignature/CodeResources",
-        "$bundle_root_dir/embedded.mobileprovision",
-      ]
-      code_signing_args = [
-        "-i=" + ios_code_signing_identity,
-        "-b=" + rebase_path("$target_gen_dir/$_output_name", root_build_dir),
-        "-e=" + rebase_path(_entitlements_path, root_build_dir),
-        rebase_path(bundle_root_dir, root_build_dir),
-      ]
-    } else {
-      assert(_entitlements_path != "",
-             "force usage of _entitlements_path to avoid unused variable error")
-    }
+  # TODO(crbug.com/395883): ensure those variables are marked as used to
+  # avoid errors while running "gn gen".
+  if (defined(invoker.entitlements_path)) {
+    assert(invoker.entitlements_path != "",
+           "mark invoker.entitlements_path as used")
+  }
+  if (defined(invoker.bundle_extension)) {
+    assert(invoker.bundle_extension != "",
+           "mark invoker.bundle_extension as used")
+  }
+  if (defined(invoker.bundle_extension)) {
+    assert(invoker.bundle_extension != "",
+           "mark invoker.bundle_extension as used")
+  }
+  if (defined(invoker.entitlements_path)) {
+    assert(invoker.entitlements_path != "",
+           "mark invoker.entitlements_path as used")
+  }
+  if (defined(invoker.extra_substitutions)) {
+    assert(invoker.extra_substitutions != [],
+           "mark invoker.extra_substitutions as used")
+  }
+  if (defined(invoker.info_plist)) {
+    assert(invoker.info_plist != "", "mark invoker.info_plist as used")
+  }
+  if (defined(invoker.info_plist_target)) {
+    assert(invoker.info_plist_target != "",
+           "mark invoker.info_plist_target as used")
+  }
+  if (defined(invoker.product_type)) {
+    assert(invoker.product_type != "", "mark product_type as used")
   }
 }
 
diff --git a/build/config/sanitizers/BUILD.gn b/build/config/sanitizers/BUILD.gn
index 0b099f4..695dba0 100644
--- a/build/config/sanitizers/BUILD.gn
+++ b/build/config/sanitizers/BUILD.gn
@@ -155,11 +155,13 @@
     }
 
     if (is_cfi && !is_nacl) {
-      ldflags += [
-        "-fsanitize=cfi-vcall",
-        "-fsanitize=cfi-derived-cast",
-        "-fsanitize=cfi-unrelated-cast",
-      ]
+      ldflags += [ "-fsanitize=cfi-vcall" ]
+      if (use_cfi_cast) {
+        ldflags += [
+          "-fsanitize=cfi-derived-cast",
+          "-fsanitize=cfi-unrelated-cast",
+        ]
+      }
       if (use_cfi_diag) {
         ldflags += [
           "-fno-sanitize-trap=cfi",
@@ -206,6 +208,12 @@
   cflags = []
   if (is_asan) {
     cflags += [ "-fsanitize=address" ]
+    if (!asan_globals) {
+      cflags += [
+        "-mllvm",
+        "-asan-globals=0",
+      ]
+    }
     if (is_win) {
       cflags += [ "-fsanitize-blacklist=" +
                   rebase_path("//tools/memory/asan/blacklist_win.txt",
@@ -216,23 +224,8 @@
           [ "-fsanitize-blacklist=" +
             rebase_path("//tools/memory/asan/blacklist.txt", root_build_dir) ]
     }
-    if (is_android) {
-      # Android build relies on -Wl,--gc-sections removing unreachable code.
-      # ASan instrumentation for globals inhibits this and results in a
-      # library with unresolvable relocations.
-      # TODO(eugenis): find a way to reenable this.
-      cflags += [
-        "-mllvm",
-        "-asan-globals=0",
-      ]
-    } else if (is_mac) {
-      # http://crbug.com/352073
-      cflags += [
-        "-mllvm",
-        "-asan-globals=0",
-      ]
-      # TODO(GYP): deal with mac_bundles.
-    } else if (is_win) {
+
+    if (is_win) {
       assert(current_cpu == "x86", "WinASan is 32-bit only currently")
       if (is_component_build) {
         libs = [
@@ -255,11 +248,16 @@
         rebase_path("//tools/cfi/blacklist.txt", root_build_dir)
     cflags += [
       "-fsanitize=cfi-vcall",
-      "-fsanitize=cfi-derived-cast",
-      "-fsanitize=cfi-unrelated-cast",
       "-fsanitize-blacklist=$cfi_blacklist_path",
     ]
 
+    if (use_cfi_cast) {
+      cflags += [
+        "-fsanitize=cfi-derived-cast",
+        "-fsanitize=cfi-unrelated-cast",
+      ]
+    }
+
     if (use_cfi_diag) {
       cflags += [
         "-fno-sanitize-trap=cfi",
diff --git a/build/config/sanitizers/sanitizers.gni b/build/config/sanitizers/sanitizers.gni
index 32cecff..c58e72f66 100644
--- a/build/config/sanitizers/sanitizers.gni
+++ b/build/config/sanitizers/sanitizers.gni
@@ -49,6 +49,11 @@
   # TODO(pcc): Remove this flag if/when CFI is enabled in official builds.
   is_cfi = false
 
+  # Enable checks for bad casts: derived cast and unrelated cast.
+  # TODO(krasin): remove this, when we're ready to add these checks by default.
+  # https://crbug.com/626794
+  use_cfi_cast = false
+
   # By default, Control Flow Integrity will crash the program if it detects a
   # violation. Set this to true to print detailed diagnostics instead.
   use_cfi_diag = false
@@ -78,7 +83,6 @@
   # trace-pc
   # Default value when unset and use_sanitizer_coverage=true:
   #     edge,indirect-calls,8bit-counters
-
   sanitizer_coverage_flags = ""
 }
 
@@ -96,6 +100,16 @@
   # Enable -fsanitize-coverage.
   use_sanitizer_coverage =
       use_libfuzzer || use_afl || sanitizer_coverage_flags != ""
+
+  # Detect overflow/underflow for global objects.
+  #
+  # Android build relies on -Wl,--gc-sections removing unreachable code.
+  # ASan instrumentation for globals inhibits this and results in a
+  # library with unresolvable relocations.
+  # TODO(eugenis): find a way to reenable this.
+  #
+  # Mac: http://crbug.com/352073
+  asan_globals = !is_android && !is_mac
 }
 
 if (use_afl && sanitizer_coverage_flags == "") {
diff --git a/cc/base/rolling_time_delta_history.cc b/cc/base/rolling_time_delta_history.cc
index e296c4b..a80ca21 100644
--- a/cc/base/rolling_time_delta_history.cc
+++ b/cc/base/rolling_time_delta_history.cc
@@ -4,6 +4,7 @@
 
 #include <stddef.h>
 
+#include <algorithm>
 #include <cmath>
 
 #include "cc/base/rolling_time_delta_history.h"
@@ -11,7 +12,9 @@
 namespace cc {
 
 RollingTimeDeltaHistory::RollingTimeDeltaHistory(size_t max_size)
-    : max_size_(max_size) {}
+    : next_index_(0), max_size_(max_size) {
+  sample_vector_.reserve(max_size_);
+}
 
 RollingTimeDeltaHistory::~RollingTimeDeltaHistory() {}
 
@@ -19,47 +22,37 @@
   if (max_size_ == 0)
     return;
 
-  if (sample_set_.size() == max_size_) {
-    sample_set_.erase(chronological_sample_deque_.front());
-    chronological_sample_deque_.pop_front();
+  if (sample_vector_.size() == max_size_) {
+    sample_vector_[next_index_++] = time;
+    if (next_index_ == max_size_)
+      next_index_ = 0;
+  } else {
+    sample_vector_.push_back(time);
   }
-
-  TimeDeltaMultiset::iterator it = sample_set_.insert(time);
-  chronological_sample_deque_.push_back(it);
 }
 
 void RollingTimeDeltaHistory::Clear() {
-  chronological_sample_deque_.clear();
-  sample_set_.clear();
+  sample_vector_.clear();
+  next_index_ = 0;
 }
 
 base::TimeDelta RollingTimeDeltaHistory::Percentile(double percent) const {
-  if (sample_set_.size() == 0)
+  if (sample_vector_.size() == 0)
     return base::TimeDelta();
 
   double fraction = percent / 100.0;
-
   if (fraction <= 0.0)
-    return *(sample_set_.begin());
+    return *std::min_element(sample_vector_.begin(), sample_vector_.end());
 
   if (fraction >= 1.0)
-    return *(sample_set_.rbegin());
+    return *std::max_element(sample_vector_.begin(), sample_vector_.end());
 
   size_t num_smaller_samples =
-      static_cast<size_t>(std::ceil(fraction * sample_set_.size())) - 1;
+      static_cast<size_t>(std::ceil(fraction * sample_vector_.size())) - 1;
 
-  if (num_smaller_samples > sample_set_.size() / 2) {
-    size_t num_larger_samples = sample_set_.size() - num_smaller_samples - 1;
-    TimeDeltaMultiset::const_reverse_iterator it = sample_set_.rbegin();
-    for (size_t i = 0; i < num_larger_samples; i++)
-      it++;
-    return *it;
-  }
-
-  TimeDeltaMultiset::const_iterator it = sample_set_.begin();
-  for (size_t i = 0; i < num_smaller_samples; i++)
-    it++;
-  return *it;
+  std::vector<base::TimeDelta> v(sample_vector_.begin(), sample_vector_.end());
+  std::nth_element(v.begin(), v.begin() + num_smaller_samples, v.end());
+  return v[num_smaller_samples];
 }
 
 }  // namespace cc
diff --git a/cc/base/rolling_time_delta_history.h b/cc/base/rolling_time_delta_history.h
index 61ed339..192c8e07 100644
--- a/cc/base/rolling_time_delta_history.h
+++ b/cc/base/rolling_time_delta_history.h
@@ -7,8 +7,7 @@
 
 #include <stddef.h>
 
-#include <deque>
-#include <set>
+#include <vector>
 
 #include "base/macros.h"
 #include "base/time/time.h"
@@ -33,10 +32,8 @@
   base::TimeDelta Percentile(double percent) const;
 
  private:
-  typedef std::multiset<base::TimeDelta> TimeDeltaMultiset;
-
-  TimeDeltaMultiset sample_set_;
-  std::deque<TimeDeltaMultiset::iterator> chronological_sample_deque_;
+  std::vector<base::TimeDelta> sample_vector_;
+  size_t next_index_;
   size_t max_size_;
 
   DISALLOW_COPY_AND_ASSIGN(RollingTimeDeltaHistory);
diff --git a/cc/ipc/cc_param_traits.cc b/cc/ipc/cc_param_traits.cc
index 43864d3..26c804f 100644
--- a/cc/ipc/cc_param_traits.cc
+++ b/cc/ipc/cc_param_traits.cc
@@ -570,13 +570,13 @@
 
 void ParamTraits<cc::SurfaceId>::GetSize(base::PickleSizer* s,
                                          const param_type& p) {
-  GetParamSize(s, p.id_namespace());
+  GetParamSize(s, p.client_id());
   GetParamSize(s, p.local_id());
   GetParamSize(s, p.nonce());
 }
 
 void ParamTraits<cc::SurfaceId>::Write(base::Pickle* m, const param_type& p) {
-  WriteParam(m, p.id_namespace());
+  WriteParam(m, p.client_id());
   WriteParam(m, p.local_id());
   WriteParam(m, p.nonce());
 }
@@ -584,8 +584,8 @@
 bool ParamTraits<cc::SurfaceId>::Read(const base::Pickle* m,
                                       base::PickleIterator* iter,
                                       param_type* p) {
-  uint32_t id_namespace;
-  if (!ReadParam(m, iter, &id_namespace))
+  uint32_t client_id;
+  if (!ReadParam(m, iter, &client_id))
     return false;
 
   uint32_t local_id;
@@ -596,13 +596,13 @@
   if (!ReadParam(m, iter, &nonce))
     return false;
 
-  *p = cc::SurfaceId(id_namespace, local_id, nonce);
+  *p = cc::SurfaceId(client_id, local_id, nonce);
   return true;
 }
 
 void ParamTraits<cc::SurfaceId>::Log(const param_type& p, std::string* l) {
   l->append("SurfaceId(");
-  LogParam(p.id_namespace(), l);
+  LogParam(p.client_id(), l);
   l->append(", ");
   LogParam(p.local_id(), l);
   l->append(", ");
@@ -677,45 +677,18 @@
 void ParamTraits<cc::CompositorFrameAck>::Write(base::Pickle* m,
                                                 const param_type& p) {
   WriteParam(m, p.resources);
-  if (p.gl_frame_data) {
-    WriteParam(m, static_cast<int>(GL_FRAME));
-    WriteParam(m, *p.gl_frame_data);
-  } else {
-    WriteParam(m, static_cast<int>(NO_FRAME));
-  }
 }
 
 bool ParamTraits<cc::CompositorFrameAck>::Read(const base::Pickle* m,
                                                base::PickleIterator* iter,
                                                param_type* p) {
-  if (!ReadParam(m, iter, &p->resources))
-    return false;
-
-  int compositor_frame_type;
-  if (!ReadParam(m, iter, &compositor_frame_type))
-    return false;
-
-  switch (compositor_frame_type) {
-    case NO_FRAME:
-      break;
-    case GL_FRAME:
-      p->gl_frame_data.reset(new cc::GLFrameData());
-      if (!ReadParam(m, iter, p->gl_frame_data.get()))
-        return false;
-      break;
-    default:
-      return false;
-  }
-  return true;
+  return ReadParam(m, iter, &p->resources);
 }
 
 void ParamTraits<cc::CompositorFrameAck>::Log(const param_type& p,
                                               std::string* l) {
   l->append("CompositorFrameAck(");
   LogParam(p.resources, l);
-  l->append(", ");
-  if (p.gl_frame_data)
-    LogParam(*p.gl_frame_data, l);
   l->append(")");
 }
 
diff --git a/cc/ipc/cc_param_traits_macros.h b/cc/ipc/cc_param_traits_macros.h
index 43431c6..655ea26 100644
--- a/cc/ipc/cc_param_traits_macros.h
+++ b/cc/ipc/cc_param_traits_macros.h
@@ -47,7 +47,7 @@
 IPC_STRUCT_TRAITS_END()
 
 IPC_STRUCT_TRAITS_BEGIN(cc::SurfaceSequence)
-  IPC_STRUCT_TRAITS_MEMBER(id_namespace)
+  IPC_STRUCT_TRAITS_MEMBER(client_id)
   IPC_STRUCT_TRAITS_MEMBER(sequence)
 IPC_STRUCT_TRAITS_END()
 
diff --git a/cc/ipc/struct_traits_unittest.cc b/cc/ipc/struct_traits_unittest.cc
index f74f10ad..2748f6f1 100644
--- a/cc/ipc/struct_traits_unittest.cc
+++ b/cc/ipc/struct_traits_unittest.cc
@@ -729,26 +729,26 @@
 }
 
 TEST_F(StructTraitsTest, SurfaceId) {
-  const uint32_t id_namespace = 1337;
+  const uint32_t client_id = 1337;
   const uint32_t local_id = 0xfbadbeef;
   const uint64_t nonce = 0xdeadbeef;
-  SurfaceId input(id_namespace, local_id, nonce);
+  SurfaceId input(client_id, local_id, nonce);
   mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy();
   SurfaceId output;
   proxy->EchoSurfaceId(input, &output);
-  EXPECT_EQ(id_namespace, output.id_namespace());
+  EXPECT_EQ(client_id, output.client_id());
   EXPECT_EQ(local_id, output.local_id());
   EXPECT_EQ(nonce, output.nonce());
 }
 
 TEST_F(StructTraitsTest, SurfaceSequence) {
-  const uint32_t id_namespace = 2016;
+  const uint32_t client_id = 2016;
   const uint32_t sequence = 0xfbadbeef;
-  SurfaceSequence input(id_namespace, sequence);
+  SurfaceSequence input(client_id, sequence);
   mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy();
   SurfaceSequence output;
   proxy->EchoSurfaceSequence(input, &output);
-  EXPECT_EQ(id_namespace, output.id_namespace);
+  EXPECT_EQ(client_id, output.client_id);
   EXPECT_EQ(sequence, output.sequence);
 }
 
diff --git a/cc/ipc/surface_id.mojom b/cc/ipc/surface_id.mojom
index f4f74272..0a0e5fa 100644
--- a/cc/ipc/surface_id.mojom
+++ b/cc/ipc/surface_id.mojom
@@ -4,19 +4,19 @@
 
 module cc.mojom;
 
-// A surface ID is composed of three parts: a namespace, a local ID, and a
+// A surface ID is composed of three parts: a client ID, a local ID, and a
 // nonce. The local part and nonce are allocated by the client using any scheme
-// that avoids duplicates and makes IDs unguessable respectively. The namespace
+// that avoids duplicates and makes IDs unguessable respectively. The client ID
 // is allocated by the service and will be different for each client.
 //
-// The special id_namespace value 0 is equivalent to the namespace of the
-// client. This can be used to create, destroy and submit frames to
-// surfaces before learning the namespace and to reference other surfaces
-// owned by the same client. The actual id namespace must be used to pass
-// surface ids to other clients for them to reference.
+// The special client_id value 0 is equivalent to the current client.
+// This can be used to create, destroy and submit frames to surfaces before
+// learning the client ID and to reference other surfaces owned by the same
+// client. The actual client ID must be used to pass surface ids to other
+// clients for them to reference.
 struct SurfaceId {
   // A service allocated ID identifying a client.
-  uint32 id_namespace;
+  uint32 client_id;
 
   // An identifier allocated by the client uniquely identifying a surface within
   // a client process.
diff --git a/cc/ipc/surface_id_struct_traits.h b/cc/ipc/surface_id_struct_traits.h
index bafadf9cd..162b398 100644
--- a/cc/ipc/surface_id_struct_traits.h
+++ b/cc/ipc/surface_id_struct_traits.h
@@ -14,16 +14,14 @@
 // respectively.
 template <typename T>
 struct StructTraits<T, cc::SurfaceId> {
-  static uint32_t id_namespace(const cc::SurfaceId& id) {
-    return id.id_namespace();
-  }
+  static uint32_t client_id(const cc::SurfaceId& id) { return id.client_id(); }
 
   static uint32_t local_id(const cc::SurfaceId& id) { return id.local_id(); }
 
   static uint64_t nonce(const cc::SurfaceId& id) { return id.nonce(); }
 
   static bool Read(typename T::DataView data, cc::SurfaceId* out) {
-    *out = cc::SurfaceId(data.id_namespace(), data.local_id(), data.nonce());
+    *out = cc::SurfaceId(data.client_id(), data.local_id(), data.nonce());
     return true;
   }
 };
diff --git a/cc/ipc/surface_sequence.mojom b/cc/ipc/surface_sequence.mojom
index 631fe8d..d186077e 100644
--- a/cc/ipc/surface_sequence.mojom
+++ b/cc/ipc/surface_sequence.mojom
@@ -7,9 +7,8 @@
 // A per-surface-namespace sequence number that's used to coordinate
 // dependencies between frames. A sequence number may be satisfied once, and
 // may be depended on once.
-// A surface sequence consists of an id namespace and a local sequence number.
 struct SurfaceSequence {
-  uint32 id_namespace;
+  uint32 client_id;
   uint32 sequence;
 };
  
diff --git a/cc/ipc/surface_sequence_struct_traits.h b/cc/ipc/surface_sequence_struct_traits.h
index 2635b4df..db47458 100644
--- a/cc/ipc/surface_sequence_struct_traits.h
+++ b/cc/ipc/surface_sequence_struct_traits.h
@@ -14,8 +14,8 @@
 // .mojom-blink.h respectively.
 template <typename T>
 struct StructTraits<T, cc::SurfaceSequence> {
-  static uint32_t id_namespace(const cc::SurfaceSequence& id) {
-    return id.id_namespace;
+  static uint32_t client_id(const cc::SurfaceSequence& id) {
+    return id.client_id;
   }
 
   static uint32_t sequence(const cc::SurfaceSequence& id) {
@@ -23,7 +23,7 @@
   }
 
   static bool Read(typename T::DataView data, cc::SurfaceSequence* out) {
-    *out = cc::SurfaceSequence(data.id_namespace(), data.sequence());
+    *out = cc::SurfaceSequence(data.client_id(), data.sequence());
     return true;
   }
 };
diff --git a/cc/layers/surface_layer.cc b/cc/layers/surface_layer.cc
index 8f0e051..5dbc7a2 100644
--- a/cc/layers/surface_layer.cc
+++ b/cc/layers/surface_layer.cc
@@ -57,7 +57,7 @@
   DCHECK(destroy_sequence_.is_null());
 }
 
-void SurfaceLayer::SetSurfaceId(SurfaceId surface_id,
+void SurfaceLayer::SetSurfaceId(const SurfaceId& surface_id,
                                 float scale,
                                 const gfx::Size& size) {
   SatisfyDestroySequence();
diff --git a/cc/layers/surface_layer.h b/cc/layers/surface_layer.h
index 1799a3a..06c84c1 100644
--- a/cc/layers/surface_layer.h
+++ b/cc/layers/surface_layer.h
@@ -32,7 +32,9 @@
       const SatisfyCallback& satisfy_callback,
       const RequireCallback& require_callback);
 
-  void SetSurfaceId(SurfaceId surface_id, float scale, const gfx::Size& size);
+  void SetSurfaceId(const SurfaceId& surface_id,
+                    float scale,
+                    const gfx::Size& size);
 
   // Layer overrides.
   std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
diff --git a/cc/layers/surface_layer_impl.cc b/cc/layers/surface_layer_impl.cc
index c262d2e..a474d87d 100644
--- a/cc/layers/surface_layer_impl.cc
+++ b/cc/layers/surface_layer_impl.cc
@@ -29,7 +29,7 @@
   return SurfaceLayerImpl::Create(tree_impl, id());
 }
 
-void SurfaceLayerImpl::SetSurfaceId(SurfaceId surface_id) {
+void SurfaceLayerImpl::SetSurfaceId(const SurfaceId& surface_id) {
   if (surface_id_ == surface_id)
     return;
 
diff --git a/cc/layers/surface_layer_impl.h b/cc/layers/surface_layer_impl.h
index d67efd86..e5d4128 100644
--- a/cc/layers/surface_layer_impl.h
+++ b/cc/layers/surface_layer_impl.h
@@ -23,10 +23,10 @@
   }
   ~SurfaceLayerImpl() override;
 
-  void SetSurfaceId(SurfaceId surface_id);
+  void SetSurfaceId(const SurfaceId& surface_id);
   void SetSurfaceScale(float scale);
   void SetSurfaceSize(const gfx::Size& size);
-  SurfaceId surface_id() const { return surface_id_; }
+  const SurfaceId& surface_id() const { return surface_id_; }
 
   // LayerImpl overrides.
   std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
diff --git a/cc/layers/surface_layer_impl_unittest.cc b/cc/layers/surface_layer_impl_unittest.cc
index e88f3e54..2223153 100644
--- a/cc/layers/surface_layer_impl_unittest.cc
+++ b/cc/layers/surface_layer_impl_unittest.cc
@@ -12,6 +12,8 @@
 namespace cc {
 namespace {
 
+static constexpr uint32_t kArbitraryClientId = 0;
+
 TEST(SurfaceLayerImplTest, Occlusion) {
   gfx::Size layer_size(1000, 1000);
   gfx::Size viewport_size(1000, 1000);
@@ -22,7 +24,7 @@
       impl.AddChildToRoot<SurfaceLayerImpl>();
   surface_layer_impl->SetBounds(layer_size);
   surface_layer_impl->SetDrawsContent(true);
-  SurfaceId surface_id(0, 9, 0);
+  SurfaceId surface_id(kArbitraryClientId, 9, 0);
   surface_layer_impl->SetSurfaceId(surface_id);
   surface_layer_impl->SetSurfaceScale(1.f);
   surface_layer_impl->SetSurfaceSize(layer_size);
diff --git a/cc/layers/surface_layer_unittest.cc b/cc/layers/surface_layer_unittest.cc
index 8ff9ad9..74537d10 100644
--- a/cc/layers/surface_layer_unittest.cc
+++ b/cc/layers/surface_layer_unittest.cc
@@ -26,6 +26,8 @@
 namespace cc {
 namespace {
 
+static constexpr uint32_t kArbitraryClientId = 0;
+
 class SurfaceLayerTest : public testing::Test {
  public:
   SurfaceLayerTest()
@@ -73,8 +75,9 @@
   scoped_refptr<SurfaceLayer> layer(SurfaceLayer::Create(
       base::Bind(&SatisfyCallback, &blank_change),
       base::Bind(&RequireCallback, &required_id, &required_seq)));
-  layer->SetSurfaceId(SurfaceId(0, 1, 0), 1.f, gfx::Size(1, 1));
-  layer_tree_host_->set_surface_id_namespace(1);
+  layer->SetSurfaceId(SurfaceId(kArbitraryClientId, 1, 0), 1.f,
+                      gfx::Size(1, 1));
+  layer_tree_host_->set_surface_client_id(1);
   layer_tree_host_->SetRootLayer(layer);
 
   std::unique_ptr<FakeLayerTreeHost> layer_tree_host2 =
@@ -82,8 +85,9 @@
   scoped_refptr<SurfaceLayer> layer2(SurfaceLayer::Create(
       base::Bind(&SatisfyCallback, &blank_change),
       base::Bind(&RequireCallback, &required_id, &required_seq)));
-  layer2->SetSurfaceId(SurfaceId(0, 1, 0), 1.f, gfx::Size(1, 1));
-  layer_tree_host2->set_surface_id_namespace(2);
+  layer2->SetSurfaceId(SurfaceId(kArbitraryClientId, 1, 0), 1.f,
+                       gfx::Size(1, 1));
+  layer_tree_host2->set_surface_client_id(2);
   layer_tree_host2->SetRootLayer(layer2);
 
   // Layers haven't been removed, so no sequence should be satisfied.
@@ -101,7 +105,7 @@
 
   // Set of sequences that need to be satisfied should include sequences from
   // both trees.
-  EXPECT_TRUE(required_id == SurfaceId(0, 1, 0));
+  EXPECT_TRUE(required_id == SurfaceId(kArbitraryClientId, 1, 0));
   EXPECT_EQ(2u, required_seq.size());
   EXPECT_TRUE(required_seq.count(expected1));
   EXPECT_TRUE(required_seq.count(expected2));
@@ -125,11 +129,12 @@
       : commit_count_(0), sequence_was_satisfied_(false) {}
 
   void BeginTest() override {
-    layer_tree_host()->set_surface_id_namespace(1);
+    layer_tree_host()->set_surface_client_id(1);
     layer_ = SurfaceLayer::Create(
         base::Bind(&SatisfyCallback, &satisfied_sequence_),
         base::Bind(&RequireCallback, &required_id_, &required_set_));
-    layer_->SetSurfaceId(SurfaceId(0, 1, 0), 1.f, gfx::Size(1, 1));
+    layer_->SetSurfaceId(SurfaceId(kArbitraryClientId, 1, 0), 1.f,
+                         gfx::Size(1, 1));
 
     // Layer hasn't been added to tree so no SurfaceSequence generated yet.
     EXPECT_EQ(0u, required_set_.size());
@@ -138,7 +143,7 @@
 
     // Should have SurfaceSequence from first tree.
     SurfaceSequence expected(1u, 1u);
-    EXPECT_TRUE(required_id_ == SurfaceId(0, 1, 0));
+    EXPECT_TRUE(required_id_ == SurfaceId(kArbitraryClientId, 1, 0));
     EXPECT_EQ(1u, required_set_.size());
     EXPECT_TRUE(required_set_.count(expected));
 
@@ -208,7 +213,7 @@
   }
 
   void AfterTest() override {
-    EXPECT_TRUE(required_id_ == SurfaceId(0, 1, 0));
+    EXPECT_TRUE(required_id_ == SurfaceId(kArbitraryClientId, 1, 0));
     EXPECT_EQ(1u, required_set_.size());
     // Sequence should have been satisfied through Swap, not with the
     // callback.
@@ -249,7 +254,7 @@
   }
 
   void AfterTest() override {
-    EXPECT_TRUE(required_id_ == SurfaceId(0, 1, 0));
+    EXPECT_TRUE(required_id_ == SurfaceId(kArbitraryClientId, 1, 0));
     EXPECT_EQ(1u, required_set_.size());
     // Sequence should have been satisfied with the callback.
     EXPECT_TRUE(satisfied_sequence_ == SurfaceSequence(1u, 1u));
diff --git a/cc/output/compositor_frame_ack.h b/cc/output/compositor_frame_ack.h
index 55ca7f1..e5fb241 100644
--- a/cc/output/compositor_frame_ack.h
+++ b/cc/output/compositor_frame_ack.h
@@ -20,7 +20,6 @@
   ~CompositorFrameAck();
 
   ReturnedResourceArray resources;
-  std::unique_ptr<GLFrameData> gl_frame_data;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(CompositorFrameAck);
diff --git a/cc/proto/layer_tree_host.proto b/cc/proto/layer_tree_host.proto
index 4d89190..71bbcf5 100644
--- a/cc/proto/layer_tree_host.proto
+++ b/cc/proto/layer_tree_host.proto
@@ -60,7 +60,7 @@
   optional int32 outer_viewport_scroll_layer_id = 29;
   optional LayerSelection selection = 30;
   optional PropertyTrees property_trees = 31;
-  optional uint32 surface_id_namespace = 32;
+  optional uint32 surface_client_id = 32;
   optional uint32 next_surface_sequence = 33;
   optional uint32 wheel_event_listener_properties = 34;
   optional bool have_scroll_event_handlers = 35;
diff --git a/cc/quads/surface_draw_quad.cc b/cc/quads/surface_draw_quad.cc
index d1a2882..4ec7fa26 100644
--- a/cc/quads/surface_draw_quad.cc
+++ b/cc/quads/surface_draw_quad.cc
@@ -16,7 +16,7 @@
 void SurfaceDrawQuad::SetNew(const SharedQuadState* shared_quad_state,
                              const gfx::Rect& rect,
                              const gfx::Rect& visible_rect,
-                             SurfaceId surface_id) {
+                             const SurfaceId& surface_id) {
   gfx::Rect opaque_rect;
   bool needs_blending = false;
   DrawQuad::SetAll(shared_quad_state, DrawQuad::SURFACE_CONTENT, rect,
@@ -29,7 +29,7 @@
                              const gfx::Rect& opaque_rect,
                              const gfx::Rect& visible_rect,
                              bool needs_blending,
-                             SurfaceId surface_id) {
+                             const SurfaceId& surface_id) {
   DrawQuad::SetAll(shared_quad_state, DrawQuad::SURFACE_CONTENT, rect,
                    opaque_rect, visible_rect, needs_blending);
   this->surface_id = surface_id;
diff --git a/cc/quads/surface_draw_quad.h b/cc/quads/surface_draw_quad.h
index 890f3bf..b0db76aa 100644
--- a/cc/quads/surface_draw_quad.h
+++ b/cc/quads/surface_draw_quad.h
@@ -20,14 +20,14 @@
   void SetNew(const SharedQuadState* shared_quad_state,
               const gfx::Rect& rect,
               const gfx::Rect& visible_rect,
-              SurfaceId surface_id);
+              const SurfaceId& surface_id);
 
   void SetAll(const SharedQuadState* shared_quad_state,
               const gfx::Rect& rect,
               const gfx::Rect& opaque_rect,
               const gfx::Rect& visible_rect,
               bool needs_blending,
-              SurfaceId surface_id);
+              const SurfaceId& surface_id);
 
   SurfaceId surface_id;
 
diff --git a/cc/surfaces/display.cc b/cc/surfaces/display.cc
index f45842d9..cc19376f 100644
--- a/cc/surfaces/display.cc
+++ b/cc/surfaces/display.cc
@@ -92,8 +92,8 @@
   DCHECK(ok);
 }
 
-void Display::SetSurfaceId(SurfaceId id, float device_scale_factor) {
-  DCHECK_EQ(id.id_namespace(), compositor_surface_namespace_);
+void Display::SetSurfaceId(const SurfaceId& id, float device_scale_factor) {
+  DCHECK_EQ(id.client_id(), compositor_surface_namespace_);
   if (current_surface_id_ == id && device_scale_factor_ == device_scale_factor)
     return;
 
@@ -402,7 +402,7 @@
     aggregator_->SetFullDamageForSurface(current_surface_id_);
 }
 
-void Display::OnSurfaceDamaged(SurfaceId surface_id, bool* changed) {
+void Display::OnSurfaceDamaged(const SurfaceId& surface_id, bool* changed) {
   if (aggregator_ &&
       aggregator_->previous_contained_surfaces().count(surface_id)) {
     Surface* surface = surface_manager_->GetSurfaceForId(surface_id);
@@ -426,7 +426,7 @@
     UpdateRootSurfaceResourcesLocked();
 }
 
-SurfaceId Display::CurrentSurfaceId() {
+const SurfaceId& Display::CurrentSurfaceId() {
   return current_surface_id_;
 }
 
diff --git a/cc/surfaces/display.h b/cc/surfaces/display.h
index 9df93d41..3ac3ae5 100644
--- a/cc/surfaces/display.h
+++ b/cc/surfaces/display.h
@@ -72,13 +72,13 @@
 
   // device_scale_factor is used to communicate to the external window system
   // what scale this was rendered at.
-  void SetSurfaceId(SurfaceId id, float device_scale_factor);
+  void SetSurfaceId(const SurfaceId& id, float device_scale_factor);
   void Resize(const gfx::Size& new_size);
   void SetColorSpace(const gfx::ColorSpace& color_space);
   void SetExternalClip(const gfx::Rect& clip);
   void SetOutputIsSecure(bool secure);
 
-  SurfaceId CurrentSurfaceId();
+  const SurfaceId& CurrentSurfaceId();
 
   // DisplaySchedulerClient implementation.
   bool DrawAndSwap() override;
@@ -108,7 +108,7 @@
   void SetFullRootLayerDamage() override;
 
   // SurfaceDamageObserver implementation.
-  void OnSurfaceDamaged(SurfaceId surface, bool* changed) override;
+  void OnSurfaceDamaged(const SurfaceId& surface, bool* changed) override;
 
   void SetEnlargePassTextureAmountForTesting(
       const gfx::Size& enlarge_texture_amount) {
diff --git a/cc/surfaces/display_scheduler.cc b/cc/surfaces/display_scheduler.cc
index 98f2a689..d26d1b6 100644
--- a/cc/surfaces/display_scheduler.cc
+++ b/cc/surfaces/display_scheduler.cc
@@ -69,7 +69,7 @@
 
 // Notification that there was a resize or the root surface changed and
 // that we should just draw immediately.
-void DisplayScheduler::SetNewRootSurface(SurfaceId root_surface_id) {
+void DisplayScheduler::SetNewRootSurface(const SurfaceId& root_surface_id) {
   TRACE_EVENT0("cc", "DisplayScheduler::SetNewRootSurface");
   root_surface_id_ = root_surface_id;
   SurfaceDamaged(root_surface_id);
@@ -78,7 +78,7 @@
 // Indicates that there was damage to one of the surfaces.
 // Has some logic to wait for multiple active surfaces before
 // triggering the deadline.
-void DisplayScheduler::SurfaceDamaged(SurfaceId surface_id) {
+void DisplayScheduler::SurfaceDamaged(const SurfaceId& surface_id) {
   TRACE_EVENT1("cc", "DisplayScheduler::SurfaceDamaged", "surface_id",
                surface_id.ToString());
 
diff --git a/cc/surfaces/display_scheduler.h b/cc/surfaces/display_scheduler.h
index aa3a9067..16d0868 100644
--- a/cc/surfaces/display_scheduler.h
+++ b/cc/surfaces/display_scheduler.h
@@ -40,8 +40,8 @@
   void SetRootSurfaceResourcesLocked(bool locked);
   void ForceImmediateSwapIfPossible();
   virtual void DisplayResized();
-  virtual void SetNewRootSurface(SurfaceId root_surface_id);
-  virtual void SurfaceDamaged(SurfaceId surface_id);
+  virtual void SetNewRootSurface(const SurfaceId& root_surface_id);
+  virtual void SurfaceDamaged(const SurfaceId& surface_id);
 
   virtual void DidSwapBuffers();
   void DidSwapBuffersComplete();
diff --git a/cc/surfaces/display_unittest.cc b/cc/surfaces/display_unittest.cc
index 0de4a9f..0778b6a2 100644
--- a/cc/surfaces/display_unittest.cc
+++ b/cc/surfaces/display_unittest.cc
@@ -70,11 +70,11 @@
 
   void DisplayResized() override { display_resized_ = true; }
 
-  void SetNewRootSurface(SurfaceId root_surface_id) override {
+  void SetNewRootSurface(const SurfaceId& root_surface_id) override {
     has_new_root_surface = true;
   }
 
-  void SurfaceDamaged(SurfaceId surface_id) override {
+  void SurfaceDamaged(const SurfaceId& surface_id) override {
     damaged = true;
     needs_draw_ = true;
   }
@@ -97,9 +97,9 @@
  public:
   DisplayTest()
       : factory_(&manager_, &surface_factory_client_),
-        id_allocator_(kArbitrarySurfaceNamespace),
+        id_allocator_(kArbitraryClientId),
         task_runner_(new base::NullTaskRunner) {
-    id_allocator_.RegisterSurfaceIdNamespace(&manager_);
+    id_allocator_.RegisterSurfaceClientId(&manager_);
   }
 
   void SetUpDisplay(const RendererSettings& settings,
@@ -125,13 +125,14 @@
     display_ = base::MakeUnique<Display>(
         &manager_, &shared_bitmap_manager_,
         nullptr /* gpu_memory_buffer_manager */, settings,
-        id_allocator_.id_namespace(), std::move(begin_frame_source),
+        id_allocator_.client_id(), std::move(begin_frame_source),
         std::move(output_surface), std::move(scheduler),
         base::MakeUnique<TextureMailboxDeleter>(task_runner_.get()));
   }
 
  protected:
-  void SubmitCompositorFrame(RenderPassList* pass_list, SurfaceId surface_id) {
+  void SubmitCompositorFrame(RenderPassList* pass_list,
+                             const SurfaceId& surface_id) {
     std::unique_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
     pass_list->swap(frame_data->render_pass_list);
 
@@ -142,7 +143,7 @@
                                    SurfaceFactory::DrawCallback());
   }
 
-  static constexpr int kArbitrarySurfaceNamespace = 3;
+  static constexpr int kArbitraryClientId = 3;
 
   SurfaceManager manager_;
   FakeSurfaceFactoryClient surface_factory_client_;
diff --git a/cc/surfaces/surface.cc b/cc/surfaces/surface.cc
index 3755d9b8..30e5ea48 100644
--- a/cc/surfaces/surface.cc
+++ b/cc/surfaces/surface.cc
@@ -89,7 +89,7 @@
     // Notify the manager that sequences were satisfied either if some new
     // sequences were satisfied, or if the set of referenced surfaces changed
     // to force a GC to happen.
-    factory_->manager()->DidSatisfySequences(surface_id_.id_namespace(),
+    factory_->manager()->DidSatisfySequences(surface_id_.client_id(),
                                              &satisfies_sequences);
   }
 }
@@ -165,13 +165,13 @@
 
 void Surface::SatisfyDestructionDependencies(
     std::unordered_set<SurfaceSequence, SurfaceSequenceHash>* sequences,
-    std::unordered_set<uint32_t>* valid_id_namespaces) {
+    std::unordered_set<uint32_t>* valid_client_ids) {
   destruction_dependencies_.erase(
       std::remove_if(destruction_dependencies_.begin(),
                      destruction_dependencies_.end(),
-                     [sequences, valid_id_namespaces](SurfaceSequence seq) {
+                     [sequences, valid_client_ids](SurfaceSequence seq) {
                        return (!!sequences->erase(seq) ||
-                               !valid_id_namespaces->count(seq.id_namespace));
+                               !valid_client_ids->count(seq.client_id));
                      }),
       destruction_dependencies_.end());
 }
diff --git a/cc/surfaces/surface_aggregator_perftest.cc b/cc/surfaces/surface_aggregator_perftest.cc
index d903743..9295e02 100644
--- a/cc/surfaces/surface_aggregator_perftest.cc
+++ b/cc/surfaces/surface_aggregator_perftest.cc
@@ -22,6 +22,8 @@
 namespace cc {
 namespace {
 
+static constexpr uint32_t kArbitraryClientId = 0;
+
 class EmptySurfaceFactoryClient : public SurfaceFactoryClient {
  public:
   void ReturnResources(const ReturnedResourceArray& resources) override {}
@@ -49,7 +51,7 @@
     aggregator_.reset(new SurfaceAggregator(&manager_, resource_provider_.get(),
                                             optimize_damage));
     for (int i = 1; i <= num_surfaces; i++) {
-      factory_.Create(SurfaceId(0, i, 0));
+      factory_.Create(SurfaceId(kArbitraryClientId, i, 0));
       std::unique_ptr<RenderPass> pass(RenderPass::Create());
       std::unique_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
 
@@ -86,17 +88,18 @@
         SurfaceDrawQuad* surface_quad =
             pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
         surface_quad->SetNew(sqs, gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1),
-                             SurfaceId(0, i - 1, 0));
+                             SurfaceId(kArbitraryClientId, i - 1, 0));
       }
 
       frame_data->render_pass_list.push_back(std::move(pass));
       CompositorFrame frame;
       frame.delegated_frame_data = std::move(frame_data);
-      factory_.SubmitCompositorFrame(SurfaceId(0, i, 0), std::move(frame),
+      factory_.SubmitCompositorFrame(SurfaceId(kArbitraryClientId, i, 0),
+                                     std::move(frame),
                                      SurfaceFactory::DrawCallback());
     }
 
-    factory_.Create(SurfaceId(0, num_surfaces + 1, 0));
+    factory_.Create(SurfaceId(kArbitraryClientId, num_surfaces + 1, 0));
     timer_.Reset();
     do {
       std::unique_ptr<RenderPass> pass(RenderPass::Create());
@@ -107,7 +110,7 @@
           pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
       surface_quad->SetNew(sqs, gfx::Rect(0, 0, 100, 100),
                            gfx::Rect(0, 0, 100, 100),
-                           SurfaceId(0, num_surfaces, 0));
+                           SurfaceId(kArbitraryClientId, num_surfaces, 0));
 
       if (full_damage)
         pass->damage_rect = gfx::Rect(0, 0, 100, 100);
@@ -117,21 +120,21 @@
       frame_data->render_pass_list.push_back(std::move(pass));
       CompositorFrame frame;
       frame.delegated_frame_data = std::move(frame_data);
-      factory_.SubmitCompositorFrame(SurfaceId(0, num_surfaces + 1, 0),
-                                     std::move(frame),
-                                     SurfaceFactory::DrawCallback());
+      factory_.SubmitCompositorFrame(
+          SurfaceId(kArbitraryClientId, num_surfaces + 1, 0), std::move(frame),
+          SurfaceFactory::DrawCallback());
 
-      CompositorFrame aggregated =
-          aggregator_->Aggregate(SurfaceId(0, num_surfaces + 1, 0));
+      CompositorFrame aggregated = aggregator_->Aggregate(
+          SurfaceId(kArbitraryClientId, num_surfaces + 1, 0));
       timer_.NextLap();
     } while (!timer_.HasTimeLimitExpired());
 
     perf_test::PrintResult("aggregator_speed", "", name, timer_.LapsPerSecond(),
                            "runs/s", true);
 
-    factory_.Destroy(SurfaceId(0, num_surfaces + 1, 0));
+    factory_.Destroy(SurfaceId(kArbitraryClientId, num_surfaces + 1, 0));
     for (int i = 1; i <= num_surfaces; i++)
-      factory_.Destroy(SurfaceId(0, i, 0));
+      factory_.Destroy(SurfaceId(kArbitraryClientId, i, 0));
   }
 
  protected:
diff --git a/cc/surfaces/surface_aggregator_unittest.cc b/cc/surfaces/surface_aggregator_unittest.cc
index 7df08f5..804620a 100644
--- a/cc/surfaces/surface_aggregator_unittest.cc
+++ b/cc/surfaces/surface_aggregator_unittest.cc
@@ -37,8 +37,10 @@
 namespace cc {
 namespace {
 
+static constexpr uint32_t kArbitraryClientId = 0;
+
 SurfaceId InvalidSurfaceId() {
-  static SurfaceId invalid(0, 0xdeadbeef, 0);
+  static SurfaceId invalid(kArbitraryClientId, 0xdeadbeef, 0);
   return invalid;
 }
 
@@ -79,7 +81,7 @@
 };
 
 TEST_F(SurfaceAggregatorTest, ValidSurfaceNoFrame) {
-  SurfaceId one_id(0, 7, 0);
+  SurfaceId one_id(kArbitraryClientId, 7, 0);
   factory_.Create(one_id);
 
   CompositorFrame frame = aggregator_.Aggregate(one_id);
@@ -138,7 +140,8 @@
     }
   }
 
-  void SubmitPassListAsFrame(SurfaceId surface_id, RenderPassList* pass_list) {
+  void SubmitPassListAsFrame(const SurfaceId& surface_id,
+                             RenderPassList* pass_list) {
     std::unique_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
     pass_list->swap(frame_data->render_pass_list);
 
@@ -151,14 +154,14 @@
 
   void SubmitCompositorFrame(test::Pass* passes,
                              size_t pass_count,
-                             SurfaceId surface_id) {
+                             const SurfaceId& surface_id) {
     RenderPassList pass_list;
     AddPasses(&pass_list, gfx::Rect(SurfaceSize()), passes, pass_count);
     SubmitPassListAsFrame(surface_id, &pass_list);
   }
 
   void QueuePassAsFrame(std::unique_ptr<RenderPass> pass,
-                        SurfaceId surface_id) {
+                        const SurfaceId& surface_id) {
     std::unique_ptr<DelegatedFrameData> delegated_frame_data(
         new DelegatedFrameData);
     delegated_frame_data->render_pass_list.push_back(std::move(pass));
@@ -1917,7 +1920,7 @@
 TEST_F(SurfaceAggregatorWithResourcesTest, TakeResourcesOneSurface) {
   ResourceTrackingSurfaceFactoryClient client;
   SurfaceFactory factory(&manager_, &client);
-  SurfaceId surface_id(0, 7u, 0);
+  SurfaceId surface_id(kArbitraryClientId, 7u, 0);
   factory.Create(surface_id);
 
   ResourceId ids[] = {11, 12, 13};
@@ -1947,7 +1950,7 @@
 TEST_F(SurfaceAggregatorWithResourcesTest, TakeInvalidResources) {
   ResourceTrackingSurfaceFactoryClient client;
   SurfaceFactory factory(&manager_, &client);
-  SurfaceId surface_id(0, 7u, 0);
+  SurfaceId surface_id(kArbitraryClientId, 7u, 0);
   factory.Create(surface_id);
 
   std::unique_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
@@ -1981,10 +1984,10 @@
 TEST_F(SurfaceAggregatorWithResourcesTest, TwoSurfaces) {
   ResourceTrackingSurfaceFactoryClient client;
   SurfaceFactory factory(&manager_, &client);
-  SurfaceId surface1_id(0, 7u, 0);
+  SurfaceId surface1_id(kArbitraryClientId, 7u, 0);
   factory.Create(surface1_id);
 
-  SurfaceId surface2_id(0, 8u, 0);
+  SurfaceId surface2_id(kArbitraryClientId, 8u, 0);
   factory.Create(surface2_id);
 
   ResourceId ids[] = {11, 12, 13};
@@ -2022,11 +2025,11 @@
 TEST_F(SurfaceAggregatorWithResourcesTest, InvalidChildSurface) {
   ResourceTrackingSurfaceFactoryClient client;
   SurfaceFactory factory(&manager_, &client);
-  SurfaceId root_surface_id(0, 7u, 0);
+  SurfaceId root_surface_id(kArbitraryClientId, 7u, 0);
   factory.Create(root_surface_id);
-  SurfaceId middle_surface_id(0, 8u, 0);
+  SurfaceId middle_surface_id(kArbitraryClientId, 8u, 0);
   factory.Create(middle_surface_id);
-  SurfaceId child_surface_id(0, 9u, 0);
+  SurfaceId child_surface_id(kArbitraryClientId, 9u, 0);
   factory.Create(child_surface_id);
 
   ResourceId ids[] = {14, 15, 16};
@@ -2070,10 +2073,10 @@
 TEST_F(SurfaceAggregatorWithResourcesTest, SecureOutputTexture) {
   ResourceTrackingSurfaceFactoryClient client;
   SurfaceFactory factory(&manager_, &client);
-  SurfaceId surface1_id(0, 7u, 0);
+  SurfaceId surface1_id(kArbitraryClientId, 7u, 0);
   factory.Create(surface1_id);
 
-  SurfaceId surface2_id(0, 8u, 0);
+  SurfaceId surface2_id(kArbitraryClientId, 8u, 0);
   factory.Create(surface2_id);
 
   ResourceId ids[] = {11, 12, 13};
diff --git a/cc/surfaces/surface_damage_observer.h b/cc/surfaces/surface_damage_observer.h
index 62ee012..b266e6e 100644
--- a/cc/surfaces/surface_damage_observer.h
+++ b/cc/surfaces/surface_damage_observer.h
@@ -5,15 +5,15 @@
 #ifndef CC_SURFACES_SURFACE_DAMAGE_OBSERVER_H_
 #define CC_SURFACES_SURFACE_DAMAGE_OBSERVER_H_
 
-#include "cc/surfaces/surface_id.h"
-
 namespace cc {
 
+class SurfaceId;
+
 class SurfaceDamageObserver {
  public:
   // Runs when a Surface is damaged. *changed should be set to true if this
   // causes a Display to be damaged.
-  virtual void OnSurfaceDamaged(SurfaceId surface_id, bool* changed) = 0;
+  virtual void OnSurfaceDamaged(const SurfaceId& surface_id, bool* changed) = 0;
 };
 
 }  // namespace cc
diff --git a/cc/surfaces/surface_display_output_surface.cc b/cc/surfaces/surface_display_output_surface.cc
index 6dc569c7..fbdb8ffc 100644
--- a/cc/surfaces/surface_display_output_surface.cc
+++ b/cc/surfaces/surface_display_output_surface.cc
@@ -86,7 +86,7 @@
   DCHECK(thread_checker_.CalledOnValidThread());
 
   surface_manager_->RegisterSurfaceFactoryClient(
-      surface_id_allocator_->id_namespace(), this);
+      surface_id_allocator_->client_id(), this);
 
   if (!OutputSurface::BindToClient(client))
     return false;
@@ -115,7 +115,7 @@
   // Unregister the SurfaceFactoryClient here instead of the dtor so that only
   // one client is alive for this namespace at any given time.
   surface_manager_->UnregisterSurfaceFactoryClient(
-      surface_id_allocator_->id_namespace());
+      surface_id_allocator_->client_id());
   if (!delegated_surface_id_.is_null())
     factory_.Destroy(delegated_surface_id_);
 
diff --git a/cc/surfaces/surface_display_output_surface_unittest.cc b/cc/surfaces/surface_display_output_surface_unittest.cc
index 27de2b9..598a982 100644
--- a/cc/surfaces/surface_display_output_surface_unittest.cc
+++ b/cc/surfaces/surface_display_output_surface_unittest.cc
@@ -25,16 +25,18 @@
 namespace cc {
 namespace {
 
+static constexpr int kArbitraryClientId = 0;
+
 class SurfaceDisplayOutputSurfaceTest : public testing::Test {
  public:
   SurfaceDisplayOutputSurfaceTest()
       : now_src_(new base::SimpleTestTickClock()),
         task_runner_(new OrderedSimpleTaskRunner(now_src_.get(), true)),
-        allocator_(0),
+        allocator_(kArbitraryClientId),
         display_size_(1920, 1080),
         display_rect_(display_size_),
         context_provider_(TestContextProvider::Create()) {
-    surface_manager_.RegisterSurfaceIdNamespace(allocator_.id_namespace());
+    surface_manager_.RegisterSurfaceClientId(allocator_.client_id());
 
     std::unique_ptr<FakeOutputSurface> display_output_surface =
         FakeOutputSurface::Create3d();
@@ -50,7 +52,7 @@
 
     display_.reset(new Display(
         &surface_manager_, &bitmap_manager_, &gpu_memory_buffer_manager_,
-        RendererSettings(), allocator_.id_namespace(),
+        RendererSettings(), allocator_.client_id(),
         std::move(begin_frame_source), std::move(display_output_surface),
         std::move(scheduler),
         base::MakeUnique<TextureMailboxDeleter>(task_runner_.get())));
diff --git a/cc/surfaces/surface_factory_unittest.cc b/cc/surfaces/surface_factory_unittest.cc
index b4620465..b5cfa1c 100644
--- a/cc/surfaces/surface_factory_unittest.cc
+++ b/cc/surfaces/surface_factory_unittest.cc
@@ -26,6 +26,8 @@
 namespace cc {
 namespace {
 
+static constexpr uint32_t kArbitraryClientId = 0;
+
 class TestSurfaceFactoryClient : public SurfaceFactoryClient {
  public:
   TestSurfaceFactoryClient() : begin_frame_source_(nullptr) {}
@@ -66,7 +68,7 @@
  public:
   SurfaceFactoryTest()
       : factory_(new SurfaceFactory(&manager_, &client_)),
-        surface_id_(0, 3, 0),
+        surface_id_(kArbitraryClientId, 3, 0),
         frame_sync_token_(GenTestSyncToken(4)),
         consumer_sync_token_(GenTestSyncToken(5)) {
     manager_.AddObserver(this);
@@ -74,7 +76,7 @@
   }
 
   // SurfaceDamageObserver implementation.
-  void OnSurfaceDamaged(SurfaceId id, bool* changed) override {
+  void OnSurfaceDamaged(const SurfaceId& id, bool* changed) override {
     *changed = true;
   }
 
@@ -419,7 +421,7 @@
 }
 
 TEST_F(SurfaceFactoryTest, BlankNoIndexIncrement) {
-  SurfaceId surface_id(0, 6, 0);
+  SurfaceId surface_id(kArbitraryClientId, 6, 0);
   factory_->Create(surface_id);
   Surface* surface = manager_.GetSurfaceForId(surface_id);
   ASSERT_NE(nullptr, surface);
@@ -437,7 +439,7 @@
                                uint32_t* execute_count,
                                SurfaceDrawStatus* result,
                                SurfaceDrawStatus drawn) {
-  SurfaceId new_id(0, 7, 0);
+  SurfaceId new_id(kArbitraryClientId, 7, 0);
   factory->Create(new_id);
   factory->Destroy(new_id);
   *execute_count += 1;
@@ -445,7 +447,7 @@
 }
 
 TEST_F(SurfaceFactoryTest, AddDuringDestroy) {
-  SurfaceId surface_id(0, 6, 0);
+  SurfaceId surface_id(kArbitraryClientId, 6, 0);
   factory_->Create(surface_id);
   CompositorFrame frame;
   frame.delegated_frame_data.reset(new DelegatedFrameData);
@@ -471,7 +473,7 @@
 
 // Tests doing a DestroyAll before shutting down the factory;
 TEST_F(SurfaceFactoryTest, DestroyAll) {
-  SurfaceId id(0, 7, 0);
+  SurfaceId id(kArbitraryClientId, 7, 0);
   factory_->Create(id);
 
   std::unique_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
@@ -494,10 +496,10 @@
 }
 
 TEST_F(SurfaceFactoryTest, DestroySequence) {
-  SurfaceId id2(0, 5, 0);
+  SurfaceId id2(kArbitraryClientId, 5, 0);
   factory_->Create(id2);
 
-  manager_.RegisterSurfaceIdNamespace(0);
+  manager_.RegisterSurfaceClientId(0);
 
   // Check that waiting before the sequence is satisfied works.
   manager_.GetSurfaceForId(id2)
@@ -525,12 +527,12 @@
 
 // Tests that Surface ID namespace invalidation correctly allows
 // Sequences to be ignored.
-TEST_F(SurfaceFactoryTest, InvalidIdNamespace) {
+TEST_F(SurfaceFactoryTest, InvalidClientId) {
   uint32_t id_namespace = 9u;
   SurfaceId id(id_namespace, 5, 0);
   factory_->Create(id);
 
-  manager_.RegisterSurfaceIdNamespace(id_namespace);
+  manager_.RegisterSurfaceClientId(id_namespace);
   manager_.GetSurfaceForId(id)
       ->AddDestructionDependency(SurfaceSequence(id_namespace, 4));
   factory_->Destroy(id);
@@ -538,7 +540,7 @@
   // Verify the dependency has prevented the surface from getting destroyed.
   EXPECT_TRUE(manager_.GetSurfaceForId(id));
 
-  manager_.InvalidateSurfaceIdNamespace(id_namespace);
+  manager_.InvalidateSurfaceClientId(id_namespace);
 
   // Verify that the invalidated namespace caused the unsatisfied sequence
   // to be ignored.
@@ -546,10 +548,10 @@
 }
 
 TEST_F(SurfaceFactoryTest, DestroyCycle) {
-  SurfaceId id2(0, 5, 0);
+  SurfaceId id2(kArbitraryClientId, 5, 0);
   factory_->Create(id2);
 
-  manager_.RegisterSurfaceIdNamespace(0);
+  manager_.RegisterSurfaceClientId(0);
 
   manager_.GetSurfaceForId(id2)
       ->AddDestructionDependency(SurfaceSequence(0, 4));
diff --git a/cc/surfaces/surface_id.h b/cc/surfaces/surface_id.h
index c48e8129..48a434a 100644
--- a/cc/surfaces/surface_id.h
+++ b/cc/surfaces/surface_id.h
@@ -18,58 +18,57 @@
 
 class SurfaceId {
  public:
-  SurfaceId() : id_namespace_(0), local_id_(0), nonce_(0) {}
+  SurfaceId() : client_id_(0), local_id_(0), nonce_(0) {}
 
   SurfaceId(const SurfaceId& other)
-      : id_namespace_(other.id_namespace_),
+      : client_id_(other.client_id_),
         local_id_(other.local_id_),
         nonce_(other.nonce_) {}
 
-  // A SurfaceId consists of three components: namespace, local Id, and nonce.
-  // An |id_namespace| is a display compositor service allocated ID that
+  // A SurfaceId consists of three components: client Id, local Id, and nonce.
+  // A |client_id| is a display compositor service allocated ID that
   // uniquely identifies a client.
   // A |local_id| is a sequentially allocated ID generated by the display
-  // compositor client.
+  // compositor client that uniquely identifies a surface.
   // A |nonce| is a cryptographically secure random int that makes a SurfaceId
   // unguessable by other clients.
-  SurfaceId(uint32_t id_namespace, uint32_t local_id, uint64_t nonce)
-      : id_namespace_(id_namespace), local_id_(local_id), nonce_(nonce) {}
+  SurfaceId(uint32_t client_id, uint32_t local_id, uint64_t nonce)
+      : client_id_(client_id), local_id_(local_id), nonce_(nonce) {}
 
   bool is_null() const {
-    return id_namespace_ == 0 && nonce_ == 0 && local_id_ == 0;
+    return client_id_ == 0 && nonce_ == 0 && local_id_ == 0;
   }
 
   size_t hash() const {
-    size_t interim = base::HashInts(id_namespace_, local_id_);
+    size_t interim = base::HashInts(client_id_, local_id_);
     return base::HashInts(static_cast<uint64_t>(interim), nonce_);
   }
 
-  uint32_t id_namespace() const { return id_namespace_; }
+  uint32_t client_id() const { return client_id_; }
 
   uint32_t local_id() const { return local_id_; }
 
   uint64_t nonce() const { return nonce_; }
 
   std::string ToString() const {
-    return base::StringPrintf("%d:%d:%" PRIu64, id_namespace_, local_id_,
-                              nonce_);
+    return base::StringPrintf("%d:%d:%" PRIu64, client_id_, local_id_, nonce_);
   }
 
   bool operator==(const SurfaceId& other) const {
-    return id_namespace_ == other.id_namespace_ &&
-           local_id_ == other.local_id_ && nonce_ == other.nonce_;
+    return client_id_ == other.client_id_ && local_id_ == other.local_id_ &&
+           nonce_ == other.nonce_;
   }
 
   bool operator!=(const SurfaceId& other) const { return !(*this == other); }
 
   bool operator<(const SurfaceId& other) const {
-    return std::tie(id_namespace_, local_id_, nonce_) <
-           std::tie(other.id_namespace_, other.local_id_, other.nonce_);
+    return std::tie(client_id_, local_id_, nonce_) <
+           std::tie(other.client_id_, other.local_id_, other.nonce_);
   }
 
  private:
   // See SurfaceIdAllocator::GenerateId.
-  uint32_t id_namespace_;
+  uint32_t client_id_;
   uint32_t local_id_;
   uint64_t nonce_;
 };
diff --git a/cc/surfaces/surface_id_allocator.cc b/cc/surfaces/surface_id_allocator.cc
index 8b169a5..9151400f 100644
--- a/cc/surfaces/surface_id_allocator.cc
+++ b/cc/surfaces/surface_id_allocator.cc
@@ -11,24 +11,23 @@
 
 namespace cc {
 
-SurfaceIdAllocator::SurfaceIdAllocator(uint32_t id_namespace)
-    : id_namespace_(id_namespace), next_id_(1u), manager_(nullptr) {
-}
+SurfaceIdAllocator::SurfaceIdAllocator(uint32_t client_id)
+    : client_id_(client_id), next_id_(1u), manager_(nullptr) {}
 
-void SurfaceIdAllocator::RegisterSurfaceIdNamespace(SurfaceManager* manager) {
+void SurfaceIdAllocator::RegisterSurfaceClientId(SurfaceManager* manager) {
   DCHECK(!manager_);
   manager_ = manager;
-  manager_->RegisterSurfaceIdNamespace(id_namespace_);
+  manager_->RegisterSurfaceClientId(client_id_);
 }
 
 SurfaceIdAllocator::~SurfaceIdAllocator() {
   if (manager_)
-    manager_->InvalidateSurfaceIdNamespace(id_namespace_);
+    manager_->InvalidateSurfaceClientId(client_id_);
 }
 
 SurfaceId SurfaceIdAllocator::GenerateId() {
   uint64_t nonce = base::RandUint64();
-  SurfaceId id(id_namespace_, next_id_, nonce);
+  SurfaceId id(client_id_, next_id_, nonce);
   next_id_++;
   return id;
 }
diff --git a/cc/surfaces/surface_id_allocator.h b/cc/surfaces/surface_id_allocator.h
index 3e1bbc7..c77f359 100644
--- a/cc/surfaces/surface_id_allocator.h
+++ b/cc/surfaces/surface_id_allocator.h
@@ -20,7 +20,7 @@
 // class in a mutex.
 class CC_SURFACES_EXPORT SurfaceIdAllocator {
  public:
-  explicit SurfaceIdAllocator(uint32_t id_namespace);
+  explicit SurfaceIdAllocator(uint32_t client_id);
   ~SurfaceIdAllocator();
 
   SurfaceId GenerateId();
@@ -31,16 +31,16 @@
   // automatically invalidated and any remaining sequences with that
   // namespace will be ignored. This method does not need to be called in
   // contexts where there is no SurfaceManager (e.g. a renderer process).
-  void RegisterSurfaceIdNamespace(SurfaceManager* manager);
+  void RegisterSurfaceClientId(SurfaceManager* manager);
 
-  uint32_t id_namespace() const { return id_namespace_; }
+  uint32_t client_id() const { return client_id_; }
 
   // SurfaceIdAllocator's owner can call this when it find out that
   // SurfaceManager is no longer alive during destruction.
   void DidDestroySurfaceManager() { manager_ = nullptr; }
 
  private:
-  const uint32_t id_namespace_;
+  const uint32_t client_id_;
   uint32_t next_id_;
   SurfaceManager* manager_;
 
diff --git a/cc/surfaces/surface_manager.cc b/cc/surfaces/surface_manager.cc
index 26c8440..d2953c4 100644
--- a/cc/surfaces/surface_manager.cc
+++ b/cc/surfaces/surface_manager.cc
@@ -65,25 +65,25 @@
   GarbageCollectSurfaces();
 }
 
-void SurfaceManager::DidSatisfySequences(uint32_t id_namespace,
+void SurfaceManager::DidSatisfySequences(uint32_t client_id,
                                          std::vector<uint32_t>* sequence) {
   DCHECK(thread_checker_.CalledOnValidThread());
   for (std::vector<uint32_t>::iterator it = sequence->begin();
        it != sequence->end();
        ++it) {
-    satisfied_sequences_.insert(SurfaceSequence(id_namespace, *it));
+    satisfied_sequences_.insert(SurfaceSequence(client_id, *it));
   }
   sequence->clear();
   GarbageCollectSurfaces();
 }
 
-void SurfaceManager::RegisterSurfaceIdNamespace(uint32_t id_namespace) {
-  bool inserted = valid_surface_id_namespaces_.insert(id_namespace).second;
+void SurfaceManager::RegisterSurfaceClientId(uint32_t client_id) {
+  bool inserted = valid_surface_client_ids_.insert(client_id).second;
   DCHECK(inserted);
 }
 
-void SurfaceManager::InvalidateSurfaceIdNamespace(uint32_t id_namespace) {
-  valid_surface_id_namespaces_.erase(id_namespace);
+void SurfaceManager::InvalidateSurfaceClientId(uint32_t client_id) {
+  valid_surface_client_ids_.erase(client_id);
   GarbageCollectSurfaces();
 }
 
@@ -98,7 +98,7 @@
   // their destruction dependencies satisfied.
   for (auto& map_entry : surface_map_) {
     map_entry.second->SatisfyDestructionDependencies(
-        &satisfied_sequences_, &valid_surface_id_namespaces_);
+        &satisfied_sequences_, &valid_surface_client_ids_);
     if (!map_entry.second->destroyed() ||
         map_entry.second->GetDestructionDependencyCount()) {
       live_surfaces_set.insert(map_entry.first);
@@ -143,16 +143,16 @@
 }
 
 void SurfaceManager::RegisterSurfaceFactoryClient(
-    uint32_t id_namespace,
+    uint32_t client_id,
     SurfaceFactoryClient* client) {
   DCHECK(client);
-  DCHECK(!namespace_client_map_[id_namespace].client);
-  DCHECK_EQ(valid_surface_id_namespaces_.count(id_namespace), 1u);
+  DCHECK(!namespace_client_map_[client_id].client);
+  DCHECK_EQ(valid_surface_client_ids_.count(client_id), 1u);
 
-  auto iter = namespace_client_map_.find(id_namespace);
+  auto iter = namespace_client_map_.find(client_id);
   if (iter == namespace_client_map_.end()) {
     auto insert_result = namespace_client_map_.insert(
-        std::make_pair(id_namespace, ClientSourceMapping()));
+        std::make_pair(client_id, ClientSourceMapping()));
     DCHECK(insert_result.second);
     iter = insert_result.first;
   }
@@ -163,11 +163,11 @@
     client->SetBeginFrameSource(iter->second.source);
 }
 
-void SurfaceManager::UnregisterSurfaceFactoryClient(uint32_t id_namespace) {
-  DCHECK_EQ(valid_surface_id_namespaces_.count(id_namespace), 1u);
-  DCHECK_EQ(namespace_client_map_.count(id_namespace), 1u);
+void SurfaceManager::UnregisterSurfaceFactoryClient(uint32_t client_id) {
+  DCHECK_EQ(valid_surface_client_ids_.count(client_id), 1u);
+  DCHECK_EQ(namespace_client_map_.count(client_id), 1u);
 
-  auto iter = namespace_client_map_.find(id_namespace);
+  auto iter = namespace_client_map_.find(client_id);
   if (iter->second.source)
     iter->second.client->SetBeginFrameSource(nullptr);
   iter->second.client = nullptr;
@@ -180,28 +180,28 @@
 }
 
 void SurfaceManager::RegisterBeginFrameSource(BeginFrameSource* source,
-                                              uint32_t id_namespace) {
+                                              uint32_t client_id) {
   DCHECK(source);
   DCHECK_EQ(registered_sources_.count(source), 0u);
-  DCHECK_EQ(valid_surface_id_namespaces_.count(id_namespace), 1u);
+  DCHECK_EQ(valid_surface_client_ids_.count(client_id), 1u);
 
-  registered_sources_[source] = id_namespace;
-  RecursivelyAttachBeginFrameSource(id_namespace, source);
+  registered_sources_[source] = client_id;
+  RecursivelyAttachBeginFrameSource(client_id, source);
 }
 
 void SurfaceManager::UnregisterBeginFrameSource(BeginFrameSource* source) {
   DCHECK(source);
   DCHECK_EQ(registered_sources_.count(source), 1u);
 
-  uint32_t id_namespace = registered_sources_[source];
+  uint32_t client_id = registered_sources_[source];
   registered_sources_.erase(source);
 
-  if (namespace_client_map_.count(id_namespace) == 0u)
+  if (namespace_client_map_.count(client_id) == 0u)
     return;
 
   // TODO(enne): these walks could be done in one step.
   // Remove this begin frame source from its subtree.
-  RecursivelyDetachBeginFrameSource(id_namespace, source);
+  RecursivelyDetachBeginFrameSource(client_id, source);
   // Then flush every remaining registered source to fix any sources that
   // became null because of the previous step but that have an alternative.
   for (auto source_iter : registered_sources_)
@@ -209,9 +209,9 @@
 }
 
 void SurfaceManager::RecursivelyAttachBeginFrameSource(
-    uint32_t id_namespace,
+    uint32_t client_id,
     BeginFrameSource* source) {
-  ClientSourceMapping& mapping = namespace_client_map_[id_namespace];
+  ClientSourceMapping& mapping = namespace_client_map_[client_id];
   if (!mapping.source) {
     mapping.source = source;
     if (mapping.client)
@@ -222,9 +222,9 @@
 }
 
 void SurfaceManager::RecursivelyDetachBeginFrameSource(
-    uint32_t id_namespace,
+    uint32_t client_id,
     BeginFrameSource* source) {
-  auto iter = namespace_client_map_.find(id_namespace);
+  auto iter = namespace_client_map_.find(client_id);
   if (iter == namespace_client_map_.end())
     return;
   if (iter->second.source == source) {
@@ -263,8 +263,8 @@
 void SurfaceManager::RegisterSurfaceNamespaceHierarchy(
     uint32_t parent_namespace,
     uint32_t child_namespace) {
-  DCHECK_EQ(valid_surface_id_namespaces_.count(parent_namespace), 1u);
-  DCHECK_EQ(valid_surface_id_namespaces_.count(child_namespace), 1u);
+  DCHECK_EQ(valid_surface_client_ids_.count(parent_namespace), 1u);
+  DCHECK_EQ(valid_surface_client_ids_.count(child_namespace), 1u);
 
   // If it's possible to reach the parent through the child's descendant chain,
   // then this will create an infinite loop.  Might as well just crash here.
diff --git a/cc/surfaces/surface_manager.h b/cc/surfaces/surface_manager.h
index 24d82aa..d5c9ed0f 100644
--- a/cc/surfaces/surface_manager.h
+++ b/cc/surfaces/surface_manager.h
@@ -52,14 +52,13 @@
 
   // A frame for a surface satisfies a set of sequence numbers in a particular
   // id namespace.
-  void DidSatisfySequences(uint32_t id_namespace,
-                           std::vector<uint32_t>* sequence);
+  void DidSatisfySequences(uint32_t client_id, std::vector<uint32_t>* sequence);
 
-  void RegisterSurfaceIdNamespace(uint32_t id_namespace);
+  void RegisterSurfaceClientId(uint32_t client_id);
 
   // Invalidate a namespace that might still have associated sequences,
   // possibly because a renderer process has crashed.
-  void InvalidateSurfaceIdNamespace(uint32_t id_namespace);
+  void InvalidateSurfaceClientId(uint32_t client_id);
 
   // SurfaceFactoryClient, hierarchy, and BeginFrameSource can be registered
   // and unregistered in any order with respect to each other.
@@ -74,15 +73,14 @@
   // Caller guarantees the client is alive between register/unregister.
   // Reregistering the same namespace when a previous client is active is not
   // valid.
-  void RegisterSurfaceFactoryClient(uint32_t id_namespace,
+  void RegisterSurfaceFactoryClient(uint32_t client_id,
                                     SurfaceFactoryClient* client);
-  void UnregisterSurfaceFactoryClient(uint32_t id_namespace);
+  void UnregisterSurfaceFactoryClient(uint32_t client_id);
 
   // Associates a |source| with a particular namespace.  That namespace and
   // any children of that namespace with valid clients can potentially use
   // that |source|.
-  void RegisterBeginFrameSource(BeginFrameSource* source,
-                                uint32_t id_namespace);
+  void RegisterBeginFrameSource(BeginFrameSource* source, uint32_t client_id);
   void UnregisterBeginFrameSource(BeginFrameSource* source);
 
   // Register a relationship between two namespaces.  This relationship means
@@ -95,9 +93,9 @@
                                            uint32_t child_namespace);
 
  private:
-  void RecursivelyAttachBeginFrameSource(uint32_t id_namespace,
+  void RecursivelyAttachBeginFrameSource(uint32_t client_id,
                                          BeginFrameSource* source);
-  void RecursivelyDetachBeginFrameSource(uint32_t id_namespace,
+  void RecursivelyDetachBeginFrameSource(uint32_t client_id,
                                          BeginFrameSource* source);
   // Returns true if |child namespace| is or has |search_namespace| as a child.
   bool ChildContains(uint32_t child_namespace, uint32_t search_namespace) const;
@@ -121,7 +119,7 @@
   // Set of valid surface ID namespaces. When a namespace is removed from
   // this set, any remaining sequences with that namespace are considered
   // satisfied.
-  std::unordered_set<uint32_t> valid_surface_id_namespaces_;
+  std::unordered_set<uint32_t> valid_surface_client_ids_;
 
   // Begin frame source routing. Both BeginFrameSource and SurfaceFactoryClient
   // pointers guaranteed alive by callers until unregistered.
diff --git a/cc/surfaces/surface_manager_unittest.cc b/cc/surfaces/surface_manager_unittest.cc
index 05edb02..9c29094 100644
--- a/cc/surfaces/surface_manager_unittest.cc
+++ b/cc/surfaces/surface_manager_unittest.cc
@@ -73,12 +73,12 @@
 
   SurfaceManagerTest() {
     for (size_t i = 0; i < MAX_NAMESPACE; ++i)
-      manager_.RegisterSurfaceIdNamespace(i);
+      manager_.RegisterSurfaceClientId(i);
   }
 
   ~SurfaceManagerTest() override {
     for (size_t i = 0; i < MAX_NAMESPACE; ++i)
-      manager_.InvalidateSurfaceIdNamespace(i);
+      manager_.InvalidateSurfaceClientId(i);
   }
 
  protected:
diff --git a/cc/surfaces/surface_sequence.h b/cc/surfaces/surface_sequence.h
index 9027ea13..fa0a8c8 100644
--- a/cc/surfaces/surface_sequence.h
+++ b/cc/surfaces/surface_sequence.h
@@ -18,17 +18,17 @@
 // dependencies between frames. A sequence number may be satisfied once, and
 // may be depended on once.
 struct SurfaceSequence {
-  SurfaceSequence() : id_namespace(0u), sequence(0u) {}
-  SurfaceSequence(uint32_t id_namespace, uint32_t sequence)
-      : id_namespace(id_namespace), sequence(sequence) {}
-  bool is_null() const { return id_namespace == 0u && sequence == 0u; }
+  SurfaceSequence() : client_id(0u), sequence(0u) {}
+  SurfaceSequence(uint32_t client_id, uint32_t sequence)
+      : client_id(client_id), sequence(sequence) {}
+  bool is_null() const { return client_id == 0u && sequence == 0u; }
 
-  uint32_t id_namespace;
+  uint32_t client_id;
   uint32_t sequence;
 };
 
 inline bool operator==(const SurfaceSequence& a, const SurfaceSequence& b) {
-  return a.id_namespace == b.id_namespace && a.sequence == b.sequence;
+  return a.client_id == b.client_id && a.sequence == b.sequence;
 }
 
 inline bool operator!=(const SurfaceSequence& a, const SurfaceSequence& b) {
@@ -36,13 +36,12 @@
 }
 
 inline bool operator<(const SurfaceSequence& a, const SurfaceSequence& b) {
-  return std::tie(a.id_namespace, a.sequence) <
-         std::tie(b.id_namespace, b.sequence);
+  return std::tie(a.client_id, a.sequence) < std::tie(b.client_id, b.sequence);
 }
 
 struct SurfaceSequenceHash {
   size_t operator()(SurfaceSequence key) const {
-    return base::HashInts(key.id_namespace, key.sequence);
+    return base::HashInts(key.client_id, key.sequence);
   }
 };
 
diff --git a/cc/surfaces/surface_unittest.cc b/cc/surfaces/surface_unittest.cc
index d4ac06e..0fe4f7d 100644
--- a/cc/surfaces/surface_unittest.cc
+++ b/cc/surfaces/surface_unittest.cc
@@ -14,6 +14,8 @@
 namespace cc {
 namespace {
 
+static constexpr uint32_t kArbitraryClientId = 0;
+
 class FakeSurfaceFactoryClient : public SurfaceFactoryClient {
  public:
   FakeSurfaceFactoryClient() : begin_frame_source_(nullptr) {}
@@ -35,7 +37,7 @@
   FakeSurfaceFactoryClient surface_factory_client;
   SurfaceFactory factory(&manager, &surface_factory_client);
 
-  SurfaceId surface_id(0, 6, 0);
+  SurfaceId surface_id(kArbitraryClientId, 6, 0);
   {
     factory.Create(surface_id);
     EXPECT_TRUE(manager.GetSurfaceForId(surface_id));
@@ -46,14 +48,14 @@
 }
 
 TEST(SurfaceTest, SurfaceIds) {
-  uint32_t namespaces[] = {0u, 37u, ~0u};
+  uint32_t client_ids[] = {0u, 37u, ~0u};
   for (size_t i = 0; i < 3; ++i) {
-    uint32_t id_namespace = namespaces[i];
-    SurfaceIdAllocator allocator(id_namespace);
+    uint32_t client_id = client_ids[i];
+    SurfaceIdAllocator allocator(client_id);
     SurfaceId id1 = allocator.GenerateId();
-    EXPECT_EQ(id1.id_namespace(), id_namespace);
+    EXPECT_EQ(id1.client_id(), client_id);
     SurfaceId id2 = allocator.GenerateId();
-    EXPECT_EQ(id2.id_namespace(), id_namespace);
+    EXPECT_EQ(id2.client_id(), client_id);
     EXPECT_NE(id1.local_id(), id2.local_id());
     EXPECT_NE(id1.nonce(), id2.nonce());
   }
diff --git a/cc/surfaces/surfaces_pixeltest.cc b/cc/surfaces/surfaces_pixeltest.cc
index ae2c9ba4..a52964c 100644
--- a/cc/surfaces/surfaces_pixeltest.cc
+++ b/cc/surfaces/surfaces_pixeltest.cc
@@ -21,6 +21,8 @@
 namespace cc {
 namespace {
 
+static constexpr uint32_t kArbitraryClientId = 1u;
+
 class EmptySurfaceFactoryClient : public SurfaceFactoryClient {
  public:
   void ReturnResources(const ReturnedResourceArray& resources) override {}
@@ -29,7 +31,8 @@
 
 class SurfacesPixelTest : public RendererPixelTest<GLRenderer> {
  public:
-  SurfacesPixelTest() : allocator_(1u), factory_(&manager_, &client_) {}
+  SurfacesPixelTest()
+      : allocator_(kArbitraryClientId), factory_(&manager_, &client_) {}
 
  protected:
   SurfaceManager manager_;
diff --git a/cc/test/pixel_test_delegating_output_surface.cc b/cc/test/pixel_test_delegating_output_surface.cc
index cc63498..9d5aaf14 100644
--- a/cc/test/pixel_test_delegating_output_surface.cc
+++ b/cc/test/pixel_test_delegating_output_surface.cc
@@ -21,7 +21,7 @@
 #include "cc/test/pixel_test_software_output_device.h"
 #include "cc/test/test_in_process_context_provider.h"
 
-static constexpr uint32_t kCompositorSurfaceNamespace = 1;
+static constexpr uint32_t kCompositorClientId = 1;
 
 namespace cc {
 
@@ -46,14 +46,13 @@
       renderer_settings_(renderer_settings),
       display_context_provider_(std::move(display_context_provider)),
       surface_manager_(new SurfaceManager),
-      surface_id_allocator_(
-          new SurfaceIdAllocator(kCompositorSurfaceNamespace)),
+      surface_id_allocator_(new SurfaceIdAllocator(kCompositorClientId)),
       surface_factory_(new SurfaceFactory(surface_manager_.get(), this)),
       weak_ptrs_(this) {
   capabilities_.delegated_rendering = true;
   capabilities_.can_force_reclaim_resources = allow_force_reclaim_resources_;
 
-  surface_id_allocator_->RegisterSurfaceIdNamespace(surface_manager_.get());
+  surface_id_allocator_->RegisterSurfaceClientId(surface_manager_.get());
 }
 
 PixelTestDelegatingOutputSurface::~PixelTestDelegatingOutputSurface() {}
@@ -64,7 +63,7 @@
     return false;
 
   surface_manager_->RegisterSurfaceFactoryClient(
-      surface_id_allocator_->id_namespace(), this);
+      surface_id_allocator_->client_id(), this);
 
   // The PixelTestOutputSurface is owned by the Display.
   std::unique_ptr<PixelTestOutputSurface> output_surface;
@@ -98,7 +97,7 @@
   display_.reset(new Display(
       surface_manager_.get(), shared_bitmap_manager_,
       gpu_memory_buffer_manager_, renderer_settings_,
-      surface_id_allocator_->id_namespace(), std::move(begin_frame_source),
+      surface_id_allocator_->client_id(), std::move(begin_frame_source),
       std::move(output_surface), std::move(scheduler),
       base::MakeUnique<TextureMailboxDeleter>(task_runner)));
   display_->SetEnlargePassTextureAmountForTesting(enlarge_pass_texture_amount_);
@@ -111,7 +110,7 @@
   if (!delegated_surface_id_.is_null())
     surface_factory_->Destroy(delegated_surface_id_);
   surface_manager_->UnregisterSurfaceFactoryClient(
-      surface_id_allocator_->id_namespace());
+      surface_id_allocator_->client_id());
 
   display_ = nullptr;
   surface_factory_ = nullptr;
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index a9d4e06..4cdf670d 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -250,7 +250,7 @@
       gpu_memory_buffer_manager_(params->gpu_memory_buffer_manager),
       task_graph_runner_(params->task_graph_runner),
       image_serialization_processor_(params->image_serialization_processor),
-      surface_id_namespace_(0u),
+      surface_client_id_(0u),
       next_surface_sequence_(1u) {
   DCHECK(task_graph_runner_);
 
@@ -1296,12 +1296,12 @@
     swap_promise->OnCommit();
 }
 
-void LayerTreeHost::set_surface_id_namespace(uint32_t id_namespace) {
-  surface_id_namespace_ = id_namespace;
+void LayerTreeHost::set_surface_client_id(uint32_t client_id) {
+  surface_client_id_ = client_id;
 }
 
 SurfaceSequence LayerTreeHost::CreateSurfaceSequence() {
-  return SurfaceSequence(surface_id_namespace_, next_surface_sequence_++);
+  return SurfaceSequence(surface_client_id_, next_surface_sequence_++);
 }
 
 void LayerTreeHost::SetLayerTreeMutator(
@@ -1587,7 +1587,7 @@
 
   property_trees_.ToProtobuf(proto->mutable_property_trees());
 
-  proto->set_surface_id_namespace(surface_id_namespace_);
+  proto->set_surface_client_id(surface_client_id_);
   proto->set_next_surface_sequence(next_surface_sequence_);
 
   TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
@@ -1689,7 +1689,7 @@
     layer->set_property_tree_sequence_number(seq_num);
   });
 
-  surface_id_namespace_ = proto.surface_id_namespace();
+  surface_client_id_ = proto.surface_client_id();
   next_surface_sequence_ = proto.next_surface_sequence();
 }
 
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index cf52e948..25a1d83 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -339,7 +339,7 @@
 
   size_t num_queued_swap_promises() const { return swap_promise_list_.size(); }
 
-  void set_surface_id_namespace(uint32_t id_namespace);
+  void set_surface_client_id(uint32_t client_id);
   SurfaceSequence CreateSurfaceSequence();
 
   PropertyTrees* property_trees() { return &property_trees_; }
@@ -598,7 +598,7 @@
   // Set of layers that need to push properties.
   std::unordered_set<Layer*> layers_that_should_push_properties_;
 
-  uint32_t surface_id_namespace_;
+  uint32_t surface_client_id_;
   uint32_t next_surface_sequence_;
 
   DISALLOW_COPY_AND_ASSIGN(LayerTreeHost);
diff --git a/cc/trees/layer_tree_host_unittest_serialization.cc b/cc/trees/layer_tree_host_unittest_serialization.cc
index 59bc7016..becf0f3 100644
--- a/cc/trees/layer_tree_host_unittest_serialization.cc
+++ b/cc/trees/layer_tree_host_unittest_serialization.cc
@@ -206,8 +206,8 @@
               layer_tree_host_dst_->selection_);
     EXPECT_EQ(layer_tree_host_src_->property_trees_,
               layer_tree_host_dst_->property_trees_);
-    EXPECT_EQ(layer_tree_host_src_->surface_id_namespace_,
-              layer_tree_host_dst_->surface_id_namespace_);
+    EXPECT_EQ(layer_tree_host_src_->surface_client_id_,
+              layer_tree_host_dst_->surface_client_id_);
     EXPECT_EQ(layer_tree_host_src_->next_surface_sequence_,
               layer_tree_host_dst_->next_surface_sequence_);
 
@@ -293,8 +293,8 @@
     layer_tree_host_src_->property_trees_.sequence_number =
         layer_tree_host_src_->property_trees_.sequence_number * 3 + 1;
 
-    layer_tree_host_src_->surface_id_namespace_ =
-        layer_tree_host_src_->surface_id_namespace_ * 3 + 1;
+    layer_tree_host_src_->surface_client_id_ =
+        layer_tree_host_src_->surface_client_id_ * 3 + 1;
     layer_tree_host_src_->next_surface_sequence_ =
         layer_tree_host_src_->next_surface_sequence_ * 3 + 1;
 
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn
index 1c26c3f..cc77145 100644
--- a/chrome/BUILD.gn
+++ b/chrome/BUILD.gn
@@ -56,6 +56,32 @@
   }
 }
 
+# This target exists above chrome and it's main components in the dependency
+# tree as a central place to put assert_no_deps annotations. Since this depends
+# on Chrome and the main DLLs it uses, it will transitively assert that those
+# targets also have no deps on disallowed things.
+group("assert_no_deps") {
+  deps = []
+
+  if (is_android) {
+    deps += [ "//chrome/android:chrome_public_apk" ]
+  } else {
+    deps += [ ":chrome" ]
+  }
+
+  if (is_win) {
+    deps += [
+      ":chrome_dll",
+      ":main_dll",
+    ]
+  }
+
+  # This should not pull in installer strings. This is will bloat the binary
+  # for no reason and is easy to mess up. See the comment at the top of
+  # //chrome/installer/util/BUILD.gn.
+  assert_no_deps = [ "//chrome/installer/util:strings" ]
+}
+
 if (!is_android && !is_mac) {
   group("chrome") {
     public_deps = [
@@ -1094,7 +1120,7 @@
   } else {
     group("chrome_dump_syms") {
     }
-    group("chrome_symbol_archive") {
+    group("chrome_dsym_archive") {
     }
   }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/banners/AppBannerManager.java b/chrome/android/java/src/org/chromium/chrome/browser/banners/AppBannerManager.java
index 19f4531..b3e0dea 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/banners/AppBannerManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/banners/AppBannerManager.java
@@ -12,44 +12,50 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.chrome.browser.ShortcutHelper;
-import org.chromium.chrome.browser.tab.EmptyTabObserver;
-import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.content_public.browser.WebContents;
 
 /**
  * Manages an AppBannerInfoBar for a Tab.
  *
- * The AppBannerManager manages a single AppBannerInfoBar, creating a new one when it detects that
- * the current webpage is requesting a banner to be built. The actual observation of the WebContents
- * (which triggers the automatic creation and removal of banners, among other things) is done by the
- * native-side AppBannerManager.
- *
- * This Java-side class owns its native-side counterpart, which is basically used to grab resources
- * from the network.
+ * The AppBannerManager is responsible for fetching details about native apps to display in the
+ * banner. The actual observation of the WebContents (which triggers the automatic creation and
+ * removal of banners, among other things) is done by the native-side AppBannerManagerAndroid.
  */
 @JNINamespace("banners")
-public class AppBannerManager extends EmptyTabObserver {
+public class AppBannerManager {
     private static final String TAG = "AppBannerManager";
 
     /** Retrieves information about a given package. */
     private static AppDetailsDelegate sAppDetailsDelegate;
 
-    /** Whether the banners are enabled. */
-    private static Boolean sIsEnabled;
+    /** Whether add to home screen is permitted by the system. */
+    private static Boolean sIsSupported;
+
+    /** Whether the tab to which this manager is attached to is permitted to show banners. */
+    private boolean mIsEnabledForTab;
 
     /** Pointer to the native side AppBannerManager. */
     private long mNativePointer;
 
     /**
-     * Checks if app banners are enabled.
-     * @return True if banners are enabled, false otherwise.
+     * Checks if the add to home screen intent is supported.
+     * @return true if add to home screen is supported, false otherwise.
      */
-    public static boolean isEnabled() {
-        if (sIsEnabled == null) {
+    public static boolean isSupported() {
+        if (sIsSupported == null) {
             Context context = ContextUtils.getApplicationContext();
-            sIsEnabled = ShortcutHelper.isAddToHomeIntentSupported(context);
+            sIsSupported = ShortcutHelper.isAddToHomeIntentSupported(context);
         }
-        return sIsEnabled;
+        return sIsSupported;
+    }
+
+    /**
+     * Checks if app banners are enabled for the tab which this manager is attached to.
+     * @return true if app banners can be shown for this tab, false otherwise.
+     */
+    @CalledByNative
+    private boolean isEnabledForTab() {
+        return isSupported() && mIsEnabledForTab;
     }
 
     /**
@@ -62,41 +68,25 @@
     }
 
     /**
-     * Constructs an AppBannerManager for the given tab.
-     * @param tab Tab that the AppBannerManager will be attached to.
+     * Constructs an AppBannerManager.
+     * @param nativePointer the native-side object that owns this AppBannerManager.
      */
-    public AppBannerManager(Tab tab, Context context) {
-        mNativePointer = nativeInit();
-        updatePointers(tab);
+    private AppBannerManager(long nativePointer) {
+        mNativePointer = nativePointer;
+        mIsEnabledForTab = isSupported();
     }
 
-    @Override
-    public void onWebContentsSwapped(Tab tab, boolean didStartLoad,
-            boolean didFinishLoad) {
-        updatePointers(tab);
+    @CalledByNative
+    private static AppBannerManager create(long nativePointer) {
+        return new AppBannerManager(nativePointer);
     }
 
-    @Override
-    public void onContentChanged(Tab tab) {
-        updatePointers(tab);
-    }
-
-    /**
-     * Destroys the native AppBannerManager.
-     */
-    public void destroy() {
-        nativeDestroy(mNativePointer);
+    @CalledByNative
+    private void destroy() {
         mNativePointer = 0;
     }
 
     /**
-     * Updates which WebContents the native AppBannerManager is monitoring.
-     */
-    private void updatePointers(Tab tab) {
-        nativeReplaceWebContents(mNativePointer, tab.getWebContents());
-    }
-
-    /**
      * Grabs package information for the banner asynchronously.
      * @param url         URL for the page that is triggering the banner.
      * @param packageName Name of the package that is being advertised.
@@ -133,15 +123,15 @@
         };
     }
 
-    /** Requests the app banner. This method is called from the DevTools. */
-    public void requestAppBanner() {
-        nativeRequestAppBanner(mNativePointer);
+    /** Enables or disables app banners. */
+    public void setIsEnabledForTab(boolean state) {
+        mIsEnabledForTab = state;
     }
 
-    /** Enables or disables the app banners for testing. */
+    /** Overrides whether the system supports add to home screen. Used in testing. */
     @VisibleForTesting
-    static void setIsEnabledForTesting(boolean state) {
-        sIsEnabled = state;
+    public static void setIsSupported(boolean state) {
+        sIsSupported = state;
     }
 
     /** Sets a constant (in days) that gets added to the time when the current time is requested. */
@@ -162,19 +152,21 @@
         nativeSetEngagementWeights(directEngagement, indirectEngagement);
     }
 
-    /** Returns whether a AppBannerDataFetcher is actively retrieving data. */
+    /** Returns whether an AppBannerDataFetcher is actively retrieving data. */
     @VisibleForTesting
     public boolean isFetcherActiveForTesting() {
         return nativeIsFetcherActive(mNativePointer);
     }
 
-    private native long nativeInit();
-    private native void nativeDestroy(long nativeAppBannerManagerAndroid);
-    private native void nativeReplaceWebContents(long nativeAppBannerManagerAndroid,
+    /** Returns the AppBannerManager object. This is owned by the C++ banner manager. */
+    public static AppBannerManager getAppBannerManagerForWebContents(WebContents webContents) {
+        return nativeGetJavaBannerManagerForWebContents(webContents);
+    }
+
+    private static native AppBannerManager nativeGetJavaBannerManagerForWebContents(
             WebContents webContents);
     private native boolean nativeOnAppDetailsRetrieved(long nativeAppBannerManagerAndroid,
             AppData data, String title, String packageName, String imageUrl);
-    private native void nativeRequestAppBanner(long nativeAppBannerManagerAndroid);
 
     // Testing methods.
     private static native void nativeSetTimeDeltaForTesting(int days);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabDelegateFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabDelegateFactory.java
index 0d4c76cd..0ab18c1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabDelegateFactory.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabDelegateFactory.java
@@ -13,7 +13,6 @@
 
 import org.chromium.base.Log;
 import org.chromium.base.VisibleForTesting;
-import org.chromium.chrome.browser.banners.AppBannerManager;
 import org.chromium.chrome.browser.contextmenu.ChromeContextMenuPopulator;
 import org.chromium.chrome.browser.contextmenu.ContextMenuPopulator;
 import org.chromium.chrome.browser.externalnav.ExternalNavigationDelegateImpl;
@@ -196,7 +195,7 @@
     }
 
     @Override
-    public AppBannerManager createAppBannerManager(Tab tab) {
-        return null;
+    public boolean canShowAppBanners(Tab tab) {
+        return false;
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/MostVisitedItem.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/MostVisitedItem.java
index 2cb6ca9..1eaecdb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/MostVisitedItem.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/MostVisitedItem.java
@@ -53,6 +53,8 @@
     private boolean mOfflineAvailable;
     private int mIndex;
     private int mTileType;
+    private int mSource;
+    private int mProviderIndex;
     private View mView;
 
     /**
@@ -66,9 +68,13 @@
      *                          visited item. Empty otherwise.
      * @param offlineAvailable Whether there is an offline copy of the URL available.
      * @param index The index of this item in the list of most visited items.
+     * @param source The {@link MostVisitedSource} that generated this item.
+     * @param providerIndex If this item comes from {@code MostVisitedSource.SUGGESTIONS_SERVICE},
+     *     this is the index of the source of the suggestion.
      */
     public MostVisitedItem(MostVisitedItemManager manager, String title, String url,
-            String whitelistIconPath, boolean offlineAvailable, int index) {
+            String whitelistIconPath, boolean offlineAvailable, int index, int source,
+            int providerIndex) {
         mManager = manager;
         mTitle = title;
         mUrl = url;
@@ -76,6 +82,8 @@
         mOfflineAvailable = offlineAvailable;
         mIndex = index;
         mTileType = MostVisitedTileType.NONE;
+        mSource = source;
+        mProviderIndex = index;
     }
 
     /**
@@ -154,6 +162,21 @@
         mTileType = type;
     }
 
+    /**
+     * @return The source of this item.  Used for metrics tracking. Valid values are listed in
+     * {@link MostVisitedSource}.
+     */
+    public int getSource() {
+        return mSource;
+    }
+
+    /**
+     * @return The provider index of this item.  Used for metrics tracking.
+     */
+    public int getProviderIndex() {
+        return mProviderIndex;
+    }
+
     @Override
     public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
         mManager.onCreateContextMenu(menu, this);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
index 7055300b..810ef0b8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
@@ -502,10 +502,16 @@
             if (!mTab.isHidden()) recordNTPShown();
 
             int tileTypes[] = new int[items.length];
+            int sources[] = new int[items.length];
+            int providerIndices[] = new int[items.length];
+
             for (int i = 0; i < items.length; i++) {
                 tileTypes[i] = items[i].getTileType();
+                sources[i] = items[i].getSource();
+                providerIndices[i] = items[i].getProviderIndex();
             }
-            mMostVisitedSites.recordTileTypeMetrics(tileTypes);
+
+            mMostVisitedSites.recordTileTypeMetrics(tileTypes, sources, providerIndices);
 
             if (isNtpOfflinePagesEnabled()) {
                 final int maxNumTiles = 12;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
index 4ddbb0c9..66e0e37e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
@@ -815,8 +815,8 @@
     // MostVisitedURLsObserver implementation
 
     @Override
-    public void onMostVisitedURLsAvailable(
-            final String[] titles, final String[] urls, final String[] whitelistIconPaths) {
+    public void onMostVisitedURLsAvailable(final String[] titles, final String[] urls,
+            final String[] whitelistIconPaths, final int[] sources, final int[] providerIndexes) {
         Set<String> urlSet = new HashSet<>(Arrays.asList(urls));
 
         // TODO(https://crbug.com/607573): We should show offline-available content in a nonblocking
@@ -825,13 +825,15 @@
         mManager.getUrlsAvailableOffline(urlSet, new Callback<Set<String>>() {
             @Override
             public void onResult(Set<String> offlineUrls) {
-                onOfflineUrlsAvailable(titles, urls, whitelistIconPaths, offlineUrls);
+                onOfflineUrlsAvailable(
+                        titles, urls, whitelistIconPaths, offlineUrls, sources, providerIndexes);
             }
         });
     }
 
     private void onOfflineUrlsAvailable(final String[] titles, final String[] urls,
-            final String[] whitelistIconPaths, final Set<String> offlineUrls) {
+            final String[] whitelistIconPaths, final Set<String> offlineUrls, final int[] sources,
+            final int[] providerIndexes) {
         mMostVisitedLayout.removeAllViews();
 
         MostVisitedItem[] oldItems = mMostVisitedItems;
@@ -846,6 +848,9 @@
             final String url = urls[i];
             final String title = titles[i];
             final String whitelistIconPath = whitelistIconPaths[i];
+            final int source = sources[i];
+            final int providerIndex = providerIndexes[i];
+
             boolean offlineAvailable = offlineUrls.contains(url);
 
             // Look for an existing item to reuse.
@@ -865,8 +870,8 @@
 
             // If nothing can be reused, create a new item.
             if (item == null) {
-                item = new MostVisitedItem(
-                        mManager, title, url, whitelistIconPath, offlineAvailable, i);
+                item = new MostVisitedItem(mManager, title, url, whitelistIconPath,
+                        offlineAvailable, i, source, providerIndex);
                 View view =
                         mMostVisitedDesign.createMostVisitedItemView(inflater, item, isInitialLoad);
                 item.initView(view);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/profiles/MostVisitedSites.java b/chrome/android/java/src/org/chromium/chrome/browser/profiles/MostVisitedSites.java
index c60da0ae..e9e02d5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/profiles/MostVisitedSites.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/profiles/MostVisitedSites.java
@@ -27,8 +27,8 @@
          *             visited URLs).
          */
         @CalledByNative("MostVisitedURLsObserver")
-        public void onMostVisitedURLsAvailable(
-                String[] titles, String[] urls, String[] whitelistIconPaths);
+        public void onMostVisitedURLsAvailable(String[] titles, String[] urls,
+                String[] whitelistIconPaths, int[] sources, int[] providerIndexes);
 
         /**
          * This is called when the list of popular URLs is initially available or updated.
@@ -72,11 +72,12 @@
     public void setMostVisitedURLsObserver(final MostVisitedURLsObserver observer, int numSites) {
         MostVisitedURLsObserver wrappedObserver = new MostVisitedURLsObserver() {
             @Override
-            public void onMostVisitedURLsAvailable(
-                    String[] titles, String[] urls, String[] whitelistIconPaths) {
+            public void onMostVisitedURLsAvailable(String[] titles, String[] urls,
+                    String[] whitelistIconPaths, int[] sources, int[] providerIndexes) {
                 // Don't notify observer if we've already been destroyed.
                 if (mNativeMostVisitedSitesBridge != 0) {
-                    observer.onMostVisitedURLsAvailable(titles, urls, whitelistIconPaths);
+                    observer.onMostVisitedURLsAvailable(
+                            titles, urls, whitelistIconPaths, sources, providerIndexes);
                 }
             }
             @Override
@@ -111,8 +112,9 @@
      * @param tileTypes An array of values from MostVisitedTileType indicating the type of each
      *                  tile that's currently showing.
      */
-    public void recordTileTypeMetrics(int[] tileTypes) {
-        nativeRecordTileTypeMetrics(mNativeMostVisitedSitesBridge, tileTypes);
+    public void recordTileTypeMetrics(int[] tileTypes, int[] sources, int[] providerIndices) {
+        nativeRecordTileTypeMetrics(
+                mNativeMostVisitedSitesBridge, tileTypes, sources, providerIndices);
     }
 
     /**
@@ -131,8 +133,8 @@
     private native void nativeAddOrRemoveBlacklistedUrl(
             long nativeMostVisitedSitesBridge, String url,
             boolean addUrl);
-    private native void nativeRecordTileTypeMetrics(
-            long nativeMostVisitedSitesBridge, int[] tileTypes);
+    private native void nativeRecordTileTypeMetrics(long nativeMostVisitedSitesBridge,
+            int[] tileTypes, int[] sources, int[] providerIndices);
     private native void nativeRecordOpenedMostVisitedItem(
             long nativeMostVisitedSitesBridge, int index, int tileType);
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
index b168c93..414dcbecd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
@@ -180,9 +180,6 @@
     /** InfoBar container to show InfoBars for this tab. */
     private InfoBarContainer mInfoBarContainer;
 
-    /** Manages app banners shown for this tab. */
-    private AppBannerManager mAppBannerManager;
-
     /** Controls overscroll pull-to-refresh behavior for this tab. */
     private SwipeRefreshHandler mSwipeRefreshHandler;
 
@@ -1435,11 +1432,6 @@
 
             RevenueStats.getInstance().tabCreated(this);
 
-            if (AppBannerManager.isEnabled()) {
-                mAppBannerManager = mDelegateFactory.createAppBannerManager(this);
-                if (mAppBannerManager != null) addObserver(mAppBannerManager);
-            }
-
             mTopControlsVisibilityDelegate =
                     mDelegateFactory.createTopControlsVisibilityDelegate(this);
 
@@ -1471,6 +1463,8 @@
             if (!creatingWebContents && webContents.isLoadingToDifferentDocument()) {
                 didStartPageLoad(webContents.getUrl(), false);
             }
+
+            getAppBannerManager().setIsEnabledForTab(mDelegateFactory.canShowAppBanners(this));
         } finally {
             if (mTimestampMillis == INVALID_TIMESTAMP) {
                 mTimestampMillis = System.currentTimeMillis();
@@ -1561,7 +1555,7 @@
                 mWebContentsDelegate, mDelegateFactory.createContextMenuPopulator(this));
         mTopControlsVisibilityDelegate = mDelegateFactory.createTopControlsVisibilityDelegate(this);
         setInterceptNavigationDelegate(mDelegateFactory.createInterceptNavigationDelegate(this));
-        mAppBannerManager = mDelegateFactory.createAppBannerManager(this);
+        getAppBannerManager().setIsEnabledForTab(mDelegateFactory.canShowAppBanners(this));
 
         // Reload the NativePage (if any), since the old NativePage has a reference to the old
         // activity.
@@ -2031,13 +2025,6 @@
             mInfoBarContainer = null;
         }
 
-        // Destroy the AppBannerManager after the InfoBarContainer because it monitors for infobar
-        // removals.
-        if (mAppBannerManager != null) {
-            mAppBannerManager.destroy();
-            mAppBannerManager = null;
-        }
-
         mPreviousFullscreenTopControlsOffsetY = Float.NaN;
         mPreviousFullscreenContentOffsetY = Float.NaN;
 
@@ -2528,13 +2515,6 @@
         }
     }
 
-    /** Requests the app banner. This method is called from the DevTools. */
-    protected boolean requestAppBanner() {
-        if (mAppBannerManager == null) return false;
-        mAppBannerManager.requestAppBanner();
-        return true;
-    }
-
     @CalledByNative
     private void clearNativePtr() {
         assert mNativeTabAndroid != 0;
@@ -3003,9 +2983,8 @@
     /**
      * @return the AppBannerManager.
      */
-    @VisibleForTesting
-    public AppBannerManager getAppBannerManagerForTesting() {
-        return mAppBannerManager;
+    public AppBannerManager getAppBannerManager() {
+        return AppBannerManager.getAppBannerManagerForWebContents(getWebContents());
     }
 
     @VisibleForTesting
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabDelegateFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabDelegateFactory.java
index ac731f2..25850127 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabDelegateFactory.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabDelegateFactory.java
@@ -4,7 +4,6 @@
 
 package org.chromium.chrome.browser.tab;
 
-import org.chromium.chrome.browser.banners.AppBannerManager;
 import org.chromium.chrome.browser.contextmenu.ChromeContextMenuPopulator;
 import org.chromium.chrome.browser.contextmenu.ContextMenuPopulator;
 import org.chromium.components.navigation_interception.InterceptNavigationDelegate;
@@ -43,12 +42,12 @@
     }
 
     /**
-     * Creates the {@link AppBannerManager} the tab will be initialized with.
+     * Return true if app banners are to be permitted in this tab.
      * @param tab The associated {@link Tab}.
-     * @return {@link AppBannerManager} to be used for the given tab. May be null.
+     * @return true if app banners are permitted, and false otherwise.
      */
-    public AppBannerManager createAppBannerManager(Tab tab) {
-        return new AppBannerManager(tab, tab.getApplicationContext());
+    public boolean canShowAppBanners(Tab tab) {
+        return true;
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java
index d485bfd..1193612 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java
@@ -343,11 +343,6 @@
         return success;
     }
 
-    @CalledByNative
-    private boolean requestAppBanner() {
-        return mTab.requestAppBanner();
-    }
-
     @Override
     public void activateContents() {
         boolean activityIsDestroyed = false;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java
index 28547bfb..b369549 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java
@@ -10,7 +10,6 @@
 import org.chromium.base.library_loader.LibraryProcessType;
 import org.chromium.chrome.browser.ChromeApplication;
 import org.chromium.chrome.browser.ShortcutHelper;
-import org.chromium.chrome.browser.banners.AppBannerManager;
 import org.chromium.chrome.browser.externalnav.ExternalNavigationParams;
 import org.chromium.chrome.browser.tab.InterceptNavigationDelegateImpl;
 import org.chromium.chrome.browser.tab.Tab;
@@ -103,11 +102,11 @@
             }
 
             @Override
-            public AppBannerManager createAppBannerManager(Tab tab) {
+            public boolean canShowAppBanners(Tab tab) {
                 // Do not show app banners for WebAPKs regardless of the current page URL.
                 // A WebAPK can display a page outside of its WebAPK scope if a page within the
                 // WebAPK scope navigates via JavaScript while the WebAPK is in the background.
-                return null;
+                return false;
             }
         };
     }
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index 87dc7e4..c9ed5982 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -30,7 +30,7 @@
   * Action bar items - 32 characters
 -->
 
-<grit current_release="1" latest_public_release="0">
+<grit current_release="1" latest_public_release="0" output_all_resource_defines="false">
   <outputs>
     <output filename="values-am/android_chrome_strings.xml" lang="am" type="android" />
     <output filename="values-ar/android_chrome_strings.xml" lang="ar" type="android" />
@@ -881,15 +881,15 @@
       <message name="IDS_DATA_REDUCTION_ENABLED_TOAST" desc="Toast message displayed after the user enables Data Saver from the promo" >
         Data Saver is on. Manage it in Settings.
       </message>
-      <message name="IDS_DATA_REDUCTION_PROMO_INFOBAR_TITLE" desc="Text to be displayed in the data reduction promo infobar title">  
+      <message name="IDS_DATA_REDUCTION_PROMO_INFOBAR_TITLE" desc="Text to be displayed in the data reduction promo infobar title">
         Save up to 60% of your data
-      </message>     
-      <message name="IDS_DATA_REDUCTION_PROMO_INFOBAR_TEXT" desc="Text to be displayed in the data reduction promo infobar">  
+      </message>
+      <message name="IDS_DATA_REDUCTION_PROMO_INFOBAR_TEXT" desc="Text to be displayed in the data reduction promo infobar">
         Google servers will optimize the pages you visit, except for HTTPS and Incognito.
       </message>
-      <message name="IDS_DATA_REDUCTION_PROMO_INFOBAR_BUTTON" desc="Text to be displayed in the data reduction promo infobar confirm button">  
+      <message name="IDS_DATA_REDUCTION_PROMO_INFOBAR_BUTTON" desc="Text to be displayed in the data reduction promo infobar confirm button">
         Turn on Data Saver
-      </message>   
+      </message>
 
       <!-- About Chrome preferences -->
       <message name="IDS_PREFS_ABOUT_CHROME" desc="Title for the About Chrome page. [CHAR-LIMIT=32]">
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 5fd2cca..16bd77d 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
@@ -172,7 +172,7 @@
     @Override
     protected void setUp() throws Exception {
         mPackageManager = new TestPackageManager();
-        AppBannerManager.setIsEnabledForTesting(true);
+        AppBannerManager.setIsSupported(true);
         AppBannerInfoBarDelegateAndroid.setPackageManagerForTesting(mPackageManager);
         ShortcutHelper.setDelegateForTests(new ShortcutHelper.Delegate() {
             @Override
@@ -223,8 +223,7 @@
         CriteriaHelper.pollUiThread(new Criteria() {
             @Override
             public boolean isSatisfied() {
-                AppBannerManager manager =
-                        getActivity().getActivityTab().getAppBannerManagerForTesting();
+                AppBannerManager manager = getActivity().getActivityTab().getAppBannerManager();
                 return mDetailsDelegate.mNumRetrieved == numExpected
                         && !manager.isFetcherActiveForTesting();
             }
@@ -313,8 +312,7 @@
         CriteriaHelper.pollUiThread(new Criteria() {
             @Override
             public boolean isSatisfied() {
-                AppBannerManager manager =
-                        getActivity().getActivityTab().getAppBannerManagerForTesting();
+                AppBannerManager manager = getActivity().getActivityTab().getAppBannerManager();
                 return !manager.isFetcherActiveForTesting();
             }
         });
@@ -326,8 +324,7 @@
         CriteriaHelper.pollUiThread(new Criteria() {
             @Override
             public boolean isSatisfied() {
-                AppBannerManager manager =
-                        getActivity().getActivityTab().getAppBannerManagerForTesting();
+                AppBannerManager manager = getActivity().getActivityTab().getAppBannerManager();
                 return !manager.isFetcherActiveForTesting();
             }
         });
@@ -486,8 +483,7 @@
         CriteriaHelper.pollUiThread(new Criteria() {
             @Override
             public boolean isSatisfied() {
-                AppBannerManager manager =
-                        getActivity().getActivityTab().getAppBannerManagerForTesting();
+                AppBannerManager manager = getActivity().getActivityTab().getAppBannerManager();
                 return !manager.isFetcherActiveForTesting();
             }
         });
@@ -504,8 +500,7 @@
         CriteriaHelper.pollUiThread(new Criteria() {
             @Override
             public boolean isSatisfied() {
-                AppBannerManager manager =
-                        getActivity().getActivityTab().getAppBannerManagerForTesting();
+                AppBannerManager manager = getActivity().getActivityTab().getAppBannerManager();
                 return !manager.isFetcherActiveForTesting();
             }
         });
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/FakeMostVisitedSites.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/FakeMostVisitedSites.java
index 617f727..99f6047 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/FakeMostVisitedSites.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/FakeMostVisitedSites.java
@@ -19,6 +19,8 @@
     private final String[] mMostVisitedTitles;
     private final String[] mMostVisitedUrls;
     private final String[] mMostVisitedWhitelistIconPaths;
+    private final int[] mMostVisitedSources;
+    private final int[] mMostVisitedProviderIndexes;
 
     private final List<String> mBlacklistedUrls = new ArrayList<String>();
 
@@ -28,12 +30,15 @@
      * @param mostVisitedUrls The URLs of the fixed list of most visited sites.
      */
     public FakeMostVisitedSites(Profile p, String[] mostVisitedTitles, String[] mostVisitedUrls,
-            String[] mostVisitedWhitelistIconPaths) {
+            String[] mostVisitedWhitelistIconPaths, int[] mostVisitedSources,
+            int[] mostVisitedProviderIndexes) {
         super(p);
         assert mostVisitedTitles.length == mostVisitedUrls.length;
         mMostVisitedTitles = mostVisitedTitles.clone();
         mMostVisitedUrls = mostVisitedUrls.clone();
         mMostVisitedWhitelistIconPaths = mostVisitedWhitelistIconPaths.clone();
+        mMostVisitedSources = mostVisitedSources.clone();
+        mMostVisitedProviderIndexes = mostVisitedProviderIndexes.clone();
     }
 
     @Override
@@ -42,7 +47,8 @@
             @Override
             public void run() {
                 observer.onMostVisitedURLsAvailable(mMostVisitedTitles.clone(),
-                        mMostVisitedUrls.clone(), mMostVisitedWhitelistIconPaths.clone());
+                        mMostVisitedUrls.clone(), mMostVisitedWhitelistIconPaths.clone(),
+                        mMostVisitedSources.clone(), mMostVisitedProviderIndexes.clone());
             }
         });
     }
@@ -65,7 +71,7 @@
     }
 
     @Override
-    public void recordTileTypeMetrics(int[] tileTypes) {
+    public void recordTileTypeMetrics(int[] tileTypes, int[] sources, int[] providerIndices) {
         // Metrics are stubbed out.
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
index 3a94395..41e7061 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
@@ -50,6 +50,8 @@
 
     private static final String[] FAKE_MOST_VISITED_TITLES = new String[] { "Simple" };
     private static final String[] FAKE_MOST_VISITED_WHITELIST_ICON_PATHS = new String[] { "" };
+    private static final int[] FAKE_MOST_VISITED_SOURCES = new int[] {MostVisitedSource.TOP_SITES};
+    private static final int[] FAKE_MOST_VISITED_PROVIDER_INDEXES = new int[] {0};
 
     private Tab mTab;
     private NewTabPage mNtp;
@@ -86,7 +88,8 @@
                     // native code.
                     mFakeMostVisitedSites =
                             new FakeMostVisitedSites(mTab.getProfile(), FAKE_MOST_VISITED_TITLES,
-                                    mFakeMostVisitedUrls, FAKE_MOST_VISITED_WHITELIST_ICON_PATHS);
+                                    mFakeMostVisitedUrls, FAKE_MOST_VISITED_WHITELIST_ICON_PATHS,
+                                    FAKE_MOST_VISITED_SOURCES, FAKE_MOST_VISITED_PROVIDER_INDEXES);
                 }
             });
         } catch (Throwable t) {
diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd
index eadfe62..71c53f77 100644
--- a/chrome/app/chromium_strings.grd
+++ b/chrome/app/chromium_strings.grd
@@ -3,7 +3,7 @@
 If you update this file, be sure also to update google_chrome_strings.grd. -->
 
 <grit base_dir="." latest_public_release="0" current_release="1"
-      source_lang_id="en" enc_check="möl">
+      output_all_resource_defines="false" source_lang_id="en" enc_check="möl">
   <outputs>
     <output filename="grit/chromium_strings.h" type="rc_header">
       <emit emit_type='prepend'></emit>
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index b3c9b5e4..5fe4708 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -8,7 +8,7 @@
 -->
 
 <grit base_dir="." latest_public_release="0" current_release="1"
-      source_lang_id="en" enc_check="möl">
+      output_all_resource_defines="false" source_lang_id="en" enc_check="möl">
   <outputs>
     <output filename="grit/generated_resources.h" type="rc_header">
       <emit emit_type='prepend'></emit>
@@ -4965,19 +4965,6 @@
         Keep changes
       </message>
 
-      <!-- chrome://settings-frame/options_settings_app.html for the App Launcher Settings App -->
-      <if expr="enable_settings_app">
-        <message name="IDS_SETTINGS_APP_LAUNCHER_PRODUCT_NAME" desc="Product name to use when referring to applications running in the App Launcher inside the non-browser Settings App">
-          App Launcher
-        </message>
-        <message name="IDS_SETTINGS_APP_PROFILES_SWITCH_BUTTON_LABEL" desc="The label that appears on the profile switch user button in the Settings App to allow a user to switch the app launcher profile to the current selection.">
-          Switch user
-        </message>
-        <message name="IDS_SETTINGS_APP_SYNC_OVERVIEW" desc="The message that appears in the non-browser Settings App when sync has not been set up by the user.">
-          Sign in with your Google Account to allow apps to synchronize settings and provide other customized services.
-        </message>
-      </if>
-
       <!-- Material Design version of chrome://policy -->
       <message name="IDS_FLAGS_ENABLE_MATERIAL_DESIGN_POLICY_PAGE_NAME" desc="Name for the flag to enable the material design policy page.">
           Enable Material Design policy page
@@ -6406,12 +6393,6 @@
         <message name="IDS_FLAGS_CENTERED_APP_LIST_DESCRIPTION" desc="Description of the flag to center the app launcher and make it wide instead of tall.">
           Positions the App Launcher in the center of the screen with a landscape aspect.
         </message>
-        <message name="IDS_FLAGS_NEW_APP_LIST_MIXER_NAME" desc="Name of the flag to enable the new mixing algorithm in the app launcher.">
-          New App Launcher mixer algorithm
-        </message>
-        <message name="IDS_FLAGS_NEW_APP_LIST_MIXER_DESCRIPTION" desc="Description of the flag to enable the new mixing algorithm in the app launcher.">
-          This enables a new search result selecting and ranking algorithm in the App Launcher.
-        </message>
       </if>
       <if expr="chromeos">
         <message name="IDS_FLAGS_FIRST_RUN_UI_TRANSITIONS_NAME" desc="Name of the flag to enable animated transitions for the first-run tutorial.">
@@ -14863,19 +14844,25 @@
 
     <if expr="not is_android and not is_ios">
       <!-- Device Chooser Prompt -->
-      <message name="IDS_DEVICE_CHOOSER_PROMPT" desc="The label that is used to introduce chooser details to the user in a popup.">
+      <message name="IDS_DEVICE_CHOOSER_PROMPT_ORIGIN" desc="The label that is used to introduce chooser details to the user in a popup when it is from a website.">
         <ph name="Origin">$1<ex>www.google.com</ex></ph> wants to connect to:
       </message>
+      <message name="IDS_DEVICE_CHOOSER_PROMPT_EXTENSION_NAME" desc="The label that is used to introduce chooser details to the user in a popup when it is from a Chrome extension.">
+        "<ph name="CHROME_EXTENSION_NAME">$1<ex>Chrome extension name</ex></ph>" wants to connect to:
+      </message>
       <message name="IDS_DEVICE_CHOOSER_NO_DEVICES_FOUND_PROMPT" desc="The label that is used to inform the user that no devices were found in the chooser popup.">
         No devices found.
       </message>
       <message name="IDS_DEVICE_CHOOSER_DEVICE_NAME_WITH_ID" desc="To distinguish devices with the same name, the device chooser shows the device name with id.">
         <ph name="DEVICE_NAME">$1<ex>device name</ex></ph> (<ph name="DEVICE_ID">$2<ex>device id</ex></ph>)
       </message>
-      <message name="IDS_DEVICE_CHOOSER_CONNECT_BUTTON_TEXT" desc="The text that is shown on the connect button in the chooser popup.">
+      <message name="IDS_BLUETOOTH_DEVICE_CHOOSER_PAIR_BUTTON_TEXT" desc="Label on the button that closes the Bluetooth chooser popup and pairs the selected device.">
+        Pair
+      </message>
+      <message name="IDS_USB_DEVICE_CHOOSER_CONNECT_BUTTON_TEXT" desc="Label on the button that closes the USB chooser popup and connects the selected device.">
         Connect
       </message>
-      <message name="IDS_DEVICE_CHOOSER_CANCEL_BUTTON_TEXT" desc="The text that is shown on the cancel button in the chooser popup.">
+      <message name="IDS_DEVICE_CHOOSER_CANCEL_BUTTON_TEXT" desc="Label on the button that closes the chooser popup without selecting an option.">
         Cancel
       </message>
       <message name="IDS_DEVICE_CHOOSER_FOOTNOTE_TEXT" desc="This text is shown at the bottom of the chooser popup with a link to part of its text.">
diff --git a/chrome/app/google_chrome_strings.grd b/chrome/app/google_chrome_strings.grd
index 5a11db3..a21bfaa 100644
--- a/chrome/app/google_chrome_strings.grd
+++ b/chrome/app/google_chrome_strings.grd
@@ -5,7 +5,7 @@
 chromium_strings.grd. -->
 
 <grit base_dir="." latest_public_release="0" current_release="1"
-      source_lang_id="en" enc_check="möl">
+      output_all_resource_defines="false" source_lang_id="en" enc_check="möl">
   <outputs>
     <output filename="grit/google_chrome_strings.h" type="rc_header">
       <emit emit_type='prepend'></emit>
diff --git a/chrome/app/resources/locale_settings.grd b/chrome/app/resources/locale_settings.grd
index b8264ad..d9cc66b74 100644
--- a/chrome/app/resources/locale_settings.grd
+++ b/chrome/app/resources/locale_settings.grd
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="0" current_release="1">
+<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
   <outputs>
     <output filename="grit/locale_settings.h" type="rc_header">
       <emit emit_type='prepend'></emit>
diff --git a/chrome/app/resources/locale_settings_chromiumos.grd b/chrome/app/resources/locale_settings_chromiumos.grd
index 4fd0bd28..16270a5 100644
--- a/chrome/app/resources/locale_settings_chromiumos.grd
+++ b/chrome/app/resources/locale_settings_chromiumos.grd
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="0" current_release="1">
+<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
   <outputs>
     <output filename="grit/platform_locale_settings.h" type="rc_header">
       <emit emit_type='prepend'></emit>
diff --git a/chrome/app/resources/locale_settings_google_chromeos.grd b/chrome/app/resources/locale_settings_google_chromeos.grd
index 8acea82..8153ec7 100644
--- a/chrome/app/resources/locale_settings_google_chromeos.grd
+++ b/chrome/app/resources/locale_settings_google_chromeos.grd
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="0" current_release="1">
+<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
   <outputs>
     <output filename="grit/platform_locale_settings.h" type="rc_header">
       <emit emit_type='prepend'></emit>
diff --git a/chrome/app/resources/locale_settings_linux.grd b/chrome/app/resources/locale_settings_linux.grd
index 77a261b9..495c925 100644
--- a/chrome/app/resources/locale_settings_linux.grd
+++ b/chrome/app/resources/locale_settings_linux.grd
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="0" current_release="1">
+<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
   <outputs>
     <output filename="grit/platform_locale_settings.h" type="rc_header">
       <emit emit_type='prepend'></emit>
diff --git a/chrome/app/resources/locale_settings_mac.grd b/chrome/app/resources/locale_settings_mac.grd
index 39f6d769..91d4b78 100644
--- a/chrome/app/resources/locale_settings_mac.grd
+++ b/chrome/app/resources/locale_settings_mac.grd
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="0" current_release="1">
+<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
   <outputs>
     <output filename="grit/platform_locale_settings.h" type="rc_header">
       <emit emit_type='prepend'></emit>
diff --git a/chrome/app/resources/locale_settings_win.grd b/chrome/app/resources/locale_settings_win.grd
index 219c9dde..a4bcf1d 100644
--- a/chrome/app/resources/locale_settings_win.grd
+++ b/chrome/app/resources/locale_settings_win.grd
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="0" current_release="1">
+<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
   <outputs>
     <output filename="grit/platform_locale_settings.h" type="rc_header">
       <emit emit_type='prepend'></emit>
diff --git a/chrome/app/settings_chromium_strings.grd b/chrome/app/settings_chromium_strings.grd
index df8a8f5..671f182c 100644
--- a/chrome/app/settings_chromium_strings.grd
+++ b/chrome/app/settings_chromium_strings.grd
@@ -7,7 +7,7 @@
 strings will begin to be translated.
 -->
 <grit base_dir="." latest_public_release="0" current_release="1"
-      source_lang_id="en" enc_check="möl">
+      output_all_resource_defines="false" source_lang_id="en" enc_check="möl">
   <outputs>
     <output filename="grit/settings_chromium_strings.h" type="rc_header">
       <emit emit_type='prepend'></emit>
diff --git a/chrome/app/settings_google_chrome_strings.grd b/chrome/app/settings_google_chrome_strings.grd
index 68c71e2..44e0013 100644
--- a/chrome/app/settings_google_chrome_strings.grd
+++ b/chrome/app/settings_google_chrome_strings.grd
@@ -7,7 +7,7 @@
 strings will begin to be translated.
 -->
 <grit base_dir="." latest_public_release="0" current_release="1"
-      source_lang_id="en" enc_check="möl">
+      output_all_resource_defines="false" source_lang_id="en" enc_check="möl">
   <outputs>
     <output filename="grit/settings_google_chrome_strings.h" type="rc_header">
       <emit emit_type='prepend'></emit>
diff --git a/chrome/app/settings_strings.grd b/chrome/app/settings_strings.grd
index 47fb06d..3ec4ed48 100644
--- a/chrome/app/settings_strings.grd
+++ b/chrome/app/settings_strings.grd
@@ -7,13 +7,12 @@
 strings will begin to be translated.
 -->
 <grit base_dir="." latest_public_release="0" current_release="1"
-      source_lang_id="en" enc_check="möl">
+      output_all_resource_defines="false" source_lang_id="en" enc_check="möl">
   <outputs>
     <output filename="grit/settings_strings.h" type="rc_header">
       <emit emit_type='prepend'></emit>
     </output>
       <output filename="settings_strings.pak" type="data_package"/>
-    
   </outputs>
 
   <release seq="1" allow_pseudo="false">
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 6e5d76a5..3c6d00f 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -985,6 +985,9 @@
   <message name="IDS_SETTINGS_SITE_SETTINGS_COOKIES" desc="Label for the cookies site settings.">
     Cookies
   </message>
+  <message name="IDS_SETTINGS_SITE_SETTINGS_HANDLERS" desc="Label for the protocol handlers (e.g. mailto) in site settings.">
+    Handlers
+  </message>
   <message name="IDS_SETTINGS_SITE_SETTINGS_LOCATION" desc="Label for the location site settings.">
     Location
   </message>
@@ -1069,6 +1072,15 @@
   <message name="IDS_SETTINGS_SITE_SETTINGS_BACKGROUND_SYNC_BLOCKED" desc="The block label for background sync in site settings.">
     Do not allow recently closed sites to finish sending and receiving data
   </message>
+  <message name="IDS_SETTINGS_SITE_SETTINGS_HANDLERS_ASK" desc="The allow label for protocol handlers in site settings.">
+    Allow sites to ask to become default handlers for protocols
+  </message>
+  <message name="IDS_SETTINGS_SITE_SETTINGS_HANDLERS_ASK_RECOMMENDED" desc="The allow label for protocol handlers in site settings (with the 'recommended' suffix).">
+    Allow sites to ask to become default handlers for protocols (recommended)
+  </message>
+  <message name="IDS_SETTINGS_SITE_SETTINGS_HANDLERS_BLOCKED" desc="The block label for protocol handlers in site settings.">
+    Do not allow any site to handle protocols
+  </message>
   <message name="IDS_SETTINGS_SITE_SETTINGS_KEYGEN_ALLOW" desc="The allow label for keygen in site settings.">
     Allow all sites to use key generation in forms
   </message>
@@ -1168,6 +1180,15 @@
   <message name="IDS_SETTINGS_SITE_SETTINGS_THIRD_PARTY_COOKIE_SUBLABEL" desc="A sub-label below the Block 3rd-party cookie checkbox.">
     Prevent third-party websites from saving and reading cookie data.
   </message>
+  <message name="IDS_SETTINGS_SITE_SETTINGS_HANDLER_IS_DEFAULT" desc="A label showing that a certain handler for a given protocol is the default.">
+    Default
+  </message>
+  <message name="IDS_SETTINGS_SITE_SETTINGS_HANDLER_SET_DEFAULT" desc="A label for the action of making a certain handler the default for a given protocol.">
+    Set as default
+  </message>
+  <message name="IDS_SETTINGS_SITE_SETTINGS_REMOVE" desc="A label for the action of removing (deleting) a certain handler.">
+    Remove
+  </message>
 
   <!-- Sync / People Page -->
   <message name="IDS_SETTINGS_PEOPLE" desc="Name of the settings page which manages Chrome's signed-in Google profile.">
diff --git a/chrome/app/theme/default_100_percent/settings_app_icon_128.png b/chrome/app/theme/default_100_percent/settings_app_icon_128.png
deleted file mode 100644
index 6d2ed790..0000000
--- a/chrome/app/theme/default_100_percent/settings_app_icon_128.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/settings_app_icon_16.png b/chrome/app/theme/default_100_percent/settings_app_icon_16.png
deleted file mode 100644
index 120c73c..0000000
--- a/chrome/app/theme/default_100_percent/settings_app_icon_16.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/settings_app_icon_32.png b/chrome/app/theme/default_100_percent/settings_app_icon_32.png
deleted file mode 100644
index ba61c5a..0000000
--- a/chrome/app/theme/default_100_percent/settings_app_icon_32.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/settings_app_icon_48.png b/chrome/app/theme/default_100_percent/settings_app_icon_48.png
deleted file mode 100644
index 38faff2..0000000
--- a/chrome/app/theme/default_100_percent/settings_app_icon_48.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/settings_app_icon_128.png b/chrome/app/theme/default_200_percent/settings_app_icon_128.png
deleted file mode 100644
index be4f20d4..0000000
--- a/chrome/app/theme/default_200_percent/settings_app_icon_128.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/settings_app_icon_16.png b/chrome/app/theme/default_200_percent/settings_app_icon_16.png
deleted file mode 100644
index ba61c5a..0000000
--- a/chrome/app/theme/default_200_percent/settings_app_icon_16.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/settings_app_icon_32.png b/chrome/app/theme/default_200_percent/settings_app_icon_32.png
deleted file mode 100644
index 8fa1f803..0000000
--- a/chrome/app/theme/default_200_percent/settings_app_icon_32.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/settings_app_icon_48.png b/chrome/app/theme/default_200_percent/settings_app_icon_48.png
deleted file mode 100644
index f5bb3c1a..0000000
--- a/chrome/app/theme/default_200_percent/settings_app_icon_48.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd
index f21c2dd8..9460b5d 100644
--- a/chrome/app/theme/theme_resources.grd
+++ b/chrome/app/theme/theme_resources.grd
@@ -759,12 +759,6 @@
       <if expr="chromeos">
         <structure type="chrome_scaled_image" name="IDR_SECONDARY_USER_SETTINGS" file="cros/secondary_user_settings.png" />
       </if>
-      <if expr="enable_settings_app">
-        <structure type="chrome_scaled_image" name="IDR_SETTINGS_APP_ICON_128" file="settings_app_icon_128.png" />
-        <structure type="chrome_scaled_image" name="IDR_SETTINGS_APP_ICON_16" file="settings_app_icon_16.png" />
-        <structure type="chrome_scaled_image" name="IDR_SETTINGS_APP_ICON_32" file="settings_app_icon_32.png" />
-        <structure type="chrome_scaled_image" name="IDR_SETTINGS_APP_ICON_48" file="settings_app_icon_48.png" />
-      </if>
       <structure type="chrome_scaled_image" name="IDR_SETTINGS_FAVICON" file="common/favicon_settings.png" />
       <structure type="chrome_scaled_image" name="IDR_STAR" file="common/star.png" />
       <structure type="chrome_scaled_image" name="IDR_STAR_LIT" file="common/star_lit.png" />
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 76d4fabf..e14c1d42 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -834,7 +834,6 @@
       "//chrome/chrome_watcher:client",
       "//chrome/common:metrics_constants_util_win",
       "//chrome/common:version_header",
-      "//chrome/installer/util:strings",
       "//chrome_elf",
       "//chrome_elf:constants",
       "//chrome_elf:dll_hash",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 62686c60..780b412 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1330,11 +1330,6 @@
     {"enable-centered-app-list", IDS_FLAGS_CENTERED_APP_LIST_NAME,
      IDS_FLAGS_CENTERED_APP_LIST_DESCRIPTION, kOsWin | kOsLinux | kOsCrOS,
      SINGLE_VALUE_TYPE(app_list::switches::kEnableCenteredAppList)},
-    {"enable-new-app-list-mixer", IDS_FLAGS_NEW_APP_LIST_MIXER_NAME,
-     IDS_FLAGS_NEW_APP_LIST_MIXER_DESCRIPTION,
-     kOsWin | kOsLinux | kOsCrOS | kOsMac,
-     ENABLE_DISABLE_VALUE_TYPE(app_list::switches::kEnableNewAppListMixer,
-                               app_list::switches::kDisableNewAppListMixer)},
 #endif
     {"disable-threaded-scrolling", IDS_FLAGS_THREADED_SCROLLING_NAME,
      IDS_FLAGS_THREADED_SCROLLING_DESCRIPTION, kOsAll,
diff --git a/chrome/browser/android/banners/app_banner_manager_android.cc b/chrome/browser/android/banners/app_banner_manager_android.cc
index 5556b54..5c8c44d 100644
--- a/chrome/browser/android/banners/app_banner_manager_android.cc
+++ b/chrome/browser/android/banners/app_banner_manager_android.cc
@@ -19,6 +19,8 @@
 using base::android::ConvertUTF8ToJavaString;
 using base::android::ConvertUTF16ToJavaString;
 
+DEFINE_WEB_CONTENTS_USER_DATA_KEY(banners::AppBannerManagerAndroid);
+
 namespace {
 
 const char kPlayPlatform[] = "play";
@@ -31,27 +33,65 @@
 namespace banners {
 
 AppBannerManagerAndroid::AppBannerManagerAndroid(
-    JNIEnv* env,
-    jobject obj)
-    : AppBannerManager(nullptr),
-      weak_java_banner_view_manager_(env, obj) {
+    content::WebContents* web_contents)
+    : AppBannerManager(web_contents) {
+  CreateJavaBannerManager();
 }
 
 AppBannerManagerAndroid::~AppBannerManagerAndroid() {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  Java_AppBannerManager_destroy(env, java_banner_manager_.obj());
+  java_banner_manager_.Reset();
 }
 
-void AppBannerManagerAndroid::Destroy(JNIEnv* env,
-                                      const JavaParamRef<jobject>& obj) {
-  delete this;
+const base::android::ScopedJavaGlobalRef<jobject>&
+AppBannerManagerAndroid::GetJavaBannerManager() const {
+  return java_banner_manager_;
 }
 
-void AppBannerManagerAndroid::ReplaceWebContents(
+bool AppBannerManagerAndroid::IsFetcherActive(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
+  return AppBannerManager::IsFetcherActive();
+}
+
+bool AppBannerManagerAndroid::OnAppDetailsRetrieved(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj,
-    const JavaParamRef<jobject>& jweb_contents) {
-  content::WebContents* web_contents =
-      content::WebContents::FromJavaWebContents(jweb_contents);
-  AppBannerManager::ReplaceWebContents(web_contents);
+    const JavaParamRef<jobject>& japp_data,
+    const JavaParamRef<jstring>& japp_title,
+    const JavaParamRef<jstring>& japp_package,
+    const JavaParamRef<jstring>& jicon_url) {
+  AppBannerDataFetcherAndroid* android_fetcher =
+      static_cast<AppBannerDataFetcherAndroid*>(data_fetcher().get());
+  if (!CheckFetcherMatchesContents(android_fetcher->is_debug_mode()))
+    return false;
+
+  GURL image_url = GURL(ConvertJavaStringToUTF8(env, jicon_url));
+
+  return android_fetcher->ContinueFetching(
+      ConvertJavaStringToUTF16(env, japp_title),
+      ConvertJavaStringToUTF8(env, japp_package), japp_data, image_url);
+}
+
+void AppBannerManagerAndroid::RequestAppBanner(const GURL& validated_url,
+                                               bool is_debug_mode) {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  if (!Java_AppBannerManager_isEnabledForTab(env, java_banner_manager_.obj()))
+    return;
+
+  AppBannerManager::RequestAppBanner(validated_url, is_debug_mode);
+}
+
+AppBannerDataFetcher* AppBannerManagerAndroid::CreateAppBannerDataFetcher(
+    base::WeakPtr<Delegate> weak_delegate,
+    bool is_debug_mode) {
+  return new AppBannerDataFetcherAndroid(
+      web_contents(), weak_delegate,
+      ShortcutHelper::GetIdealHomescreenIconSizeInDp(),
+      ShortcutHelper::GetMinimumHomescreenIconSizeInDp(),
+      ShortcutHelper::GetIdealSplashImageSizeInDp(),
+      ShortcutHelper::GetMinimumSplashImageSizeInDp(), is_debug_mode);
 }
 
 bool AppBannerManagerAndroid::HandleNonWebApp(const std::string& platform,
@@ -65,8 +105,7 @@
 
   // Send the info to the Java side to get info about the app.
   JNIEnv* env = base::android::AttachCurrentThread();
-  ScopedJavaLocalRef<jobject> jobj = weak_java_banner_view_manager_.get(env);
-  if (jobj.is_null())
+  if (java_banner_manager_.is_null())
     return false;
 
   std::string id_from_app_url = ExtractQueryValueForName(url, kIdName);
@@ -93,12 +132,32 @@
   ScopedJavaLocalRef<jstring> jreferrer(
       ConvertUTF8ToJavaString(env, referrer));
   Java_AppBannerManager_fetchAppDetails(
-      env, jobj.obj(), jurl.obj(),
+      env, java_banner_manager_.obj(), jurl.obj(),
       jpackage.obj(), jreferrer.obj(),
       ShortcutHelper::GetIdealHomescreenIconSizeInDp());
   return true;
 }
 
+void AppBannerManagerAndroid::CreateJavaBannerManager() {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  java_banner_manager_.Reset(
+      Java_AppBannerManager_create(env, reinterpret_cast<intptr_t>(this)));
+}
+
+bool AppBannerManagerAndroid::CheckFetcherMatchesContents(bool is_debug_mode) {
+  if (!web_contents())
+    return false;
+
+  if (!data_fetcher() ||
+      data_fetcher()->validated_url() != web_contents()->GetURL()) {
+    banners::OutputDeveloperNotShownMessage(
+        web_contents(), banners::kUserNavigatedBeforeBannerShown,
+        is_debug_mode);
+    return false;
+  }
+  return true;
+}
+
 bool AppBannerManagerAndroid::CheckPlatformAndId(const std::string& platform,
                                                  const std::string& id,
                                                  bool is_debug_mode) {
@@ -116,20 +175,6 @@
   return true;
 }
 
-bool AppBannerManagerAndroid::CheckFetcherMatchesContents(bool is_debug_mode) {
-  if (!web_contents())
-    return false;
-
-  if (!data_fetcher() ||
-      data_fetcher()->validated_url() != web_contents()->GetURL()) {
-    banners::OutputDeveloperNotShownMessage(
-        web_contents(), banners::kUserNavigatedBeforeBannerShown,
-        is_debug_mode);
-    return false;
-  }
-  return true;
-}
-
 std::string AppBannerManagerAndroid::ExtractQueryValueForName(
     const GURL& url,
     const std::string& name) {
@@ -146,72 +191,31 @@
   return "";
 }
 
-AppBannerDataFetcher* AppBannerManagerAndroid::CreateAppBannerDataFetcher(
-    base::WeakPtr<Delegate> weak_delegate,
-    bool is_debug_mode) {
-  return new AppBannerDataFetcherAndroid(
-      web_contents(), weak_delegate,
-      ShortcutHelper::GetIdealHomescreenIconSizeInDp(),
-      ShortcutHelper::GetMinimumHomescreenIconSizeInDp(),
-      ShortcutHelper::GetIdealSplashImageSizeInDp(),
-      ShortcutHelper::GetMinimumSplashImageSizeInDp(), is_debug_mode);
-}
-
-bool AppBannerManagerAndroid::OnAppDetailsRetrieved(
-    JNIEnv* env,
-    const JavaParamRef<jobject>& obj,
-    const JavaParamRef<jobject>& japp_data,
-    const JavaParamRef<jstring>& japp_title,
-    const JavaParamRef<jstring>& japp_package,
-    const JavaParamRef<jstring>& jicon_url) {
-  AppBannerDataFetcherAndroid* android_fetcher =
-      static_cast<AppBannerDataFetcherAndroid*>(data_fetcher().get());
-  if (!CheckFetcherMatchesContents(android_fetcher->is_debug_mode()))
-    return false;
-
-  GURL image_url = GURL(ConvertJavaStringToUTF8(env, jicon_url));
-
-  return android_fetcher->ContinueFetching(
-      ConvertJavaStringToUTF16(env, japp_title),
-      ConvertJavaStringToUTF8(env, japp_package), japp_data, image_url);
-}
-
-bool AppBannerManagerAndroid::IsFetcherActive(
-    JNIEnv* env,
-    const JavaParamRef<jobject>& obj) {
-  return AppBannerManager::IsFetcherActive();
-}
-
-void AppBannerManagerAndroid::RequestAppBanner(
-    JNIEnv* env,
-    const JavaParamRef<jobject>& obj) {
-  // Set debug mode to true as this method is only called from DevTools.
-  AppBannerManager::RequestAppBanner(web_contents()->GetLastCommittedURL(),
-                                     true /* is_debug_mode */);
-}
-
 // static
 bool AppBannerManagerAndroid::Register(JNIEnv* env) {
   return RegisterNativesImpl(env);
 }
 
-jlong Init(JNIEnv* env,
-           const JavaParamRef<jobject>& obj) {
-  AppBannerManagerAndroid* manager = new AppBannerManagerAndroid(env, obj);
-  return reinterpret_cast<intptr_t>(manager);
+// static
+ScopedJavaLocalRef<jobject> GetJavaBannerManagerForWebContents(
+    JNIEnv* env,
+    const JavaParamRef<jclass>& clazz,
+    const JavaParamRef<jobject>& java_web_contents) {
+  AppBannerManagerAndroid* manager = AppBannerManagerAndroid::FromWebContents(
+      content::WebContents::FromJavaWebContents(java_web_contents));
+  if (!manager)
+    return ScopedJavaLocalRef<jobject>();
+
+  return ScopedJavaLocalRef<jobject>(manager->GetJavaBannerManager());
 }
 
-void SetTimeDeltaForTesting(JNIEnv* env,
-                            const JavaParamRef<jclass>& clazz,
-                            jint days) {
-  AppBannerDataFetcher::SetTimeDeltaForTesting(days);
-}
-
+// static
 void DisableSecureSchemeCheckForTesting(JNIEnv* env,
                                         const JavaParamRef<jclass>& clazz) {
   AppBannerManager::DisableSecureSchemeCheckForTesting();
 }
 
+// static
 void SetEngagementWeights(JNIEnv* env,
                           const JavaParamRef<jclass>& clazz,
                           jdouble direct_engagement,
@@ -220,4 +224,11 @@
                                          indirect_engagement);
 }
 
+// static
+void SetTimeDeltaForTesting(JNIEnv* env,
+                            const JavaParamRef<jclass>& clazz,
+                            jint days) {
+  AppBannerDataFetcher::SetTimeDeltaForTesting(days);
+}
+
 }  // namespace banners
diff --git a/chrome/browser/android/banners/app_banner_manager_android.h b/chrome/browser/android/banners/app_banner_manager_android.h
index 69a2b78..d7f67684 100644
--- a/chrome/browser/android/banners/app_banner_manager_android.h
+++ b/chrome/browser/android/banners/app_banner_manager_android.h
@@ -12,31 +12,21 @@
 #include "chrome/browser/android/banners/app_banner_data_fetcher_android.h"
 #include "chrome/browser/banners/app_banner_debug_log.h"
 #include "chrome/browser/banners/app_banner_manager.h"
+#include "content/public/browser/web_contents_user_data.h"
 
 namespace banners {
 class AppBannerDataFetcherAndroid;
 
 // Extends the AppBannerManager to support native Android apps.
-// TODO(dfalcantara): Flip it so the C++ AppBannerManagerAndroid owns the
-// Java AppBannerManager, move ownership of the AppBannerManagerAndroid to
-// the TabAndroid class, then move functions for retriving info from Java to
-// the AppBannerDataFetcherAndroid.
-class AppBannerManagerAndroid : public AppBannerManager {
+class AppBannerManagerAndroid
+    : public AppBannerManager,
+      public content::WebContentsUserData<AppBannerManagerAndroid> {
  public:
-  // Registers native methods.
-  static bool Register(JNIEnv* env);
-
-  AppBannerManagerAndroid(JNIEnv* env, jobject obj);
+  explicit AppBannerManagerAndroid(content::WebContents* web_contents);
   ~AppBannerManagerAndroid() override;
 
-  // Destroys the AppBannerManagerAndroid.
-  void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
-
-  // Observes a new WebContents, if necessary.
-  void ReplaceWebContents(
-      JNIEnv* env,
-      const base::android::JavaParamRef<jobject>& obj,
-      const base::android::JavaParamRef<jobject>& jweb_contents);
+  const base::android::ScopedJavaGlobalRef<jobject>& GetJavaBannerManager()
+      const;
 
   // Return whether a BitmapFetcher is active.
   bool IsFetcherActive(JNIEnv* env,
@@ -52,9 +42,10 @@
       const base::android::JavaParamRef<jstring>& japp_package,
       const base::android::JavaParamRef<jstring>& jicon_url);
 
-  // Requests the app banner. This method is called from the DevTools.
-  void RequestAppBanner(JNIEnv* env,
-                        const base::android::JavaParamRef<jobject>& jobj);
+  void RequestAppBanner(const GURL& validated_url, bool is_debug_mode) override;
+
+  // Registers native methods.
+  static bool Register(JNIEnv* env);
 
  protected:
   AppBannerDataFetcher* CreateAppBannerDataFetcher(
@@ -62,23 +53,26 @@
       bool is_debug_mode) override;
 
  private:
+  friend class content::WebContentsUserData<AppBannerManagerAndroid>;
+
   // AppBannerDataFetcher::Delegate overrides.
   bool HandleNonWebApp(const std::string& platform,
                        const GURL& url,
                        const std::string& id,
                        bool is_debug_mode) override;
 
+  void CreateJavaBannerManager();
+
+  bool CheckFetcherMatchesContents(bool is_debug_mode);
   bool CheckPlatformAndId(const std::string& platform,
                           const std::string& id,
                           bool is_debug_mode);
 
-  bool CheckFetcherMatchesContents(bool is_debug_mode);
-
   std::string ExtractQueryValueForName(const GURL& url,
                                        const std::string& name);
 
   // AppBannerManager on the Java side.
-  JavaObjectWeakGlobalRef weak_java_banner_view_manager_;
+  base::android::ScopedJavaGlobalRef<jobject> java_banner_manager_;
 
   DISALLOW_COPY_AND_ASSIGN(AppBannerManagerAndroid);
 };  // class AppBannerManagerAndroid
diff --git a/chrome/browser/android/ntp/most_visited_sites_bridge.cc b/chrome/browser/android/ntp/most_visited_sites_bridge.cc
index 54f2fd0c..92e83a83 100644
--- a/chrome/browser/android/ntp/most_visited_sites_bridge.cc
+++ b/chrome/browser/android/ntp/most_visited_sites_bridge.cc
@@ -36,6 +36,7 @@
 using base::android::ScopedJavaGlobalRef;
 using base::android::ScopedJavaLocalRef;
 using base::android::ToJavaArrayOfStrings;
+using base::android::ToJavaIntArray;
 using content::BrowserThread;
 using ntp_tiles::MostVisitedSites;
 using ntp_tiles::MostVisitedSitesSupervisor;
@@ -118,18 +119,27 @@
   std::vector<base::string16> titles;
   std::vector<std::string> urls;
   std::vector<std::string> whitelist_icon_paths;
+  std::vector<int> sources;
+  std::vector<int> provider_indexes;
+
   titles.reserve(suggestions.size());
   urls.reserve(suggestions.size());
   whitelist_icon_paths.reserve(suggestions.size());
+  sources.reserve(suggestions.size());
+  provider_indexes.reserve(suggestions.size());
   for (const auto& suggestion : suggestions) {
     titles.emplace_back(suggestion.title);
     urls.emplace_back(suggestion.url.spec());
     whitelist_icon_paths.emplace_back(suggestion.whitelist_icon_path.value());
+    sources.emplace_back(suggestion.source);
+    provider_indexes.emplace_back(suggestion.provider_index);
   }
   Java_MostVisitedURLsObserver_onMostVisitedURLsAvailable(
       env, observer_.obj(), ToJavaArrayOfStrings(env, titles).obj(),
       ToJavaArrayOfStrings(env, urls).obj(),
-      ToJavaArrayOfStrings(env, whitelist_icon_paths).obj());
+      ToJavaArrayOfStrings(env, whitelist_icon_paths).obj(),
+      ToJavaIntArray(env, sources).obj(),
+      ToJavaIntArray(env, provider_indexes).obj());
 }
 
 void MostVisitedSitesBridge::JavaObserver::OnPopularURLsAvailable(
@@ -193,10 +203,19 @@
 void MostVisitedSitesBridge::RecordTileTypeMetrics(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj,
-    const JavaParamRef<jintArray>& jtile_types) {
+    const JavaParamRef<jintArray>& jtile_types,
+    const JavaParamRef<jintArray>& jsources,
+    const JavaParamRef<jintArray>& jprovider_indices) {
   std::vector<int> tile_types;
+  std::vector<int> sources;
+  std::vector<int> provider_indices;
+
   base::android::JavaIntArrayToIntVector(env, jtile_types, &tile_types);
-  most_visited_.RecordTileTypeMetrics(tile_types);
+  base::android::JavaIntArrayToIntVector(env, jsources, &sources);
+  base::android::JavaIntArrayToIntVector(env, jprovider_indices,
+                                         &provider_indices);
+
+  most_visited_.RecordTileTypeMetrics(tile_types, sources, provider_indices);
 }
 
 void MostVisitedSitesBridge::RecordOpenedMostVisitedItem(
diff --git a/chrome/browser/android/ntp/most_visited_sites_bridge.h b/chrome/browser/android/ntp/most_visited_sites_bridge.h
index 2959c92..2a95173 100644
--- a/chrome/browser/android/ntp/most_visited_sites_bridge.h
+++ b/chrome/browser/android/ntp/most_visited_sites_bridge.h
@@ -41,7 +41,9 @@
   void RecordTileTypeMetrics(
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& obj,
-      const base::android::JavaParamRef<jintArray>& jtile_types);
+      const base::android::JavaParamRef<jintArray>& jtile_types,
+      const base::android::JavaParamRef<jintArray>& jsources,
+      const base::android::JavaParamRef<jintArray>& jprovider_indices);
   void RecordOpenedMostVisitedItem(
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& obj,
diff --git a/chrome/browser/android/ntp/ntp_snippets_bridge.cc b/chrome/browser/android/ntp/ntp_snippets_bridge.cc
index e6e9cdd..373de14c8 100644
--- a/chrome/browser/android/ntp/ntp_snippets_bridge.cc
+++ b/chrome/browser/android/ntp/ntp_snippets_bridge.cc
@@ -93,7 +93,7 @@
                                    const JavaParamRef<jstring>& snippet_id,
                                    const JavaParamRef<jobject>& j_callback) {
   base::android::ScopedJavaGlobalRef<jobject> callback(j_callback);
-  ntp_snippets_service_->FetchSnippetImage(
+  ntp_snippets_service_->FetchSuggestionImage(
       ConvertJavaStringToUTF8(env, snippet_id),
       base::Bind(&NTPSnippetsBridge::OnImageFetched,
                  weak_ptr_factory_.GetWeakPtr(), callback));
@@ -102,7 +102,7 @@
 void NTPSnippetsBridge::DiscardSnippet(JNIEnv* env,
                                        const JavaParamRef<jobject>& obj,
                                        const JavaParamRef<jstring>& id) {
-  ntp_snippets_service_->DiscardSnippet(ConvertJavaStringToUTF8(env, id));
+  ntp_snippets_service_->DiscardSuggestion(ConvertJavaStringToUTF8(env, id));
 }
 
 void NTPSnippetsBridge::SnippetVisited(JNIEnv* env,
diff --git a/chrome/browser/android/preferences/website_preference_bridge.cc b/chrome/browser/android/preferences/website_preference_bridge.cc
index c6b5d7d..fd92c2d1 100644
--- a/chrome/browser/android/preferences/website_preference_bridge.cc
+++ b/chrome/browser/android/preferences/website_preference_bridge.cc
@@ -471,7 +471,7 @@
         NULL);
 
     cookies_tree_model_.reset(new CookiesTreeModel(
-        container, profile_->GetExtensionSpecialStoragePolicy(), false));
+        container, profile_->GetExtensionSpecialStoragePolicy()));
     cookies_tree_model_->AddCookiesTreeObserver(this);
   }
 
diff --git a/chrome/browser/android/tab_web_contents_delegate_android.cc b/chrome/browser/android/tab_web_contents_delegate_android.cc
index 81f87c8..ea60eac 100644
--- a/chrome/browser/android/tab_web_contents_delegate_android.cc
+++ b/chrome/browser/android/tab_web_contents_delegate_android.cc
@@ -10,6 +10,7 @@
 #include "base/android/jni_string.h"
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
+#include "chrome/browser/android/banners/app_banner_manager_android.h"
 #include "chrome/browser/android/feature_utilities.h"
 #include "chrome/browser/android/hung_renderer_infobar_delegate.h"
 #include "chrome/browser/android/media/media_throttle_infobar_delegate.h"
@@ -417,11 +418,10 @@
 
 void TabWebContentsDelegateAndroid::RequestAppBannerFromDevTools(
     content::WebContents* web_contents) {
-  JNIEnv* env = base::android::AttachCurrentThread();
-  ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
-  if (obj.is_null())
-    return;
-  Java_TabWebContentsDelegateAndroid_requestAppBanner(env, obj.obj());
+  banners::AppBannerManagerAndroid* manager =
+      banners::AppBannerManagerAndroid::FromWebContents(web_contents);
+  DCHECK(manager);
+  manager->RequestAppBanner(web_contents->GetLastCommittedURL(), true);
 }
 
 }  // namespace android
diff --git a/chrome/browser/apps/app_browsertest.cc b/chrome/browser/apps/app_browsertest.cc
index fcc1f00..f6f699e 100644
--- a/chrome/browser/apps/app_browsertest.cc
+++ b/chrome/browser/apps/app_browsertest.cc
@@ -90,7 +90,7 @@
  protected:
   // RenderViewContextMenu implementation.
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override {
+                                  ui::Accelerator* accelerator) const override {
     return false;
   }
 };
diff --git a/chrome/browser/banners/app_banner_data_fetcher.cc b/chrome/browser/banners/app_banner_data_fetcher.cc
index fe4e8742..3cc2811 100644
--- a/chrome/browser/banners/app_banner_data_fetcher.cc
+++ b/chrome/browser/banners/app_banner_data_fetcher.cc
@@ -106,8 +106,8 @@
   transition_type_ = transition_type;
   validated_url_ = validated_url;
   referrer_.erase();
-  web_contents->HasManifest(
-      base::Bind(&AppBannerDataFetcher::OnDidHasManifest, this));
+  web_contents->GetManifest(
+      base::Bind(&AppBannerDataFetcher::OnDidGetManifest, this));
 }
 
 void AppBannerDataFetcher::Cancel() {
@@ -270,21 +270,6 @@
                                           web_contents->GetURL());
 }
 
-void AppBannerDataFetcher::OnDidHasManifest(bool has_manifest) {
-  content::WebContents* web_contents = GetWebContents();
-
-  if (!CheckFetcherIsStillAlive(web_contents) || !has_manifest) {
-    if (!has_manifest)
-      OutputDeveloperNotShownMessage(web_contents, kNoManifest, is_debug_mode_);
-
-    Cancel();
-    return;
-  }
-
-  web_contents->GetManifest(
-      base::Bind(&AppBannerDataFetcher::OnDidGetManifest, this));
-}
-
 void AppBannerDataFetcher::OnDidGetManifest(
     const GURL& manifest_url,
     const content::Manifest& manifest) {
@@ -293,6 +278,11 @@
     Cancel();
     return;
   }
+  if (manifest_url.is_empty()) {
+    OutputDeveloperNotShownMessage(web_contents, kNoManifest, is_debug_mode_);
+    Cancel();
+    return;
+  }
   if (manifest.IsEmpty()) {
     OutputDeveloperNotShownMessage(web_contents, kManifestEmpty,
                                    is_debug_mode_);
diff --git a/chrome/browser/banners/app_banner_data_fetcher.h b/chrome/browser/banners/app_banner_data_fetcher.h
index a1af6fc..e5b259ae 100644
--- a/chrome/browser/banners/app_banner_data_fetcher.h
+++ b/chrome/browser/banners/app_banner_data_fetcher.h
@@ -147,7 +147,6 @@
 
  private:
   // Callbacks for data retrieval.
-  void OnDidHasManifest(bool has_manifest);
   void OnDidGetManifest(const GURL& manifest_url,
                         const content::Manifest& manifest);
   void OnDidCheckHasServiceWorker(bool has_service_worker);
diff --git a/chrome/browser/banners/app_banner_manager.h b/chrome/browser/banners/app_banner_manager.h
index b42eb32..20969abb 100644
--- a/chrome/browser/banners/app_banner_manager.h
+++ b/chrome/browser/banners/app_banner_manager.h
@@ -40,7 +40,7 @@
 
   // Requests an app banner. Set |is_debug_mode| when it is triggered by the
   // developer's action in DevTools.
-  void RequestAppBanner(const GURL& validated_url, bool is_debug_mode);
+  virtual void RequestAppBanner(const GURL& validated_url, bool is_debug_mode);
 
   ~AppBannerManager() override;
 
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index 39d810a1..f71c9bd 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -347,9 +347,6 @@
       </if>
       <include name="IDR_PROFILER_HTML" file="resources\profiler\profiler.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
       <include name="IDR_PROFILER_JS" file="resources\profiler\profiler.js" flattenhtml="true" type="BINDATA" />
-      <if expr="enable_settings_app">
-        <include name="IDR_SETTINGS_APP_MANIFEST" file="resources\settings_app\manifest.json" type="BINDATA" />
-      </if>
       <if expr="enable_google_now">
         <include name="IDR_GOOGLE_NOW_MANIFEST" file="resources\google_now\manifest.json" type="BINDATA" />
       </if>
diff --git a/chrome/browser/browsing_data/browsing_data_cookie_helper_unittest.cc b/chrome/browser/browsing_data/browsing_data_cookie_helper_unittest.cc
index 0220cd5..d8c9decf 100644
--- a/chrome/browser/browsing_data/browsing_data_cookie_helper_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_cookie_helper_unittest.cc
@@ -22,8 +22,6 @@
   CookieExpectation() {}
 
   bool MatchesCookie(const net::CanonicalCookie& cookie) const {
-    if (!source_.is_empty() && source_ != cookie.Source())
-      return false;
     if (!domain_.empty() && domain_ != cookie.Domain())
       return false;
     if (!path_.empty() && path_ != cookie.Path())
@@ -189,9 +187,10 @@
     ASSERT_EQ(3U, cookie_list.size());
   }
 
-  void DeleteCookie(BrowsingDataCookieHelper* helper, const GURL origin) {
+  void DeleteCookie(BrowsingDataCookieHelper* helper,
+                    const std::string& domain) {
     for (const auto& cookie : cookie_list_) {
-      if (cookie.Source() == origin)
+      if (cookie.Domain() == domain)
         helper->DeleteCookie(cookie);
     }
   }
@@ -265,7 +264,7 @@
 
   EXPECT_EQ(2u, helper->GetCookieCount());
 
-  DeleteCookie(helper.get(), origin1);
+  DeleteCookie(helper.get(), origin1.host());
 
   EXPECT_EQ(1u, helper->GetCookieCount());
   helper->StartFetching(
diff --git a/chrome/browser/browsing_data/browsing_data_remover.cc b/chrome/browser/browsing_data/browsing_data_remover.cc
index 455327d7..a877c039 100644
--- a/chrome/browser/browsing_data/browsing_data_remover.cc
+++ b/chrome/browser/browsing_data/browsing_data_remover.cc
@@ -784,7 +784,8 @@
       base::Closure on_cleared_auto_sign_in =
           base::Bind(&BrowsingDataRemover::OnClearedAutoSignIn,
                      weak_ptr_factory_.GetWeakPtr());
-      password_store->DisableAutoSignInForAllLogins(on_cleared_auto_sign_in);
+      password_store->DisableAutoSignInForOrigins(
+          filter, on_cleared_auto_sign_in);
     }
   }
 
diff --git a/chrome/browser/browsing_data/browsing_data_remover_unittest.cc b/chrome/browser/browsing_data/browsing_data_remover_unittest.cc
index 0084c25e..9567c8ea 100644
--- a/chrome/browser/browsing_data/browsing_data_remover_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_remover_unittest.cc
@@ -2384,8 +2384,12 @@
 
 TEST_F(BrowsingDataRemoverTest, DisableAutoSignIn) {
   RemovePasswordsTester tester(GetProfile());
+  base::Callback<bool(const GURL&)> empty_filter =
+      BrowsingDataFilterBuilder::BuildNoopFilter();
 
-  EXPECT_CALL(*tester.store(), DisableAutoSignInForAllLoginsImpl())
+  EXPECT_CALL(
+      *tester.store(),
+      DisableAutoSignInForOriginsImpl(ProbablySameFilter(empty_filter)))
       .WillOnce(Return(password_manager::PasswordStoreChangeList()));
 
   BlockUntilBrowsingDataRemoved(browsing_data::EVERYTHING,
@@ -2394,10 +2398,14 @@
 
 TEST_F(BrowsingDataRemoverTest, DisableAutoSignInAfterRemovingPasswords) {
   RemovePasswordsTester tester(GetProfile());
+  base::Callback<bool(const GURL&)> empty_filter =
+      BrowsingDataFilterBuilder::BuildNoopFilter();
 
   EXPECT_CALL(*tester.store(), RemoveLoginsByURLAndTimeImpl(_, _, _))
       .WillOnce(Return(password_manager::PasswordStoreChangeList()));
-  EXPECT_CALL(*tester.store(), DisableAutoSignInForAllLoginsImpl())
+  EXPECT_CALL(
+      *tester.store(),
+      DisableAutoSignInForOriginsImpl(ProbablySameFilter(empty_filter)))
       .WillOnce(Return(password_manager::PasswordStoreChangeList()));
 
   BlockUntilBrowsingDataRemoved(browsing_data::EVERYTHING,
diff --git a/chrome/browser/browsing_data/cookies_tree_model.cc b/chrome/browser/browsing_data/cookies_tree_model.cc
index 959624e..0b7d81e 100644
--- a/chrome/browser/browsing_data/cookies_tree_model.cc
+++ b/chrome/browser/browsing_data/cookies_tree_model.cc
@@ -117,21 +117,6 @@
   return retval;
 }
 
-// When creating a cookie tree node from a cookie, strip the port of the
-// cookie source and treat all non-file:// URLs as http://.
-GURL CanonicalizeCookieSource(const net::CanonicalCookie& cookie) {
-  GURL url = cookie.Source();
-  if (url.SchemeIsFile())
-    return url;
-
-  url::Replacements<char> replacements;
-  replacements.ClearPort();
-  if (url.SchemeIsCryptographic())
-    replacements.SetScheme("http", url::Component(0, 4));
-
-  return url.GetOrigin().ReplaceComponents(replacements);
-}
-
 #if defined(ENABLE_EXTENSIONS)
 bool TypeIsProtected(CookieTreeNode::DetailedInfo::NodeType type) {
   switch (type) {
@@ -971,14 +956,12 @@
 // CookiesTreeModel, public:
 CookiesTreeModel::CookiesTreeModel(
     LocalDataContainer* data_container,
-    ExtensionSpecialStoragePolicy* special_storage_policy,
-    bool group_by_cookie_source)
+    ExtensionSpecialStoragePolicy* special_storage_policy)
     : ui::TreeNodeModel<CookieTreeNode>(new CookieTreeRootNode(this)),
-      data_container_(data_container),
 #if defined(ENABLE_EXTENSIONS)
       special_storage_policy_(special_storage_policy),
 #endif
-      group_by_cookie_source_(group_by_cookie_source) {
+      data_container_(data_container) {
   data_container_->Init(this);
 }
 
@@ -1219,18 +1202,13 @@
   notifier->StartBatchUpdate();
   for (CookieList::iterator it = container->cookie_list_.begin();
        it != container->cookie_list_.end(); ++it) {
-    GURL source = CanonicalizeCookieSource(*it);
-    if (source.is_empty() || !group_by_cookie_source_) {
-      std::string domain = it->Domain();
-      if (domain.length() > 1 && domain[0] == '.')
-        domain = domain.substr(1);
+    std::string domain = it->Domain();
+    if (domain.length() > 1 && domain[0] == '.')
+      domain = domain.substr(1);
 
-      // We treat secure cookies just the same as normal ones.
-      source = GURL(std::string(url::kHttpScheme) +
-                    url::kStandardSchemeSeparator + domain + "/");
-    }
-    if (!source.SchemeIsHTTPOrHTTPS())
-      continue;
+    // Cookies ignore schemes, so group all HTTP and HTTPS cookies together.
+    GURL source(std::string(url::kHttpScheme) + url::kStandardSchemeSeparator +
+                domain + "/");
 
     if (filter.empty() || (CookieTreeHostNode::TitleForUrl(source)
                                .find(filter) != base::string16::npos)) {
diff --git a/chrome/browser/browsing_data/cookies_tree_model.h b/chrome/browser/browsing_data/cookies_tree_model.h
index 5a050bf..c693ce79 100644
--- a/chrome/browser/browsing_data/cookies_tree_model.h
+++ b/chrome/browser/browsing_data/cookies_tree_model.h
@@ -686,8 +686,7 @@
 class CookiesTreeModel : public ui::TreeNodeModel<CookieTreeNode> {
  public:
   CookiesTreeModel(LocalDataContainer* data_container,
-                   ExtensionSpecialStoragePolicy* special_storage_policy,
-                   bool group_by_cookie_source);
+                   ExtensionSpecialStoragePolicy* special_storage_policy);
   ~CookiesTreeModel() override;
 
   // Given a CanonicalCookie, return the ID of the message which should be
@@ -849,23 +848,19 @@
                                       ScopedBatchUpdateNotifier* notifier,
                                       const base::string16& filter);
 
-  // Map of app ids to LocalDataContainer objects to use when retrieving
-  // locally stored data.
-  std::unique_ptr<LocalDataContainer> data_container_;
-
 #if defined(ENABLE_EXTENSIONS)
   // The extension special storage policy; see ExtensionsProtectingNode() above.
   scoped_refptr<ExtensionSpecialStoragePolicy> special_storage_policy_;
 #endif
 
+  // Map of app ids to LocalDataContainer objects to use when retrieving
+  // locally stored data.
+  std::unique_ptr<LocalDataContainer> data_container_;
+
   // The CookiesTreeModel maintains a separate list of observers that are
   // specifically of the type CookiesTreeModel::Observer.
   base::ObserverList<Observer> cookies_observer_list_;
 
-  // If true, use the CanonicalCookie::Source attribute to group cookies.
-  // Otherwise, use the CanonicalCookie::Domain attribute.
-  bool group_by_cookie_source_;
-
   // Keeps track of how many batches the consumer of this class says it is going
   // to send.
   int batches_expected_ = 0;
diff --git a/chrome/browser/browsing_data/cookies_tree_model_unittest.cc b/chrome/browser/browsing_data/cookies_tree_model_unittest.cc
index 1170490..89a237a6 100644
--- a/chrome/browser/browsing_data/cookies_tree_model_unittest.cc
+++ b/chrome/browser/browsing_data/cookies_tree_model_unittest.cc
@@ -125,7 +125,7 @@
                                mock_browsing_data_flash_lso_helper_.get());
 
     CookiesTreeModel* cookies_model =
-        new CookiesTreeModel(container, special_storage_policy(), false);
+        new CookiesTreeModel(container, special_storage_policy());
     mock_browsing_data_cookie_helper_->
         AddCookieSamples(GURL("http://foo1"), "A=1");
     mock_browsing_data_cookie_helper_->
@@ -1100,7 +1100,7 @@
                              mock_browsing_data_service_worker_helper_.get(),
                              mock_browsing_data_cache_storage_helper_.get(),
                              mock_browsing_data_flash_lso_helper_.get());
-  CookiesTreeModel cookies_model(container, special_storage_policy(), false);
+  CookiesTreeModel cookies_model(container, special_storage_policy());
 
   mock_browsing_data_cookie_helper_->
       AddCookieSamples(GURL("http://foo1"), "A=1");
@@ -1207,7 +1207,7 @@
                              mock_browsing_data_service_worker_helper_.get(),
                              mock_browsing_data_cache_storage_helper_.get(),
                              mock_browsing_data_flash_lso_helper_.get());
-  CookiesTreeModel cookies_model(container, special_storage_policy(), false);
+  CookiesTreeModel cookies_model(container, special_storage_policy());
 
   mock_browsing_data_cookie_helper_->
       AddCookieSamples(GURL("http://foo1"), "A=1");
@@ -1317,7 +1317,7 @@
                              mock_browsing_data_service_worker_helper_.get(),
                              mock_browsing_data_cache_storage_helper_.get(),
                              mock_browsing_data_flash_lso_helper_.get());
-  CookiesTreeModel cookies_model(container, special_storage_policy(), false);
+  CookiesTreeModel cookies_model(container, special_storage_policy());
 
   mock_browsing_data_cookie_helper_->
       AddCookieSamples(GURL("http://foo1"), "A=1");
@@ -1361,7 +1361,7 @@
                              mock_browsing_data_service_worker_helper_.get(),
                              mock_browsing_data_cache_storage_helper_.get(),
                              mock_browsing_data_flash_lso_helper_.get());
-  CookiesTreeModel cookies_model(container, special_storage_policy(), false);
+  CookiesTreeModel cookies_model(container, special_storage_policy());
 
   mock_browsing_data_cookie_helper_->
       AddCookieSamples(GURL("http://a.foo2.com"), "A=1");
@@ -1410,7 +1410,7 @@
                              mock_browsing_data_service_worker_helper_.get(),
                              mock_browsing_data_cache_storage_helper_.get(),
                              mock_browsing_data_flash_lso_helper_.get());
-  CookiesTreeModel cookies_model(container, special_storage_policy(), false);
+  CookiesTreeModel cookies_model(container, special_storage_policy());
 
   mock_browsing_data_cookie_helper_->AddCookieSamples(host, "A=1");
   mock_browsing_data_cookie_helper_->Notify();
@@ -1515,7 +1515,7 @@
                              mock_browsing_data_service_worker_helper_.get(),
                              mock_browsing_data_cache_storage_helper_.get(),
                              mock_browsing_data_flash_lso_helper_.get());
-  CookiesTreeModel cookies_model(container, special_storage_policy(), false);
+  CookiesTreeModel cookies_model(container, special_storage_policy());
 
   mock_browsing_data_cookie_helper_->
       AddCookieSamples(GURL("http://123.com"), "A=1");
@@ -1557,8 +1557,7 @@
                              mock_browsing_data_service_worker_helper_.get(),
                              mock_browsing_data_cache_storage_helper_.get(),
                              mock_browsing_data_flash_lso_helper_.get());
-  CookiesTreeModel cookies_model(container, special_storage_policy(),
-                                 true /* group by cookie source */);
+  CookiesTreeModel cookies_model(container, special_storage_policy());
 
   mock_browsing_data_cookie_helper_->AddCookieSamples(
       GURL("file:///tmp/test.html"), "A=1");
@@ -1646,7 +1645,7 @@
                              mock_browsing_data_service_worker_helper_.get(),
                              mock_browsing_data_cache_storage_helper_.get(),
                              mock_browsing_data_flash_lso_helper_.get());
-  CookiesTreeModel cookies_model(container, special_storage_policy(), false);
+  CookiesTreeModel cookies_model(container, special_storage_policy());
 
   mock_browsing_data_cookie_helper_->
       AddCookieSamples(GURL(), "A=1");
diff --git a/chrome/browser/chooser_controller/chooser_controller.cc b/chrome/browser/chooser_controller/chooser_controller.cc
index 00c52f9..ce26370b 100644
--- a/chrome/browser/chooser_controller/chooser_controller.cc
+++ b/chrome/browser/chooser_controller/chooser_controller.cc
@@ -4,7 +4,14 @@
 
 #include "chrome/browser/chooser_controller/chooser_controller.h"
 
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/url_formatter/elide_url.h"
 #include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/common/constants.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "url/origin.h"
 
 ChooserController::ChooserController(content::RenderFrameHost* owner)
@@ -12,7 +19,32 @@
 
 ChooserController::~ChooserController() {}
 
-url::Origin ChooserController::GetOrigin() const {
-  return owning_frame_ ? owning_frame_->GetLastCommittedOrigin()
-                       : url::Origin();
+base::string16 ChooserController::GetTitle() const {
+  if (!owning_frame_)
+    return base::string16();
+
+  url::Origin origin = owning_frame_->GetLastCommittedOrigin();
+
+  if (origin.scheme() == extensions::kExtensionScheme) {
+    content::WebContents* web_contents =
+        content::WebContents::FromRenderFrameHost(owning_frame_);
+    content::BrowserContext* browser_context =
+        web_contents->GetBrowserContext();
+    extensions::ExtensionRegistry* extension_registry =
+        extensions::ExtensionRegistry::Get(browser_context);
+    if (extension_registry) {
+      const extensions::Extension* extension =
+          extension_registry->enabled_extensions().GetByID(origin.host());
+      if (extension) {
+        return l10n_util::GetStringFUTF16(
+            IDS_DEVICE_CHOOSER_PROMPT_EXTENSION_NAME,
+            base::UTF8ToUTF16(extension->name()));
+      }
+    }
+  }
+
+  return l10n_util::GetStringFUTF16(
+      IDS_DEVICE_CHOOSER_PROMPT_ORIGIN,
+      url_formatter::FormatOriginForSecurityDisplay(
+          origin, url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC));
 }
diff --git a/chrome/browser/chooser_controller/chooser_controller.h b/chrome/browser/chooser_controller/chooser_controller.h
index 275f0243..bb20a77f 100644
--- a/chrome/browser/chooser_controller/chooser_controller.h
+++ b/chrome/browser/chooser_controller/chooser_controller.h
@@ -12,10 +12,6 @@
 class RenderFrameHost;
 }
 
-namespace url {
-class Origin;
-}
-
 // Subclass ChooserController to implement a chooser, which has some
 // introductory text and a list of options that users can pick one of.
 // Your subclass must define the set of options users can pick from;
@@ -52,8 +48,11 @@
     virtual ~Observer() {}
   };
 
-  // Return the origin URL to be displayed on the chooser title.
-  url::Origin GetOrigin() const;
+  // Returns the text to be displayed in the chooser title.
+  base::string16 GetTitle() const;
+
+  // Returns the label for OK button.
+  virtual base::string16 GetOkButtonLabel() const = 0;
 
   // The number of options users can pick from. For example, it can be
   // the number of USB/Bluetooth device names which are listed in the
diff --git a/chrome/browser/chooser_controller/mock_chooser_controller.cc b/chrome/browser/chooser_controller/mock_chooser_controller.cc
index dbcd172..57ffe1e 100644
--- a/chrome/browser/chooser_controller/mock_chooser_controller.cc
+++ b/chrome/browser/chooser_controller/mock_chooser_controller.cc
@@ -9,6 +9,10 @@
 
 MockChooserController::~MockChooserController() {}
 
+base::string16 MockChooserController::GetOkButtonLabel() const {
+  return base::string16();
+}
+
 size_t MockChooserController::NumOptions() const {
   return option_names_.size();
 }
diff --git a/chrome/browser/chooser_controller/mock_chooser_controller.h b/chrome/browser/chooser_controller/mock_chooser_controller.h
index 85ab055..1ff9e25 100644
--- a/chrome/browser/chooser_controller/mock_chooser_controller.h
+++ b/chrome/browser/chooser_controller/mock_chooser_controller.h
@@ -17,6 +17,7 @@
   ~MockChooserController() override;
 
   // ChooserController:
+  base::string16 GetOkButtonLabel() const override;
   size_t NumOptions() const override;
   base::string16 GetOption(size_t index) const override;
   MOCK_METHOD1(Select, void(size_t index));
diff --git a/chrome/browser/chrome_browser_field_trials.cc b/chrome/browser/chrome_browser_field_trials.cc
index 8dc2258..38589ebe 100644
--- a/chrome/browser/chrome_browser_field_trials.cc
+++ b/chrome/browser/chrome_browser_field_trials.cc
@@ -11,6 +11,7 @@
 #include "base/files/file_util.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram_base.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/metrics/persistent_histogram_allocator.h"
 #include "base/path_service.h"
 #include "base/strings/string_util.h"
@@ -57,6 +58,18 @@
   if (!base::ReplaceFile(active_file, metrics_file, nullptr))
     base::DeleteFile(metrics_file, /*recursive=*/false);
 
+  // This is used to report results to an UMA histogram. It's an int because
+  // arithmetic is done on the value. The corresponding "failed" case must
+  // always appear directly after the "success" case.
+  enum : int {
+    LOCAL_MEMORY_SUCCESS,
+    LOCAL_MEMORY_FAILED,
+    MAPPED_FILE_SUCCESS,
+    MAPPED_FILE_FAILED,
+    CREATE_ALLOCATOR_RESULTS
+  };
+  int result;
+
   // Create persistent/shared memory and allow histograms to be stored in
   // it. Memory that is not actualy used won't be physically mapped by the
   // system. BrowserMetrics usage, as reported in UMA, peaked around 1.9MiB
@@ -70,18 +83,29 @@
     base::GlobalHistogramAllocator::CreateWithFile(
         active_file, kAllocSize, kAllocId,
         ChromeMetricsServiceClient::kBrowserMetricsName);
+    result = MAPPED_FILE_SUCCESS;
   } else if (storage == "LocalMemory") {
     // Use local memory for storage even though it will not persist across
     // an unclean shutdown.
     base::GlobalHistogramAllocator::CreateWithLocalMemory(
         kAllocSize, kAllocId, ChromeMetricsServiceClient::kBrowserMetricsName);
+    result = LOCAL_MEMORY_SUCCESS;
   } else {
     // Persistent metric storage is disabled.
     return;
   }
 
+  // Get the allocator that was just created and report result. Exit if the
+  // allocator could not be created.
   base::GlobalHistogramAllocator* allocator =
       base::GlobalHistogramAllocator::Get();
+  UMA_HISTOGRAM_ENUMERATION("UMA.PersistentHistograms.InitResult",
+                            result + (allocator ? 0 : 1),
+                            CREATE_ALLOCATOR_RESULTS);
+  if (!allocator)
+    return;
+
+  // Create tracking histograms for the allocator and record storage file.
   allocator->CreateTrackingHistograms(
       ChromeMetricsServiceClient::kBrowserMetricsName);
   allocator->SetPersistentLocation(active_file);
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index e1ac0da..64a3c5ee 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -1385,7 +1385,10 @@
     "LowPriorityIFrames",
 
     // Keys: disallowFetchForDocWrittenScriptsInMainFrame
-    "DisallowFetchForDocWrittenScriptsInMainFrame"
+    "DisallowFetchForDocWrittenScriptsInMainFrame",
+
+    // Keys: parseHTMLOnMainThreadSyncTokenize
+    "ParseHTMLOnMainThread",
   };
 
   std::vector<std::string> blink_settings;
diff --git a/chrome/browser/chrome_quota_permission_context.cc b/chrome/browser/chrome_quota_permission_context.cc
index 9e853c8..e5aa8bc 100644
--- a/chrome/browser/chrome_quota_permission_context.cc
+++ b/chrome/browser/chrome_quota_permission_context.cc
@@ -31,7 +31,7 @@
 #include "components/infobars/core/confirm_infobar_delegate.h"
 #include "components/infobars/core/infobar.h"
 #else
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
+#include "chrome/browser/permissions/permission_request_manager.h"
 #endif
 
 namespace {
@@ -270,10 +270,10 @@
     return;
   }
 #else
-  PermissionBubbleManager* bubble_manager =
-      PermissionBubbleManager::FromWebContents(web_contents);
-  if (bubble_manager) {
-    bubble_manager->AddRequest(
+  PermissionRequestManager* permission_request_manager =
+      PermissionRequestManager::FromWebContents(web_contents);
+  if (permission_request_manager) {
+    permission_request_manager->AddRequest(
         new QuotaPermissionRequest(this, params.origin_url, callback));
     return;
   }
diff --git a/chrome/browser/chromeos/arc/arc_auth_service.cc b/chrome/browser/chromeos/arc/arc_auth_service.cc
index cc7bb452..2f68cd3 100644
--- a/chrome/browser/chromeos/arc/arc_auth_service.cc
+++ b/chrome/browser/chromeos/arc/arc_auth_service.cc
@@ -97,6 +97,7 @@
   g_arc_auth_service = this;
 
   arc_bridge_service()->AddObserver(this);
+  arc_bridge_service()->auth()->AddObserver(this);
 }
 
 ArcAuthService::~ArcAuthService() {
@@ -104,6 +105,7 @@
   DCHECK_EQ(this, g_arc_auth_service);
 
   Shutdown();
+  arc_bridge_service()->auth()->RemoveObserver(this);
   arc_bridge_service()->RemoveObserver(this);
 
   g_arc_auth_service = nullptr;
@@ -185,8 +187,8 @@
   return true;
 }
 
-void ArcAuthService::OnAuthInstanceReady() {
-  arc_bridge_service()->auth_instance()->Init(
+void ArcAuthService::OnInstanceReady() {
+  arc_bridge_service()->auth()->instance()->Init(
       binding_.CreateInterfacePtrAndBind());
 }
 
diff --git a/chrome/browser/chromeos/arc/arc_auth_service.h b/chrome/browser/chromeos/arc/arc_auth_service.h
index 3c3a98b..d86d93f9 100644
--- a/chrome/browser/chromeos/arc/arc_auth_service.h
+++ b/chrome/browser/chromeos/arc/arc_auth_service.h
@@ -17,6 +17,7 @@
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_service.h"
 #include "components/arc/common/auth.mojom.h"
+#include "components/arc/instance_holder.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "components/syncable_prefs/pref_service_syncable_observer.h"
 #include "components/syncable_prefs/synced_pref_observer.h"
@@ -43,6 +44,7 @@
 class ArcAuthService : public ArcService,
                        public mojom::AuthHost,
                        public ArcBridgeService::Observer,
+                       public InstanceHolder<mojom::AuthInstance>::Observer,
                        public ArcAndroidManagementCheckerDelegate,
                        public ArcAuthContextDelegate,
                        public syncable_prefs::PrefServiceSyncableObserver,
@@ -122,9 +124,11 @@
   void RemoveObserver(Observer* observer);
 
   // ArcBridgeService::Observer:
-  void OnAuthInstanceReady() override;
   void OnBridgeStopped() override;
 
+  // InstanceHolder<mojom::AuthInstance>::Observer:
+  void OnInstanceReady() override;
+
   // AuthHost:
   // For security reason this code can be used only once and exists for specific
   // period of time.
diff --git a/chrome/browser/chromeos/arc/arc_downloads_watcher_service.cc b/chrome/browser/chromeos/arc/arc_downloads_watcher_service.cc
index 348ea55..cf63bf4 100644
--- a/chrome/browser/chromeos/arc/arc_downloads_watcher_service.cc
+++ b/chrome/browser/chromeos/arc/arc_downloads_watcher_service.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/chromeos/arc/arc_downloads_watcher_service.h"
 
+#include <map>
 #include <memory>
 #include <utility>
 
@@ -175,22 +176,22 @@
     ArcBridgeService* bridge_service)
     : ArcService(bridge_service), weak_ptr_factory_(this) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  arc_bridge_service()->AddObserver(this);
+  arc_bridge_service()->file_system()->AddObserver(this);
 }
 
 ArcDownloadsWatcherService::~ArcDownloadsWatcherService() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  arc_bridge_service()->RemoveObserver(this);
+  arc_bridge_service()->file_system()->RemoveObserver(this);
   StopWatchingDownloads();
   DCHECK(!watcher_);
 }
 
-void ArcDownloadsWatcherService::OnFileSystemInstanceReady() {
+void ArcDownloadsWatcherService::OnInstanceReady() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   StartWatchingDownloads();
 }
 
-void ArcDownloadsWatcherService::OnFileSystemInstanceClosed() {
+void ArcDownloadsWatcherService::OnInstanceClosed() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   StopWatchingDownloads();
 }
@@ -219,7 +220,7 @@
     const std::vector<base::FilePath>& paths) {
   DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
-  auto* instance = arc_bridge_service()->file_system_instance();
+  auto* instance = arc_bridge_service()->file_system()->instance();
   if (!instance)
     return;
 
diff --git a/chrome/browser/chromeos/arc/arc_downloads_watcher_service.h b/chrome/browser/chromeos/arc/arc_downloads_watcher_service.h
index 42c28ce..598fc42d 100644
--- a/chrome/browser/chromeos/arc/arc_downloads_watcher_service.h
+++ b/chrome/browser/chromeos/arc/arc_downloads_watcher_service.h
@@ -12,6 +12,7 @@
 #include "base/memory/weak_ptr.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_service.h"
+#include "components/arc/instance_holder.h"
 
 namespace base {
 class FilePath;
@@ -21,15 +22,16 @@
 
 // Watches Downloads directory and registers newly created media files to
 // Android MediaProvider.
-class ArcDownloadsWatcherService : public ArcService,
-                                   public ArcBridgeService::Observer {
+class ArcDownloadsWatcherService
+    : public ArcService,
+      public InstanceHolder<mojom::FileSystemInstance>::Observer {
  public:
   explicit ArcDownloadsWatcherService(ArcBridgeService* bridge_service);
   ~ArcDownloadsWatcherService() override;
 
-  // ArcBridgeService::Observer
-  void OnFileSystemInstanceReady() override;
-  void OnFileSystemInstanceClosed() override;
+  // InstanceHolder<mojom::FileSystemInstance>::Observer
+  void OnInstanceReady() override;
+  void OnInstanceClosed() override;
 
  private:
   class DownloadsWatcher;
diff --git a/chrome/browser/chromeos/arc/arc_navigation_throttle.cc b/chrome/browser/chromeos/arc/arc_navigation_throttle.cc
index 26551d5..98f2507 100644
--- a/chrome/browser/chromeos/arc/arc_navigation_throttle.cc
+++ b/chrome/browser/chromeos/arc/arc_navigation_throttle.cc
@@ -35,12 +35,12 @@
     return nullptr;
   }
   mojom::IntentHelperInstance* intent_helper_instance =
-      bridge_service->intent_helper_instance();
+      bridge_service->intent_helper()->instance();
   if (!intent_helper_instance) {
     VLOG(1) << "ARC intent helper instance is not ready.";
     return nullptr;
   }
-  if (bridge_service->intent_helper_version() < kMinInstanceVersion) {
+  if (bridge_service->intent_helper()->version() < kMinInstanceVersion) {
     VLOG(1) << "ARC intent helper instance is too old.";
     return nullptr;
   }
diff --git a/chrome/browser/chromeos/arc/arc_policy_bridge.cc b/chrome/browser/chromeos/arc/arc_policy_bridge.cc
index a9dff1d..e154398 100644
--- a/chrome/browser/chromeos/arc/arc_policy_bridge.cc
+++ b/chrome/browser/chromeos/arc/arc_policy_bridge.cc
@@ -235,7 +235,7 @@
 ArcPolicyBridge::ArcPolicyBridge(ArcBridgeService* bridge_service)
     : ArcService(bridge_service), binding_(this) {
   VLOG(2) << "ArcPolicyBridge::ArcPolicyBridge";
-  arc_bridge_service()->AddObserver(this);
+  arc_bridge_service()->policy()->AddObserver(this);
 }
 
 ArcPolicyBridge::ArcPolicyBridge(ArcBridgeService* bridge_service,
@@ -244,19 +244,19 @@
       binding_(this),
       policy_service_(policy_service) {
   VLOG(2) << "ArcPolicyBridge::ArcPolicyBridge(bridge_service, policy_service)";
-  arc_bridge_service()->AddObserver(this);
+  arc_bridge_service()->policy()->AddObserver(this);
 }
 
 ArcPolicyBridge::~ArcPolicyBridge() {
   VLOG(2) << "ArcPolicyBridge::~ArcPolicyBridge";
-  arc_bridge_service()->RemoveObserver(this);
+  arc_bridge_service()->policy()->RemoveObserver(this);
 }
 
 void ArcPolicyBridge::OverrideIsManagedForTesting(bool is_managed) {
   is_managed_ = is_managed;
 }
 
-void ArcPolicyBridge::OnPolicyInstanceReady() {
+void ArcPolicyBridge::OnInstanceReady() {
   VLOG(1) << "ArcPolicyBridge::OnPolicyInstanceReady";
   if (policy_service_ == nullptr) {
     InitializePolicyService();
@@ -264,7 +264,7 @@
   policy_service_->AddObserver(policy::POLICY_DOMAIN_CHROME, this);
 
   mojom::PolicyInstance* const policy_instance =
-      arc_bridge_service()->policy_instance();
+      arc_bridge_service()->policy()->instance();
   if (!policy_instance) {
     LOG(ERROR) << "OnPolicyInstanceReady called, but no policy instance found";
     return;
@@ -273,7 +273,7 @@
   policy_instance->Init(binding_.CreateInterfacePtrAndBind());
 }
 
-void ArcPolicyBridge::OnPolicyInstanceClosed() {
+void ArcPolicyBridge::OnInstanceClosed() {
   VLOG(1) << "ArcPolicyBridge::OnPolicyInstanceClosed";
   policy_service_->RemoveObserver(policy::POLICY_DOMAIN_CHROME, this);
   policy_service_ = nullptr;
@@ -297,8 +297,8 @@
                                       const policy::PolicyMap& previous,
                                       const policy::PolicyMap& current) {
   VLOG(1) << "ArcPolicyBridge::OnPolicyUpdated";
-  DCHECK(arc_bridge_service()->policy_instance());
-  arc_bridge_service()->policy_instance()->OnPolicyUpdated();
+  DCHECK(arc_bridge_service()->policy()->instance());
+  arc_bridge_service()->policy()->instance()->OnPolicyUpdated();
 }
 
 void ArcPolicyBridge::InitializePolicyService() {
diff --git a/chrome/browser/chromeos/arc/arc_policy_bridge.h b/chrome/browser/chromeos/arc/arc_policy_bridge.h
index e9e6558..b26697e 100644
--- a/chrome/browser/chromeos/arc/arc_policy_bridge.h
+++ b/chrome/browser/chromeos/arc/arc_policy_bridge.h
@@ -8,6 +8,7 @@
 #include "base/macros.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_service.h"
+#include "components/arc/instance_holder.h"
 #include "components/policy/core/common/policy_service.h"
 #include "mojo/public/cpp/bindings/binding.h"
 
@@ -27,7 +28,7 @@
 };
 
 class ArcPolicyBridge : public ArcService,
-                        public ArcBridgeService::Observer,
+                        public InstanceHolder<mojom::PolicyInstance>::Observer,
                         public mojom::PolicyHost,
                         public policy::PolicyService::Observer {
  public:
@@ -38,9 +39,9 @@
 
   void OverrideIsManagedForTesting(bool is_managed);
 
-  // ArcBridgeService::Observer overrides.
-  void OnPolicyInstanceReady() override;
-  void OnPolicyInstanceClosed() override;
+  // InstanceHolder<mojom::PolicyInstance>::Observer overrides.
+  void OnInstanceReady() override;
+  void OnInstanceClosed() override;
 
   // PolicyHost overrides.
   void GetPolicies(const GetPoliciesCallback& callback) override;
diff --git a/chrome/browser/chromeos/arc/arc_policy_bridge_unittest.cc b/chrome/browser/chromeos/arc/arc_policy_bridge_unittest.cc
index 139333ab..22ab4a8 100644
--- a/chrome/browser/chromeos/arc/arc_policy_bridge_unittest.cc
+++ b/chrome/browser/chromeos/arc/arc_policy_bridge_unittest.cc
@@ -108,7 +108,7 @@
     mojom::PolicyInstancePtr policy_instance_ptr;
     policy_instance_ = base::MakeUnique<FakePolicyInstance>(
         GetProxy(&policy_instance_ptr), bridge_service_.get());
-    bridge_service_->OnPolicyInstanceReady(std::move(policy_instance_ptr));
+    bridge_service_->policy()->OnInstanceReady(std::move(policy_instance_ptr));
     policy_instance()->WaitForOnPolicyInstanceReady();
   }
 
@@ -159,11 +159,11 @@
       nullptr);
   policy_bridge()->GetPolicies(PolicyStringCallback(
       "{\"applications\":"
-          "[{\"installType\":\"REQUIRED\","
-            "\"lockTaskAllowed\":false,"
-            "\"packageName\":\"com.google.android.apps.youtube.kids\","
-            "\"permissionGrants\":[]"
-          "}],"
+      "[{\"installType\":\"REQUIRED\","
+      "\"lockTaskAllowed\":false,"
+      "\"packageName\":\"com.google.android.apps.youtube.kids\","
+      "\"permissionGrants\":[]"
+      "}],"
       "\"defaultPermissionPolicy\":\"GRANT\""
       "}"));
 }
@@ -319,13 +319,13 @@
       base::WrapUnique(new base::FundamentalValue(false)), nullptr);
   policy_bridge()->GetPolicies(PolicyStringCallback(
       "{\"applications\":"
-          "[{\"installType\":\"REQUIRED\","
-            "\"lockTaskAllowed\":false,"
-            "\"packageName\":\"com.google.android.apps.youtube.kids\","
-            "\"permissionGrants\":[]"
-          "}],"
-        "\"cameraDisabled\":true,"
-        "\"defaultPermissionPolicy\":\"GRANT\""
+      "[{\"installType\":\"REQUIRED\","
+      "\"lockTaskAllowed\":false,"
+      "\"packageName\":\"com.google.android.apps.youtube.kids\","
+      "\"permissionGrants\":[]"
+      "}],"
+      "\"cameraDisabled\":true,"
+      "\"defaultPermissionPolicy\":\"GRANT\""
       "}"));
 }
 
diff --git a/chrome/browser/chromeos/arc/arc_process_service.cc b/chrome/browser/chromeos/arc/arc_process_service.cc
index 550ea0a..b84ddaf 100644
--- a/chrome/browser/chromeos/arc/arc_process_service.cc
+++ b/chrome/browser/chromeos/arc/arc_process_service.cc
@@ -43,7 +43,7 @@
       worker_pool_(new SequencedWorkerPool(1, "arc_process_manager")),
       weak_ptr_factory_(this) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  arc_bridge_service()->AddObserver(this);
+  arc_bridge_service()->process()->AddObserver(this);
   DCHECK(!g_arc_process_service);
   g_arc_process_service = this;
   // Not intended to be used from the creating thread.
@@ -53,7 +53,7 @@
 ArcProcessService::~ArcProcessService() {
   DCHECK(g_arc_process_service == this);
   g_arc_process_service = nullptr;
-  arc_bridge_service()->RemoveObserver(this);
+  arc_bridge_service()->process()->RemoveObserver(this);
   worker_pool_->Shutdown();
 }
 
@@ -63,7 +63,7 @@
   return g_arc_process_service;
 }
 
-void ArcProcessService::OnProcessInstanceReady() {
+void ArcProcessService::OnInstanceReady() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   worker_pool_->PostNamedSequencedWorkerTask(
       kSequenceToken,
@@ -82,7 +82,7 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   arc::mojom::ProcessInstance* process_instance =
-      arc_bridge_service()->process_instance();
+      arc_bridge_service()->process()->instance();
   if (!process_instance) {
     return false;
   }
diff --git a/chrome/browser/chromeos/arc/arc_process_service.h b/chrome/browser/chromeos/arc/arc_process_service.h
index 231c58d..32f1486 100644
--- a/chrome/browser/chromeos/arc/arc_process_service.h
+++ b/chrome/browser/chromeos/arc/arc_process_service.h
@@ -16,6 +16,7 @@
 #include "chrome/browser/chromeos/arc/arc_process.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_service.h"
+#include "components/arc/instance_holder.h"
 
 namespace arc {
 
@@ -34,8 +35,9 @@
 //           base::Bind(&OnUpdateProcessList)) {
 //     LOG(ERROR) << "ARC process instance not ready.";
 //   }
-class ArcProcessService : public ArcService,
-                          public ArcBridgeService::Observer {
+class ArcProcessService
+    : public ArcService,
+      public InstanceHolder<mojom::ProcessInstance>::Observer {
  public:
   using RequestProcessListCallback =
       base::Callback<void(const std::vector<ArcProcess>&)>;
@@ -46,8 +48,8 @@
   // Returns nullptr before the global instance is ready.
   static ArcProcessService* Get();
 
-  // ArcBridgeService::Observer overrides.
-  void OnProcessInstanceReady() override;
+  // InstanceHolder<mojom::ProcessInstance>::Observer overrides.
+  void OnInstanceReady() override;
 
   // Returns true if ARC IPC is ready for process list request,
   // otherwise false.
diff --git a/chrome/browser/chromeos/arc/arc_settings_service.cc b/chrome/browser/chromeos/arc/arc_settings_service.cc
index 3c6afe3..74dd19c 100644
--- a/chrome/browser/chromeos/arc/arc_settings_service.cc
+++ b/chrome/browser/chromeos/arc/arc_settings_service.cc
@@ -365,7 +365,7 @@
 void ArcSettingsServiceImpl::SendSettingsBroadcast(
     const std::string& action,
     const base::DictionaryValue& extras) const {
-  if (!arc_bridge_service_->intent_helper_instance()) {
+  if (!arc_bridge_service_->intent_helper()->instance()) {
     LOG(ERROR) << "IntentHelper instance is not ready.";
     return;
   }
@@ -374,8 +374,8 @@
   bool write_success = base::JSONWriter::Write(extras, &extras_json);
   DCHECK(write_success);
 
-  if (arc_bridge_service_->intent_helper_version() >= 1) {
-    arc_bridge_service_->intent_helper_instance()->SendBroadcast(
+  if (arc_bridge_service_->intent_helper()->version() >= 1) {
+    arc_bridge_service_->intent_helper()->instance()->SendBroadcast(
         action, "org.chromium.arc.intent_helper",
         "org.chromium.arc.intent_helper.SettingsReceiver", extras_json);
   }
@@ -383,18 +383,18 @@
 
 ArcSettingsService::ArcSettingsService(ArcBridgeService* bridge_service)
     : ArcService(bridge_service) {
-  arc_bridge_service()->AddObserver(this);
+  arc_bridge_service()->intent_helper()->AddObserver(this);
 }
 
 ArcSettingsService::~ArcSettingsService() {
-  arc_bridge_service()->RemoveObserver(this);
+  arc_bridge_service()->intent_helper()->RemoveObserver(this);
 }
 
-void ArcSettingsService::OnIntentHelperInstanceReady() {
+void ArcSettingsService::OnInstanceReady() {
   impl_.reset(new ArcSettingsServiceImpl(arc_bridge_service()));
 }
 
-void ArcSettingsService::OnIntentHelperInstanceClosed() {
+void ArcSettingsService::OnInstanceClosed() {
   impl_.reset();
 }
 
diff --git a/chrome/browser/chromeos/arc/arc_settings_service.h b/chrome/browser/chromeos/arc/arc_settings_service.h
index d1cca0d..7096f3da 100644
--- a/chrome/browser/chromeos/arc/arc_settings_service.h
+++ b/chrome/browser/chromeos/arc/arc_settings_service.h
@@ -10,20 +10,22 @@
 #include "base/macros.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_service.h"
+#include "components/arc/instance_holder.h"
 
 namespace arc {
 
 class ArcSettingsServiceImpl;
 
-class ArcSettingsService : public ArcService,
-                           public ArcBridgeService::Observer {
+class ArcSettingsService
+    : public ArcService,
+      public InstanceHolder<mojom::IntentHelperInstance>::Observer {
  public:
   explicit ArcSettingsService(ArcBridgeService* bridge_service);
   ~ArcSettingsService() override;
 
-  // ArcBridgeService::Observer
-  void OnIntentHelperInstanceReady() override;
-  void OnIntentHelperInstanceClosed() override;
+  // InstanceHolder<mojom::IntentHelperInstance>::Observer
+  void OnInstanceReady() override;
+  void OnInstanceClosed() override;
 
  private:
   std::unique_ptr<ArcSettingsServiceImpl> impl_;
diff --git a/chrome/browser/chromeos/arc/arc_support_host.cc b/chrome/browser/chromeos/arc/arc_support_host.cc
index ace97f7..f347717 100644
--- a/chrome/browser/chromeos/arc/arc_support_host.cc
+++ b/chrome/browser/chromeos/arc/arc_support_host.cc
@@ -26,6 +26,7 @@
 #include "components/user_manager/known_user.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/webui/web_ui_util.h"
+#include "ui/display/screen.h"
 
 namespace {
 const char kAction[] = "action";
@@ -41,6 +42,7 @@
 const char kText[] = "text";
 const char kActionInitialize[] = "initialize";
 const char kActionSetMetricsMode[] = "setMetricsMode";
+const char kActionSetWindowBounds[] = "setWindowBounds";
 const char kActionStartLso[] = "startLso";
 const char kActionCancelAuthCode[] = "cancelAuthCode";
 const char kActionSetAuthCode[] = "setAuthCode";
@@ -73,6 +75,7 @@
   arc::ArcAuthService* arc_auth_service = arc::ArcAuthService::Get();
   DCHECK(arc_auth_service);
   arc_auth_service->AddObserver(this);
+  display::Screen::GetScreen()->AddObserver(this);
 
   pref_change_registrar_.Init(g_browser_process->local_state());
   pref_change_registrar_.Add(
@@ -82,6 +85,7 @@
 }
 
 ArcSupportHost::~ArcSupportHost() {
+  display::Screen::GetScreen()->RemoveObserver(this);
   arc::ArcAuthService* arc_auth_service = arc::ArcAuthService::Get();
   if (arc_auth_service)
     arc_auth_service->RemoveObserver(this);
@@ -167,6 +171,19 @@
   client_->PostMessageFromNativeHost(request_string);
 }
 
+void ArcSupportHost::OnDisplayAdded(const display::Display& new_display) {}
+
+void ArcSupportHost::OnDisplayRemoved(const display::Display& old_display) {}
+
+void ArcSupportHost::OnDisplayMetricsChanged(const display::Display& display,
+                                             uint32_t changed_metrics) {
+  base::DictionaryValue request;
+  std::string request_string;
+  request.SetString(kAction, kActionSetWindowBounds);
+  base::JSONWriter::Write(request, &request_string);
+  client_->PostMessageFromNativeHost(request_string);
+}
+
 void ArcSupportHost::OnMetricsPreferenceChanged() {
   SendMetricsMode();
 }
diff --git a/chrome/browser/chromeos/arc/arc_support_host.h b/chrome/browser/chromeos/arc/arc_support_host.h
index a7164e3..75d786a 100644
--- a/chrome/browser/chromeos/arc/arc_support_host.h
+++ b/chrome/browser/chromeos/arc/arc_support_host.h
@@ -9,10 +9,12 @@
 #include "chrome/browser/chromeos/arc/arc_auth_service.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "extensions/browser/api/messaging/native_message_host.h"
+#include "ui/display/display_observer.h"
 
 // Supports communication with Arc support dialog.
 class ArcSupportHost : public extensions::NativeMessageHost,
-                       public arc::ArcAuthService::Observer {
+                       public arc::ArcAuthService::Observer,
+                       public display::DisplayObserver {
  public:
   static const char kHostName[];
   static const char kHostAppId[];
@@ -33,6 +35,12 @@
   void OnOptInUIShowPage(arc::ArcAuthService::UIPage page,
                          const base::string16& status) override;
 
+  // display::DisplayObserver:
+  void OnDisplayAdded(const display::Display& new_display) override;
+  void OnDisplayRemoved(const display::Display& old_display) override;
+  void OnDisplayMetricsChanged(const display::Display& display,
+                               uint32_t changed_metrics) override;
+
  private:
   ArcSupportHost();
 
diff --git a/chrome/browser/chromeos/arc/gpu_arc_video_service_host.cc b/chrome/browser/chromeos/arc/gpu_arc_video_service_host.cc
index 9b82d1b..9da329c 100644
--- a/chrome/browser/chromeos/arc/gpu_arc_video_service_host.cc
+++ b/chrome/browser/chromeos/arc/gpu_arc_video_service_host.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/chromeos/arc/gpu_arc_video_service_host.h"
 
+#include <string>
+
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/message_loop/message_loop.h"
@@ -61,17 +63,17 @@
     arc::ArcBridgeService* bridge_service)
     : ArcService(bridge_service), binding_(this) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  arc_bridge_service()->AddObserver(this);
+  arc_bridge_service()->video()->AddObserver(this);
 }
 
 GpuArcVideoServiceHost::~GpuArcVideoServiceHost() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  arc_bridge_service()->RemoveObserver(this);
+  arc_bridge_service()->video()->RemoveObserver(this);
 }
 
-void GpuArcVideoServiceHost::OnVideoInstanceReady() {
+void GpuArcVideoServiceHost::OnInstanceReady() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  auto video_instance = arc_bridge_service()->video_instance();
+  auto video_instance = arc_bridge_service()->video()->instance();
   DCHECK(video_instance);
   video_instance->Init(binding_.CreateInterfacePtrAndBind());
 }
diff --git a/chrome/browser/chromeos/arc/gpu_arc_video_service_host.h b/chrome/browser/chromeos/arc/gpu_arc_video_service_host.h
index 86a48c3..b6f9540 100644
--- a/chrome/browser/chromeos/arc/gpu_arc_video_service_host.h
+++ b/chrome/browser/chromeos/arc/gpu_arc_video_service_host.h
@@ -9,6 +9,7 @@
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_service.h"
 #include "components/arc/common/video.mojom.h"
+#include "components/arc/instance_holder.h"
 #include "mojo/public/cpp/bindings/binding.h"
 
 namespace arc {
@@ -21,15 +22,16 @@
 // process. The corresponding end "GpuArcVideoService" runs in the GPU process.
 //
 // Lives on the UI thread.
-class GpuArcVideoServiceHost : public arc::ArcService,
-                               public arc::ArcBridgeService::Observer,
-                               public arc::mojom::VideoHost {
+class GpuArcVideoServiceHost
+    : public arc::ArcService,
+      public arc::InstanceHolder<mojom::VideoInstance>::Observer,
+      public arc::mojom::VideoHost {
  public:
   explicit GpuArcVideoServiceHost(arc::ArcBridgeService* bridge_service);
   ~GpuArcVideoServiceHost() override;
 
-  // arc::ArcBridgeService::Observer implementation.
-  void OnVideoInstanceReady() override;
+  // arc::InstanceHolder<mojom::VideoInstance>::Observer implementation.
+  void OnInstanceReady() override;
 
   // arc::mojom::VideoHost implementation.
   void DeprecatedOnRequestArcVideoAcceleratorChannel(
diff --git a/chrome/browser/chromeos/file_manager/arc_file_tasks.cc b/chrome/browser/chromeos/file_manager/arc_file_tasks.cc
index e16e6e5a..091fca0 100644
--- a/chrome/browser/chromeos/file_manager/arc_file_tasks.cc
+++ b/chrome/browser/chromeos/file_manager/arc_file_tasks.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/chromeos/file_manager/arc_file_tasks.h"
 
+#include <map>
 #include <memory>
 #include <string>
 #include <vector>
@@ -52,7 +53,7 @@
 // Returns the Mojo interface for ARC Intent Helper, with version |minVersion|
 // or above. If the ARC bridge is not established, returns null.
 arc::mojom::IntentHelperInstance* GetArcIntentHelper(Profile* profile,
-                                                     int min_version) {
+                                                     uint32_t min_version) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   // File manager in secondary profile cannot access ARC.
@@ -64,11 +65,11 @@
     return nullptr;
 
   arc::mojom::IntentHelperInstance* intent_helper_instance =
-      arc_service->intent_helper_instance();
+      arc_service->intent_helper()->instance();
   if (!intent_helper_instance)
     return nullptr;
 
-  if (arc_service->intent_helper_version() < min_version) {
+  if (arc_service->intent_helper()->version() < min_version) {
     DLOG(WARNING) << "ARC intent helper instance is too old.";
     return nullptr;
   }
@@ -296,6 +297,11 @@
 
   mojo::Array<arc::mojom::UrlWithMimeTypePtr> urls;
   for (const extensions::EntryInfo& entry : entries) {
+    if (entry.is_directory) {  // ARC apps don't support directories.
+      callback.Run(std::move(result_list));
+      return;
+    }
+
     GURL url;
     if (!ConvertToArcUrl(entry.path, &url)) {
       callback.Run(std::move(result_list));
diff --git a/chrome/browser/chromeos/login/quick_unlock/quick_unlock_notification_controller.cc b/chrome/browser/chromeos/login/quick_unlock/quick_unlock_notification_controller.cc
new file mode 100644
index 0000000..fbde9b41
--- /dev/null
+++ b/chrome/browser/chromeos/login/quick_unlock/quick_unlock_notification_controller.cc
@@ -0,0 +1,157 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_notification_controller.h"
+
+#include "ash/common/system/system_notifier.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/chromeos/login/quick_unlock/pin_storage.h"
+#include "chrome/browser/chromeos/login/quick_unlock/pin_storage_factory.h"
+#include "chrome/browser/notifications/notification.h"
+#include "chrome/browser/notifications/notification_ui_manager.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
+#include "components/prefs/pref_service.h"
+#include "content/public/browser/notification_service.h"
+#include "grit/ash_strings.h"
+#include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/strings/grit/ui_strings.h"
+
+namespace {
+
+const char kDelegateId[] = "quickunlock_delegate";
+const char kNotificationId[] = "quickunlock_notification";
+const char kChromeAuthenticationSettingsURL[] =
+    "chrome://md-settings/quickUnlock/authenticate";
+
+void UpdatePreferenceForProfile(Profile* profile) {
+  PrefService* pref_service = profile->GetPrefs();
+  pref_service->SetBoolean(prefs::kQuickUnlockFeatureNotificationShown, true);
+}
+
+}  // namespace
+
+namespace chromeos {
+
+QuickUnlockNotificationController::QuickUnlockNotificationController(
+    Profile* profile)
+    : profile_(profile) {
+  registrar_.Add(this, chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED,
+                 content::NotificationService::AllSources());
+}
+
+QuickUnlockNotificationController::~QuickUnlockNotificationController() {
+  UnregisterObserver();
+}
+
+// static
+// TODO(http://crbug.com/291747): Add check for a policy that might disable
+// quick unlock.
+bool QuickUnlockNotificationController::ShouldShow(Profile* profile) {
+  // Do not show notification if this is a guest session.
+  if (profile->IsGuestSession())
+    return false;
+
+  // Do not show notification to user if already displayed in the past.
+  if (profile->GetPrefs()->GetBoolean(
+          prefs::kQuickUnlockFeatureNotificationShown)) {
+    return false;
+  }
+
+  // Do not show the notification if the pin is already set.
+  PinStorage* pin_storage = PinStorageFactory::GetForProfile(profile);
+  if (pin_storage->IsPinSet())
+    return false;
+
+  // TODO(jdufault): Enable once quick unlock settings land(crbug.com/291747).
+  return false;
+}
+
+// NotificationDelegate override:
+std::string QuickUnlockNotificationController::id() const {
+  return kDelegateId;
+}
+
+void QuickUnlockNotificationController::Observe(
+    int type,
+    const content::NotificationSource& source,
+    const content::NotificationDetails& details) {
+  if (type != chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED)
+    return;
+
+  bool is_screen_locked = *content::Details<bool>(details).ptr();
+
+  // Return if the screen is locked, indicating that the notification was
+  // emitted due to a screen lock event.
+  if (is_screen_locked)
+    return;
+
+  UnregisterObserver();
+
+  // The user may have enabled the quick unlock feature during the current
+  // session and after the notificaiton controller has already been initialized.
+  if (!ShouldShow(profile_)) {
+    UpdatePreferenceForProfile(profile_);
+    return;
+  }
+
+  // Create and add notification to notification manager.
+  std::unique_ptr<Notification> notification(CreateNotification());
+  g_browser_process->notification_ui_manager()->Add(*notification, profile_);
+}
+
+// message_center::NotificationDelegate override:
+void QuickUnlockNotificationController::Close(bool by_user) {
+  if (by_user)
+    UpdatePreferenceForProfile(profile_);
+}
+
+// message_center::NotificationDelegate override:
+void QuickUnlockNotificationController::Click() {
+  chrome::NavigateParams params(profile_,
+                                GURL(kChromeAuthenticationSettingsURL),
+                                ui::PAGE_TRANSITION_LINK);
+  params.disposition = NEW_FOREGROUND_TAB;
+  params.window_action = chrome::NavigateParams::SHOW_WINDOW;
+  chrome::Navigate(&params);
+
+  UpdatePreferenceForProfile(profile_);
+
+  // Remove the notification from tray.
+  g_browser_process->notification_ui_manager()->CancelById(
+      id(), NotificationUIManager::GetProfileID(profile_));
+}
+
+void QuickUnlockNotificationController::UnregisterObserver() {
+  if (registrar_.IsRegistered(this,
+                              chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED,
+                              content::NotificationService::AllSources())) {
+    registrar_.Remove(this, chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED,
+                      content::NotificationService::AllSources());
+  }
+}
+
+Notification* QuickUnlockNotificationController::CreateNotification() {
+  return new Notification(
+      message_center::NOTIFICATION_TYPE_SIMPLE,
+      l10n_util::GetStringUTF16(IDS_ASH_QUICK_UNLOCK_NOTIFICATION_TITLE),
+      l10n_util::GetStringUTF16(IDS_ASH_QUICK_UNLOCK_NOTIFICATION_BODY),
+      // TODO(http://crbug.com/291747): Change this to actual icon for
+      // quick unlock feature notification.
+      ui::ResourceBundle::GetSharedInstance().GetImageNamed(
+          IDR_SCREENSHOT_NOTIFICATION_ICON),
+      message_center::NotifierId(message_center::NotifierId::SYSTEM_COMPONENT,
+                                 ash::system_notifier::kNotifierQuickUnlock),
+      l10n_util::GetStringUTF16(
+          IDS_MESSAGE_CENTER_NOTIFIER_QUICK_UNLOCK_FEATURE_NAME),
+      GURL(), kNotificationId, message_center::RichNotificationData(), this);
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/quick_unlock/quick_unlock_notification_controller.h b/chrome/browser/chromeos/login/quick_unlock/quick_unlock_notification_controller.h
new file mode 100644
index 0000000..8a07b91
--- /dev/null
+++ b/chrome/browser/chromeos/login/quick_unlock/quick_unlock_notification_controller.h
@@ -0,0 +1,55 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_QUICK_UNLOCK_QUICK_UNLOCK_NOTIFICATION_CONTROLLER_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_QUICK_UNLOCK_QUICK_UNLOCK_NOTIFICATION_CONTROLLER_H_
+
+#include "base/macros.h"
+#include "base/time/time.h"
+#include "chrome/browser/notifications/notification_delegate.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+
+class Profile;
+class NetworkState;
+class Notification;
+
+namespace chromeos {
+
+// Quick Unlock feature notification controller is responsible for managing the
+// new feature notification displayed to the user.
+class QuickUnlockNotificationController : public NotificationDelegate,
+                                          public content::NotificationObserver {
+ public:
+  explicit QuickUnlockNotificationController(Profile* profile);
+
+  // Returns true if the notification needs to be displayed for the given
+  // |profile|.
+  static bool ShouldShow(Profile* profile);
+
+  // content::NotificationObserver implementation.
+  void Observe(int type,
+               const content::NotificationSource& source,
+               const content::NotificationDetails& details) override;
+
+ private:
+  ~QuickUnlockNotificationController() override;
+
+  // NotificationDelegate overrides:
+  void Close(bool by_user) override;
+  void Click() override;
+  std::string id() const override;
+
+  Notification* CreateNotification();
+  void UnregisterObserver();
+
+  Profile* profile_;
+  content::NotificationRegistrar registrar_;
+
+  DISALLOW_COPY_AND_ASSIGN(QuickUnlockNotificationController);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_QUICK_UNLOCK_QUICK_UNLOCK_NOTIFICATION_CONTROLLER_H_
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc
index f461799a..4a7f9fc 100644
--- a/chrome/browser/chromeos/login/session/user_session_manager.cc
+++ b/chrome/browser/chromeos/login/session/user_session_manager.cc
@@ -1740,6 +1740,15 @@
   if (HatsNotificationController::ShouldShowSurveyToProfile(profile))
     hats_notification_controller_ = new HatsNotificationController(profile);
 
+  if (QuickUnlockNotificationController::ShouldShow(profile) &&
+      quick_unlock_notification_handler_.find(profile) ==
+          quick_unlock_notification_handler_.end()) {
+    auto* qu_feature_notification_controller =
+        new QuickUnlockNotificationController(profile);
+    quick_unlock_notification_handler_.insert(
+        std::make_pair(profile, qu_feature_notification_controller));
+  }
+
   // Mark login host for deletion after browser starts.  This
   // guarantees that the message loop will be referenced by the
   // browser before it is dereferenced by the login host.
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.h b/chrome/browser/chromeos/login/session/user_session_manager.h
index 06f51c7..b485d17 100644
--- a/chrome/browser/chromeos/login/session/user_session_manager.h
+++ b/chrome/browser/chromeos/login/session/user_session_manager.h
@@ -16,6 +16,7 @@
 #include "chrome/browser/chromeos/base/locale_util.h"
 #include "chrome/browser/chromeos/eol_notification.h"
 #include "chrome/browser/chromeos/hats/hats_notification_controller.h"
+#include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_notification_controller.h"
 #include "chrome/browser/chromeos/login/signin/oauth2_login_manager.h"
 #include "chrome/browser/chromeos/login/signin/token_handle_util.h"
 #include "chromeos/dbus/session_manager_client.h"
@@ -475,6 +476,12 @@
   std::map<Profile*, std::unique_ptr<EolNotification>, ProfileCompare>
       eol_notification_handler_;
 
+  // Per-user-session Quick Unlock Feature Notification
+  std::map<Profile*,
+           scoped_refptr<QuickUnlockNotificationController>,
+           ProfileCompare>
+      quick_unlock_notification_handler_;
+
   // Manages Easy unlock cryptohome keys.
   std::unique_ptr<EasyUnlockKeyManager> easy_unlock_key_manager_;
   bool running_easy_unlock_key_ops_;
diff --git a/chrome/browser/chromeos/preferences.cc b/chrome/browser/chromeos/preferences.cc
index b80d87d..e3f59c5 100644
--- a/chrome/browser/chromeos/preferences.cc
+++ b/chrome/browser/chromeos/preferences.cc
@@ -318,6 +318,9 @@
   registry->RegisterInt64Pref(prefs::kHatsLastInteractionTimestamp,
                               base::Time().ToInternalValue());
 
+  registry->RegisterBooleanPref(prefs::kQuickUnlockFeatureNotificationShown,
+                                false);
+
   // We don't sync EOL related prefs because they are device specific.
   registry->RegisterBooleanPref(prefs::kEolNotificationDismissed, false);
   registry->RegisterIntegerPref(prefs::kEolStatus,
diff --git a/chrome/browser/content_settings/local_shared_objects_container.cc b/chrome/browser/content_settings/local_shared_objects_container.cc
index 7327d2a3..d82aa46d 100644
--- a/chrome/browser/content_settings/local_shared_objects_container.cc
+++ b/chrome/browser/content_settings/local_shared_objects_container.cc
@@ -221,8 +221,8 @@
 LocalSharedObjectsContainer::CreateCookiesTreeModel() const {
   LocalDataContainer* container = new LocalDataContainer(
       cookies(), databases(), local_storages(), session_storages(), appcaches(),
-      indexed_dbs(), file_systems(), NULL, channel_ids(), service_workers(),
-      cache_storages(), NULL);
+      indexed_dbs(), file_systems(), nullptr, channel_ids(), service_workers(),
+      cache_storages(), nullptr);
 
-  return base::WrapUnique(new CookiesTreeModel(container, NULL, true));
+  return base::WrapUnique(new CookiesTreeModel(container, nullptr));
 }
diff --git a/chrome/browser/devtools/devtools_sanity_browsertest.cc b/chrome/browser/devtools/devtools_sanity_browsertest.cc
index f2a907b..9c0571da 100644
--- a/chrome/browser/devtools/devtools_sanity_browsertest.cc
+++ b/chrome/browser/devtools/devtools_sanity_browsertest.cc
@@ -1066,6 +1066,10 @@
   RunTest("testDeviceMetricsOverrides", "about:blank");
 }
 
+IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestDispatchKeyEventDoesNotCrash) {
+  RunTest("testDispatchKeyEventDoesNotCrash", "about:blank");
+}
+
 // Tests that settings are stored in profile correctly.
 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestSettings) {
   OpenDevToolsWindow("about:blank", true);
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc
index fc6b5fb..46cd6f1b9 100644
--- a/chrome/browser/download/download_browsertest.cc
+++ b/chrome/browser/download/download_browsertest.cc
@@ -48,6 +48,7 @@
 #include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/browser/net/url_request_mock_util.h"
 #include "chrome/browser/notifications/notification_ui_manager.h"
+#include "chrome/browser/permissions/permission_request_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_context_menu/render_view_context_menu_browsertest_util.h"
 #include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h"
@@ -59,7 +60,6 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
@@ -2776,17 +2776,17 @@
       DownloadItem::COMPLETE));
 }
 #else
-IN_PROC_BROWSER_TEST_F(DownloadTest, TestMultipleDownloadsBubble) {
+IN_PROC_BROWSER_TEST_F(DownloadTest, TestMultipleDownloadsRequests) {
   // Create a downloads observer.
   std::unique_ptr<content::DownloadTestObserver> downloads_observer(
       CreateWaiter(browser(), 2));
 
-  PermissionBubbleManager* permission_bubble_manager =
-      PermissionBubbleManager::FromWebContents(
+  PermissionRequestManager* permission_request_manager =
+      PermissionRequestManager::FromWebContents(
           browser()->tab_strip_model()->GetActiveWebContents());
-  permission_bubble_manager->DisplayPendingRequests();
-  permission_bubble_manager->set_auto_response_for_test(
-      PermissionBubbleManager::ACCEPT_ALL);
+  permission_request_manager->DisplayPendingRequests();
+  permission_request_manager->set_auto_response_for_test(
+      PermissionRequestManager::ACCEPT_ALL);
 
   ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
       browser(), net::URLRequestMockHTTPJob::GetMockUrl(
diff --git a/chrome/browser/download/download_request_limiter.cc b/chrome/browser/download/download_request_limiter.cc
index 8f2fceb..17247d4 100644
--- a/chrome/browser/download/download_request_limiter.cc
+++ b/chrome/browser/download/download_request_limiter.cc
@@ -31,7 +31,7 @@
 #include "chrome/browser/download/download_request_infobar_delegate_android.h"
 #else
 #include "chrome/browser/download/download_permission_request.h"
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
+#include "chrome/browser/permissions/permission_request_manager.h"
 #endif
 
 using content::BrowserThread;
@@ -135,7 +135,7 @@
   bool promptable = InfoBarService::FromWebContents(web_contents()) != nullptr;
 #else
   bool promptable =
-      PermissionBubbleManager::FromWebContents(web_contents()) != nullptr;
+      PermissionRequestManager::FromWebContents(web_contents()) != nullptr;
 #endif
 
   // See PromptUserForDownload(): if there's no InfoBarService, then
@@ -169,10 +169,10 @@
   DownloadRequestInfoBarDelegateAndroid::Create(
       InfoBarService::FromWebContents(web_contents_), factory_.GetWeakPtr());
 #else
-  PermissionBubbleManager* bubble_manager =
-      PermissionBubbleManager::FromWebContents(web_contents_);
-  if (bubble_manager) {
-    bubble_manager->AddRequest(
+  PermissionRequestManager* permission_request_manager =
+      PermissionRequestManager::FromWebContents(web_contents_);
+  if (permission_request_manager) {
+    permission_request_manager->AddRequest(
         new DownloadPermissionRequest(factory_.GetWeakPtr()));
   } else {
     Cancel();
diff --git a/chrome/browser/download/download_request_limiter_unittest.cc b/chrome/browser/download/download_request_limiter_unittest.cc
index 3583e49..4dab572a 100644
--- a/chrome/browser/download/download_request_limiter_unittest.cc
+++ b/chrome/browser/download/download_request_limiter_unittest.cc
@@ -27,8 +27,8 @@
 #include "chrome/browser/infobars/infobar_service.h"
 #else
 #include "chrome/browser/download/download_permission_request.h"
+#include "chrome/browser/permissions/permission_request_manager.h"
 #include "chrome/browser/ui/website_settings/mock_permission_bubble_factory.h"
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
 #endif
 
 using content::WebContents;
@@ -98,10 +98,10 @@
 class TestingDelegate {
  public:
   void SetUp(WebContents* web_contents) {
-    PermissionBubbleManager::CreateForWebContents(web_contents);
+    PermissionRequestManager::CreateForWebContents(web_contents);
     mock_permission_bubble_factory_.reset(new MockPermissionBubbleFactory(
-        PermissionBubbleManager::FromWebContents(web_contents)));
-    PermissionBubbleManager::FromWebContents(web_contents)
+        PermissionRequestManager::FromWebContents(web_contents)));
+    PermissionRequestManager::FromWebContents(web_contents)
         ->DisplayPendingRequests();
   }
 
@@ -116,19 +116,19 @@
   int AllowCount() { return mock_permission_bubble_factory_->show_count(); }
 
   void UpdateExpectations(TestingAction action) {
-    // Set expectations for PermissionBubbleManager.
+    // Set expectations for PermissionRequestManager.
     if (action == ACCEPT) {
       mock_permission_bubble_factory_->set_response_type(
-          PermissionBubbleManager::ACCEPT_ALL);
+          PermissionRequestManager::ACCEPT_ALL);
     } else if (action == CANCEL) {
       mock_permission_bubble_factory_->set_response_type(
-          PermissionBubbleManager::DENY_ALL);
+          PermissionRequestManager::DENY_ALL);
     } else if (action == WAIT) {
       mock_permission_bubble_factory_->set_response_type(
-          PermissionBubbleManager::NONE);
+          PermissionRequestManager::NONE);
     } else {
       mock_permission_bubble_factory_->set_response_type(
-          PermissionBubbleManager::DISMISS);
+          PermissionRequestManager::DISMISS);
     }
   }
 
diff --git a/chrome/browser/download/download_shelf_context_menu.cc b/chrome/browser/download/download_shelf_context_menu.cc
index 53dc0235..fe8769c 100644
--- a/chrome/browser/download/download_shelf_context_menu.cc
+++ b/chrome/browser/download/download_shelf_context_menu.cc
@@ -88,7 +88,7 @@
 
 bool DownloadShelfContextMenu::GetAcceleratorForCommandId(
     int command_id,
-    ui::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) const {
   return false;
 }
 
diff --git a/chrome/browser/download/download_shelf_context_menu.h b/chrome/browser/download/download_shelf_context_menu.h
index da4960e..22ba178 100644
--- a/chrome/browser/download/download_shelf_context_menu.h
+++ b/chrome/browser/download/download_shelf_context_menu.h
@@ -44,7 +44,7 @@
   bool IsCommandIdVisible(int command_id) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   bool IsItemForCommandIdDynamic(int command_id) const override;
   base::string16 GetLabelForCommandId(int command_id) const override;
 
diff --git a/chrome/browser/extensions/api/webrtc_from_web_accessible_resource_browsertest.cc b/chrome/browser/extensions/api/webrtc_from_web_accessible_resource_browsertest.cc
index 32306a74..7db1679d 100644
--- a/chrome/browser/extensions/api/webrtc_from_web_accessible_resource_browsertest.cc
+++ b/chrome/browser/extensions/api/webrtc_from_web_accessible_resource_browsertest.cc
@@ -5,8 +5,8 @@
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "chrome/browser/extensions/extension_apitest.h"
+#include "chrome/browser/permissions/permission_request_manager.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "extensions/test/result_catcher.h"
 #include "media/base/media_switches.h"
@@ -18,28 +18,29 @@
 namespace {
 
 // Used to observe the creation of permission prompt without responding.
-class PermissionRequestObserver : public PermissionBubbleManager::Observer {
+class PermissionRequestObserver : public PermissionRequestManager::Observer {
  public:
   explicit PermissionRequestObserver(content::WebContents* web_contents)
-      : bubble_manager_(PermissionBubbleManager::FromWebContents(web_contents)),
+      : request_manager_(
+            PermissionRequestManager::FromWebContents(web_contents)),
         request_shown_(false) {
-    bubble_manager_->AddObserver(this);
+    request_manager_->AddObserver(this);
   }
   ~PermissionRequestObserver() override {
     // Safe to remove twice if it happens.
-    bubble_manager_->RemoveObserver(this);
+    request_manager_->RemoveObserver(this);
   }
 
   bool request_shown() const { return request_shown_; }
 
  private:
-  // PermissionBubbleManager::Observer
+  // PermissionRequestManager::Observer
   void OnBubbleAdded() override {
     request_shown_ = true;
-    bubble_manager_->RemoveObserver(this);
+    request_manager_->RemoveObserver(this);
   }
 
-  PermissionBubbleManager* bubble_manager_;
+  PermissionRequestManager* request_manager_;
   bool request_shown_;
 
   DISALLOW_COPY_AND_ASSIGN(PermissionRequestObserver);
@@ -91,10 +92,10 @@
   GURL url = GetTestServerInsecureUrl("/extensions/test_file.html?succeed");
   content::WebContents* web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
-  PermissionBubbleManager* bubble_manager =
-      PermissionBubbleManager::FromWebContents(web_contents);
-  bubble_manager->set_auto_response_for_test(
-      PermissionBubbleManager::ACCEPT_ALL);
+  PermissionRequestManager* request_manager =
+      PermissionRequestManager::FromWebContents(web_contents);
+  request_manager->set_auto_response_for_test(
+      PermissionRequestManager::ACCEPT_ALL);
   PermissionRequestObserver permission_request_observer(web_contents);
   extensions::ResultCatcher catcher;
   ui_test_utils::NavigateToURL(browser(), url);
@@ -104,7 +105,7 @@
 }
 
 // Verify that a chrome-extension:// web accessible URL will fail to access
-// getUserMedia() if it is denied by the permission bubble, even if it is
+// getUserMedia() if it is denied by the permission request, even if it is
 // embedded in an insecure context.
 IN_PROC_BROWSER_TEST_F(WebRtcFromWebAccessibleResourceTest,
                        GetUserMediaInWebAccessibleResourceFail) {
@@ -115,9 +116,10 @@
   GURL url = GetTestServerInsecureUrl("/extensions/test_file.html?fail");
   content::WebContents* web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
-  PermissionBubbleManager* bubble_manager =
-      PermissionBubbleManager::FromWebContents(web_contents);
-  bubble_manager->set_auto_response_for_test(PermissionBubbleManager::DENY_ALL);
+  PermissionRequestManager* request_manager =
+      PermissionRequestManager::FromWebContents(web_contents);
+  request_manager->set_auto_response_for_test(
+      PermissionRequestManager::DENY_ALL);
   PermissionRequestObserver permission_request_observer(web_contents);
   extensions::ResultCatcher catcher;
   ui_test_utils::NavigateToURL(browser(), url);
diff --git a/chrome/browser/extensions/chrome_component_extension_resource_manager.cc b/chrome/browser/extensions/chrome_component_extension_resource_manager.cc
index cb1b9625..3207a71 100644
--- a/chrome/browser/extensions/chrome_component_extension_resource_manager.cc
+++ b/chrome/browser/extensions/chrome_component_extension_resource_manager.cc
@@ -36,12 +36,6 @@
     {"webstore_widget/app/icons/icon_32.png", IDR_WEBSTORE_ICON_32},
     {"webstore_widget/app/icons/icon_128.png", IDR_WEBSTORE_ICON},
 #endif
-#if defined(ENABLE_SETTINGS_APP)
-    {"settings_app/settings_app_icon_128.png", IDR_SETTINGS_APP_ICON_128},
-    {"settings_app/settings_app_icon_16.png", IDR_SETTINGS_APP_ICON_16},
-    {"settings_app/settings_app_icon_32.png", IDR_SETTINGS_APP_ICON_32},
-    {"settings_app/settings_app_icon_48.png", IDR_SETTINGS_APP_ICON_48},
-#endif
   };
 
   AddComponentResourceEntries(
diff --git a/chrome/browser/extensions/component_extensions_whitelist/whitelist.cc b/chrome/browser/extensions/component_extensions_whitelist/whitelist.cc
index ddabb67..39783ef 100644
--- a/chrome/browser/extensions/component_extensions_whitelist/whitelist.cc
+++ b/chrome/browser/extensions/component_extensions_whitelist/whitelist.cc
@@ -80,7 +80,6 @@
     IDR_HOTWORD_MANIFEST,
     IDR_IDENTITY_API_SCOPE_APPROVAL_MANIFEST,
     IDR_NETWORK_SPEECH_SYNTHESIS_MANIFEST,
-    IDR_SETTINGS_APP_MANIFEST,
     IDR_WALLPAPERMANAGER_MANIFEST,
     IDR_WEBSTORE_MANIFEST,
 #if defined(IMAGE_LOADER_EXTENSION)
diff --git a/chrome/browser/extensions/component_loader.cc b/chrome/browser/extensions/component_loader.cc
index 0760fe2..c750cbb 100644
--- a/chrome/browser/extensions/component_loader.cc
+++ b/chrome/browser/extensions/component_loader.cc
@@ -589,11 +589,6 @@
 #endif  // defined(GOOGLE_CHROME_BUILD)
     if (install_feedback)
       Add(IDR_FEEDBACK_MANIFEST, base::FilePath(FILE_PATH_LITERAL("feedback")));
-
-#if defined(ENABLE_SETTINGS_APP)
-    Add(IDR_SETTINGS_APP_MANIFEST,
-        base::FilePath(FILE_PATH_LITERAL("settings_app")));
-#endif
   }
 
 #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/extensions/extension_context_menu_model.cc b/chrome/browser/extensions/extension_context_menu_model.cc
index b5079f9..34be392 100644
--- a/chrome/browser/extensions/extension_context_menu_model.cc
+++ b/chrome/browser/extensions/extension_context_menu_model.cc
@@ -228,7 +228,8 @@
 }
 
 bool ExtensionContextMenuModel::GetAcceleratorForCommandId(
-    int command_id, ui::Accelerator* accelerator) {
+    int command_id,
+    ui::Accelerator* accelerator) const {
   return false;
 }
 
diff --git a/chrome/browser/extensions/extension_context_menu_model.h b/chrome/browser/extensions/extension_context_menu_model.h
index 7543dc3..095e84db 100644
--- a/chrome/browser/extensions/extension_context_menu_model.h
+++ b/chrome/browser/extensions/extension_context_menu_model.h
@@ -81,7 +81,7 @@
   bool IsCommandIdChecked(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
 
   ui::SimpleMenuModel* page_access_submenu_for_testing() {
diff --git a/chrome/browser/geolocation/geolocation_browsertest.cc b/chrome/browser/geolocation/geolocation_browsertest.cc
index d440c861..ced160d 100644
--- a/chrome/browser/geolocation/geolocation_browsertest.cc
+++ b/chrome/browser/geolocation/geolocation_browsertest.cc
@@ -17,11 +17,11 @@
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
+#include "chrome/browser/permissions/permission_request_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/content_settings/core/browser/content_settings_usages_state.h"
@@ -127,21 +127,22 @@
     base::MessageLoopForUI::current()->QuitWhenIdle();
 }
 
-// PermissionBubbleObserver ---------------------------------------------------
+// PermissionRequestObserver ---------------------------------------------------
 
-// Used to observe the creation of a single permission bubble without
+// Used to observe the creation of a single permission request without
 // responding.
-class PermissionBubbleObserver : public PermissionBubbleManager::Observer {
+class PermissionRequestObserver : public PermissionRequestManager::Observer {
  public:
-  explicit PermissionBubbleObserver(content::WebContents* web_contents)
-      : bubble_manager_(PermissionBubbleManager::FromWebContents(web_contents)),
+  explicit PermissionRequestObserver(content::WebContents* web_contents)
+      : request_manager_(
+            PermissionRequestManager::FromWebContents(web_contents)),
         request_shown_(false),
         message_loop_runner_(new content::MessageLoopRunner) {
-    bubble_manager_->AddObserver(this);
+    request_manager_->AddObserver(this);
   }
-  ~PermissionBubbleObserver() override {
+  ~PermissionRequestObserver() override {
     // Safe to remove twice if it happens.
-    bubble_manager_->RemoveObserver(this);
+    request_manager_->RemoveObserver(this);
   }
 
   void Wait() { message_loop_runner_->Run(); }
@@ -149,18 +150,18 @@
   bool request_shown() { return request_shown_; }
 
  private:
-  // PermissionBubbleManager::Observer
+  // PermissionRequestManager::Observer
   void OnBubbleAdded() override {
     request_shown_ = true;
-    bubble_manager_->RemoveObserver(this);
+    request_manager_->RemoveObserver(this);
     message_loop_runner_->Quit();
   }
 
-  PermissionBubbleManager* bubble_manager_;
+  PermissionRequestManager* request_manager_;
   bool request_shown_;
   scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
 
-  DISALLOW_COPY_AND_ASSIGN(PermissionBubbleObserver);
+  DISALLOW_COPY_AND_ASSIGN(PermissionRequestObserver);
 };
 
 }  // namespace
@@ -221,14 +222,14 @@
   HostContentSettingsMap* GetHostContentSettingsMap();
 
   // Calls watchPosition in JavaScript and accepts or denies the resulting
-  // permission bubble. Returns |true| if the expected behavior happened.
+  // permission request. Returns |true| if the expected behavior happened.
   bool WatchPositionAndGrantPermission() WARN_UNUSED_RESULT;
   bool WatchPositionAndDenyPermission() WARN_UNUSED_RESULT;
 
   // Calls watchPosition in JavaScript and observes whether the permission
-  // bubble is shown without interacting with it. Callers should set
-  // |bubble_should_display| to |true| if they expect a bubble to display.
-  void WatchPositionAndObservePermissionBubble(bool bubble_should_display);
+  // request is shown without interacting with it. Callers should set
+  // |request_should_display| to |true| if they expect a request to display.
+  void WatchPositionAndObservePermissionRequest(bool request_should_display);
 
   // Checks that no errors have been received in JavaScript, and checks that the
   // position most recently received matches |latitude| and |longitude|.
@@ -250,14 +251,14 @@
   // successfully in JavaScript.
   bool SetPositionAndWaitUntilUpdated(double latitude, double longitude);
 
-  // Convenience method to look up the number of queued permission bubbles.
-  int GetBubbleQueueSize(PermissionBubbleManager* manager);
+  // Convenience method to look up the number of queued permission requests.
+  int GetRequestQueueSize(PermissionRequestManager* manager);
 
  private:
   // Calls watchPosition() in JavaScript and accepts or denies the resulting
-  // permission bubble. Returns the JavaScript response.
-  std::string WatchPositionAndRespondToPermissionBubble(
-      PermissionBubbleManager::AutoResponseType bubble_response);
+  // permission request. Returns the JavaScript response.
+  std::string WatchPositionAndRespondToPermissionRequest(
+      PermissionRequestManager::AutoResponseType request_response);
 
   // The current Browser as set in Initialize. May be for an incognito profile.
   Browser* current_browser_ = nullptr;
@@ -347,39 +348,39 @@
 }
 
 bool GeolocationBrowserTest::WatchPositionAndGrantPermission() {
-  std::string result = WatchPositionAndRespondToPermissionBubble(
-      PermissionBubbleManager::ACCEPT_ALL);
+  std::string result = WatchPositionAndRespondToPermissionRequest(
+      PermissionRequestManager::ACCEPT_ALL);
   return "request-callback-success" == result;
 }
 
 bool GeolocationBrowserTest::WatchPositionAndDenyPermission() {
-  std::string result = WatchPositionAndRespondToPermissionBubble(
-      PermissionBubbleManager::DENY_ALL);
+  std::string result = WatchPositionAndRespondToPermissionRequest(
+      PermissionRequestManager::DENY_ALL);
   return "request-callback-error" == result;
 }
 
-std::string GeolocationBrowserTest::WatchPositionAndRespondToPermissionBubble(
-    PermissionBubbleManager::AutoResponseType bubble_response) {
-  PermissionBubbleManager::FromWebContents(
+std::string GeolocationBrowserTest::WatchPositionAndRespondToPermissionRequest(
+    PermissionRequestManager::AutoResponseType request_response) {
+  PermissionRequestManager::FromWebContents(
       current_browser_->tab_strip_model()->GetActiveWebContents())
-      ->set_auto_response_for_test(bubble_response);
+      ->set_auto_response_for_test(request_response);
   return RunScript(render_frame_host_, "geoStartWithAsyncResponse()");
 }
 
-void GeolocationBrowserTest::WatchPositionAndObservePermissionBubble(
-    bool bubble_should_display) {
-  PermissionBubbleObserver observer(
+void GeolocationBrowserTest::WatchPositionAndObservePermissionRequest(
+    bool request_should_display) {
+  PermissionRequestObserver observer(
       current_browser_->tab_strip_model()->GetActiveWebContents());
-  if (bubble_should_display) {
+  if (request_should_display) {
     // Control will return as soon as the API call is made, and then the
-    // observer will wait for the bubble to display.
+    // observer will wait for the request to display.
     RunScript(render_frame_host_, "geoStartWithSyncResponse()");
     observer.Wait();
   } else {
     // Control will return once one of the callbacks fires.
     RunScript(render_frame_host_, "geoStartWithAsyncResponse()");
   }
-  EXPECT_EQ(bubble_should_display, observer.request_shown());
+  EXPECT_EQ(request_should_display, observer.request_shown());
 }
 
 void GeolocationBrowserTest::ExpectPosition(double latitude, double longitude) {
@@ -423,8 +424,8 @@
   return result == "geoposition-updated";
 }
 
-int GeolocationBrowserTest::GetBubbleQueueSize(
-    PermissionBubbleManager* manager) {
+int GeolocationBrowserTest::GetRequestQueueSize(
+    PermissionRequestManager* manager) {
   return static_cast<int>(manager->requests_.size());
 }
 
@@ -469,9 +470,9 @@
   ASSERT_NO_FATAL_FAILURE(Initialize(INITIALIZATION_DEFAULT));
   ASSERT_TRUE(WatchPositionAndGrantPermission());
 
-  // Checks bubble is not needed in a second tab.
+  // Checks request is not needed in a second tab.
   ASSERT_NO_FATAL_FAILURE(Initialize(INITIALIZATION_NEWTAB));
-  WatchPositionAndObservePermissionBubble(false);
+  WatchPositionAndObservePermissionRequest(false);
   ExpectPosition(fake_latitude(), fake_longitude());
 }
 
@@ -481,13 +482,13 @@
       current_url(), current_url(), CONTENT_SETTINGS_TYPE_GEOLOCATION,
       std::string(), CONTENT_SETTING_BLOCK);
 
-  // Check that the bubble wasn't shown but we get an error for this origin.
-  WatchPositionAndObservePermissionBubble(false);
+  // Check that the request wasn't shown but we get an error for this origin.
+  WatchPositionAndObservePermissionRequest(false);
   ExpectValueFromScript(GetErrorCodePermissionDenied(), "geoGetLastError()");
 
   // Checks prompt will not be created a second tab.
   ASSERT_NO_FATAL_FAILURE(Initialize(INITIALIZATION_NEWTAB));
-  WatchPositionAndObservePermissionBubble(false);
+  WatchPositionAndObservePermissionRequest(false);
   ExpectValueFromScript(GetErrorCodePermissionDenied(), "geoGetLastError()");
 }
 
@@ -502,9 +503,9 @@
   GetHostContentSettingsMap()->SetContentSettingDefaultScope(
       current_url(), current_url(), CONTENT_SETTINGS_TYPE_GEOLOCATION,
       std::string(), CONTENT_SETTING_ALLOW);
-  // The bubble is not shown, there is no error, and the position gets to the
+  // The request is not shown, there is no error, and the position gets to the
   // script.
-  WatchPositionAndObservePermissionBubble(false);
+  WatchPositionAndObservePermissionRequest(false);
   ExpectPosition(fake_latitude(), fake_longitude());
 }
 
@@ -519,7 +520,7 @@
   // incognito profile. Go incognito, and check that the user is not prompted
   // again and the position gets to the script.
   ASSERT_NO_FATAL_FAILURE(Initialize(INITIALIZATION_OFFTHERECORD));
-  WatchPositionAndObservePermissionBubble(false);
+  WatchPositionAndObservePermissionRequest(false);
   ExpectPosition(fake_latitude(), fake_longitude());
 }
 
@@ -558,7 +559,7 @@
   // In a second iframe from a different origin with a cached position the user
   // is prompted.
   SetFrameForScriptExecution("iframe_1");
-  WatchPositionAndObservePermissionBubble(true);
+  WatchPositionAndObservePermissionRequest(true);
 
   // Back to the first frame, enable navigation and refresh geoposition.
   SetFrameForScriptExecution("iframe_0");
@@ -620,15 +621,15 @@
   // Test second iframe from a different origin with a cached position will
   // create the prompt.
   SetFrameForScriptExecution("iframe_1");
-  WatchPositionAndObservePermissionBubble(true);
+  WatchPositionAndObservePermissionRequest(true);
 
   // Navigate the iframe, and ensure the prompt is gone.
   content::WebContents* web_contents =
       current_browser()->tab_strip_model()->GetActiveWebContents();
   IFrameLoader change_iframe_1(current_browser(), 1, current_url());
-  int num_bubbles_after_cancel = GetBubbleQueueSize(
-      PermissionBubbleManager::FromWebContents(web_contents));
-  EXPECT_EQ(0, num_bubbles_after_cancel);
+  int num_requests_after_cancel = GetRequestQueueSize(
+      PermissionRequestManager::FromWebContents(web_contents));
+  EXPECT_EQ(0, num_requests_after_cancel);
 }
 
 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, InvalidUrlRequest) {
@@ -710,15 +711,15 @@
   LoadIFrames();
 
   SetFrameForScriptExecution("iframe_0");
-  WatchPositionAndObservePermissionBubble(true);
+  WatchPositionAndObservePermissionRequest(true);
 
   SetFrameForScriptExecution("iframe_1");
-  WatchPositionAndObservePermissionBubble(true);
+  WatchPositionAndObservePermissionRequest(true);
 }
 
 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, TabDestroyed) {
   ASSERT_NO_FATAL_FAILURE(Initialize(INITIALIZATION_DEFAULT));
-  WatchPositionAndObservePermissionBubble(true);
+  WatchPositionAndObservePermissionRequest(true);
 
   // TODO(mvanouwerkerk): Can't close a window you did not open. Maybe this was
   // valid when the test was written, but now it just prints "Scripts may close
@@ -755,7 +756,7 @@
   clock_->Advance(base::TimeDelta::FromSeconds(3));
 
   // Calling watchPosition should trigger the last usage update.
-  WatchPositionAndObservePermissionBubble(false);
+  WatchPositionAndObservePermissionRequest(false);
   ExpectPosition(fake_latitude(), fake_longitude());
 
   // Last usage has been updated.
diff --git a/chrome/browser/geolocation/geolocation_permission_context_unittest.cc b/chrome/browser/geolocation/geolocation_permission_context_unittest.cc
index ad3a68d67..047dfd3 100644
--- a/chrome/browser/geolocation/geolocation_permission_context_unittest.cc
+++ b/chrome/browser/geolocation/geolocation_permission_context_unittest.cc
@@ -55,8 +55,8 @@
 #include "chrome/browser/geolocation/geolocation_permission_context_android.h"
 #include "components/prefs/pref_service.h"
 #else
+#include "chrome/browser/permissions/permission_request_manager.h"
 #include "chrome/browser/ui/website_settings/mock_permission_bubble_factory.h"
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
 #endif
 
 #if defined(ENABLE_EXTENSIONS)
@@ -150,14 +150,14 @@
   void CheckTabContentsState(const GURL& requesting_frame,
                              ContentSetting expected_content_setting);
 #if !BUILDFLAG(ANDROID_JAVA_UI)
-  void SetupBubbleManager(content::WebContents* web_contents);
-  size_t GetBubblesQueueSize(PermissionBubbleManager* manager);
-  void AcceptBubble(PermissionBubbleManager* manager);
-  void DenyBubble(PermissionBubbleManager* manager);
-  void CloseBubble(PermissionBubbleManager* manager);
+  void SetupRequestManager(content::WebContents* web_contents);
+  size_t GetBubblesQueueSize(PermissionRequestManager* manager);
+  void AcceptBubble(PermissionRequestManager* manager);
+  void DenyBubble(PermissionRequestManager* manager);
+  void CloseBubble(PermissionRequestManager* manager);
 #endif
-  void BubbleManagerDocumentLoadCompleted();
-  void BubbleManagerDocumentLoadCompleted(content::WebContents* web_contents);
+  void RequestManagerDocumentLoadCompleted();
+  void RequestManagerDocumentLoadCompleted(content::WebContents* web_contents);
   ContentSetting GetGeolocationContentSetting(GURL frame_0, GURL frame_1);
   size_t GetNumberOfPrompts();
   void AcceptPrompt();
@@ -254,7 +254,7 @@
 #if BUILDFLAG(ANDROID_JAVA_UI)
   InfoBarService::CreateForWebContents(new_tab);
 #else
-  SetupBubbleManager(new_tab);
+  SetupRequestManager(new_tab);
 #endif
 
   extra_tabs_.push_back(base::WrapUnique(new_tab));
@@ -295,7 +295,7 @@
           std::unique_ptr<LocationSettings>(new MockLocationSettings()));
   MockLocationSettings::SetLocationStatus(true, true);
 #else
-  SetupBubbleManager(web_contents());
+  SetupRequestManager(web_contents());
 #endif
 }
 
@@ -308,51 +308,51 @@
 }
 
 #if !BUILDFLAG(ANDROID_JAVA_UI)
-void GeolocationPermissionContextTests::SetupBubbleManager(
+void GeolocationPermissionContextTests::SetupRequestManager(
     content::WebContents* web_contents) {
-  // Create PermissionBubbleManager.
-  PermissionBubbleManager::CreateForWebContents(web_contents);
-  PermissionBubbleManager* permission_bubble_manager =
-      PermissionBubbleManager::FromWebContents(web_contents);
+  // Create PermissionRequestManager.
+  PermissionRequestManager::CreateForWebContents(web_contents);
+  PermissionRequestManager* permission_request_manager =
+      PermissionRequestManager::FromWebContents(web_contents);
 
-  // Create a MockPermissionBubbleFactory for the PermissionBubbleManager.
+  // Create a MockPermissionBubbleFactory for the PermissionRequestManager.
   mock_permission_bubble_factories_.push_back(base::WrapUnique(
-      new MockPermissionBubbleFactory(permission_bubble_manager)));
+      new MockPermissionBubbleFactory(permission_request_manager)));
 
-  // Prepare the PermissionBubbleManager to display a mock bubble.
-  permission_bubble_manager->DisplayPendingRequests();
+  // Prepare the PermissionRequestManager to display a mock bubble.
+  permission_request_manager->DisplayPendingRequests();
 }
 
 size_t GeolocationPermissionContextTests::GetBubblesQueueSize(
-    PermissionBubbleManager* manager) {
+    PermissionRequestManager* manager) {
   return manager->requests_.size();
 }
 
 void GeolocationPermissionContextTests::AcceptBubble(
-    PermissionBubbleManager* manager) {
+    PermissionRequestManager* manager) {
   manager->Accept();
 }
 
 void GeolocationPermissionContextTests::DenyBubble(
-    PermissionBubbleManager* manager) {
+    PermissionRequestManager* manager) {
   manager->Deny();
 }
 
 void GeolocationPermissionContextTests::CloseBubble(
-    PermissionBubbleManager* manager) {
+    PermissionRequestManager* manager) {
   manager->Closing();
 }
 #endif
 
-void GeolocationPermissionContextTests::BubbleManagerDocumentLoadCompleted() {
-  GeolocationPermissionContextTests::BubbleManagerDocumentLoadCompleted(
+void GeolocationPermissionContextTests::RequestManagerDocumentLoadCompleted() {
+  GeolocationPermissionContextTests::RequestManagerDocumentLoadCompleted(
       web_contents());
 }
 
-void GeolocationPermissionContextTests::BubbleManagerDocumentLoadCompleted(
+void GeolocationPermissionContextTests::RequestManagerDocumentLoadCompleted(
     content::WebContents* web_contents) {
 #if !BUILDFLAG(ANDROID_JAVA_UI)
-  PermissionBubbleManager::FromWebContents(web_contents)->
+  PermissionRequestManager::FromWebContents(web_contents)->
       DocumentOnLoadCompletedInMainFrame();
 #endif
 }
@@ -368,8 +368,8 @@
 
 size_t GeolocationPermissionContextTests::GetNumberOfPrompts() {
 #if !BUILDFLAG(ANDROID_JAVA_UI)
-  PermissionBubbleManager* manager =
-      PermissionBubbleManager::FromWebContents(web_contents());
+  PermissionRequestManager* manager =
+      PermissionRequestManager::FromWebContents(web_contents());
   return GetBubblesQueueSize(manager);
 #else
   return infobar_service()->infobar_count();
@@ -378,8 +378,8 @@
 
 void GeolocationPermissionContextTests::AcceptPrompt() {
 #if !BUILDFLAG(ANDROID_JAVA_UI)
-  PermissionBubbleManager* manager =
-      PermissionBubbleManager::FromWebContents(web_contents());
+  PermissionRequestManager* manager =
+      PermissionRequestManager::FromWebContents(web_contents());
   AcceptBubble(manager);
 #else
   infobars::InfoBar* infobar = infobar_service()->infobar_at(0);
@@ -391,8 +391,8 @@
 
 base::string16 GeolocationPermissionContextTests::GetPromptText() {
 #if !BUILDFLAG(ANDROID_JAVA_UI)
-  PermissionBubbleManager* manager =
-      PermissionBubbleManager::FromWebContents(web_contents());
+  PermissionRequestManager* manager =
+      PermissionRequestManager::FromWebContents(web_contents());
   PermissionBubbleRequest* request = manager->requests_.front();
   return base::ASCIIToUTF16(request->GetOrigin().spec()) +
          request->GetMessageTextFragment();
@@ -409,7 +409,7 @@
 TEST_F(GeolocationPermissionContextTests, SinglePermissionBubble) {
   GURL requesting_frame("https://www.example.com/geolocation");
   NavigateAndCommit(requesting_frame);
-  BubbleManagerDocumentLoadCompleted();
+  RequestManagerDocumentLoadCompleted();
 
   EXPECT_EQ(0U, GetNumberOfPrompts());
   RequestGeolocationPermission(
@@ -421,7 +421,7 @@
        SinglePermissionBubbleFailsOnInsecureOrigin) {
   GURL requesting_frame("http://www.example.com/geolocation");
   NavigateAndCommit(requesting_frame);
-  BubbleManagerDocumentLoadCompleted();
+  RequestManagerDocumentLoadCompleted();
 
   EXPECT_EQ(0U, GetNumberOfPrompts());
   RequestGeolocationPermission(web_contents(), RequestID(0), requesting_frame,
@@ -508,7 +508,7 @@
       GetGeolocationContentSetting(requesting_frame_1, requesting_frame_1));
 
   NavigateAndCommit(requesting_frame_0);
-  BubbleManagerDocumentLoadCompleted();
+  RequestManagerDocumentLoadCompleted();
 
   // Check that no permission requests have happened yet.
   EXPECT_EQ(0U, GetNumberOfPrompts());
@@ -544,8 +544,8 @@
 
   // Cancel (block) this frame.
 #if !BUILDFLAG(ANDROID_JAVA_UI)
-  PermissionBubbleManager* manager =
-      PermissionBubbleManager::FromWebContents(web_contents());
+  PermissionRequestManager* manager =
+      PermissionRequestManager::FromWebContents(web_contents());
   DenyBubble(manager);
 #else
   infobars::InfoBar* infobar_1 = infobar_service()->infobar_at(0);
@@ -569,7 +569,7 @@
 
   // Navigate to the first url.
   NavigateAndCommit(url_a);
-  BubbleManagerDocumentLoadCompleted();
+  RequestManagerDocumentLoadCompleted();
 
   // Check permission is requested.
   ASSERT_EQ(0U, GetNumberOfPrompts());
@@ -584,7 +584,7 @@
 
   // Change the hash, we'll still be on the same page.
   NavigateAndCommit(url_b);
-  BubbleManagerDocumentLoadCompleted();
+  RequestManagerDocumentLoadCompleted();
 
   // Accept.
   AcceptPrompt();
@@ -611,7 +611,7 @@
 TEST_F(GeolocationPermissionContextTests, MAYBE_PermissionForFileScheme) {
   GURL requesting_frame("file://example/geolocation.html");
   NavigateAndCommit(requesting_frame);
-  BubbleManagerDocumentLoadCompleted();
+  RequestManagerDocumentLoadCompleted();
 
   // Check permission is requested.
   ASSERT_EQ(0U, GetNumberOfPrompts());
@@ -639,7 +639,7 @@
       CONTENT_SETTING_ASK, GetGeolocationContentSetting(frame_1, frame_0));
 
   NavigateAndCommit(frame_0);
-  BubbleManagerDocumentLoadCompleted();
+  RequestManagerDocumentLoadCompleted();
 
   ASSERT_EQ(0U, GetNumberOfPrompts());
 
@@ -656,8 +656,8 @@
 
   // Simulate the frame going away; the request should be removed.
 #if !BUILDFLAG(ANDROID_JAVA_UI)
-  PermissionBubbleManager* manager =
-      PermissionBubbleManager::FromWebContents(web_contents());
+  PermissionRequestManager* manager =
+      PermissionRequestManager::FromWebContents(web_contents());
   CloseBubble(manager);
 #else
   geolocation_permission_context_->CancelPermissionRequest(web_contents(),
@@ -685,7 +685,7 @@
   GURL invalid_embedder("about:blank");
   GURL requesting_frame;
   NavigateAndCommit(invalid_embedder);
-  BubbleManagerDocumentLoadCompleted();
+  RequestManagerDocumentLoadCompleted();
 
   // Nothing should be displayed.
   EXPECT_EQ(0U, GetNumberOfPrompts());
@@ -701,16 +701,16 @@
   NavigateAndCommit(url_a);  // Tab A0
   AddNewTab(url_b);          // Tab B (extra_tabs_[0])
   AddNewTab(url_a);          // Tab A1 (extra_tabs_[1])
-  BubbleManagerDocumentLoadCompleted();
-  BubbleManagerDocumentLoadCompleted(extra_tabs_[0].get());
-  BubbleManagerDocumentLoadCompleted(extra_tabs_[1].get());
+  RequestManagerDocumentLoadCompleted();
+  RequestManagerDocumentLoadCompleted(extra_tabs_[0].get());
+  RequestManagerDocumentLoadCompleted(extra_tabs_[1].get());
 #if !BUILDFLAG(ANDROID_JAVA_UI)
-  PermissionBubbleManager* manager_a0 =
-      PermissionBubbleManager::FromWebContents(web_contents());
-  PermissionBubbleManager* manager_b =
-      PermissionBubbleManager::FromWebContents(extra_tabs_[0].get());
-  PermissionBubbleManager* manager_a1 =
-      PermissionBubbleManager::FromWebContents(extra_tabs_[1].get());
+  PermissionRequestManager* manager_a0 =
+      PermissionRequestManager::FromWebContents(web_contents());
+  PermissionRequestManager* manager_b =
+      PermissionRequestManager::FromWebContents(extra_tabs_[0].get());
+  PermissionRequestManager* manager_a1 =
+      PermissionRequestManager::FromWebContents(extra_tabs_[1].get());
 #endif
 
   // Request permission in all three tabs.
@@ -762,12 +762,12 @@
   NavigateAndCommit(url_a);  // Tab A0.
   AddNewTab(url_a);          // Tab A1.
 #if !BUILDFLAG(ANDROID_JAVA_UI)
-  BubbleManagerDocumentLoadCompleted();
-  BubbleManagerDocumentLoadCompleted(extra_tabs_[0].get());
-  PermissionBubbleManager* manager_a0 =
-      PermissionBubbleManager::FromWebContents(web_contents());
-  PermissionBubbleManager* manager_a1 =
-      PermissionBubbleManager::FromWebContents(extra_tabs_[0].get());
+  RequestManagerDocumentLoadCompleted();
+  RequestManagerDocumentLoadCompleted(extra_tabs_[0].get());
+  PermissionRequestManager* manager_a0 =
+      PermissionRequestManager::FromWebContents(web_contents());
+  PermissionRequestManager* manager_a1 =
+      PermissionRequestManager::FromWebContents(extra_tabs_[0].get());
 #endif
 
   // Request permission in both tabs; the extra tab will have two permission
@@ -842,7 +842,7 @@
       GetGeolocationContentSetting(requesting_frame_1, requesting_frame_0));
 
   NavigateAndCommit(requesting_frame_0);
-  BubbleManagerDocumentLoadCompleted();
+  RequestManagerDocumentLoadCompleted();
 
   // Request permission for two frames.
   RequestGeolocationPermission(
@@ -873,7 +873,7 @@
 TEST_F(GeolocationPermissionContextTests, LastUsageAudited) {
   GURL requesting_frame("https://www.example.com/geolocation");
   NavigateAndCommit(requesting_frame);
-  BubbleManagerDocumentLoadCompleted();
+  RequestManagerDocumentLoadCompleted();
 
   base::SimpleTestClock* test_clock = new base::SimpleTestClock;
   test_clock->SetNow(base::Time::UnixEpoch() +
@@ -937,7 +937,7 @@
             0);
 
   NavigateAndCommit(requesting_frame_0);
-  BubbleManagerDocumentLoadCompleted();
+  RequestManagerDocumentLoadCompleted();
 
   EXPECT_EQ(0U, GetNumberOfPrompts());
 
diff --git a/chrome/browser/media/media_stream_device_permission_context_unittest.cc b/chrome/browser/media/media_stream_device_permission_context_unittest.cc
index 9082e45..e3aa150e 100644
--- a/chrome/browser/media/media_stream_device_permission_context_unittest.cc
+++ b/chrome/browser/media/media_stream_device_permission_context_unittest.cc
@@ -22,7 +22,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 #if !defined(OS_ANDROID)
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
+#include "chrome/browser/permissions/permission_request_manager.h"
 #endif
 
 namespace {
@@ -103,7 +103,7 @@
 #if defined(OS_ANDROID)
     InfoBarService::CreateForWebContents(web_contents());
 #else
-    PermissionBubbleManager::CreateForWebContents(web_contents());
+    PermissionRequestManager::CreateForWebContents(web_contents());
 #endif
   }
 
diff --git a/chrome/browser/media/media_stream_devices_controller.cc b/chrome/browser/media/media_stream_devices_controller.cc
index 57e1dbcc..8995a28 100644
--- a/chrome/browser/media/media_stream_devices_controller.cc
+++ b/chrome/browser/media/media_stream_devices_controller.cc
@@ -72,23 +72,25 @@
 }
 
 using PermissionActionCallback =
-    base::Callback<void(content::PermissionType, const GURL&)>;
+    base::Callback<void(content::PermissionType, const GURL&, Profile*)>;
 
 void RecordSinglePermissionAction(const content::MediaStreamRequest& request,
                                   content::PermissionType permission_type,
+                                  Profile* profile,
                                   PermissionActionCallback callback) {
   if (ContentTypeIsRequested(permission_type, request)) {
-    callback.Run(permission_type, request.security_origin);
+    callback.Run(permission_type, request.security_origin, profile);
   }
 }
 
 // Calls |action_function| for each permission requested by |request|.
 void RecordPermissionAction(const content::MediaStreamRequest& request,
+                            Profile* profile,
                             PermissionActionCallback callback) {
   RecordSinglePermissionAction(request, content::PermissionType::AUDIO_CAPTURE,
-                               callback);
+                               profile, callback);
   RecordSinglePermissionAction(request, content::PermissionType::VIDEO_CAPTURE,
-                               callback);
+                               profile, callback);
 }
 
 // This helper class helps to measure the number of media stream requests that
@@ -204,8 +206,8 @@
 
 MediaStreamDevicesController::~MediaStreamDevicesController() {
   if (!callback_.is_null()) {
-    RecordPermissionAction(
-        request_, base::Bind(PermissionUmaUtil::PermissionIgnored));
+    RecordPermissionAction(request_, profile_,
+                           base::Bind(PermissionUmaUtil::PermissionIgnored));
     callback_.Run(content::MediaStreamDevices(),
                   content::MEDIA_DEVICE_FAILED_DUE_TO_SHUTDOWN,
                   std::unique_ptr<content::MediaStreamUI>());
@@ -280,8 +282,8 @@
 }
 
 void MediaStreamDevicesController::PermissionGranted() {
-  RecordPermissionAction(
-      request_, base::Bind(PermissionUmaUtil::PermissionGranted));
+  RecordPermissionAction(request_, profile_,
+                         base::Bind(PermissionUmaUtil::PermissionGranted));
   RunCallback(GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
                             old_audio_setting_, CONTENT_SETTING_ALLOW),
               GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
@@ -290,8 +292,8 @@
 }
 
 void MediaStreamDevicesController::PermissionDenied() {
-  RecordPermissionAction(
-      request_, base::Bind(PermissionUmaUtil::PermissionDenied));
+  RecordPermissionAction(request_, profile_,
+                         base::Bind(PermissionUmaUtil::PermissionDenied));
   RunCallback(GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
                             old_audio_setting_, CONTENT_SETTING_BLOCK),
               GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
@@ -302,11 +304,11 @@
 void MediaStreamDevicesController::GroupedRequestFinished(bool audio_accepted,
                                                           bool video_accepted) {
   RecordSinglePermissionAction(
-      request_, content::PermissionType::AUDIO_CAPTURE,
+      request_, content::PermissionType::AUDIO_CAPTURE, profile_,
       base::Bind(audio_accepted ? PermissionUmaUtil::PermissionGranted
                                 : PermissionUmaUtil::PermissionDenied));
   RecordSinglePermissionAction(
-      request_, content::PermissionType::VIDEO_CAPTURE,
+      request_, content::PermissionType::VIDEO_CAPTURE, profile_,
       base::Bind(video_accepted ? PermissionUmaUtil::PermissionGranted
                                 : PermissionUmaUtil::PermissionDenied));
 
@@ -322,8 +324,8 @@
 }
 
 void MediaStreamDevicesController::Cancelled() {
-  RecordPermissionAction(
-      request_, base::Bind(PermissionUmaUtil::PermissionDismissed));
+  RecordPermissionAction(request_, profile_,
+                         base::Bind(PermissionUmaUtil::PermissionDismissed));
   RunCallback(old_audio_setting_, old_video_setting_,
               content::MEDIA_DEVICE_PERMISSION_DISMISSED);
 }
diff --git a/chrome/browser/media/media_stream_infobar_browsertest.cc b/chrome/browser/media/media_stream_infobar_browsertest.cc
index 1ba1799..51c72282 100644
--- a/chrome/browser/media/media_stream_infobar_browsertest.cc
+++ b/chrome/browser/media/media_stream_infobar_browsertest.cc
@@ -15,7 +15,6 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/test_switches.h"
diff --git a/chrome/browser/media/midi_permission_context_unittest.cc b/chrome/browser/media/midi_permission_context_unittest.cc
index 77675ec..6a73e470 100644
--- a/chrome/browser/media/midi_permission_context_unittest.cc
+++ b/chrome/browser/media/midi_permission_context_unittest.cc
@@ -22,7 +22,7 @@
 #if defined(OS_ANDROID)
 #include "chrome/browser/infobars/infobar_service.h"
 #else
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
+#include "chrome/browser/permissions/permission_request_manager.h"
 #endif
 
 namespace {
@@ -80,7 +80,7 @@
 #if defined(OS_ANDROID)
     InfoBarService::CreateForWebContents(web_contents());
 #else
-    PermissionBubbleManager::CreateForWebContents(web_contents());
+    PermissionRequestManager::CreateForWebContents(web_contents());
 #endif
   }
 
diff --git a/chrome/browser/media/permission_bubble_media_access_handler.cc b/chrome/browser/media/permission_bubble_media_access_handler.cc
index 7a11015..4d2f701 100644
--- a/chrome/browser/media/permission_bubble_media_access_handler.cc
+++ b/chrome/browser/media/permission_bubble_media_access_handler.cc
@@ -27,7 +27,7 @@
 #include "chrome/browser/media/media_stream_infobar_delegate_android.h"
 #include "chrome/browser/permissions/permission_update_infobar_delegate_android.h"
 #else
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
+#include "chrome/browser/permissions/permission_request_manager.h"
 #endif  // BUILDFLAG(ANDROID_JAVA_UI)
 
 #if BUILDFLAG(ANDROID_JAVA_UI)
@@ -163,10 +163,10 @@
   MediaStreamInfoBarDelegateAndroid::Create(web_contents,
                                             std::move(controller));
 #else
-  PermissionBubbleManager* bubble_manager =
-      PermissionBubbleManager::FromWebContents(web_contents);
-  if (bubble_manager)
-    bubble_manager->AddRequest(controller.release());
+  PermissionRequestManager* permission_request_manager =
+      PermissionRequestManager::FromWebContents(web_contents);
+  if (permission_request_manager)
+    permission_request_manager->AddRequest(controller.release());
 #endif
 }
 
diff --git a/chrome/browser/media/router/mojo/media_router_mojo_impl_unittest.cc b/chrome/browser/media/router/mojo/media_router_mojo_impl_unittest.cc
index c56fba5a..3769258 100644
--- a/chrome/browser/media/router/mojo/media_router_mojo_impl_unittest.cc
+++ b/chrome/browser/media/router/mojo/media_router_mojo_impl_unittest.cc
@@ -1289,6 +1289,9 @@
   void TearDown() override {
     media_router_.reset();
     profile_.reset();
+    // Explicitly delete the TestingBrowserProcess before |thread_bundle_|.
+    // This allows it to do cleanup before |thread_bundle_| goes away.
+    TestingBrowserProcess::DeleteInstance();
   }
 
   // Constructs bindings so that |media_router_| delegates calls to
diff --git a/chrome/browser/media/webrtc_apprtc_browsertest.cc b/chrome/browser/media/webrtc_apprtc_browsertest.cc
index 0af80d4..52cde589 100644
--- a/chrome/browser/media/webrtc_apprtc_browsertest.cc
+++ b/chrome/browser/media/webrtc_apprtc_browsertest.cc
@@ -14,10 +14,10 @@
 #include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/browser/media/webrtc_browsertest_base.h"
 #include "chrome/browser/media/webrtc_browsertest_common.h"
+#include "chrome/browser/permissions/permission_request_manager.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/common/content_switches.h"
@@ -243,8 +243,8 @@
   chrome::AddTabAt(browser(), GURL(), -1, true);
   content::WebContents* left_tab =
       browser()->tab_strip_model()->GetActiveWebContents();
-  PermissionBubbleManager::FromWebContents(left_tab)
-      ->set_auto_response_for_test(PermissionBubbleManager::ACCEPT_ALL);
+  PermissionRequestManager::FromWebContents(left_tab)
+      ->set_auto_response_for_test(PermissionRequestManager::ACCEPT_ALL);
   InfoBarResponder left_infobar_responder(
       InfoBarService::FromWebContents(left_tab), InfoBarResponder::ACCEPT);
   ui_test_utils::NavigateToURL(browser(), room_url);
@@ -253,8 +253,8 @@
   chrome::AddTabAt(browser(), GURL(), -1, true);
   content::WebContents* right_tab =
       browser()->tab_strip_model()->GetActiveWebContents();
-  PermissionBubbleManager::FromWebContents(right_tab)
-      ->set_auto_response_for_test(PermissionBubbleManager::ACCEPT_ALL);
+  PermissionRequestManager::FromWebContents(right_tab)
+      ->set_auto_response_for_test(PermissionRequestManager::ACCEPT_ALL);
   InfoBarResponder right_infobar_responder(
       InfoBarService::FromWebContents(right_tab), InfoBarResponder::ACCEPT);
   ui_test_utils::NavigateToURL(browser(), room_url);
@@ -291,8 +291,8 @@
   chrome::AddTabAt(browser(), GURL(), -1, true);
   content::WebContents* chrome_tab =
       browser()->tab_strip_model()->GetActiveWebContents();
-  PermissionBubbleManager::FromWebContents(chrome_tab)
-      ->set_auto_response_for_test(PermissionBubbleManager::ACCEPT_ALL);
+  PermissionRequestManager::FromWebContents(chrome_tab)
+      ->set_auto_response_for_test(PermissionRequestManager::ACCEPT_ALL);
   InfoBarResponder infobar_responder(
       InfoBarService::FromWebContents(chrome_tab), InfoBarResponder::ACCEPT);
   ui_test_utils::NavigateToURL(browser(), room_url);
diff --git a/chrome/browser/media/webrtc_browsertest_base.cc b/chrome/browser/media/webrtc_browsertest_base.cc
index 9a40c5b..2213da9 100644
--- a/chrome/browser/media/webrtc_browsertest_base.cc
+++ b/chrome/browser/media/webrtc_browsertest_base.cc
@@ -12,10 +12,10 @@
 #include "base/strings/stringprintf.h"
 #include "build/build_config.h"
 #include "chrome/browser/media/webrtc_browsertest_common.h"
+#include "chrome/browser/permissions/permission_request_manager.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/test/browser_test_utils.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
@@ -87,17 +87,18 @@
 // PermissionRequestObserver ---------------------------------------------------
 
 // Used to observe the creation of permission prompt without responding.
-class PermissionRequestObserver : public PermissionBubbleManager::Observer {
+class PermissionRequestObserver : public PermissionRequestManager::Observer {
  public:
   explicit PermissionRequestObserver(content::WebContents* web_contents)
-      : bubble_manager_(PermissionBubbleManager::FromWebContents(web_contents)),
+      : request_manager_(
+            PermissionRequestManager::FromWebContents(web_contents)),
         request_shown_(false),
         message_loop_runner_(new content::MessageLoopRunner) {
-    bubble_manager_->AddObserver(this);
+    request_manager_->AddObserver(this);
   }
   ~PermissionRequestObserver() override {
     // Safe to remove twice if it happens.
-    bubble_manager_->RemoveObserver(this);
+    request_manager_->RemoveObserver(this);
   }
 
   void Wait() { message_loop_runner_->Run(); }
@@ -105,14 +106,14 @@
   bool request_shown() const { return request_shown_; }
 
  private:
-  // PermissionBubbleManager::Observer
+  // PermissionRequestManager::Observer
   void OnBubbleAdded() override {
     request_shown_ = true;
-    bubble_manager_->RemoveObserver(this);
+    request_manager_->RemoveObserver(this);
     message_loop_runner_->Quit();
   }
 
-  PermissionBubbleManager* bubble_manager_;
+  PermissionRequestManager* request_manager_;
   bool request_shown_;
   scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
 
@@ -148,8 +149,8 @@
     content::WebContents* tab_contents,
     const std::string& constraints) const {
   std::string result;
-  PermissionBubbleManager::FromWebContents(tab_contents)
-      ->set_auto_response_for_test(PermissionBubbleManager::ACCEPT_ALL);
+  PermissionRequestManager::FromWebContents(tab_contents)
+      ->set_auto_response_for_test(PermissionRequestManager::ACCEPT_ALL);
   PermissionRequestObserver permissionRequestObserver(tab_contents);
   GetUserMedia(tab_contents, constraints);
   EXPECT_TRUE(permissionRequestObserver.request_shown());
@@ -162,8 +163,8 @@
     content::WebContents* tab_contents,
     const std::string& constraints) const {
   std::string result;
-  PermissionBubbleManager::FromWebContents(tab_contents)
-      ->set_auto_response_for_test(PermissionBubbleManager::ACCEPT_ALL);
+  PermissionRequestManager::FromWebContents(tab_contents)
+      ->set_auto_response_for_test(PermissionRequestManager::ACCEPT_ALL);
   GetUserMedia(tab_contents, constraints);
   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
       tab_contents->GetMainFrame(), "obtainGetUserMediaResult();", &result));
@@ -179,8 +180,8 @@
     content::WebContents* tab_contents,
     const std::string& constraints) const {
   std::string result;
-  PermissionBubbleManager::FromWebContents(tab_contents)
-      ->set_auto_response_for_test(PermissionBubbleManager::DENY_ALL);
+  PermissionRequestManager::FromWebContents(tab_contents)
+      ->set_auto_response_for_test(PermissionRequestManager::DENY_ALL);
   PermissionRequestObserver permissionRequestObserver(tab_contents);
   GetUserMedia(tab_contents, constraints);
   EXPECT_TRUE(permissionRequestObserver.request_shown());
@@ -192,8 +193,8 @@
 void WebRtcTestBase::GetUserMediaAndDismiss(
     content::WebContents* tab_contents) const {
   std::string result;
-  PermissionBubbleManager::FromWebContents(tab_contents)
-      ->set_auto_response_for_test(PermissionBubbleManager::DISMISS);
+  PermissionRequestManager::FromWebContents(tab_contents)
+      ->set_auto_response_for_test(PermissionRequestManager::DISMISS);
   PermissionRequestObserver permissionRequestObserver(tab_contents);
   GetUserMedia(tab_contents, kAudioVideoCallConstraints);
   EXPECT_TRUE(permissionRequestObserver.request_shown());
@@ -214,8 +215,8 @@
   // we set an auto-response to avoid leaving the prompt hanging. The choice of
   // DENY_ALL makes sure that the response to the prompt doesn't accidentally
   // result in a newly granted media stream permission.
-  PermissionBubbleManager::FromWebContents(tab_contents)
-      ->set_auto_response_for_test(PermissionBubbleManager::DENY_ALL);
+  PermissionRequestManager::FromWebContents(tab_contents)
+      ->set_auto_response_for_test(PermissionRequestManager::DENY_ALL);
   PermissionRequestObserver permissionRequestObserver(tab_contents);
   GetUserMedia(tab_contents, kAudioVideoCallConstraints);
   EXPECT_FALSE(permissionRequestObserver.request_shown());
@@ -235,8 +236,8 @@
   // we set an auto-response to avoid leaving the prompt hanging. The choice of
   // ACCEPT_ALL makes sure that the response to the prompt doesn't accidentally
   // result in a newly granted media stream permission.
-  PermissionBubbleManager::FromWebContents(tab_contents)
-      ->set_auto_response_for_test(PermissionBubbleManager::ACCEPT_ALL);
+  PermissionRequestManager::FromWebContents(tab_contents)
+      ->set_auto_response_for_test(PermissionRequestManager::ACCEPT_ALL);
   PermissionRequestObserver permissionRequestObserver(tab_contents);
   GetUserMedia(tab_contents, kAudioVideoCallConstraints);
   EXPECT_FALSE(permissionRequestObserver.request_shown());
@@ -271,8 +272,8 @@
       browser()->tab_strip_model()->GetActiveWebContents();
   // Accept if necessary, but don't expect a prompt (because auto-accept is also
   // okay).
-  PermissionBubbleManager::FromWebContents(new_tab)
-      ->set_auto_response_for_test(PermissionBubbleManager::ACCEPT_ALL);
+  PermissionRequestManager::FromWebContents(new_tab)
+      ->set_auto_response_for_test(PermissionRequestManager::ACCEPT_ALL);
   GetUserMedia(new_tab, constraints);
   std::string result;
   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
diff --git a/chrome/browser/media_galleries/media_gallery_context_menu.cc b/chrome/browser/media_galleries/media_gallery_context_menu.cc
index 1e637a1..79d021d 100644
--- a/chrome/browser/media_galleries/media_gallery_context_menu.cc
+++ b/chrome/browser/media_galleries/media_gallery_context_menu.cc
@@ -30,7 +30,8 @@
 }
 
 bool MediaGalleryContextMenu::GetAcceleratorForCommandId(
-    int command_id, ui::Accelerator* accelerator) {
+    int command_id,
+    ui::Accelerator* accelerator) const {
   return false;
 }
 
diff --git a/chrome/browser/media_galleries/media_gallery_context_menu.h b/chrome/browser/media_galleries/media_gallery_context_menu.h
index 35bc8c6..f3a44452 100644
--- a/chrome/browser/media_galleries/media_gallery_context_menu.h
+++ b/chrome/browser/media_galleries/media_gallery_context_menu.h
@@ -28,7 +28,7 @@
   bool IsCommandIdEnabled(int command_id) const override;
   bool IsCommandIdVisible(int command_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
 
  private:
diff --git a/chrome/browser/memory/tab_manager_delegate_chromeos.cc b/chrome/browser/memory/tab_manager_delegate_chromeos.cc
index 482efe3..9345322 100644
--- a/chrome/browser/memory/tab_manager_delegate_chromeos.cc
+++ b/chrome/browser/memory/tab_manager_delegate_chromeos.cc
@@ -284,15 +284,14 @@
 }
 
 class TabManagerDelegate::UmaReporter {
-  public:
-   UmaReporter()
-       : last_kill_time_(), total_kills_(0) {}
-   ~UmaReporter() {}
-   void ReportKill(const int memory_freed);
+ public:
+  UmaReporter() : last_kill_time_(), total_kills_(0) {}
+  ~UmaReporter() {}
+  void ReportKill(const int memory_freed);
 
-  private:
-   base::Time last_kill_time_;
-   int total_kills_;
+ private:
+  base::Time last_kill_time_;
+  int total_kills_;
 };
 
 void TabManagerDelegate::UmaReporter::ReportKill(const int memory_freed) {
@@ -336,7 +335,7 @@
                  content::NotificationService::AllBrowserContextsAndSources());
   auto arc_bridge_service = arc::ArcBridgeService::Get();
   if (arc_bridge_service)
-    arc_bridge_service->AddObserver(this);
+    arc_bridge_service->process()->AddObserver(this);
   auto activation_client = GetActivationClient();
   if (activation_client)
     activation_client->AddObserver(this);
@@ -350,7 +349,7 @@
     activation_client->RemoveObserver(this);
   auto arc_bridge_service = arc::ArcBridgeService::Get();
   if (arc_bridge_service)
-    arc_bridge_service->RemoveObserver(this);
+    arc_bridge_service->process()->RemoveObserver(this);
 }
 
 void TabManagerDelegate::OnBrowserSetLastActive(Browser* browser) {
@@ -369,12 +368,12 @@
   AdjustFocusedTabScore(pid);
 }
 
-void TabManagerDelegate::OnProcessInstanceReady() {
+void TabManagerDelegate::OnInstanceReady() {
   auto arc_bridge_service = arc::ArcBridgeService::Get();
   DCHECK(arc_bridge_service);
 
-  arc_process_instance_ = arc_bridge_service->process_instance();
-  arc_process_instance_version_ = arc_bridge_service->process_version();
+  arc_process_instance_ = arc_bridge_service->process()->instance();
+  arc_process_instance_version_ = arc_bridge_service->process()->version();
 
   DCHECK(arc_process_instance_);
 
@@ -399,7 +398,7 @@
   arc_process_instance_->DisableLowMemoryKiller();
 }
 
-void TabManagerDelegate::OnProcessInstanceClosed() {
+void TabManagerDelegate::OnInstanceClosed() {
   arc_process_instance_ = nullptr;
   arc_process_instance_version_ = 0;
 }
diff --git a/chrome/browser/memory/tab_manager_delegate_chromeos.h b/chrome/browser/memory/tab_manager_delegate_chromeos.h
index 3722980..85e985e 100644
--- a/chrome/browser/memory/tab_manager_delegate_chromeos.h
+++ b/chrome/browser/memory/tab_manager_delegate_chromeos.h
@@ -20,6 +20,7 @@
 #include "chrome/browser/memory/tab_stats.h"
 #include "chrome/browser/ui/browser_list_observer.h"
 #include "components/arc/arc_bridge_service.h"
+#include "components/arc/instance_holder.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "ui/wm/public/activation_change_observer.h"
@@ -75,10 +76,11 @@
 // Note that AdjustOomPriorities will be called on the UI thread by
 // TabManager, but the actual work will take place on the file thread
 // (see implementation of AdjustOomPriorities).
-class TabManagerDelegate : public arc::ArcBridgeService::Observer,
-                           public aura::client::ActivationChangeObserver,
-                           public content::NotificationObserver,
-                           public chrome::BrowserListObserver {
+class TabManagerDelegate
+    : public arc::InstanceHolder<arc::mojom::ProcessInstance>::Observer,
+      public aura::client::ActivationChangeObserver,
+      public content::NotificationObserver,
+      public chrome::BrowserListObserver {
  public:
   class MemoryStat;
 
@@ -91,9 +93,9 @@
 
   void OnBrowserSetLastActive(Browser* browser) override;
 
-  // ArcBridgeService::Observer overrides.
-  void OnProcessInstanceReady() override;
-  void OnProcessInstanceClosed() override;
+  // InstanceHolder<arc::mojom::ProcessInstance>::Observer overrides.
+  void OnInstanceReady() override;
+  void OnInstanceClosed() override;
 
   // aura::ActivationChangeObserver overrides.
   void OnWindowActivated(
@@ -136,8 +138,8 @@
   class FocusedProcess;
   class UmaReporter;
 
-  friend std::ostream& operator<<(
-      std::ostream& out, const Candidate& candidate);
+  friend std::ostream& operator<<(std::ostream& out,
+                                  const Candidate& candidate);
 
   // content::NotificationObserver:
   void Observe(int type,
@@ -148,7 +150,7 @@
   typedef std::pair<int, base::ProcessHandle> ProcessInfo;
 
   // Cache OOM scores in memory.
-  typedef base::hash_map<base::ProcessHandle, int> ProcessScoreMap;
+  typedef base::hash_map<base::ProcessHandle, int> ProcessScoreMap;  // NOLINT
 
   // Get the list of candidates to kill, sorted by reversed importance.
   static std::vector<Candidate> GetSortedCandidates(
@@ -243,9 +245,7 @@
   Candidate(const arc::ArcProcess* _app, int _priority)
       : app(_app), priority(_priority), is_arc_app(true) {}
 
-  bool operator<(const Candidate& rhs) const {
-    return priority < rhs.priority;
-  }
+  bool operator<(const Candidate& rhs) const { return priority < rhs.priority; }
 
   union {
     const TabStats* tab;
diff --git a/chrome/browser/notifications/notification_interactive_uitest.cc b/chrome/browser/notifications/notification_interactive_uitest.cc
index 454830e..453fb59 100644
--- a/chrome/browser/notifications/notification_interactive_uitest.cc
+++ b/chrome/browser/notifications/notification_interactive_uitest.cc
@@ -23,12 +23,12 @@
 #include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/browser/notifications/desktop_notification_profile_util.h"
 #include "chrome/browser/notifications/notification.h"
+#include "chrome/browser/permissions/permission_request_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
@@ -141,17 +141,18 @@
 };
 
 // Used to observe the creation of permission prompt without responding.
-class PermissionRequestObserver : public PermissionBubbleManager::Observer {
+class PermissionRequestObserver : public PermissionRequestManager::Observer {
  public:
   explicit PermissionRequestObserver(content::WebContents* web_contents)
-      : bubble_manager_(PermissionBubbleManager::FromWebContents(web_contents)),
+      : request_manager_(
+            PermissionRequestManager::FromWebContents(web_contents)),
         request_shown_(false),
         message_loop_runner_(new content::MessageLoopRunner) {
-    bubble_manager_->AddObserver(this);
+    request_manager_->AddObserver(this);
   }
   ~PermissionRequestObserver() override {
     // Safe to remove twice if it happens.
-    bubble_manager_->RemoveObserver(this);
+    request_manager_->RemoveObserver(this);
   }
 
   void Wait() { message_loop_runner_->Run(); }
@@ -159,14 +160,14 @@
   bool request_shown() { return request_shown_; }
 
  private:
-  // PermissionBubbleManager::Observer
+  // PermissionRequestManager::Observer
   void OnBubbleAdded() override {
     request_shown_ = true;
-    bubble_manager_->RemoveObserver(this);
+    request_manager_->RemoveObserver(this);
     message_loop_runner_->Quit();
   }
 
-  PermissionBubbleManager* bubble_manager_;
+  PermissionRequestManager* request_manager_;
   bool request_shown_;
   scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
 
@@ -226,7 +227,7 @@
   void DropOriginPreference(const GURL& origin);
   std::string RequestAndRespondToPermission(
       Browser* browser,
-      PermissionBubbleManager::AutoResponseType bubble_response);
+      PermissionRequestManager::AutoResponseType bubble_response);
 };
 
 int NotificationsTest::GetNotificationCount() {
@@ -303,10 +304,10 @@
 
 std::string NotificationsTest::RequestAndRespondToPermission(
     Browser* browser,
-    PermissionBubbleManager::AutoResponseType bubble_response) {
+    PermissionRequestManager::AutoResponseType bubble_response) {
   std::string result;
   content::WebContents* web_contents = GetActiveWebContents(browser);
-  PermissionBubbleManager::FromWebContents(web_contents)
+  PermissionRequestManager::FromWebContents(web_contents)
       ->set_auto_response_for_test(bubble_response);
   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
       web_contents, "requestPermission();", &result));
@@ -315,19 +316,19 @@
 
 bool NotificationsTest::RequestAndAcceptPermission(Browser* browser) {
   std::string result = RequestAndRespondToPermission(
-      browser, PermissionBubbleManager::ACCEPT_ALL);
+      browser, PermissionRequestManager::ACCEPT_ALL);
   return "request-callback-granted" == result;
 }
 
 bool NotificationsTest::RequestAndDenyPermission(Browser* browser) {
-  std::string result =
-      RequestAndRespondToPermission(browser, PermissionBubbleManager::DENY_ALL);
+  std::string result = RequestAndRespondToPermission(
+      browser, PermissionRequestManager::DENY_ALL);
   return "request-callback-denied" == result;
 }
 
 bool NotificationsTest::RequestAndDismissPermission(Browser* browser) {
   std::string result =
-      RequestAndRespondToPermission(browser, PermissionBubbleManager::DISMISS);
+      RequestAndRespondToPermission(browser, PermissionRequestManager::DISMISS);
   return "request-callback-default" == result;
 }
 
diff --git a/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc b/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc
index 3d5530f..ddfa643 100644
--- a/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc
+++ b/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc
@@ -17,9 +17,9 @@
 #include "chrome/browser/notifications/notification_test_util.h"
 #include "chrome/browser/notifications/platform_notification_service_impl.h"
 #include "chrome/browser/permissions/permission_manager.h"
+#include "chrome/browser/permissions/permission_request_manager.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
@@ -87,7 +87,7 @@
 
  private:
   std::string RequestAndRespondToPermission(
-      PermissionBubbleManager::AutoResponseType bubble_response);
+      PermissionRequestManager::AutoResponseType bubble_response);
 
   content::WebContents* GetActiveWebContents(Browser* browser) {
     return browser->tab_strip_model()->GetActiveWebContents();
@@ -175,10 +175,10 @@
 
 std::string
 PlatformNotificationServiceBrowserTest::RequestAndRespondToPermission(
-    PermissionBubbleManager::AutoResponseType bubble_response) {
+    PermissionRequestManager::AutoResponseType bubble_response) {
   std::string result;
   content::WebContents* web_contents = GetActiveWebContents(browser());
-  PermissionBubbleManager::FromWebContents(web_contents)
+  PermissionRequestManager::FromWebContents(web_contents)
       ->set_auto_response_for_test(bubble_response);
   EXPECT_TRUE(RunScript("RequestPermission();", &result));
   return result;
@@ -186,13 +186,13 @@
 
 bool PlatformNotificationServiceBrowserTest::RequestAndAcceptPermission() {
   std::string result =
-      RequestAndRespondToPermission(PermissionBubbleManager::ACCEPT_ALL);
+      RequestAndRespondToPermission(PermissionRequestManager::ACCEPT_ALL);
   return "granted" == result;
 }
 
 bool PlatformNotificationServiceBrowserTest::RequestAndDenyPermission() {
   std::string result =
-      RequestAndRespondToPermission(PermissionBubbleManager::DENY_ALL);
+      RequestAndRespondToPermission(PermissionRequestManager::DENY_ALL);
   return "denied" == result;
 }
 
diff --git a/chrome/browser/ntp_snippets/ntp_snippets_service_factory.cc b/chrome/browser/ntp_snippets/ntp_snippets_service_factory.cc
index ab7bfc0..4e3a6865 100644
--- a/chrome/browser/ntp_snippets/ntp_snippets_service_factory.cc
+++ b/chrome/browser/ntp_snippets/ntp_snippets_service_factory.cc
@@ -9,6 +9,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/memory/singleton.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/ntp_snippets/content_suggestions_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search/suggestions/image_decoder_impl.h"
 #include "chrome/browser/search/suggestions/suggestions_service_factory.h"
@@ -22,6 +23,7 @@
 #include "components/image_fetcher/image_fetcher.h"
 #include "components/image_fetcher/image_fetcher_impl.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "components/ntp_snippets/content_suggestions_service.h"
 #include "components/ntp_snippets/ntp_snippets_constants.h"
 #include "components/ntp_snippets/ntp_snippets_database.h"
 #include "components/ntp_snippets/ntp_snippets_fetcher.h"
@@ -48,6 +50,7 @@
 using suggestions::ImageDecoderImpl;
 using suggestions::SuggestionsService;
 using suggestions::SuggestionsServiceFactory;
+using ntp_snippets::ContentSuggestionsService;
 
 // static
 NTPSnippetsServiceFactory* NTPSnippetsServiceFactory::GetInstance() {
@@ -70,6 +73,7 @@
   DependsOn(ProfileSyncServiceFactory::GetInstance());
   DependsOn(SigninManagerFactory::GetInstance());
   DependsOn(SuggestionsServiceFactory::GetInstance());
+  DependsOn(ContentSuggestionsServiceFactory::GetInstance());
 }
 
 NTPSnippetsServiceFactory::~NTPSnippetsServiceFactory() {}
@@ -78,6 +82,13 @@
     content::BrowserContext* context) const {
   Profile* profile = Profile::FromBrowserContext(context);
 
+  ContentSuggestionsService* content_suggestions_service =
+      ContentSuggestionsServiceFactory::GetForProfile(profile);
+  // TODO(pke): When the AndroidBridge does not access the NTPSnippetsService
+  // directly anymore (for retrieving content), the NTPSnippetsService does not
+  // need to be created if content_suggestions_service->state() == DISABLED,
+  // just return nullptr then and remove the other "if" below.
+
   // TODO(mvanouwerkerk): Move the enable logic into the service once we start
   // observing pref changes.
   bool enabled = false;
@@ -111,18 +122,25 @@
               base::SequencedWorkerPool::GetSequenceToken(),
               base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
 
-  return new ntp_snippets::NTPSnippetsService(
-      enabled, profile->GetPrefs(), suggestions_service,
-      g_browser_process->GetApplicationLocale(), scheduler,
-      base::MakeUnique<ntp_snippets::NTPSnippetsFetcher>(
-          signin_manager, token_service, request_context,
-          base::Bind(&safe_json::SafeJsonParser::Parse),
-          chrome::GetChannel() == version_info::Channel::STABLE),
-      base::MakeUnique<ImageFetcherImpl>(
-          base::MakeUnique<ImageDecoderImpl>(), request_context.get()),
-      base::MakeUnique<ImageDecoderImpl>(),
-      base::MakeUnique<ntp_snippets::NTPSnippetsDatabase>(database_dir,
-                                                          task_runner),
-      base::MakeUnique<ntp_snippets::NTPSnippetsStatusService>(signin_manager,
-                                                               sync_service));
+  ntp_snippets::NTPSnippetsService* ntp_snippets_service =
+      new ntp_snippets::NTPSnippetsService(
+          enabled, profile->GetPrefs(), suggestions_service,
+          g_browser_process->GetApplicationLocale(), scheduler,
+          base::MakeUnique<ntp_snippets::NTPSnippetsFetcher>(
+              signin_manager, token_service, request_context,
+              base::Bind(&safe_json::SafeJsonParser::Parse),
+              chrome::GetChannel() == version_info::Channel::STABLE),
+          base::MakeUnique<ImageFetcherImpl>(
+              base::MakeUnique<ImageDecoderImpl>(), request_context.get()),
+          base::MakeUnique<ImageDecoderImpl>(),
+          base::MakeUnique<ntp_snippets::NTPSnippetsDatabase>(database_dir,
+                                                              task_runner),
+          base::MakeUnique<ntp_snippets::NTPSnippetsStatusService>(
+              signin_manager, sync_service));
+
+  if (content_suggestions_service->state() ==
+      ContentSuggestionsService::State::ENABLED) {
+    content_suggestions_service->RegisterProvider(ntp_snippets_service);
+  }
+  return ntp_snippets_service;
 }
diff --git a/chrome/browser/password_manager/native_backend_gnome_x.cc b/chrome/browser/password_manager/native_backend_gnome_x.cc
index 75dde044..5b3e38e 100644
--- a/chrome/browser/password_manager/native_backend_gnome_x.cc
+++ b/chrome/browser/password_manager/native_backend_gnome_x.cc
@@ -699,14 +699,15 @@
   return RemoveLoginsBetween(delete_begin, delete_end, SYNC_TIMESTAMP, changes);
 }
 
-bool NativeBackendGnome::DisableAutoSignInForAllLogins(
+bool NativeBackendGnome::DisableAutoSignInForOrigins(
+    const base::Callback<bool(const GURL&)>& origin_filter,
     password_manager::PasswordStoreChangeList* changes) {
   ScopedVector<PasswordForm> forms;
   if (!GetAllLogins(&forms))
     return false;
 
   for (auto& form : forms) {
-    if (!form->skip_zero_click) {
+    if (origin_filter.Run(form->origin) && !form->skip_zero_click) {
       form->skip_zero_click = true;
       if (!UpdateLogin(*form, changes))
         return false;
diff --git a/chrome/browser/password_manager/native_backend_gnome_x.h b/chrome/browser/password_manager/native_backend_gnome_x.h
index 1867bcf..7c81abce 100644
--- a/chrome/browser/password_manager/native_backend_gnome_x.h
+++ b/chrome/browser/password_manager/native_backend_gnome_x.h
@@ -107,7 +107,8 @@
       base::Time delete_begin,
       base::Time delete_end,
       password_manager::PasswordStoreChangeList* changes) override;
-  bool DisableAutoSignInForAllLogins(
+  bool DisableAutoSignInForOrigins(
+      const base::Callback<bool(const GURL&)>& origin_filter,
       password_manager::PasswordStoreChangeList* changes) override;
   bool GetLogins(const autofill::PasswordForm& form,
                  ScopedVector<autofill::PasswordForm>* forms) override;
diff --git a/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc b/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc
index 6875891..5f0d40b 100644
--- a/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc
+++ b/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc
@@ -1177,7 +1177,7 @@
   CheckRemoveLoginsBetween(SYNCED);
 }
 
-TEST_F(NativeBackendGnomeTest, DisableAutoSignInForAllLogins) {
+TEST_F(NativeBackendGnomeTest, DisableAutoSignInForOrigins) {
   NativeBackendGnome backend(42);
   backend.Init();
   form_google_.skip_zero_click = false;
@@ -1204,20 +1204,25 @@
   PasswordStoreChangeList expected_changes;
   expected_changes.push_back(
       PasswordStoreChange(PasswordStoreChange::UPDATE, form_facebook_));
-  expected_changes.push_back(
-      PasswordStoreChange(PasswordStoreChange::UPDATE, form_google_));
 
   PasswordStoreChangeList changes;
   BrowserThread::PostTaskAndReplyWithResult(
       BrowserThread::DB, FROM_HERE,
-      base::Bind(&NativeBackendGnome::DisableAutoSignInForAllLogins,
-                 base::Unretained(&backend), &changes),
+      base::Bind(&NativeBackendGnome::DisableAutoSignInForOrigins,
+                 base::Unretained(&backend),
+                 base::Bind(&GURL::operator==,
+                            base::Unretained(&form_facebook_.origin)),
+                 &changes),
       base::Bind(&CheckPasswordChangesWithResult, &expected_changes, &changes));
   RunBothThreads();
 
   EXPECT_EQ(2u, mock_keyring_items.size());
-  for (const auto& item : mock_keyring_items)
-    CheckUint32Attribute(&item, "should_skip_zero_click", 1);
+  CheckStringAttribute(
+      &mock_keyring_items[0], "origin_url", form_google_.origin.spec());
+  CheckUint32Attribute(&mock_keyring_items[0], "should_skip_zero_click", 0);
+  CheckStringAttribute(
+      &mock_keyring_items[1], "origin_url", form_facebook_.origin.spec());
+  CheckUint32Attribute(&mock_keyring_items[1], "should_skip_zero_click", 1);
 }
 
 TEST_F(NativeBackendGnomeTest, ReadDuplicateForms) {
diff --git a/chrome/browser/password_manager/native_backend_kwallet_x.cc b/chrome/browser/password_manager/native_backend_kwallet_x.cc
index 08813a2..a2346ba 100644
--- a/chrome/browser/password_manager/native_backend_kwallet_x.cc
+++ b/chrome/browser/password_manager/native_backend_kwallet_x.cc
@@ -502,14 +502,15 @@
   return RemoveLoginsBetween(delete_begin, delete_end, SYNC_TIMESTAMP, changes);
 }
 
-bool NativeBackendKWallet::DisableAutoSignInForAllLogins(
+bool NativeBackendKWallet::DisableAutoSignInForOrigins(
+    const base::Callback<bool(const GURL&)>& origin_filter,
     password_manager::PasswordStoreChangeList* changes) {
   ScopedVector<autofill::PasswordForm> all_forms;
   if (!GetAllLogins(&all_forms))
     return false;
 
   for (auto& form : all_forms) {
-    if (!form->skip_zero_click) {
+    if (origin_filter.Run(form->origin) && !form->skip_zero_click) {
       form->skip_zero_click = true;
       if (!UpdateLogin(*form, changes))
         return false;
diff --git a/chrome/browser/password_manager/native_backend_kwallet_x.h b/chrome/browser/password_manager/native_backend_kwallet_x.h
index 313f7c4b..bad33d1 100644
--- a/chrome/browser/password_manager/native_backend_kwallet_x.h
+++ b/chrome/browser/password_manager/native_backend_kwallet_x.h
@@ -54,7 +54,8 @@
       base::Time delete_begin,
       base::Time delete_end,
       password_manager::PasswordStoreChangeList* changes) override;
-  bool DisableAutoSignInForAllLogins(
+  bool DisableAutoSignInForOrigins(
+      const base::Callback<bool(const GURL&)>& origin_filter,
       password_manager::PasswordStoreChangeList* changes) override;
   bool GetLogins(const autofill::PasswordForm& form,
                  ScopedVector<autofill::PasswordForm>* forms) override;
diff --git a/chrome/browser/password_manager/native_backend_kwallet_x_unittest.cc b/chrome/browser/password_manager/native_backend_kwallet_x_unittest.cc
index d892a71a..ac77b99 100644
--- a/chrome/browser/password_manager/native_backend_kwallet_x_unittest.cc
+++ b/chrome/browser/password_manager/native_backend_kwallet_x_unittest.cc
@@ -13,6 +13,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/callback.h"
 #include "base/location.h"
 #include "base/pickle.h"
 #include "base/single_thread_task_runner.h"
@@ -1000,15 +1001,20 @@
   TestRemoveLoginsBetween(SYNCED);
 }
 
-TEST_P(NativeBackendKWalletTest, DisableAutoSignInForAllLogins) {
+TEST_P(NativeBackendKWalletTest, DisableAutoSignInForOrigins) {
   NativeBackendKWalletStub backend(42, desktop_env_);
   EXPECT_TRUE(backend.InitWithBus(mock_session_bus_));
 
+  form_isc_.skip_zero_click = false;
   form_google_.skip_zero_click = false;
 
   BrowserThread::PostTask(
       BrowserThread::DB, FROM_HERE,
       base::Bind(base::IgnoreResult(&NativeBackendKWallet::AddLogin),
+                 base::Unretained(&backend), form_isc_));
+  BrowserThread::PostTask(
+      BrowserThread::DB, FROM_HERE,
+      base::Bind(base::IgnoreResult(&NativeBackendKWallet::AddLogin),
                  base::Unretained(&backend), form_google_));
 
   RunDBThread();
@@ -1022,8 +1028,11 @@
   PasswordStoreChangeList changes;
   BrowserThread::PostTaskAndReplyWithResult(
       BrowserThread::DB, FROM_HERE,
-      base::Bind(&NativeBackendKWallet::DisableAutoSignInForAllLogins,
-                 base::Unretained(&backend), &changes),
+      base::Bind(&NativeBackendKWallet::DisableAutoSignInForOrigins,
+                 base::Unretained(&backend),
+                 base::Bind(&GURL::operator==,
+                            base::Unretained(&form_google_.origin)),
+                 &changes),
       base::Bind(&CheckPasswordChangesWithResult, &expected_changes, &changes));
   RunDBThread();
 
@@ -1031,6 +1040,9 @@
   forms.push_back(&form_google_);
   ExpectationArray expected;
   expected.push_back(make_pair(std::string(form_google_.signon_realm), forms));
+  forms.clear();
+  forms.push_back(&form_isc_);
+  expected.push_back(make_pair(std::string(form_isc_.signon_realm), forms));
   CheckPasswordForms("Chrome Form Data (42)", expected);
 }
 
diff --git a/chrome/browser/password_manager/native_backend_libsecret.cc b/chrome/browser/password_manager/native_backend_libsecret.cc
index 7d5b258..7ad4ed4d 100644
--- a/chrome/browser/password_manager/native_backend_libsecret.cc
+++ b/chrome/browser/password_manager/native_backend_libsecret.cc
@@ -281,14 +281,15 @@
   return RemoveLoginsBetween(delete_begin, delete_end, SYNC_TIMESTAMP, changes);
 }
 
-bool NativeBackendLibsecret::DisableAutoSignInForAllLogins(
+bool NativeBackendLibsecret::DisableAutoSignInForOrigins(
+    const base::Callback<bool(const GURL&)>& origin_filter,
     password_manager::PasswordStoreChangeList* changes) {
   ScopedVector<autofill::PasswordForm> all_forms;
   if (!GetLoginsList(nullptr, ALL_LOGINS, &all_forms))
     return false;
 
   for (auto& form : all_forms) {
-    if (!form->skip_zero_click) {
+    if (origin_filter.Run(form->origin) && !form->skip_zero_click) {
       form->skip_zero_click = true;
       if (!UpdateLogin(*form, changes))
         return false;
diff --git a/chrome/browser/password_manager/native_backend_libsecret.h b/chrome/browser/password_manager/native_backend_libsecret.h
index f125e2ad..bfdf5bf 100644
--- a/chrome/browser/password_manager/native_backend_libsecret.h
+++ b/chrome/browser/password_manager/native_backend_libsecret.h
@@ -43,7 +43,8 @@
       base::Time delete_begin,
       base::Time delete_end,
       password_manager::PasswordStoreChangeList* changes) override;
-  bool DisableAutoSignInForAllLogins(
+  bool DisableAutoSignInForOrigins(
+      const base::Callback<bool(const GURL&)>& origin_filter,
       password_manager::PasswordStoreChangeList* changes) override;
   bool GetLogins(const autofill::PasswordForm& form,
                  ScopedVector<autofill::PasswordForm>* forms) override;
diff --git a/chrome/browser/password_manager/native_backend_libsecret_unittest.cc b/chrome/browser/password_manager/native_backend_libsecret_unittest.cc
index 85fac00..f3ecee1 100644
--- a/chrome/browser/password_manager/native_backend_libsecret_unittest.cc
+++ b/chrome/browser/password_manager/native_backend_libsecret_unittest.cc
@@ -887,7 +887,7 @@
   CheckRemoveLoginsBetween(SYNCED);
 }
 
-TEST_F(NativeBackendLibsecretTest, DisableAutoSignInForAllLogins) {
+TEST_F(NativeBackendLibsecretTest, DisableAutoSignInForOrigins) {
   NativeBackendLibsecret backend(42);
   backend.Init();
   form_google_.skip_zero_click = false;
@@ -906,16 +906,22 @@
   PasswordStoreChangeList expected_changes;
   expected_changes.push_back(
       PasswordStoreChange(PasswordStoreChange::UPDATE, form_facebook_));
-  expected_changes.push_back(
-      PasswordStoreChange(PasswordStoreChange::UPDATE, form_google_));
 
   PasswordStoreChangeList changes;
-  EXPECT_TRUE(backend.DisableAutoSignInForAllLogins(&changes));
+  EXPECT_TRUE(backend.DisableAutoSignInForOrigins(
+      base::Bind(&GURL::operator==, base::Unretained(&form_facebook_.origin)),
+      &changes));
   CheckPasswordChanges(expected_changes, changes);
 
   EXPECT_EQ(2u, global_mock_libsecret_items->size());
-  for (const auto& item : *global_mock_libsecret_items)
-    CheckUint32Attribute(item, "should_skip_zero_click", 1);
+  CheckStringAttribute((*global_mock_libsecret_items)[0],
+                       "origin_url", form_google_.origin.spec());
+  CheckUint32Attribute((*global_mock_libsecret_items)[0],
+                       "should_skip_zero_click", 0);
+  CheckStringAttribute((*global_mock_libsecret_items)[1],
+                       "origin_url", form_facebook_.origin.spec());
+  CheckUint32Attribute((*global_mock_libsecret_items)[1],
+                       "should_skip_zero_click", 1);
 }
 
 TEST_F(NativeBackendLibsecretTest, SomeKeyringAttributesAreMissing) {
diff --git a/chrome/browser/password_manager/password_store_mac.cc b/chrome/browser/password_manager/password_store_mac.cc
index fb82842..b39fdef8 100644
--- a/chrome/browser/password_manager/password_store_mac.cc
+++ b/chrome/browser/password_manager/password_store_mac.cc
@@ -1196,16 +1196,35 @@
   return changes;
 }
 
-PasswordStoreChangeList PasswordStoreMac::DisableAutoSignInForAllLoginsImpl() {
-  ScopedVector<PasswordForm> forms;
-  PasswordStoreChangeList list;
-  if (login_metadata_db_ && login_metadata_db_->GetAutoSignInLogins(&forms) &&
-      login_metadata_db_->DisableAutoSignInForAllLogins()) {
-    for (const auto& form : forms)
-      list.push_back(PasswordStoreChange(PasswordStoreChange::UPDATE, *form));
+PasswordStoreChangeList PasswordStoreMac::DisableAutoSignInForOriginsImpl(
+    const base::Callback<bool(const GURL&)>& origin_filter) {
+  ScopedVector<autofill::PasswordForm> forms;
+  PasswordStoreChangeList changes;
+  if (!login_metadata_db_ ||
+      !login_metadata_db_->GetAutoSignInLogins(&forms)) {
+    return changes;
   }
 
-  return list;
+  std::set<GURL> origins_to_update;
+  for (const auto* form : forms) {
+    if (origin_filter.Run(form->origin))
+      origins_to_update.insert(form->origin);
+  }
+
+  std::set<GURL> origins_updated;
+  for (const GURL& origin : origins_to_update) {
+    if (login_metadata_db_->DisableAutoSignInForOrigin(origin))
+      origins_updated.insert(origin);
+  }
+
+  for (const auto* form : forms) {
+    if (origins_updated.count(form->origin)) {
+      changes.push_back(
+          PasswordStoreChange(PasswordStoreChange::UPDATE, *form));
+    }
+  }
+
+  return changes;
 }
 
 bool PasswordStoreMac::RemoveStatisticsCreatedBetweenImpl(
diff --git a/chrome/browser/password_manager/password_store_mac.h b/chrome/browser/password_manager/password_store_mac.h
index 9d0682a..f42ebb2 100644
--- a/chrome/browser/password_manager/password_store_mac.h
+++ b/chrome/browser/password_manager/password_store_mac.h
@@ -89,8 +89,8 @@
   password_manager::PasswordStoreChangeList RemoveLoginsSyncedBetweenImpl(
       base::Time delete_begin,
       base::Time delete_end) override;
-  password_manager::PasswordStoreChangeList DisableAutoSignInForAllLoginsImpl()
-      override;
+  password_manager::PasswordStoreChangeList DisableAutoSignInForOriginsImpl(
+      const base::Callback<bool(const GURL&)>& origin_filter) override;
   bool RemoveStatisticsCreatedBetweenImpl(base::Time delete_begin,
                                           base::Time delete_end) override;
   ScopedVector<autofill::PasswordForm> FillMatchingLogins(
diff --git a/chrome/browser/password_manager/password_store_mac_unittest.cc b/chrome/browser/password_manager/password_store_mac_unittest.cc
index b0cc46f..76836e70 100644
--- a/chrome/browser/password_manager/password_store_mac_unittest.cc
+++ b/chrome/browser/password_manager/password_store_mac_unittest.cc
@@ -1778,7 +1778,7 @@
   CheckRemoveLoginsBetween(this, false);
 }
 
-TEST_F(PasswordStoreMacTest, TestDisableAutoSignInForAllLogins) {
+TEST_F(PasswordStoreMacTest, TestDisableAutoSignInForOrigins) {
   PasswordFormData www_form_data_facebook = {
       PasswordForm::SCHEME_HTML,
       "http://www.facebook.com/",
@@ -1796,22 +1796,45 @@
       CreatePasswordFormFromDataForTesting(www_form_data_facebook);
   form_facebook->skip_zero_click = false;
 
-  // Add the zero-clickable form to the database.
+  PasswordFormData www_form_data_google = {
+      PasswordForm::SCHEME_HTML,
+      "http://www.google.com/",
+      "http://www.google.com/foo/bar/index.html",
+      "login",
+      L"submit",
+      L"username",
+      L"password",
+      L"joe_user",
+      L"sekrit",
+      true,
+      false,
+      0};
+  std::unique_ptr<PasswordForm> form_google =
+      CreatePasswordFormFromDataForTesting(www_form_data_google);
+  form_google->skip_zero_click = false;
+
+  // Add the zero-clickable forms to the database.
   PasswordsChangeObserver observer(store());
   store()->AddLogin(*form_facebook);
+  store()->AddLogin(*form_google);
   EXPECT_CALL(observer, OnLoginsChanged(GetAddChangeList(*form_facebook)));
+  EXPECT_CALL(observer, OnLoginsChanged(GetAddChangeList(*form_google)));
   observer.WaitAndVerify(this);
 
   ScopedVector<autofill::PasswordForm> forms;
   EXPECT_TRUE(login_db()->GetAutoSignInLogins(&forms));
-  EXPECT_EQ(1u, forms.size());
+  EXPECT_EQ(2u, forms.size());
   EXPECT_FALSE(forms[0]->skip_zero_click);
+  EXPECT_FALSE(forms[1]->skip_zero_click);
 
-  store()->DisableAutoSignInForAllLogins(base::Closure());
+  store()->DisableAutoSignInForOrigins(
+    base::Bind(&GURL::operator==, base::Unretained(&form_google->origin)),
+    base::Closure());
   FinishAsyncProcessing();
 
   EXPECT_TRUE(login_db()->GetAutoSignInLogins(&forms));
-  EXPECT_EQ(0u, forms.size());
+  EXPECT_EQ(1u, forms.size());
+  EXPECT_EQ(form_facebook->origin, forms[0]->origin);
 }
 
 TEST_F(PasswordStoreMacTest, TestRemoveLoginsMultiProfile) {
diff --git a/chrome/browser/password_manager/password_store_proxy_mac.cc b/chrome/browser/password_manager/password_store_proxy_mac.cc
index 4a3fe4f6..c42c2c2 100644
--- a/chrome/browser/password_manager/password_store_proxy_mac.cc
+++ b/chrome/browser/password_manager/password_store_proxy_mac.cc
@@ -190,8 +190,9 @@
 }
 
 PasswordStoreChangeList
-PasswordStoreProxyMac::DisableAutoSignInForAllLoginsImpl() {
-  return GetBackend()->DisableAutoSignInForAllLoginsImpl();
+PasswordStoreProxyMac::DisableAutoSignInForOriginsImpl(
+    const base::Callback<bool(const GURL&)>& origin_filter) {
+  return GetBackend()->DisableAutoSignInForOriginsImpl(origin_filter);
 }
 
 bool PasswordStoreProxyMac::RemoveStatisticsCreatedBetweenImpl(
diff --git a/chrome/browser/password_manager/password_store_proxy_mac.h b/chrome/browser/password_manager/password_store_proxy_mac.h
index 40ba71f..8326376 100644
--- a/chrome/browser/password_manager/password_store_proxy_mac.h
+++ b/chrome/browser/password_manager/password_store_proxy_mac.h
@@ -86,8 +86,8 @@
   password_manager::PasswordStoreChangeList RemoveLoginsSyncedBetweenImpl(
       base::Time delete_begin,
       base::Time delete_end) override;
-  password_manager::PasswordStoreChangeList DisableAutoSignInForAllLoginsImpl()
-      override;
+  password_manager::PasswordStoreChangeList DisableAutoSignInForOriginsImpl(
+      const base::Callback<bool(const GURL&)>& origin_filter) override;
   bool RemoveStatisticsCreatedBetweenImpl(base::Time delete_begin,
                                           base::Time delete_end) override;
   ScopedVector<autofill::PasswordForm> FillMatchingLogins(
diff --git a/chrome/browser/password_manager/password_store_x.cc b/chrome/browser/password_manager/password_store_x.cc
index 1cfa3d0..75f8244 100644
--- a/chrome/browser/password_manager/password_store_x.cc
+++ b/chrome/browser/password_manager/password_store_x.cc
@@ -161,14 +161,16 @@
   return changes;
 }
 
-PasswordStoreChangeList PasswordStoreX::DisableAutoSignInForAllLoginsImpl() {
+PasswordStoreChangeList PasswordStoreX::DisableAutoSignInForOriginsImpl(
+    const base::Callback<bool(const GURL&)>& origin_filter) {
   CheckMigration();
   PasswordStoreChangeList changes;
   if (use_native_backend() &&
-      backend_->DisableAutoSignInForAllLogins(&changes)) {
+      backend_->DisableAutoSignInForOrigins(origin_filter, &changes)) {
     allow_fallback_ = false;
   } else if (allow_default_store()) {
-    changes = PasswordStoreDefault::DisableAutoSignInForAllLoginsImpl();
+    changes =
+        PasswordStoreDefault::DisableAutoSignInForOriginsImpl(origin_filter);
   }
   return changes;
 }
diff --git a/chrome/browser/password_manager/password_store_x.h b/chrome/browser/password_manager/password_store_x.h
index a33709d..f6851bc 100644
--- a/chrome/browser/password_manager/password_store_x.h
+++ b/chrome/browser/password_manager/password_store_x.h
@@ -69,8 +69,10 @@
         base::Time delete_end,
         password_manager::PasswordStoreChangeList* changes) = 0;
 
-    // Sets the 'skip_zero_click' flag to 'true' for all logins in the database.
-    virtual bool DisableAutoSignInForAllLogins(
+    // Sets the 'skip_zero_click' flag to 'true' for all logins in the database
+    // that match |origin_filter|.
+    virtual bool DisableAutoSignInForOrigins(
+        const base::Callback<bool(const GURL&)>& origin_filter,
         password_manager::PasswordStoreChangeList* changes) = 0;
 
     // The three methods below overwrite |forms| with all stored credentials
@@ -116,8 +118,8 @@
   password_manager::PasswordStoreChangeList RemoveLoginsSyncedBetweenImpl(
       base::Time delete_begin,
       base::Time delete_end) override;
-  password_manager::PasswordStoreChangeList DisableAutoSignInForAllLoginsImpl()
-      override;
+  password_manager::PasswordStoreChangeList DisableAutoSignInForOriginsImpl(
+      const base::Callback<bool(const GURL&)>& origin_filter) override;
   ScopedVector<autofill::PasswordForm> FillMatchingLogins(
       const autofill::PasswordForm& form) override;
   bool FillAutofillableLogins(
diff --git a/chrome/browser/password_manager/password_store_x_unittest.cc b/chrome/browser/password_manager/password_store_x_unittest.cc
index 36a99f3..2f26468 100644
--- a/chrome/browser/password_manager/password_store_x_unittest.cc
+++ b/chrome/browser/password_manager/password_store_x_unittest.cc
@@ -84,7 +84,8 @@
     return false;
   }
 
-  bool DisableAutoSignInForAllLogins(
+  bool DisableAutoSignInForOrigins(
+      const base::Callback<bool(const GURL&)>& origin_filter,
       password_manager::PasswordStoreChangeList* changes) override {
     return false;
   }
@@ -191,7 +192,8 @@
     return true;
   }
 
-  bool DisableAutoSignInForAllLogins(
+  bool DisableAutoSignInForOrigins(
+      const base::Callback<bool(const GURL&)>& origin_filter,
       password_manager::PasswordStoreChangeList* changes) override {
     return true;
   }
diff --git a/chrome/browser/permissions/permission_bubble_request_impl.cc b/chrome/browser/permissions/permission_bubble_request_impl.cc
index 2001775..e2389b16 100644
--- a/chrome/browser/permissions/permission_bubble_request_impl.cc
+++ b/chrome/browser/permissions/permission_bubble_request_impl.cc
@@ -29,7 +29,9 @@
 PermissionBubbleRequestImpl::~PermissionBubbleRequestImpl() {
   DCHECK(is_finished_);
   if (!action_taken_)
-    PermissionUmaUtil::PermissionIgnored(permission_type_, request_origin_);
+    // TODO(stefanocs): Pass in a non null profile.
+    PermissionUmaUtil::PermissionIgnored(permission_type_, request_origin_,
+                                         nullptr);
 }
 
 gfx::VectorIconId PermissionBubbleRequestImpl::GetVectorIconId() const {
diff --git a/chrome/browser/permissions/permission_context_base.cc b/chrome/browser/permissions/permission_context_base.cc
index 093f6b2..802cb50 100644
--- a/chrome/browser/permissions/permission_context_base.cc
+++ b/chrome/browser/permissions/permission_context_base.cc
@@ -29,7 +29,7 @@
 #include "chrome/browser/permissions/permission_queue_controller.h"
 #else
 #include "chrome/browser/permissions/permission_bubble_request_impl.h"
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
+#include "chrome/browser/permissions/permission_request_manager.h"
 #endif
 
 // static
@@ -153,8 +153,8 @@
 #else
   PermissionBubbleRequest* cancelling = pending_bubbles_.get(id.ToString());
   if (cancelling != NULL && web_contents != NULL &&
-      PermissionBubbleManager::FromWebContents(web_contents) != NULL) {
-    PermissionBubbleManager::FromWebContents(web_contents)
+      PermissionRequestManager::FromWebContents(web_contents) != NULL) {
+    PermissionRequestManager::FromWebContents(web_contents)
         ->CancelRequest(cancelling);
   }
 #endif
@@ -170,11 +170,11 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
 #if !defined(OS_ANDROID)
-  PermissionBubbleManager* bubble_manager =
-      PermissionBubbleManager::FromWebContents(web_contents);
-  // TODO(felt): sometimes |bubble_manager| is null. This check is meant to
-  // prevent crashes. See crbug.com/457091.
-  if (!bubble_manager)
+  PermissionRequestManager* permission_request_manager =
+      PermissionRequestManager::FromWebContents(web_contents);
+  // TODO(felt): sometimes |permission_request_manager| is null. This check is
+  // meant to prevent crashes. See crbug.com/457091.
+  if (!permission_request_manager)
     return;
   std::unique_ptr<PermissionBubbleRequest> request_ptr(
       new PermissionBubbleRequestImpl(
@@ -189,7 +189,7 @@
   bool inserted =
       pending_bubbles_.add(id.ToString(), std::move(request_ptr)).second;
   DCHECK(inserted) << "Duplicate id " << id.ToString();
-  bubble_manager->AddRequest(request);
+  permission_request_manager->AddRequest(request);
 #else
   GetQueueController()->CreateInfoBarRequest(
       id, requesting_origin, embedding_origin,
@@ -216,12 +216,15 @@
     DCHECK(content_setting == CONTENT_SETTING_ALLOW ||
            content_setting == CONTENT_SETTING_BLOCK);
     if (content_setting == CONTENT_SETTING_ALLOW)
-      PermissionUmaUtil::PermissionGranted(permission_type_, requesting_origin);
+      PermissionUmaUtil::PermissionGranted(permission_type_, requesting_origin,
+                                           profile_);
     else
-      PermissionUmaUtil::PermissionDenied(permission_type_, requesting_origin);
+      PermissionUmaUtil::PermissionDenied(permission_type_, requesting_origin,
+                                          profile_);
   } else {
     DCHECK_EQ(content_setting, CONTENT_SETTING_DEFAULT);
-    PermissionUmaUtil::PermissionDismissed(permission_type_, requesting_origin);
+    PermissionUmaUtil::PermissionDismissed(permission_type_, requesting_origin,
+                                           profile_);
   }
 #endif
 
diff --git a/chrome/browser/permissions/permission_context_base_unittest.cc b/chrome/browser/permissions/permission_context_base_unittest.cc
index 62d3bd88..13a1f34a 100644
--- a/chrome/browser/permissions/permission_context_base_unittest.cc
+++ b/chrome/browser/permissions/permission_context_base_unittest.cc
@@ -17,7 +17,6 @@
 #include "chrome/browser/permissions/permission_queue_controller.h"
 #include "chrome/browser/permissions/permission_request_id.h"
 #include "chrome/browser/permissions/permission_util.h"
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "chrome/test/base/testing_profile.h"
@@ -34,7 +33,7 @@
 #if defined(OS_ANDROID)
 #include "chrome/browser/permissions/permission_queue_controller.h"
 #else
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
+#include "chrome/browser/permissions/permission_request_manager.h"
 #endif
 
 const char* kPermissionsKillSwitchFieldStudy =
@@ -122,8 +121,8 @@
     context->GetInfoBarController()->OnPermissionSet(
         id, url, url, update_content_setting, allowed);
 #else
-    PermissionBubbleManager* manager =
-        PermissionBubbleManager::FromWebContents(web_contents());
+    PermissionRequestManager* manager =
+        PermissionRequestManager::FromWebContents(web_contents());
     switch (response) {
       case CONTENT_SETTING_ALLOW:
         manager->Accept();
@@ -314,7 +313,7 @@
 #if defined(OS_ANDROID)
     InfoBarService::CreateForWebContents(web_contents());
 #else
-    PermissionBubbleManager::CreateForWebContents(web_contents());
+    PermissionRequestManager::CreateForWebContents(web_contents());
 #endif
   }
 
diff --git a/chrome/browser/permissions/permission_infobar_delegate.cc b/chrome/browser/permissions/permission_infobar_delegate.cc
index 14a9f5d..32cea3dd 100644
--- a/chrome/browser/permissions/permission_infobar_delegate.cc
+++ b/chrome/browser/permissions/permission_infobar_delegate.cc
@@ -12,7 +12,9 @@
 
 PermissionInfobarDelegate::~PermissionInfobarDelegate() {
   if (!action_taken_)
-    PermissionUmaUtil::PermissionIgnored(permission_type_, requesting_origin_);
+    // TODO(stefanocs): Pass in a non null profile.
+    PermissionUmaUtil::PermissionIgnored(permission_type_, requesting_origin_,
+                                         nullptr);
 }
 
 PermissionInfobarDelegate::PermissionInfobarDelegate(
diff --git a/chrome/browser/permissions/permission_queue_controller.cc b/chrome/browser/permissions/permission_queue_controller.cc
index 76e1a6d2..5f6bbfc0 100644
--- a/chrome/browser/permissions/permission_queue_controller.cc
+++ b/chrome/browser/permissions/permission_queue_controller.cc
@@ -205,11 +205,14 @@
   if (update_content_setting) {
     UpdateContentSetting(requesting_frame, embedder, allowed);
     if (allowed)
-      PermissionUmaUtil::PermissionGranted(permission_type_, requesting_frame);
+      PermissionUmaUtil::PermissionGranted(permission_type_, requesting_frame,
+                                           profile_);
     else
-      PermissionUmaUtil::PermissionDenied(permission_type_, requesting_frame);
+      PermissionUmaUtil::PermissionDenied(permission_type_, requesting_frame,
+                                          profile_);
   } else {
-    PermissionUmaUtil::PermissionDismissed(permission_type_, requesting_frame);
+    PermissionUmaUtil::PermissionDismissed(permission_type_, requesting_frame,
+                                           profile_);
   }
 
   // Cancel this request first, then notify listeners.  TODO(pkasting): Why
diff --git a/chrome/browser/ui/website_settings/permission_bubble_manager.cc b/chrome/browser/permissions/permission_request_manager.cc
similarity index 86%
rename from chrome/browser/ui/website_settings/permission_bubble_manager.cc
rename to chrome/browser/permissions/permission_request_manager.cc
index a0ccb8fb..5d500c3 100644
--- a/chrome/browser/ui/website_settings/permission_bubble_manager.cc
+++ b/chrome/browser/permissions/permission_request_manager.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
+#include "chrome/browser/permissions/permission_request_manager.h"
 
 #include <algorithm>
 
@@ -63,19 +63,19 @@
 
 }  // namespace
 
-// PermissionBubbleManager::Observer -------------------------------------------
+// PermissionRequestManager::Observer ------------------------------------------
 
-PermissionBubbleManager::Observer::~Observer() {
+PermissionRequestManager::Observer::~Observer() {
 }
 
-void PermissionBubbleManager::Observer::OnBubbleAdded() {
+void PermissionRequestManager::Observer::OnBubbleAdded() {
 }
 
-// PermissionBubbleManager -----------------------------------------------------
+// PermissionRequestManager ----------------------------------------------------
 
-DEFINE_WEB_CONTENTS_USER_DATA_KEY(PermissionBubbleManager);
+DEFINE_WEB_CONTENTS_USER_DATA_KEY(PermissionRequestManager);
 
-PermissionBubbleManager::PermissionBubbleManager(
+PermissionRequestManager::PermissionRequestManager(
     content::WebContents* web_contents)
     : content::WebContentsObserver(web_contents),
 #if !defined(OS_ANDROID)  // No bubbles in android tests.
@@ -87,7 +87,7 @@
       weak_factory_(this) {
 }
 
-PermissionBubbleManager::~PermissionBubbleManager() {
+PermissionRequestManager::~PermissionRequestManager() {
   if (view_ != NULL)
     view_->SetDelegate(NULL);
 
@@ -101,7 +101,7 @@
     entry.second->RequestFinished();
 }
 
-void PermissionBubbleManager::AddRequest(PermissionBubbleRequest* request) {
+void PermissionRequestManager::AddRequest(PermissionBubbleRequest* request) {
   content::RecordAction(base::UserMetricsAction("PermissionBubbleRequest"));
   // TODO(gbillock): is there a race between an early request on a
   // newly-navigated page and the to-be-cleaned-up requests on the previous
@@ -154,7 +154,7 @@
   ScheduleShowBubble();
 }
 
-void PermissionBubbleManager::CancelRequest(PermissionBubbleRequest* request) {
+void PermissionRequestManager::CancelRequest(PermissionBubbleRequest* request) {
   // First look in the queued requests, where we can simply finish the request
   // and go on.
   std::vector<PermissionBubbleRequest*>::iterator requests_iter;
@@ -224,7 +224,7 @@
   NOTREACHED();  // Callers should not cancel requests that are not pending.
 }
 
-void PermissionBubbleManager::HideBubble() {
+void PermissionRequestManager::HideBubble() {
   // Disengage from the existing view if there is one.
   if (!view_)
     return;
@@ -234,7 +234,7 @@
   view_.reset();
 }
 
-void PermissionBubbleManager::DisplayPendingRequests() {
+void PermissionRequestManager::DisplayPendingRequests() {
   if (IsBubbleVisible())
     return;
 
@@ -249,22 +249,22 @@
   TriggerShowBubble();
 }
 
-void PermissionBubbleManager::UpdateAnchorPosition() {
+void PermissionRequestManager::UpdateAnchorPosition() {
   if (view_)
     view_->UpdateAnchorPosition();
 }
 
-bool PermissionBubbleManager::IsBubbleVisible() {
+bool PermissionRequestManager::IsBubbleVisible() {
   return view_ && view_->IsVisible();
 }
 
-gfx::NativeWindow PermissionBubbleManager::GetBubbleWindow() {
+gfx::NativeWindow PermissionRequestManager::GetBubbleWindow() {
   if (view_)
     return view_->GetNativeWindow();
   return nullptr;
 }
 
-void PermissionBubbleManager::DidNavigateMainFrame(
+void PermissionRequestManager::DidNavigateMainFrame(
     const content::LoadCommittedDetails& details,
     const content::FrameNavigateParams& params) {
   if (details.is_in_page)
@@ -275,7 +275,7 @@
   main_frame_has_fully_loaded_ = false;
 }
 
-void PermissionBubbleManager::DocumentOnLoadCompletedInMainFrame() {
+void PermissionRequestManager::DocumentOnLoadCompletedInMainFrame() {
   main_frame_has_fully_loaded_ = true;
   // This is scheduled because while all calls to the browser have been
   // issued at DOMContentLoaded, they may be bouncing around in scheduled
@@ -285,12 +285,12 @@
   ScheduleShowBubble();
 }
 
-void PermissionBubbleManager::DocumentLoadedInFrame(
+void PermissionRequestManager::DocumentLoadedInFrame(
     content::RenderFrameHost* render_frame_host) {
   ScheduleShowBubble();
 }
 
-void PermissionBubbleManager::WebContentsDestroyed() {
+void PermissionRequestManager::WebContentsDestroyed() {
   // If the web contents has been destroyed, treat the bubble as cancelled.
   CancelPendingQueues();
   FinalizeBubble();
@@ -303,12 +303,12 @@
   // returning from this function is the only safe thing to do.
 }
 
-void PermissionBubbleManager::ToggleAccept(int request_index, bool new_value) {
+void PermissionRequestManager::ToggleAccept(int request_index, bool new_value) {
   DCHECK(request_index < static_cast<int>(accept_states_.size()));
   accept_states_[request_index] = new_value;
 }
 
-void PermissionBubbleManager::Accept() {
+void PermissionRequestManager::Accept() {
   PermissionUmaUtil::PermissionPromptAccepted(requests_, accept_states_);
 
   std::vector<PermissionBubbleRequest*>::iterator requests_iter;
@@ -325,7 +325,7 @@
   FinalizeBubble();
 }
 
-void PermissionBubbleManager::Deny() {
+void PermissionRequestManager::Deny() {
   PermissionUmaUtil::PermissionPromptDenied(requests_);
 
   std::vector<PermissionBubbleRequest*>::iterator requests_iter;
@@ -337,7 +337,7 @@
   FinalizeBubble();
 }
 
-void PermissionBubbleManager::Closing() {
+void PermissionRequestManager::Closing() {
   std::vector<PermissionBubbleRequest*>::iterator requests_iter;
   for (requests_iter = requests_.begin();
        requests_iter != requests_.end();
@@ -347,7 +347,7 @@
   FinalizeBubble();
 }
 
-void PermissionBubbleManager::ScheduleShowBubble() {
+void PermissionRequestManager::ScheduleShowBubble() {
   // ::ScheduleShowBubble() will be called again when the main frame will be
   // loaded.
   if (!main_frame_has_fully_loaded_)
@@ -356,11 +356,11 @@
   content::BrowserThread::PostTask(
       content::BrowserThread::UI,
       FROM_HERE,
-      base::Bind(&PermissionBubbleManager::TriggerShowBubble,
+      base::Bind(&PermissionRequestManager::TriggerShowBubble,
                  weak_factory_.GetWeakPtr()));
 }
 
-void PermissionBubbleManager::TriggerShowBubble() {
+void PermissionRequestManager::TriggerShowBubble() {
   if (!view_)
     return;
   if (IsBubbleVisible())
@@ -391,7 +391,7 @@
     DoAutoResponseForTesting();
 }
 
-void PermissionBubbleManager::FinalizeBubble() {
+void PermissionRequestManager::FinalizeBubble() {
   if (view_)
     view_->Hide();
 
@@ -409,7 +409,7 @@
     request_url_ = GURL();
 }
 
-void PermissionBubbleManager::CancelPendingQueues() {
+void PermissionRequestManager::CancelPendingQueues() {
   std::vector<PermissionBubbleRequest*>::iterator requests_iter;
   for (requests_iter = queued_requests_.begin();
        requests_iter != queued_requests_.end();
@@ -425,7 +425,7 @@
   queued_frame_requests_.clear();
 }
 
-PermissionBubbleRequest* PermissionBubbleManager::GetExistingRequest(
+PermissionBubbleRequest* PermissionRequestManager::GetExistingRequest(
     PermissionBubbleRequest* request) {
   for (PermissionBubbleRequest* existing_request : requests_)
     if (IsMessageTextEqual(existing_request, request))
@@ -439,7 +439,7 @@
   return nullptr;
 }
 
-void PermissionBubbleManager::PermissionGrantedIncludingDuplicates(
+void PermissionRequestManager::PermissionGrantedIncludingDuplicates(
     PermissionBubbleRequest* request) {
   DCHECK_EQ(request, GetExistingRequest(request))
       << "Only requests in [queued_[frame_]]requests_ can have duplicates";
@@ -448,7 +448,7 @@
   for (auto it = range.first; it != range.second; ++it)
     it->second->PermissionGranted();
 }
-void PermissionBubbleManager::PermissionDeniedIncludingDuplicates(
+void PermissionRequestManager::PermissionDeniedIncludingDuplicates(
     PermissionBubbleRequest* request) {
   DCHECK_EQ(request, GetExistingRequest(request))
       << "Only requests in [queued_[frame_]]requests_ can have duplicates";
@@ -457,7 +457,7 @@
   for (auto it = range.first; it != range.second; ++it)
     it->second->PermissionDenied();
 }
-void PermissionBubbleManager::CancelledIncludingDuplicates(
+void PermissionRequestManager::CancelledIncludingDuplicates(
     PermissionBubbleRequest* request) {
   DCHECK_EQ(request, GetExistingRequest(request))
       << "Only requests in [queued_[frame_]]requests_ can have duplicates";
@@ -466,7 +466,7 @@
   for (auto it = range.first; it != range.second; ++it)
     it->second->Cancelled();
 }
-void PermissionBubbleManager::RequestFinishedIncludingDuplicates(
+void PermissionRequestManager::RequestFinishedIncludingDuplicates(
     PermissionBubbleRequest* request) {
   // We can't call GetExistingRequest here, because other entries in requests_,
   // queued_requests_ or queued_frame_requests_ might already have been deleted.
@@ -485,19 +485,19 @@
   duplicate_requests_.erase(request);
 }
 
-void PermissionBubbleManager::AddObserver(Observer* observer) {
+void PermissionRequestManager::AddObserver(Observer* observer) {
   observer_list_.AddObserver(observer);
 }
 
-void PermissionBubbleManager::RemoveObserver(Observer* observer) {
+void PermissionRequestManager::RemoveObserver(Observer* observer) {
   observer_list_.RemoveObserver(observer);
 }
 
-void PermissionBubbleManager::NotifyBubbleAdded() {
+void PermissionRequestManager::NotifyBubbleAdded() {
   FOR_EACH_OBSERVER(Observer, observer_list_, OnBubbleAdded());
 }
 
-void PermissionBubbleManager::DoAutoResponseForTesting() {
+void PermissionRequestManager::DoAutoResponseForTesting() {
   switch (auto_response_for_test_) {
     case ACCEPT_ALL:
       Accept();
diff --git a/chrome/browser/ui/website_settings/permission_bubble_manager.h b/chrome/browser/permissions/permission_request_manager.h
similarity index 88%
rename from chrome/browser/ui/website_settings/permission_bubble_manager.h
rename to chrome/browser/permissions/permission_request_manager.h
index 6a1c036..78b626c 100644
--- a/chrome/browser/ui/website_settings/permission_bubble_manager.h
+++ b/chrome/browser/permissions/permission_request_manager.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_WEBSITE_SETTINGS_PERMISSION_BUBBLE_MANAGER_H_
-#define CHROME_BROWSER_UI_WEBSITE_SETTINGS_PERMISSION_BUBBLE_MANAGER_H_
+#ifndef CHROME_BROWSER_PERMISSIONS_PERMISSION_REQUEST_MANAGER_H_
+#define CHROME_BROWSER_PERMISSIONS_PERMISSION_REQUEST_MANAGER_H_
 
 #include <unordered_map>
 #include <vector>
@@ -24,13 +24,13 @@
 // visible UI action at all. (In that case, the request will be immediately
 // informed that the permission request failed.)
 //
-// A PermissionBubbleManager is associated with a particular WebContents.
+// A PermissionRequestManager is associated with a particular WebContents.
 // Requests attached to a particular WebContents' PBM must outlive it.
 //
-// The PermissionBubbleManager should be addressed on the UI thread.
-class PermissionBubbleManager
+// The PermissionRequestManager should be addressed on the UI thread.
+class PermissionRequestManager
     : public content::WebContentsObserver,
-      public content::WebContentsUserData<PermissionBubbleManager>,
+      public content::WebContentsUserData<PermissionRequestManager>,
       public PermissionBubbleView::Delegate {
  public:
   class Observer {
@@ -46,11 +46,11 @@
     DISMISS
   };
 
-  ~PermissionBubbleManager() override;
+  ~PermissionRequestManager() override;
 
   // Adds a new request to the permission bubble. Ownership of the request
   // remains with the caller. The caller must arrange for the request to
-  // outlive the PermissionBubbleManager. If a bubble is visible when this
+  // outlive the PermissionRequestManager. If a bubble is visible when this
   // call is made, the request will be queued up and shown after the current
   // bubble closes. A request with message text identical to an outstanding
   // request will be merged with the outstanding request, and will have the same
@@ -70,7 +70,7 @@
   void HideBubble();
 
   // Will show a permission bubble if there is a pending permission request on
-  // the web contents that the PermissionBubbleManager belongs to.
+  // the web contents that the PermissionRequestManager belongs to.
   void DisplayPendingRequests();
 
   // Will reposition the bubble (may change parent if necessary).
@@ -102,12 +102,12 @@
   friend class GeolocationPermissionContextTests;
   friend class MockPermissionBubbleFactory;
   friend class MockPermissionBubbleView;
-  friend class PermissionBubbleManagerTest;
+  friend class PermissionRequestManagerTest;
   friend class PermissionContextBaseTests;
-  friend class content::WebContentsUserData<PermissionBubbleManager>;
+  friend class content::WebContentsUserData<PermissionRequestManager>;
   FRIEND_TEST_ALL_PREFIXES(DownloadTest, TestMultipleDownloadsBubble);
 
-  explicit PermissionBubbleManager(content::WebContents* web_contents);
+  explicit PermissionRequestManager(content::WebContents* web_contents);
 
   // WebContentsObserver:
   void DidNavigateMainFrame(
@@ -188,7 +188,7 @@
   base::ObserverList<Observer> observer_list_;
   AutoResponseType auto_response_for_test_;
 
-  base::WeakPtrFactory<PermissionBubbleManager> weak_factory_;
+  base::WeakPtrFactory<PermissionRequestManager> weak_factory_;
 };
 
-#endif  // CHROME_BROWSER_UI_WEBSITE_SETTINGS_PERMISSION_BUBBLE_MANAGER_H_
+#endif  // CHROME_BROWSER_PERMISSIONS_PERMISSION_REQUEST_MANAGER_H_
diff --git a/chrome/browser/ui/website_settings/permission_bubble_manager_browsertest.cc b/chrome/browser/permissions/permission_request_manager_browsertest.cc
similarity index 89%
rename from chrome/browser/ui/website_settings/permission_bubble_manager_browsertest.cc
rename to chrome/browser/permissions/permission_request_manager_browsertest.cc
index 01155cb..694a11e 100644
--- a/chrome/browser/ui/website_settings/permission_bubble_manager_browsertest.cc
+++ b/chrome/browser/permissions/permission_request_manager_browsertest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
+#include "chrome/browser/permissions/permission_request_manager.h"
 
 #include "base/command_line.h"
 #include "base/metrics/field_trial.h"
@@ -28,14 +28,14 @@
     PermissionContextBase::kPermissionsKillSwitchBlockedValue;
 const char kPermissionsKillSwitchTestGroup[] = "TestGroup";
 
-class PermissionBubbleManagerBrowserTest : public InProcessBrowserTest {
+class PermissionRequestManagerBrowserTest : public InProcessBrowserTest {
  public:
-  PermissionBubbleManagerBrowserTest() = default;
-  ~PermissionBubbleManagerBrowserTest() override = default;
+  PermissionRequestManagerBrowserTest() = default;
+  ~PermissionRequestManagerBrowserTest() override = default;
 
   void SetUpOnMainThread() override {
     InProcessBrowserTest::SetUpOnMainThread();
-    PermissionBubbleManager* manager = GetPermissionBubbleManager();
+    PermissionRequestManager* manager = GetPermissionRequestManager();
     mock_permission_bubble_factory_.reset(
         new MockPermissionBubbleFactory(manager));
     manager->DisplayPendingRequests();
@@ -46,8 +46,8 @@
     InProcessBrowserTest::TearDownOnMainThread();
   }
 
-  PermissionBubbleManager* GetPermissionBubbleManager() {
-    return PermissionBubbleManager::FromWebContents(
+  PermissionRequestManager* GetPermissionRequestManager() {
+    return PermissionRequestManager::FromWebContents(
         browser()->tab_strip_model()->GetActiveWebContents());
   }
 
@@ -72,7 +72,7 @@
 
 // Requests before the load event should be bundled into one bubble.
 // http://crbug.com/512849 flaky
-IN_PROC_BROWSER_TEST_F(PermissionBubbleManagerBrowserTest,
+IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest,
                        DISABLED_RequestsBeforeLoad) {
   ASSERT_TRUE(embedded_test_server()->Start());
 
@@ -87,7 +87,7 @@
 }
 
 // Requests before the load should not be bundled with a request after the load.
-IN_PROC_BROWSER_TEST_F(PermissionBubbleManagerBrowserTest,
+IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest,
                        RequestsBeforeAfterLoad) {
   ASSERT_TRUE(embedded_test_server()->Start());
 
@@ -110,7 +110,7 @@
 #else
 #define MAYBE_NavTwice NavTwice
 #endif
-IN_PROC_BROWSER_TEST_F(PermissionBubbleManagerBrowserTest, MAYBE_NavTwice) {
+IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest, MAYBE_NavTwice) {
   ASSERT_TRUE(embedded_test_server()->Start());
 
   ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
@@ -137,7 +137,7 @@
 #else
 #define MAYBE_NavTwiceWithHash NavTwiceWithHash
 #endif
-IN_PROC_BROWSER_TEST_F(PermissionBubbleManagerBrowserTest,
+IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest,
                        MAYBE_NavTwiceWithHash) {
   ASSERT_TRUE(embedded_test_server()->Start());
 
@@ -159,7 +159,7 @@
 }
 
 // Bubble requests should be shown after in-page navigation.
-IN_PROC_BROWSER_TEST_F(PermissionBubbleManagerBrowserTest, InPageNavigation) {
+IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest, InPageNavigation) {
   ASSERT_TRUE(embedded_test_server()->Start());
 
   ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
@@ -183,7 +183,7 @@
 }
 
 // Bubble requests should not be shown when the killswitch is on.
-IN_PROC_BROWSER_TEST_F(PermissionBubbleManagerBrowserTest,
+IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest,
                        KillSwitchGeolocation) {
   ASSERT_TRUE(embedded_test_server()->Start());
 
@@ -219,7 +219,7 @@
 }
 
 // Bubble requests should not be shown when the killswitch is on.
-IN_PROC_BROWSER_TEST_F(PermissionBubbleManagerBrowserTest,
+IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest,
                        KillSwitchNotifications) {
   ASSERT_TRUE(embedded_test_server()->Start());
 
diff --git a/chrome/browser/ui/website_settings/permission_bubble_manager_unittest.cc b/chrome/browser/permissions/permission_request_manager_unittest.cc
similarity index 87%
rename from chrome/browser/ui/website_settings/permission_bubble_manager_unittest.cc
rename to chrome/browser/permissions/permission_request_manager_unittest.cc
index a75aab1..66d056e 100644
--- a/chrome/browser/ui/website_settings/permission_bubble_manager_unittest.cc
+++ b/chrome/browser/permissions/permission_request_manager_unittest.cc
@@ -9,18 +9,18 @@
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/histogram_tester.h"
+#include "chrome/browser/permissions/permission_request_manager.h"
 #include "chrome/browser/permissions/permission_uma_util.h"
 #include "chrome/browser/ui/website_settings/mock_permission_bubble_factory.h"
 #include "chrome/browser/ui/website_settings/mock_permission_bubble_request.h"
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
 #include "chrome/browser/ui/website_settings/permission_bubble_request.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-class PermissionBubbleManagerTest : public ChromeRenderViewHostTestHarness {
+class PermissionRequestManagerTest : public ChromeRenderViewHostTestHarness {
  public:
-  PermissionBubbleManagerTest()
+  PermissionRequestManagerTest()
       : ChromeRenderViewHostTestHarness(),
         request1_("test1", PermissionBubbleType::QUOTA),
         request2_("test2", PermissionBubbleType::DOWNLOAD),
@@ -28,14 +28,14 @@
                                     GURL("http://www.google.com/some/url")),
         iframe_request_other_domain_("iframe",
                                      GURL("http://www.youtube.com")) {}
-  ~PermissionBubbleManagerTest() override {}
+  ~PermissionRequestManagerTest() override {}
 
   void SetUp() override {
     ChromeRenderViewHostTestHarness::SetUp();
     SetContents(CreateTestWebContents());
     NavigateAndCommit(GURL("http://www.google.com"));
 
-    manager_.reset(new PermissionBubbleManager(web_contents()));
+    manager_.reset(new PermissionRequestManager(web_contents()));
     view_factory_.reset(new MockPermissionBubbleFactory(manager_.get()));
   }
 
@@ -62,7 +62,7 @@
   }
 
   void WaitForFrameLoad() {
-    // PermissionBubbleManager ignores all parameters. Yay?
+    // PermissionRequestManager ignores all parameters. Yay?
     manager_->DocumentLoadedInFrame(NULL);
     base::RunLoop().RunUntilIdle();
   }
@@ -86,11 +86,11 @@
   MockPermissionBubbleRequest request2_;
   MockPermissionBubbleRequest iframe_request_same_domain_;
   MockPermissionBubbleRequest iframe_request_other_domain_;
-  std::unique_ptr<PermissionBubbleManager> manager_;
+  std::unique_ptr<PermissionRequestManager> manager_;
   std::unique_ptr<MockPermissionBubbleFactory> view_factory_;
 };
 
-TEST_F(PermissionBubbleManagerTest, SingleRequest) {
+TEST_F(PermissionRequestManagerTest, SingleRequest) {
   manager_->AddRequest(&request1_);
   manager_->DisplayPendingRequests();
   WaitForCoalescing();
@@ -103,7 +103,7 @@
   EXPECT_TRUE(request1_.granted());
 }
 
-TEST_F(PermissionBubbleManagerTest, SingleRequestViewFirst) {
+TEST_F(PermissionRequestManagerTest, SingleRequestViewFirst) {
   manager_->DisplayPendingRequests();
   manager_->AddRequest(&request1_);
   WaitForCoalescing();
@@ -116,7 +116,7 @@
   EXPECT_TRUE(request1_.granted());
 }
 
-TEST_F(PermissionBubbleManagerTest, TwoRequests) {
+TEST_F(PermissionRequestManagerTest, TwoRequests) {
   manager_->AddRequest(&request1_);
   manager_->AddRequest(&request2_);
   manager_->DisplayPendingRequests();
@@ -132,7 +132,7 @@
   EXPECT_FALSE(request2_.granted());
 }
 
-TEST_F(PermissionBubbleManagerTest, TwoRequestsTabSwitch) {
+TEST_F(PermissionRequestManagerTest, TwoRequestsTabSwitch) {
   manager_->AddRequest(&request1_);
   manager_->AddRequest(&request2_);
   manager_->DisplayPendingRequests();
@@ -157,20 +157,20 @@
   EXPECT_FALSE(request2_.granted());
 }
 
-TEST_F(PermissionBubbleManagerTest, NoRequests) {
+TEST_F(PermissionRequestManagerTest, NoRequests) {
   manager_->DisplayPendingRequests();
   WaitForCoalescing();
   EXPECT_FALSE(view_factory_->is_visible());
 }
 
-TEST_F(PermissionBubbleManagerTest, NoView) {
+TEST_F(PermissionRequestManagerTest, NoView) {
   manager_->AddRequest(&request1_);
   // Don't display the pending requests.
   WaitForCoalescing();
   EXPECT_FALSE(view_factory_->is_visible());
 }
 
-TEST_F(PermissionBubbleManagerTest, TwoRequestsCoalesce) {
+TEST_F(PermissionRequestManagerTest, TwoRequestsCoalesce) {
   manager_->DisplayPendingRequests();
   manager_->AddRequest(&request1_);
   manager_->AddRequest(&request2_);
@@ -181,7 +181,7 @@
   ASSERT_EQ(view_factory_->request_count(), 2);
 }
 
-TEST_F(PermissionBubbleManagerTest, TwoRequestsDoNotCoalesce) {
+TEST_F(PermissionRequestManagerTest, TwoRequestsDoNotCoalesce) {
   manager_->DisplayPendingRequests();
   manager_->AddRequest(&request1_);
   WaitForCoalescing();
@@ -191,7 +191,7 @@
   ASSERT_EQ(view_factory_->request_count(), 1);
 }
 
-TEST_F(PermissionBubbleManagerTest, TwoRequestsShownInTwoBubbles) {
+TEST_F(PermissionRequestManagerTest, TwoRequestsShownInTwoBubbles) {
   manager_->DisplayPendingRequests();
   manager_->AddRequest(&request1_);
   WaitForCoalescing();
@@ -208,7 +208,7 @@
   ASSERT_EQ(view_factory_->show_count(), 2);
 }
 
-TEST_F(PermissionBubbleManagerTest, TestAddDuplicateRequest) {
+TEST_F(PermissionRequestManagerTest, TestAddDuplicateRequest) {
   manager_->DisplayPendingRequests();
   manager_->AddRequest(&request1_);
   manager_->AddRequest(&request2_);
@@ -219,7 +219,7 @@
   ASSERT_EQ(view_factory_->request_count(), 2);
 }
 
-TEST_F(PermissionBubbleManagerTest, SequentialRequests) {
+TEST_F(PermissionRequestManagerTest, SequentialRequests) {
   manager_->DisplayPendingRequests();
   manager_->AddRequest(&request1_);
   WaitForCoalescing();
@@ -238,7 +238,7 @@
   EXPECT_TRUE(request2_.granted());
 }
 
-TEST_F(PermissionBubbleManagerTest, SameRequestRejected) {
+TEST_F(PermissionRequestManagerTest, SameRequestRejected) {
   manager_->DisplayPendingRequests();
   manager_->AddRequest(&request1_);
   manager_->AddRequest(&request1_);
@@ -249,7 +249,7 @@
   ASSERT_EQ(view_factory_->request_count(), 1);
 }
 
-TEST_F(PermissionBubbleManagerTest, DuplicateRequestCancelled) {
+TEST_F(PermissionRequestManagerTest, DuplicateRequestCancelled) {
   manager_->DisplayPendingRequests();
   manager_->AddRequest(&request1_);
   MockPermissionBubbleRequest dupe_request("test1");
@@ -261,7 +261,7 @@
   EXPECT_TRUE(request1_.finished());
 }
 
-TEST_F(PermissionBubbleManagerTest, DuplicateQueuedRequest) {
+TEST_F(PermissionRequestManagerTest, DuplicateQueuedRequest) {
   manager_->DisplayPendingRequests();
   manager_->AddRequest(&request1_);
   WaitForCoalescing();
@@ -286,7 +286,7 @@
   EXPECT_TRUE(request2_.finished());
 }
 
-TEST_F(PermissionBubbleManagerTest, ForgetRequestsOnPageNavigation) {
+TEST_F(PermissionRequestManagerTest, ForgetRequestsOnPageNavigation) {
   manager_->DisplayPendingRequests();
   manager_->AddRequest(&request1_);
   WaitForCoalescing();
@@ -305,7 +305,7 @@
   EXPECT_TRUE(iframe_request_other_domain_.finished());
 }
 
-TEST_F(PermissionBubbleManagerTest, TestCancelQueued) {
+TEST_F(PermissionRequestManagerTest, TestCancelQueued) {
   manager_->AddRequest(&request1_);
   EXPECT_FALSE(view_factory_->is_visible());
 
@@ -321,7 +321,7 @@
   ASSERT_EQ(view_factory_->request_count(), 1);
 }
 
-TEST_F(PermissionBubbleManagerTest, TestCancelWhileDialogShown) {
+TEST_F(PermissionRequestManagerTest, TestCancelWhileDialogShown) {
   manager_->DisplayPendingRequests();
   manager_->AddRequest(&request1_);
   WaitForCoalescing();
@@ -335,7 +335,7 @@
   EXPECT_FALSE(view_factory_->is_visible());
 }
 
-TEST_F(PermissionBubbleManagerTest, TestCancelWhileDialogShownNoUpdate) {
+TEST_F(PermissionRequestManagerTest, TestCancelWhileDialogShownNoUpdate) {
   manager_->DisplayPendingRequests();
   view_factory_->SetCanUpdateUi(false);
   manager_->AddRequest(&request1_);
@@ -350,7 +350,7 @@
   Closing();
 }
 
-TEST_F(PermissionBubbleManagerTest, TestCancelPendingRequest) {
+TEST_F(PermissionRequestManagerTest, TestCancelPendingRequest) {
   manager_->DisplayPendingRequests();
   manager_->AddRequest(&request1_);
   WaitForCoalescing();
@@ -365,7 +365,7 @@
   EXPECT_TRUE(request2_.finished());
 }
 
-TEST_F(PermissionBubbleManagerTest, MainFrameNoRequestIFrameRequest) {
+TEST_F(PermissionRequestManagerTest, MainFrameNoRequestIFrameRequest) {
   manager_->DisplayPendingRequests();
   manager_->AddRequest(&iframe_request_same_domain_);
   WaitForCoalescing();
@@ -376,7 +376,7 @@
   EXPECT_TRUE(iframe_request_same_domain_.finished());
 }
 
-TEST_F(PermissionBubbleManagerTest, MainFrameAndIFrameRequestSameDomain) {
+TEST_F(PermissionRequestManagerTest, MainFrameAndIFrameRequestSameDomain) {
   manager_->DisplayPendingRequests();
   manager_->AddRequest(&request1_);
   manager_->AddRequest(&iframe_request_same_domain_);
@@ -391,7 +391,7 @@
   EXPECT_FALSE(view_factory_->is_visible());
 }
 
-TEST_F(PermissionBubbleManagerTest, MainFrameAndIFrameRequestOtherDomain) {
+TEST_F(PermissionRequestManagerTest, MainFrameAndIFrameRequestOtherDomain) {
   manager_->DisplayPendingRequests();
   manager_->AddRequest(&request1_);
   manager_->AddRequest(&iframe_request_other_domain_);
@@ -407,7 +407,7 @@
   EXPECT_TRUE(iframe_request_other_domain_.finished());
 }
 
-TEST_F(PermissionBubbleManagerTest, IFrameRequestWhenMainRequestVisible) {
+TEST_F(PermissionRequestManagerTest, IFrameRequestWhenMainRequestVisible) {
   manager_->DisplayPendingRequests();
   manager_->AddRequest(&request1_);
   WaitForCoalescing();
@@ -425,7 +425,7 @@
   EXPECT_TRUE(iframe_request_same_domain_.finished());
 }
 
-TEST_F(PermissionBubbleManagerTest,
+TEST_F(PermissionRequestManagerTest,
        IFrameRequestOtherDomainWhenMainRequestVisible) {
   manager_->DisplayPendingRequests();
   manager_->AddRequest(&request1_);
@@ -442,7 +442,7 @@
   EXPECT_TRUE(iframe_request_other_domain_.finished());
 }
 
-TEST_F(PermissionBubbleManagerTest, RequestsDontNeedUserGesture) {
+TEST_F(PermissionRequestManagerTest, RequestsDontNeedUserGesture) {
   manager_->DisplayPendingRequests();
   WaitForFrameLoad();
   WaitForCoalescing();
@@ -454,7 +454,7 @@
   EXPECT_TRUE(view_factory_->is_visible());
 }
 
-TEST_F(PermissionBubbleManagerTest, UMAForSimpleAcceptedBubble) {
+TEST_F(PermissionRequestManagerTest, UMAForSimpleAcceptedBubble) {
   base::HistogramTester histograms;
 
   manager_->AddRequest(&request1_);
@@ -474,7 +474,7 @@
       static_cast<base::HistogramBase::Sample>(PermissionBubbleType::QUOTA), 1);
 }
 
-TEST_F(PermissionBubbleManagerTest, UMAForSimpleDeniedBubble) {
+TEST_F(PermissionRequestManagerTest, UMAForSimpleDeniedBubble) {
   base::HistogramTester histograms;
 
   manager_->AddRequest(&request1_);
@@ -492,7 +492,7 @@
 // This code path (calling Accept on a non-merged bubble, with no accepted
 // permission) would never be used in actual Chrome, but its still tested for
 // completeness.
-TEST_F(PermissionBubbleManagerTest, UMAForSimpleDeniedBubbleAlternatePath) {
+TEST_F(PermissionRequestManagerTest, UMAForSimpleDeniedBubbleAlternatePath) {
   base::HistogramTester histograms;
 
   manager_->AddRequest(&request1_);
@@ -508,7 +508,7 @@
       static_cast<base::HistogramBase::Sample>(PermissionBubbleType::QUOTA), 1);
 }
 
-TEST_F(PermissionBubbleManagerTest, UMAForMergedAcceptedBubble) {
+TEST_F(PermissionRequestManagerTest, UMAForMergedAcceptedBubble) {
   base::HistogramTester histograms;
 
   manager_->AddRequest(&request1_);
@@ -549,7 +549,7 @@
       1);
 }
 
-TEST_F(PermissionBubbleManagerTest, UMAForMergedMixedBubble) {
+TEST_F(PermissionRequestManagerTest, UMAForMergedMixedBubble) {
   base::HistogramTester histograms;
 
   manager_->AddRequest(&request1_);
@@ -577,7 +577,7 @@
       1);
 }
 
-TEST_F(PermissionBubbleManagerTest, UMAForMergedDeniedBubble) {
+TEST_F(PermissionRequestManagerTest, UMAForMergedDeniedBubble) {
   base::HistogramTester histograms;
 
   manager_->AddRequest(&request1_);
diff --git a/chrome/browser/permissions/permission_uma_util.cc b/chrome/browser/permissions/permission_uma_util.cc
index efbdf5f0..70324dd5 100644
--- a/chrome/browser/permissions/permission_uma_util.cc
+++ b/chrome/browser/permissions/permission_uma_util.cc
@@ -6,13 +6,21 @@
 
 #include <utility>
 
+#include "base/command_line.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/permissions/permission_manager.h"
 #include "chrome/browser/permissions/permission_util.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/safe_browsing/safe_browsing_service.h"
+#include "chrome/browser/safe_browsing/ui_manager.h"
+#include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/ui/website_settings/permission_bubble_request.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "components/browser_sync/browser/profile_sync_service.h"
+#include "components/prefs/pref_service.h"
 #include "components/rappor/rappor_service.h"
 #include "components/rappor/rappor_utils.h"
 #include "content/public/browser/permission_type.h"
@@ -74,99 +82,6 @@
                             permission_str.c_str(), action_str.c_str());
 }
 
-void RecordPermissionAction(PermissionType permission,
-                            PermissionAction action,
-                            const GURL& requesting_origin) {
-  bool secure_origin = content::IsOriginSecure(requesting_origin);
-
-  switch (permission) {
-    case PermissionType::GEOLOCATION:
-        PERMISSION_ACTION_UMA(
-            secure_origin,
-            "Permissions.Action.Geolocation",
-            "Permissions.Action.SecureOrigin.Geolocation",
-            "Permissions.Action.InsecureOrigin.Geolocation",
-            action);
-        break;
-    case PermissionType::NOTIFICATIONS:
-        PERMISSION_ACTION_UMA(
-            secure_origin,
-            "Permissions.Action.Notifications",
-            "Permissions.Action.SecureOrigin.Notifications",
-            "Permissions.Action.InsecureOrigin.Notifications",
-            action);
-        break;
-    case PermissionType::MIDI_SYSEX:
-        PERMISSION_ACTION_UMA(
-            secure_origin,
-            "Permissions.Action.MidiSysEx",
-            "Permissions.Action.SecureOrigin.MidiSysEx",
-            "Permissions.Action.InsecureOrigin.MidiSysEx",
-            action);
-        break;
-    case PermissionType::PUSH_MESSAGING:
-        PERMISSION_ACTION_UMA(
-            secure_origin,
-            "Permissions.Action.PushMessaging",
-            "Permissions.Action.SecureOrigin.PushMessaging",
-            "Permissions.Action.InsecureOrigin.PushMessaging",
-            action);
-        break;
-    case PermissionType::PROTECTED_MEDIA_IDENTIFIER:
-        PERMISSION_ACTION_UMA(
-            secure_origin,
-            "Permissions.Action.ProtectedMedia",
-            "Permissions.Action.SecureOrigin.ProtectedMedia",
-            "Permissions.Action.InsecureOrigin.ProtectedMedia",
-            action);
-        break;
-    case PermissionType::DURABLE_STORAGE:
-        PERMISSION_ACTION_UMA(
-            secure_origin,
-            "Permissions.Action.DurableStorage",
-            "Permissions.Action.SecureOrigin.DurableStorage",
-            "Permissions.Action.InsecureOrigin.DurableStorage",
-            action);
-        break;
-    case PermissionType::AUDIO_CAPTURE:
-        // Media permissions are disabled on insecure origins, so there's no
-        // need to record metrics for secure/insecue.
-        UMA_HISTOGRAM_ENUMERATION("Permissions.Action.AudioCapture", action,
-                                  PERMISSION_ACTION_NUM);
-        break;
-    case PermissionType::VIDEO_CAPTURE:
-        UMA_HISTOGRAM_ENUMERATION("Permissions.Action.VideoCapture", action,
-                                  PERMISSION_ACTION_NUM);
-        break;
-    // The user is not prompted for these permissions, thus there is no
-    // permission action recorded for them.
-    case PermissionType::MIDI:
-    case PermissionType::BACKGROUND_SYNC:
-    case PermissionType::NUM:
-      NOTREACHED() << "PERMISSION "
-                   << PermissionUtil::GetPermissionString(permission)
-                   << " not accounted for";
-  }
-
-  // Retrieve the name of the RAPPOR metric. Currently, the new metric name is
-  // the deprecated name with "2" on the end, e.g.
-  // ContentSettings.PermissionActions_Geolocation.Granted.Url2. For simplicity,
-  // we retrieve the deprecated name and append the "2" for the new name.
-  // TODO(dominickn): remove the deprecated metric and replace it solely with
-  // the new one in GetRapporMetric - crbug.com/605836.
-  const std::string deprecated_metric = GetRapporMetric(permission, action);
-  rappor::RapporService* rappor_service = g_browser_process->rappor_service();
-  if (!deprecated_metric.empty() && rappor_service) {
-    rappor::SampleDomainAndRegistryFromGURL(rappor_service, deprecated_metric,
-                                            requesting_origin);
-
-    std::string rappor_metric = deprecated_metric + "2";
-    rappor_service->RecordSample(
-        rappor_metric, rappor::LOW_FREQUENCY_ETLD_PLUS_ONE_RAPPOR_TYPE,
-        rappor::GetDomainAndRegistrySampleFromGURL(requesting_origin));
-  }
-}
-
 void RecordPermissionRequest(PermissionType permission,
                              const GURL& requesting_origin,
                              const GURL& embedding_origin,
@@ -280,34 +195,39 @@
 }
 
 void PermissionUmaUtil::PermissionGranted(PermissionType permission,
-                                          const GURL& requesting_origin) {
-  RecordPermissionAction(permission, GRANTED, requesting_origin);
+                                          const GURL& requesting_origin,
+                                          Profile* profile) {
+  RecordPermissionAction(permission, GRANTED, requesting_origin, profile);
 }
 
 void PermissionUmaUtil::PermissionDenied(PermissionType permission,
-                                         const GURL& requesting_origin) {
-  RecordPermissionAction(permission, DENIED, requesting_origin);
+                                         const GURL& requesting_origin,
+                                         Profile* profile) {
+  RecordPermissionAction(permission, DENIED, requesting_origin, profile);
 }
 
 void PermissionUmaUtil::PermissionDismissed(PermissionType permission,
-                                            const GURL& requesting_origin) {
-  RecordPermissionAction(permission, DISMISSED, requesting_origin);
+                                            const GURL& requesting_origin,
+                                            Profile* profile) {
+  RecordPermissionAction(permission, DISMISSED, requesting_origin, profile);
 }
 
 void PermissionUmaUtil::PermissionIgnored(PermissionType permission,
-                                          const GURL& requesting_origin) {
-  RecordPermissionAction(permission, IGNORED, requesting_origin);
+                                          const GURL& requesting_origin,
+                                          Profile* profile) {
+  RecordPermissionAction(permission, IGNORED, requesting_origin, profile);
 }
 
 void PermissionUmaUtil::PermissionRevoked(PermissionType permission,
-                                          const GURL& revoked_origin) {
+                                          const GURL& revoked_origin,
+                                          Profile* profile) {
   // TODO(tsergeant): Expand metrics definitions for revocation to include all
   // permissions.
   if (permission == PermissionType::NOTIFICATIONS ||
       permission == PermissionType::GEOLOCATION ||
       permission == PermissionType::AUDIO_CAPTURE ||
       permission == PermissionType::VIDEO_CAPTURE) {
-    RecordPermissionAction(permission, REVOKED, revoked_origin);
+    RecordPermissionAction(permission, REVOKED, revoked_origin, profile);
   }
 }
 
@@ -374,3 +294,127 @@
   PERMISSION_BUBBLE_TYPE_UMA(kPermissionsPromptDenied,
                              requests[0]->GetPermissionBubbleType());
 }
+
+bool PermissionUmaUtil::IsOptedIntoPermissionActionReporting(Profile* profile) {
+  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnablePermissionActionReporting))
+    return false;
+  // TODO(stefanocs): Remove this check once all callsites have been updated
+  // to not pass a nullptr.
+  if (!profile)
+    return false;
+  if (profile->GetProfileType() == Profile::INCOGNITO_PROFILE)
+    return false;
+  if (!profile->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled))
+    return false;
+
+  ProfileSyncService* profile_sync_service =
+      ProfileSyncServiceFactory::GetForProfile(profile);
+
+  // Do not report if profile can't get a profile sync service due to disable
+  // sync flag.
+  if (!profile_sync_service)
+    return false;
+
+  if (!profile_sync_service->CanSyncStart())
+    return false;
+
+  syncer::ModelTypeSet preferred_data_types =
+      profile_sync_service->GetPreferredDataTypes();
+  if (!preferred_data_types.Has(syncer::PROXY_TABS))
+    return false;
+  if (!preferred_data_types.Has(syncer::PRIORITY_PREFERENCES))
+    return false;
+
+  return true;
+}
+
+void PermissionUmaUtil::RecordPermissionAction(PermissionType permission,
+                                               PermissionAction action,
+                                               const GURL& requesting_origin,
+                                               Profile* profile) {
+  if (IsOptedIntoPermissionActionReporting(profile)) {
+    // TODO(stefanocs): Add browsertests to make sure the reports are being
+    // sent.
+    g_browser_process->safe_browsing_service()
+        ->ui_manager()
+        ->ReportPermissionAction(requesting_origin, permission, action);
+  }
+
+  bool secure_origin = content::IsOriginSecure(requesting_origin);
+
+  switch (permission) {
+    case PermissionType::GEOLOCATION:
+      PERMISSION_ACTION_UMA(secure_origin, "Permissions.Action.Geolocation",
+                            "Permissions.Action.SecureOrigin.Geolocation",
+                            "Permissions.Action.InsecureOrigin.Geolocation",
+                            action);
+      break;
+    case PermissionType::NOTIFICATIONS:
+      PERMISSION_ACTION_UMA(secure_origin, "Permissions.Action.Notifications",
+                            "Permissions.Action.SecureOrigin.Notifications",
+                            "Permissions.Action.InsecureOrigin.Notifications",
+                            action);
+      break;
+    case PermissionType::MIDI_SYSEX:
+      PERMISSION_ACTION_UMA(secure_origin, "Permissions.Action.MidiSysEx",
+                            "Permissions.Action.SecureOrigin.MidiSysEx",
+                            "Permissions.Action.InsecureOrigin.MidiSysEx",
+                            action);
+      break;
+    case PermissionType::PUSH_MESSAGING:
+      PERMISSION_ACTION_UMA(secure_origin, "Permissions.Action.PushMessaging",
+                            "Permissions.Action.SecureOrigin.PushMessaging",
+                            "Permissions.Action.InsecureOrigin.PushMessaging",
+                            action);
+      break;
+    case PermissionType::PROTECTED_MEDIA_IDENTIFIER:
+      PERMISSION_ACTION_UMA(secure_origin, "Permissions.Action.ProtectedMedia",
+                            "Permissions.Action.SecureOrigin.ProtectedMedia",
+                            "Permissions.Action.InsecureOrigin.ProtectedMedia",
+                            action);
+      break;
+    case PermissionType::DURABLE_STORAGE:
+      PERMISSION_ACTION_UMA(secure_origin, "Permissions.Action.DurableStorage",
+                            "Permissions.Action.SecureOrigin.DurableStorage",
+                            "Permissions.Action.InsecureOrigin.DurableStorage",
+                            action);
+      break;
+    case PermissionType::AUDIO_CAPTURE:
+      // Media permissions are disabled on insecure origins, so there's no
+      // need to record metrics for secure/insecue.
+      UMA_HISTOGRAM_ENUMERATION("Permissions.Action.AudioCapture", action,
+                                PERMISSION_ACTION_NUM);
+      break;
+    case PermissionType::VIDEO_CAPTURE:
+      UMA_HISTOGRAM_ENUMERATION("Permissions.Action.VideoCapture", action,
+                                PERMISSION_ACTION_NUM);
+      break;
+    // The user is not prompted for these permissions, thus there is no
+    // permission action recorded for them.
+    case PermissionType::MIDI:
+    case PermissionType::BACKGROUND_SYNC:
+    case PermissionType::NUM:
+      NOTREACHED() << "PERMISSION "
+                   << PermissionUtil::GetPermissionString(permission)
+                   << " not accounted for";
+  }
+
+  // Retrieve the name of the RAPPOR metric. Currently, the new metric name is
+  // the deprecated name with "2" on the end, e.g.
+  // ContentSettings.PermissionActions_Geolocation.Granted.Url2. For simplicity,
+  // we retrieve the deprecated name and append the "2" for the new name.
+  // TODO(dominickn): remove the deprecated metric and replace it solely with
+  // the new one in GetRapporMetric - crbug.com/605836.
+  const std::string deprecated_metric = GetRapporMetric(permission, action);
+  rappor::RapporService* rappor_service = g_browser_process->rappor_service();
+  if (!deprecated_metric.empty() && rappor_service) {
+    rappor::SampleDomainAndRegistryFromGURL(rappor_service, deprecated_metric,
+                                            requesting_origin);
+
+    std::string rappor_metric = deprecated_metric + "2";
+    rappor_service->RecordSample(
+        rappor_metric, rappor::LOW_FREQUENCY_ETLD_PLUS_ONE_RAPPOR_TYPE,
+        rappor::GetDomainAndRegistrySampleFromGURL(requesting_origin));
+  }
+}
diff --git a/chrome/browser/permissions/permission_uma_util.h b/chrome/browser/permissions/permission_uma_util.h
index f1636173..0d7c771 100644
--- a/chrome/browser/permissions/permission_uma_util.h
+++ b/chrome/browser/permissions/permission_uma_util.h
@@ -51,15 +51,20 @@
                                   const GURL& embedding_origin,
                                   Profile* profile);
   static void PermissionGranted(content::PermissionType permission,
-                                const GURL& requesting_origin);
+                                const GURL& requesting_origin,
+                                Profile* profile);
   static void PermissionDenied(content::PermissionType permission,
-                               const GURL& requesting_origin);
+                               const GURL& requesting_origin,
+                               Profile* profile);
   static void PermissionDismissed(content::PermissionType permission,
-                                  const GURL& requesting_origin);
+                                  const GURL& requesting_origin,
+                                  Profile* profile);
   static void PermissionIgnored(content::PermissionType permission,
-                                const GURL& requesting_origin);
+                                const GURL& requesting_origin,
+                                Profile* profile);
   static void PermissionRevoked(content::PermissionType permission,
-                                const GURL& revoked_origin);
+                                const GURL& revoked_origin,
+                                Profile* profile);
 
   // UMA specifically for when permission prompts are shown. This should be
   // roughly equivalent to the metrics above, however it is
@@ -86,7 +91,16 @@
       const std::vector<PermissionBubbleRequest*>& requests);
 
  private:
+  friend class PermissionUmaUtilTest;
+
   DISALLOW_IMPLICIT_CONSTRUCTORS(PermissionUmaUtil);
+
+  static bool IsOptedIntoPermissionActionReporting(Profile* profile);
+
+  static void RecordPermissionAction(content::PermissionType permission,
+                                     PermissionAction action,
+                                     const GURL& requesting_origin,
+                                     Profile* profile);
 };
 
 #endif  // CHROME_BROWSER_PERMISSIONS_PERMISSION_UMA_UTIL_H_
diff --git a/chrome/browser/permissions/permission_uma_util_unittest.cc b/chrome/browser/permissions/permission_uma_util_unittest.cc
new file mode 100644
index 0000000..4921fceb
--- /dev/null
+++ b/chrome/browser/permissions/permission_uma_util_unittest.cc
@@ -0,0 +1,161 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/permissions/permission_uma_util.h"
+
+#include "base/command_line.h"
+#include "chrome/browser/signin/fake_signin_manager_builder.h"
+#include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/sync/profile_sync_service_factory.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/browser_sync/browser/profile_sync_service.h"
+#include "components/browser_sync/common/browser_sync_switches.h"
+#include "components/prefs/pref_service.h"
+#include "components/sync_driver/glue/sync_backend_host_mock.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "sync/internal_api/public/base/model_type.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+const char* kTestingGaiaId = "gaia_id";
+const char* kTestingUsername = "fake_username";
+}  // namespace
+
+class PermissionUmaUtilTest : public testing::Test {
+ protected:
+  PermissionUmaUtilTest() : profile_(new TestingProfile()) {}
+
+  static bool IsOptedIntoPermissionActionReporting(Profile* profile) {
+    return PermissionUmaUtil::IsOptedIntoPermissionActionReporting(profile);
+  }
+
+  void SetUp() override {
+    profile_.reset(new TestingProfile());
+    ResetCommandLine();
+  }
+
+  void FakeSignIn() {
+    SigninManagerBase* signin_manager =
+        static_cast<FakeSigninManagerForTesting*>(
+            SigninManagerFactory::GetForProfile(profile()));
+    signin_manager->SetAuthenticatedAccountInfo(kTestingGaiaId,
+                                                kTestingUsername);
+    // Attach a sync backend to the profile sync service.
+    GetProfileSyncService()->backend_.reset(
+        new browser_sync::SyncBackendHostMock());
+    GetProfileSyncService()->backend_initialized_ = true;
+  }
+
+  void ResetCommandLine() {
+    base::CommandLine::Reset();
+    base::CommandLine::Init(0, NULL);
+  }
+
+  void SetKeepEverythingSynced(bool flag) {
+    GetProfileSyncService()->sync_prefs_.SetKeepEverythingSynced(flag);
+  }
+
+  void SetSafeBrowsing(bool enabled) {
+    PrefService* preferences = profile_->GetPrefs();
+    preferences->SetBoolean(prefs::kSafeBrowsingEnabled, enabled);
+  }
+
+  ProfileSyncService* GetProfileSyncService() {
+    return ProfileSyncServiceFactory::GetForProfile(profile());
+  }
+
+  Profile* profile() { return profile_.get(); }
+
+ private:
+  content::TestBrowserThreadBundle thread_bundle_;
+  std::unique_ptr<Profile> profile_;
+};
+
+// Test that PermissionUmaUtil::IsOptedIntoPermissionActionReporting returns
+// true if Safe Browsing is enabled, Permission Action Reporting flag is
+// enabled, not in incognito mode and signed in with default sync preferences.
+TEST_F(PermissionUmaUtilTest, IsOptedIntoPermissionActionReportingSignInCheck) {
+  SetSafeBrowsing(true);
+  base::CommandLine::ForCurrentProcess()->AppendSwitch(
+      switches::kEnablePermissionActionReporting);
+  EXPECT_FALSE(IsOptedIntoPermissionActionReporting(profile()));
+
+  FakeSignIn();
+  EXPECT_FALSE(IsOptedIntoPermissionActionReporting(
+      profile()->GetOffTheRecordProfile()));
+  EXPECT_TRUE(IsOptedIntoPermissionActionReporting(profile()));
+}
+
+// Test that PermissionUmaUtil::IsOptedIntoPermissionActionReporting returns
+// false if Permission Action Reporting is not enabled.
+TEST_F(PermissionUmaUtilTest, IsOptedIntoPermissionActionReportingFlagCheck) {
+  SetSafeBrowsing(true);
+  FakeSignIn();
+  base::CommandLine::ForCurrentProcess()->AppendSwitch(
+      switches::kEnablePermissionActionReporting);
+  EXPECT_TRUE(IsOptedIntoPermissionActionReporting(profile()));
+
+  ResetCommandLine();
+  EXPECT_FALSE(IsOptedIntoPermissionActionReporting(profile()));
+
+  base::CommandLine::ForCurrentProcess()->AppendSwitch(
+      switches::kDisablePermissionActionReporting);
+  EXPECT_FALSE(IsOptedIntoPermissionActionReporting(profile()));
+}
+
+// Test that PermissionUmaUtil::IsOptedIntoPermissionActionReporting returns
+// false if Safe Browsing is disabled.
+TEST_F(PermissionUmaUtilTest,
+       IsOptedIntoPermissionActionReportingSafeBrowsingCheck) {
+  base::CommandLine::ForCurrentProcess()->AppendSwitch(
+      switches::kEnablePermissionActionReporting);
+  FakeSignIn();
+  SetSafeBrowsing(true);
+  EXPECT_TRUE(IsOptedIntoPermissionActionReporting(profile()));
+
+  SetSafeBrowsing(false);
+  EXPECT_FALSE(IsOptedIntoPermissionActionReporting(profile()));
+}
+
+// Test that PermissionUmaUtil::IsOptedIntoPermissionActionReporting returns
+// false if Sync is disabled.
+TEST_F(PermissionUmaUtilTest,
+       IsOptedIntoPermissionActionReportingProfileSyncServiceCheck) {
+  base::CommandLine::ForCurrentProcess()->AppendSwitch(
+      switches::kEnablePermissionActionReporting);
+  SetSafeBrowsing(true);
+  FakeSignIn();
+  EXPECT_TRUE(IsOptedIntoPermissionActionReporting(profile()));
+
+  base::CommandLine::ForCurrentProcess()->AppendSwitch(switches::kDisableSync);
+  EXPECT_FALSE(IsOptedIntoPermissionActionReporting(profile()));
+}
+
+// Test that PermissionUmaUtil::IsOptedIntoPermissionActionReporting returns
+// false if Tab Sync and Pref Sync are not both enabled.
+TEST_F(PermissionUmaUtilTest,
+       IsOptedIntoPermissionActionReportingSyncPreferenceCheck) {
+  base::CommandLine::ForCurrentProcess()->AppendSwitch(
+      switches::kEnablePermissionActionReporting);
+  SetSafeBrowsing(true);
+  FakeSignIn();
+  EXPECT_TRUE(IsOptedIntoPermissionActionReporting(profile()));
+
+  SetKeepEverythingSynced(false);
+  GetProfileSyncService()->ChangePreferredDataTypes(
+      syncer::ModelTypeSet(syncer::PROXY_TABS));
+  EXPECT_FALSE(IsOptedIntoPermissionActionReporting(profile()));
+
+  SetKeepEverythingSynced(false);
+  GetProfileSyncService()->ChangePreferredDataTypes(
+      syncer::ModelTypeSet(syncer::PRIORITY_PREFERENCES));
+  EXPECT_FALSE(IsOptedIntoPermissionActionReporting(profile()));
+
+  SetKeepEverythingSynced(true);
+  GetProfileSyncService()->ChangePreferredDataTypes(
+      syncer::ModelTypeSet(syncer::PROXY_TABS, syncer::PREFERENCES));
+  EXPECT_TRUE(IsOptedIntoPermissionActionReporting(profile()));
+}
diff --git a/chrome/browser/permissions/permission_util.cc b/chrome/browser/permissions/permission_util.cc
index 8749ac4..78271a2c5 100644
--- a/chrome/browser/permissions/permission_util.cc
+++ b/chrome/browser/permissions/permission_util.cc
@@ -100,7 +100,8 @@
       final_value != CONTENT_SETTING_ALLOW) {
     PermissionType permission_type;
     if (PermissionUtil::GetPermissionType(content_type, &permission_type)) {
-      PermissionUmaUtil::PermissionRevoked(permission_type, primary_url);
+      PermissionUmaUtil::PermissionRevoked(permission_type, primary_url,
+                                           profile);
     }
   }
 }
diff --git a/chrome/browser/prefs/chrome_pref_service_factory.cc b/chrome/browser/prefs/chrome_pref_service_factory.cc
index 0c7a9f5..9d95bbd 100644
--- a/chrome/browser/prefs/chrome_pref_service_factory.cc
+++ b/chrome/browser/prefs/chrome_pref_service_factory.cc
@@ -429,9 +429,7 @@
   if (supervised_user_settings) {
     scoped_refptr<PrefStore> supervised_user_prefs = make_scoped_refptr(
         new SupervisedUserPrefStore(supervised_user_settings));
-    // TODO(bauerb): Temporary CHECK while investigating
-    // https://crbug.com/425785. Remove when that bug is fixed.
-    CHECK(async || supervised_user_prefs->IsInitializationComplete());
+    DCHECK(async || supervised_user_prefs->IsInitializationComplete());
     factory->set_supervised_user_prefs(supervised_user_prefs);
   }
 #endif
diff --git a/chrome/browser/profiles/profile_window_browsertest.cc b/chrome/browser/profiles/profile_window_browsertest.cc
index f722e54a..d1233ae5 100644
--- a/chrome/browser/profiles/profile_window_browsertest.cc
+++ b/chrome/browser/profiles/profile_window_browsertest.cc
@@ -87,7 +87,7 @@
  public:
   // Don't handle accelerators.
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override {
+                                  ui::Accelerator* accelerator) const override {
     return false;
   }
 };
diff --git a/chrome/browser/push_messaging/push_messaging_browsertest.cc b/chrome/browser/push_messaging/push_messaging_browsertest.cc
index de9d4eb..550e4a4 100644
--- a/chrome/browser/push_messaging/push_messaging_browsertest.cc
+++ b/chrome/browser/push_messaging/push_messaging_browsertest.cc
@@ -29,6 +29,7 @@
 #include "chrome/browser/notifications/message_center_display_service.h"
 #include "chrome/browser/notifications/notification_test_util.h"
 #include "chrome/browser/notifications/platform_notification_service_impl.h"
+#include "chrome/browser/permissions/permission_request_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/push_messaging/push_messaging_app_identifier.h"
 #include "chrome/browser/push_messaging/push_messaging_constants.h"
@@ -38,7 +39,6 @@
 #include "chrome/browser/services/gcm/gcm_profile_service_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/features.h"
 #include "chrome/test/base/in_process_browser_test.h"
@@ -207,8 +207,8 @@
         kPushMessagingAppIdentifierPrefix);
   }
 
-  PermissionBubbleManager* GetPermissionBubbleManager() {
-    return PermissionBubbleManager::FromWebContents(
+  PermissionRequestManager* GetPermissionRequestManager() {
+    return PermissionRequestManager::FromWebContents(
         GetBrowser()->tab_strip_model()->GetActiveWebContents());
   }
 
@@ -296,16 +296,16 @@
 
 void PushMessagingBrowserTest::RequestAndAcceptPermission() {
   std::string script_result;
-  GetPermissionBubbleManager()->set_auto_response_for_test(
-      PermissionBubbleManager::ACCEPT_ALL);
+  GetPermissionRequestManager()->set_auto_response_for_test(
+      PermissionRequestManager::ACCEPT_ALL);
   EXPECT_TRUE(RunScript("requestNotificationPermission();", &script_result));
   EXPECT_EQ("permission status - granted", script_result);
 }
 
 void PushMessagingBrowserTest::RequestAndDenyPermission() {
   std::string script_result;
-  GetPermissionBubbleManager()->set_auto_response_for_test(
-      PermissionBubbleManager::DENY_ALL);
+  GetPermissionRequestManager()->set_auto_response_for_test(
+      PermissionRequestManager::DENY_ALL);
   EXPECT_TRUE(RunScript("requestNotificationPermission();", &script_result));
   EXPECT_EQ("permission status - denied", script_result);
 }
@@ -383,8 +383,8 @@
   ASSERT_TRUE(RunScript("registerServiceWorker()", &script_result));
   ASSERT_EQ("ok - service worker registered", script_result);
 
-  GetPermissionBubbleManager()->set_auto_response_for_test(
-      PermissionBubbleManager::ACCEPT_ALL);
+  GetPermissionRequestManager()->set_auto_response_for_test(
+      PermissionRequestManager::ACCEPT_ALL);
   ASSERT_TRUE(RunScript("documentSubscribePush()", &script_result));
   EXPECT_EQ(GetEndpointForSubscriptionId("1-0"), script_result);
 
diff --git a/chrome/browser/push_messaging/push_messaging_permission_context.cc b/chrome/browser/push_messaging/push_messaging_permission_context.cc
index a7a786f1..c7ae175 100644
--- a/chrome/browser/push_messaging/push_messaging_permission_context.cc
+++ b/chrome/browser/push_messaging/push_messaging_permission_context.cc
@@ -118,7 +118,8 @@
 
   if (push_content_setting == CONTENT_SETTING_BLOCK) {
     DVLOG(1) << "Push permission was explicitly blocked.";
-    PermissionUmaUtil::PermissionDenied(permission_type(), requesting_origin);
+    PermissionUmaUtil::PermissionDenied(permission_type(), requesting_origin,
+                                        profile_);
     NotifyPermissionSet(id, requesting_origin, embedding_origin, callback,
                         true /* persist */, CONTENT_SETTING_BLOCK);
     return;
@@ -131,7 +132,8 @@
     return;
   }
 
-  PermissionUmaUtil::PermissionGranted(permission_type(), requesting_origin);
+  PermissionUmaUtil::PermissionGranted(permission_type(), requesting_origin,
+                                       profile_);
   NotifyPermissionSet(id, requesting_origin, embedding_origin, callback,
                       true /* persist */, CONTENT_SETTING_ALLOW);
 }
diff --git a/chrome/browser/renderer_context_menu/mock_render_view_context_menu.cc b/chrome/browser/renderer_context_menu/mock_render_view_context_menu.cc
index 71239482..c78af76 100644
--- a/chrome/browser/renderer_context_menu/mock_render_view_context_menu.cc
+++ b/chrome/browser/renderer_context_menu/mock_render_view_context_menu.cc
@@ -53,7 +53,7 @@
 
 bool MockRenderViewContextMenu::GetAcceleratorForCommandId(
     int command_id,
-    ui::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) const {
   return false;
 }
 
diff --git a/chrome/browser/renderer_context_menu/mock_render_view_context_menu.h b/chrome/browser/renderer_context_menu/mock_render_view_context_menu.h
index 133ca40..d286cdb 100644
--- a/chrome/browser/renderer_context_menu/mock_render_view_context_menu.h
+++ b/chrome/browser/renderer_context_menu/mock_render_view_context_menu.h
@@ -52,7 +52,7 @@
   void MenuWillShow(ui::SimpleMenuModel* source) override;
   void MenuClosed(ui::SimpleMenuModel* source) override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
 
   // RenderViewContextMenuProxy implementation.
   void AddMenuItem(int command_id, const base::string16& title) override;
diff --git a/chrome/browser/renderer_context_menu/open_with_menu_factory_ash.cc b/chrome/browser/renderer_context_menu/open_with_menu_factory_ash.cc
index 2909bd22..c4494b2 100644
--- a/chrome/browser/renderer_context_menu/open_with_menu_factory_ash.cc
+++ b/chrome/browser/renderer_context_menu/open_with_menu_factory_ash.cc
@@ -37,7 +37,7 @@
 
 bool OpenWithMenuObserver::SubMenuDelegate::GetAcceleratorForCommandId(
     int command_id,
-    ui::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) const {
   return false;
 }
 
diff --git a/chrome/browser/renderer_context_menu/open_with_menu_factory_ash.h b/chrome/browser/renderer_context_menu/open_with_menu_factory_ash.h
index b6e7348..e801f2e 100644
--- a/chrome/browser/renderer_context_menu/open_with_menu_factory_ash.h
+++ b/chrome/browser/renderer_context_menu/open_with_menu_factory_ash.h
@@ -36,8 +36,9 @@
 
     bool IsCommandIdChecked(int command_id) const override;
     bool IsCommandIdEnabled(int command_id) const override;
-    bool GetAcceleratorForCommandId(int command_id,
-                                    ui::Accelerator* accelerator) override;
+    bool GetAcceleratorForCommandId(
+        int command_id,
+        ui::Accelerator* accelerator) const override;
     void ExecuteCommand(int command_id, int event_flags) override;
 
    private:
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.cc
index a0da432c..40de50b 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.cc
@@ -37,7 +37,7 @@
 
 bool TestRenderViewContextMenu::GetAcceleratorForCommandId(
     int command_id,
-    ui::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) const {
   // None of our commands have accelerators, so always return false.
   return false;
 }
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h b/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h
index 391f5ec..0d2249a 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h
@@ -42,7 +42,7 @@
 
   // Implementation of pure virtuals in RenderViewContextMenu.
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
 
   // Returns true if the command specified by |command_id| is present
   // in the menu.
diff --git a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc
index acad9e3..11bc778 100644
--- a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc
+++ b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc
@@ -714,8 +714,7 @@
 void ChromeResourceDispatcherHostDelegate::OnResponseStarted(
     net::URLRequest* request,
     content::ResourceContext* resource_context,
-    content::ResourceResponse* response,
-    IPC::Sender* sender) {
+    content::ResourceResponse* response) {
   const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
   ProfileIOData* io_data = ProfileIOData::FromResourceContext(resource_context);
 
diff --git a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h
index 5afcfd5..dd211f29 100644
--- a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h
+++ b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h
@@ -84,8 +84,7 @@
                        std::unique_ptr<content::StreamInfo> stream) override;
   void OnResponseStarted(net::URLRequest* request,
                          content::ResourceContext* resource_context,
-                         content::ResourceResponse* response,
-                         IPC::Sender* sender) override;
+                         content::ResourceResponse* response) override;
   void OnRequestRedirected(const GURL& redirect_url,
                            net::URLRequest* request,
                            content::ResourceContext* resource_context,
diff --git a/chrome/browser/resources/bookmark_manager/js/main.js b/chrome/browser/resources/bookmark_manager/js/main.js
index 48e74f2..319397ec 100644
--- a/chrome/browser/resources/bookmark_manager/js/main.js
+++ b/chrome/browser/resources/bookmark_manager/js/main.js
@@ -77,24 +77,24 @@
 var commandShortcutMap = cr.isMac ? {
   'edit': 'Enter',
   // On Mac we also allow Meta+Backspace.
-  'delete': 'U+007F  U+0008 Meta-U+0008',
-  'open-in-background-tab': 'Meta-Enter',
-  'open-in-new-tab': 'Shift-Meta-Enter',
-  'open-in-same-window': 'Meta-Down',
-  'open-in-new-window': 'Shift-Enter',
+  'delete': 'Delete Backspace Meta|Backspace',
+  'open-in-background-tab': 'Meta|Enter',
+  'open-in-new-tab': 'Shift|Meta|Enter',
+  'open-in-same-window': 'Meta|Down',
+  'open-in-new-window': 'Shift|Enter',
   'rename-folder': 'Enter',
   // Global undo is Command-Z. It is not in any menu.
-  'undo': 'Meta-U+005A',
+  'undo': 'Meta|z',
 } : {
   'edit': 'F2',
-  'delete': 'U+007F',
-  'open-in-background-tab': 'Ctrl-Enter',
-  'open-in-new-tab': 'Shift-Ctrl-Enter',
+  'delete': 'Delete',
+  'open-in-background-tab': 'Ctrl|Enter',
+  'open-in-new-tab': 'Shift|Ctrl|Enter',
   'open-in-same-window': 'Enter',
-  'open-in-new-window': 'Shift-Enter',
+  'open-in-new-window': 'Shift|Enter',
   'rename-folder': 'F2',
   // Global undo is Ctrl-Z. It is not in any menu.
-  'undo': 'Ctrl-U+005A',
+  'undo': 'Ctrl|z',
 };
 
 /**
diff --git a/chrome/browser/resources/chromeos/arc_support/background.js b/chrome/browser/resources/chromeos/arc_support/background.js
index 41a744e6..e6acea59 100644
--- a/chrome/browser/resources/chromeos/arc_support/background.js
+++ b/chrome/browser/resources/chromeos/arc_support/background.js
@@ -66,6 +66,19 @@
 var termsAccepted = false;
 
 /**
+ * Host window inner default width.
+ * @const {number}
+ */
+var INNER_WIDTH = 960;
+
+/**
+ * Host window inner default height.
+ * @const {number}
+ */
+var INNER_HEIGHT = 688;
+
+
+/**
  * Closes current window in response to request from native code. This does not
  * issue 'cancelAuthCode' message to native code.
  */
@@ -207,6 +220,8 @@
     closeWindowInternally();
   } else if (message.action == 'showPage') {
     showPageWithStatus(message.page, message.status);
+  } else if (message.action == 'setWindowBounds') {
+    setWindowBounds();
   }
 }
 
@@ -307,10 +322,46 @@
   termsView.src = 'https://play.google.com/about/play-terms.html';
 }
 
+function setWindowBounds() {
+  if (!appWindow) {
+    return;
+  }
+
+  var decorationWidth = appWindow.outerBounds.width -
+      appWindow.innerBounds.width;
+  var decorationHeight = appWindow.outerBounds.height -
+      appWindow.innerBounds.height;
+
+  var outerWidth = INNER_WIDTH + decorationWidth;
+  var outerHeight = INNER_HEIGHT + decorationHeight;
+  if (outerWidth > screen.availWidth) {
+    outerWidth = screen.availWidth;
+  }
+  if (outerHeight > screen.availHeight) {
+    outerHeight = screen.availHeight;
+  }
+  if (appWindow.outerBounds.width == outerWidth &&
+      appWindow.outerBounds.height == outerHeight) {
+    return;
+  }
+
+  appWindow.outerBounds.width = outerWidth;
+  appWindow.outerBounds.height = outerHeight;
+  appWindow.outerBounds.left = Math.ceil((screen.availWidth - outerWidth) / 2);
+  appWindow.outerBounds.top =
+    Math.ceil((screen.availHeight - outerHeight) / 2);
+}
+
 chrome.app.runtime.onLaunched.addListener(function() {
   var onAppContentLoad = function() {
     var doc = appWindow.contentWindow.document;
     lsoView = doc.getElementById('arc-support');
+    lsoView.addContentScripts([
+        { name: 'postProcess',
+          matches: ['https://accounts.google.com/*'],
+          css: { files: ['lso.css'] },
+          run_at: 'document_end'
+        }]);
 
     var isApprovalResponse = function(url) {
       var resultUrlPrefix = 'https://accounts.google.com/o/oauth2/approval?';
@@ -340,6 +391,10 @@
       if (!isApprovalResponse(lsoView.src)) {
         // Show LSO page when its content is ready.
         showPage('lso');
+        // We have fixed width for LSO page in css file in order to prevent
+        // unwanted webview resize animation when it is shown first time. Now
+        // it safe to make it up to window width.
+        lsoView.style.width = '100%';
         return;
       }
 
@@ -457,6 +512,8 @@
     appWindow = createdWindow;
     appWindow.contentWindow.onload = onAppContentLoad;
     createdWindow.onClosed.addListener(onWindowClosed);
+
+    setWindowBounds();
   };
 
   var onWindowClosed = function() {
@@ -472,6 +529,7 @@
   };
 
   windowClosedInternally = false;
+
   var options = {
     'id': 'play_store_wnd',
     'resizable': false,
@@ -481,8 +539,8 @@
       color: '#ffffff'
     },
     'innerBounds': {
-      'width': 960,
-      'height': 688
+      'width': INNER_WIDTH,
+      'height': INNER_HEIGHT
     }
   };
   chrome.app.window.create('main.html', options, onWindowCreated);
diff --git a/chrome/browser/resources/chromeos/arc_support/lso.css b/chrome/browser/resources/chromeos/arc_support/lso.css
new file mode 100644
index 0000000..3e5556544
--- /dev/null
+++ b/chrome/browser/resources/chromeos/arc_support/lso.css
@@ -0,0 +1,20 @@
+/**
+ * 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.
+ */
+
+::-webkit-scrollbar {
+  background: transparent;
+  height: 4px;
+  width: 4px;
+}
+
+::-webkit-scrollbar-thumb {
+  background: rgba(0, 0, 0, 0.3);
+  height: 16px;
+}
+
+::-webkit-scrollbar-thumb:hover {
+  background: rgba(0, 0, 0, 0.2);
+}
diff --git a/chrome/browser/resources/chromeos/arc_support/main.css b/chrome/browser/resources/chromeos/arc_support/main.css
index 1ca1369a..a71d6563 100644
--- a/chrome/browser/resources/chromeos/arc_support/main.css
+++ b/chrome/browser/resources/chromeos/arc_support/main.css
@@ -15,7 +15,24 @@
   width: 100%;
 }
 
+::-webkit-scrollbar {
+  background: transparent;
+  height: 4px;
+  width: 4px;
+}
+
+::-webkit-scrollbar-thumb {
+  background: rgba(0, 0, 0, 0.3);
+  height: 16px;
+}
+
+::-webkit-scrollbar-thumb:hover {
+  background: rgba(0, 0, 0, 0.2);
+}
+
 #arc-support {
+  flex: auto;
+  overflow: hidden;
   width: 960px;
 }
 
@@ -34,6 +51,13 @@
   width: 16px;
 }
 
+.content {
+  /* Default window inner height (688px) minus image caption height (300px) */
+  height: 388px;
+  margin: 0;
+  padding: 0;
+}
+
 .image-header {
   display: block;
   height: 300px;
@@ -41,7 +65,16 @@
   width: 960px;
 }
 
+.scrollable {
+  flex: auto;
+  margin: 0;
+  overflow: auto;
+  padding: 0;
+}
+
 .section {
+  display: flex;
+  flex-direction: column;
   text-align: center;
 }
 
@@ -54,7 +87,6 @@
 .section-flex {
   display: flex;
   flex-direction: column;
-  height: 688px;
 }
 
 .section-checkbox-container {
diff --git a/chrome/browser/resources/chromeos/arc_support/main.html b/chrome/browser/resources/chromeos/arc_support/main.html
index 4cd3b6d..c9dd9b23 100644
--- a/chrome/browser/resources/chromeos/arc_support/main.html
+++ b/chrome/browser/resources/chromeos/arc_support/main.html
@@ -44,40 +44,55 @@
 <body>
   <div id="terms-loading" class="section">
     <img class="image-header" src="images/header.png">
-    <p class="text-title" i18n-content="greetingHeader"></p>
-    <p class="text-desc" i18n-content="greetingDescription"></p>
-    <paper-progress class="blue" indeterminate></paper-progress>
+    <div class="scrollable">
+      <div class="content">
+        <p class="text-title" i18n-content="greetingHeader"></p>
+        <p class="text-desc" i18n-content="greetingDescription"></p>
+        <paper-progress class="blue" indeterminate></paper-progress>
+      </div>
+    </div>
   </div>
-  <div id="terms" class="section section-flex" hidden>
+  <div id="terms" class="section" hidden>
     <img class="image-header" src="images/header.png">
-    <p class="text-title" i18n-content="greetingHeader"></p>
-    <p class="text-desc" i18n-content="greetingDescription"></p>
-    <p class="text-terms-title" i18n-content="termsOfService"></p>
-    <div class="section-terms" id ="terms-container">
-      <webview id="terms-view" partition="persist:arc_support"></webview>
-    </div>
-    <div class="layout horizontal section-checkbox-container">
-      <input type="checkbox" class="checkbox-option" id="enable-metrics" hidden>
-      <p class="checkbox-text" id="text-metrics"></p>
-    </div>
-    <div id="section-backup-restore" class="layout horizontal
-        section-checkbox-container">
-      <input type="checkbox" class="checkbox-option" id="enable-backup-restore">
-      <p class="checkbox-text" id="text-backup-restore"></p>
-    </div>
-    <div class="layout horizontal end-justified section-buttons">
-      <paper-button class="white" id="button-cancel"
-          i18n-content="buttonCancel">
-      </paper-button>
-      <div class="button-separator"></div>
-      <paper-button class="blue" id="button-agree" i18n-content="buttonAgree">
-      </paper-button>
+    <div class="scrollable" >
+      <div class="content section-flex">
+        <p class="text-title" i18n-content="greetingHeader"></p>
+        <p class="text-desc" i18n-content="greetingDescription"></p>
+        <p class="text-terms-title" i18n-content="termsOfService"></p>
+        <div class="section-terms" id ="terms-container">
+          <webview id="terms-view" partition="persist:arc_support"></webview>
+        </div>
+        <div class="layout horizontal section-checkbox-container">
+          <input type="checkbox" class="checkbox-option" id="enable-metrics"
+              hidden>
+          <p class="checkbox-text" id="text-metrics"></p>
+        </div>
+        <div id="section-backup-restore" class="layout horizontal
+            section-checkbox-container">
+          <input type="checkbox" class="checkbox-option"
+              id="enable-backup-restore">
+          <p class="checkbox-text" id="text-backup-restore"></p>
+        </div>
+        <div class="layout horizontal end-justified section-buttons">
+          <paper-button class="white" id="button-cancel"
+              i18n-content="buttonCancel">
+          </paper-button>
+          <div class="button-separator"></div>
+          <paper-button class="blue" id="button-agree"
+            i18n-content="buttonAgree">
+          </paper-button>
+        </div>
+      </div>
     </div>
   </div>
   <div id="lso-loading" class="section" hidden>
     <img class="image-header" src="images/header.png">
-    <paper-progress class="blue" indeterminate></paper-progress>
-    <p class="text-status" i18n-content=progressLsoLoading></p>
+    <div class="scrollable">
+      <div class="content">
+        <paper-progress class="blue" indeterminate></paper-progress>
+        <p class="text-status" i18n-content=progressLsoLoading></p>
+      </div>
+    </div>
   </div>
   <div id="lso" class="section" hidden>
     <img class="image-header" src="images/header.png">
@@ -85,18 +100,26 @@
   </div>
   <div id="arc-loading" class="section" hidden>
     <img class="image-header" src="images/header.png">
-    <paper-progress class="blue" indeterminate></paper-progress>
-    <p class="text-status" i18n-content="progressAndroidLoading"></p>
+    <div class="scrollable">
+      <div class="content">
+        <paper-progress class="blue" indeterminate></paper-progress>
+        <p class="text-status" i18n-content="progressAndroidLoading"></p>
+      </div>
+    </div>
   </div>
   <div id="error" class="section" hidden>
     <img class="image-header" src="images/header.png">
-    <paper-progress class="red" value="100" max="100" ></paper-progress>
-    <p class="text-status" id="error-message"></p>
-    <paper-button class="blue" id="button-send-feedback"
-        i18n-content="buttonSendFeedback">
-    </paper-button>
-    <paper-button class="blue" id="button-retry" i18n-content="buttonRetry">
-    </paper-button>
+    <div class="scrollable">
+      <div class="content">
+        <paper-progress class="red" value="100" max="100" ></paper-progress>
+        <p class="text-status" id="error-message"></p>
+        <paper-button class="blue" id="button-send-feedback"
+            i18n-content="buttonSendFeedback">
+        </paper-button>
+        <paper-button class="blue" id="button-retry" i18n-content="buttonRetry">
+        </paper-button>
+      </div>
+    </div>
   </div>
 </body>
 </html>
diff --git a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd
index 8cd5d2958..22d61ef 100644
--- a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd
+++ b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
-<grit base_dir="." current_release="1" enc_check="möl" latest_public_release="0" source_lang_id="en">
+<grit base_dir="." current_release="1" latest_public_release="0"
+      output_all_resource_defines="false" enc_check="möl" source_lang_id="en">
   <outputs>
     <output filename="_locales/am/messages.json" type="chrome_messages_json" lang="am"/>
     <output filename="_locales/ar/messages.json" type="chrome_messages_json" lang="ar"/>
diff --git a/chrome/browser/resources/chromeos/login/custom_elements_oobe.html b/chrome/browser/resources/chromeos/login/custom_elements_oobe.html
index 40599cd77..69db270 100644
--- a/chrome/browser/resources/chromeos/login/custom_elements_oobe.html
+++ b/chrome/browser/resources/chromeos/login/custom_elements_oobe.html
@@ -16,6 +16,7 @@
 <include src="navigation_bar.html">
 <include src="oobe_buttons.html">
 <include src="oobe_card.html">
+<include src="oobe_dialog.html">
 <include src="oobe_welcome.html">
 
 <script src="chrome://oobe/custom_elements.js"></script>
diff --git a/chrome/browser/resources/chromeos/login/custom_elements_oobe.js b/chrome/browser/resources/chromeos/login/custom_elements_oobe.js
index bbef3bc4..347df431 100644
--- a/chrome/browser/resources/chromeos/login/custom_elements_oobe.js
+++ b/chrome/browser/resources/chromeos/login/custom_elements_oobe.js
@@ -23,4 +23,5 @@
 <include src="navigation_bar.js">
 <include src="oobe_buttons.js">
 <include src="oobe_card.js">
+<include src="oobe_dialog.js">
 <include src="oobe_welcome.js">
diff --git a/chrome/browser/resources/chromeos/login/login_non_lock_shared.html b/chrome/browser/resources/chromeos/login/login_non_lock_shared.html
index 4badc40..10ac9cdd 100644
--- a/chrome/browser/resources/chromeos/login/login_non_lock_shared.html
+++ b/chrome/browser/resources/chromeos/login/login_non_lock_shared.html
@@ -35,4 +35,3 @@
 <link rel="stylesheet" href="../../options/chromeos/bluetooth.css">
 
 <script src="chrome://oobe/keyboard_utils.js"></script>
-<script src="chrome://resources/js/polymer_config.js"></script>
diff --git a/chrome/browser/resources/chromeos/login/login_shared.html b/chrome/browser/resources/chromeos/login/login_shared.html
index 144c679..1f9eefc 100644
--- a/chrome/browser/resources/chromeos/login/login_shared.html
+++ b/chrome/browser/resources/chromeos/login/login_shared.html
@@ -6,6 +6,8 @@
 Any additional include increases the lock screen initialization time.
 -->
 
+<!-- This must be the first import in all login pages. -->
+<link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="stylesheet" href="chrome://resources/css/butter_bar.css">
 <link rel="stylesheet" href="chrome://resources/css/dialogs.css">
 <link rel="stylesheet" href="chrome://resources/css/list.css">
diff --git a/chrome/browser/resources/chromeos/login/oobe_dialog.css b/chrome/browser/resources/chromeos/login/oobe_dialog.css
new file mode 100644
index 0000000..4b4e4959
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/oobe_dialog.css
@@ -0,0 +1,74 @@
+/* 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. */
+
+:host {
+  display: flex;
+  flex-direction: column;
+  position: relative;
+}
+
+.oobe-icon-div {
+ --iron-icon-height: 20px;
+ --iron-icon-width: 20px;
+ color: var(--google-blue-500);
+}
+
+.oobe-header {
+  background-color: white;
+  color: black;
+  height: 150px;
+}
+
+.oobe-footer {
+  background-color: white;
+  position: relative;
+}
+
+.header-container {
+  padding: 50px 40px 18px;
+}
+
+.footer-container {
+  padding: 24px 40px 34px;
+}
+
+::content div.oobe-body-text {
+  margin-bottom: 24px;
+}
+
+::content div.oobe-body-text p {
+  color: rgba(0, 0, 0, 0.87);
+  font-size: 14px;
+  line-height: 20px;
+  margin: 0;
+}
+
+::content h1.welcome-message {
+  color: rgba(0, 0, 0, 0.87);
+  font-size: 20px;
+  font-weight: normal;
+  margin-bottom: 0;
+}
+
+::content h1.welcome-message-hint {
+  color: rgba(0, 0, 0, 0.87);
+  font-size: 12px;
+  font-weight: normal;
+  margin-bottom: 0;
+}
+
+.overlay {
+  background-color: rgba(0, 0, 0, 0.5);
+  display: none;
+  height: 100%;
+  position: absolute;
+  right: 0;
+  top: 0;
+  width: 100%;
+  z-index: 11;
+}
+
+:host(.full-disabled) #full-overlay,
+:host(.disabled) #bottom-overlay,
+
diff --git a/chrome/browser/resources/chromeos/login/oobe_dialog.html b/chrome/browser/resources/chromeos/login/oobe_dialog.html
new file mode 100644
index 0000000..80b000c
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/oobe_dialog.html
@@ -0,0 +1,45 @@
+<!-- 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. -->
+
+<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-styles/color.html">
+
+<!--
+  Simple OOBE card which should be used for OOBE UI elements.
+  It has blue header and grey footer.
+
+  Example:
+    <oobe-dialog>
+      <iron-icon ... class="oobe-icon">
+      <div class="header flex vertical layout end-justified start">
+        ...
+      </div>
+      <oobe-input-form class="footer" ...>
+      </oobe-input-form>
+    </oobe-dialog>
+
+  Add class |header| to all which you want to go inside the header.  Similar
+  with clases |footer| and |oobe-icon|.
+-->
+<dom-module name="oobe-dialog">
+  <link rel="stylesheet" href="oobe_dialog.css">
+  <template>
+    <div class="oobe-header vertical layout relative">
+      <div class="header-container flex vertical layout relative">
+        <div class="oobe-icon-div">
+          <content select=".oobe-icon"></content>
+        </div>
+        <content select=".header"></content>
+      </div>
+    </div>
+    <div class="oobe-footer flex vertical layout">
+      <div class="footer-container flex vertical layout">
+        <content select=".footer"></content>
+      </div>
+      <div id="bottom-overlay" class="overlay"></div>
+    </div>
+    <div id="full-overlay" class="overlay"></div>
+  </template>
+</dom-module>
+
diff --git a/chrome/browser/resources/chromeos/login/oobe_dialog.js b/chrome/browser/resources/chromeos/login/oobe_dialog.js
new file mode 100644
index 0000000..8dd5bc3
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/oobe_dialog.js
@@ -0,0 +1,5 @@
+// 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.
+
+Polymer({is: 'oobe-dialog'});
diff --git a/chrome/browser/resources/chromeos/login/oobe_welcome.html b/chrome/browser/resources/chromeos/login/oobe_welcome.html
index a666a05..d4a2e85 100644
--- a/chrome/browser/resources/chromeos/login/oobe_welcome.html
+++ b/chrome/browser/resources/chromeos/login/oobe_welcome.html
@@ -2,12 +2,26 @@
      Use of this source code is governed by a BSD-style license that can be
      found in the LICENSE file. -->
 
+<link rel="import" href="chrome://resources/cr_elements/network/cr_network_icon.html">
+<link rel="import" href="chrome://resources/cr_elements/network/cr_network_select.html">
+<link rel="import" href="chrome://resources/cr_elements/network/cr_onc_types.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/iron-icon/iron-icon.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-iconset-svg/iron-iconset-svg.html">
+
+<iron-iconset-svg name="oobe-welcome" size="24">
+  <svg>
+    <defs>
+      <g id="add"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"></path></g>
+      <g id="wifi"><path d="M1 9l2 2c4.97-4.97 13.03-4.97 18 0l2-2C16.93 2.93 7.08 2.93 1 9zm8 8l3 3 3-3c-1.65-1.66-4.34-1.66-6 0zm-4-4l2 2c2.76-2.76 7.24-2.76 10 0l2-2C15.14 9.14 8.87 9.14 5 13z"></path></g>
+    </defs>
+  </svg>
+</iron-iconset-svg>
 
 <dom-module name="oobe-welcome-md">
   <link rel="stylesheet" href="oobe_welcome.css">
   <template>
-    <oobe-card class="fit">
+    <oobe-card id="welcomeSection" class="fit" hidden="[[networkSelectionScreenShown]]">
       <div class="header flex vertical layout end-justified start">
         <h1 class="welcome-message" i18n-content="networkScreenGreeting"></h1>
       </div>
@@ -27,6 +41,22 @@
         </div>
       </div>
     </oobe-card>
+    <oobe-dialog id="networkSection" class="fit" hidden="[[!networkSelectionScreenShown]]">
+      <iron-icon icon="oobe-welcome:wifi" class="oobe-icon"></iron-icon>
+      <div class="header flex vertical layout end-justified start">
+        <h1 class="welcome-message" i18n-content="networkSectionTitle"></h1>
+        <h1 class="welcome-message-hint" i18n-content="networkSectionHint"></h1>
+      </div>
+      <div class="footer flex vertical layout justified">
+        <cr-network-select id="networkSelect"
+            on-network-connected="onNetworkConnected_"
+            on-network-item-selected="onNetworkListNetworkItemSelected_"
+            on-custom-item-selected="onNetworkListCustomItemSelected_"
+            custom-items="[[_getNetworkCustomItems()]]"
+            max-height="280">
+        </cr-network-select>
+      </div>
+    </oobe-dialog>
   </template>
 </dom-module>
 
diff --git a/chrome/browser/resources/chromeos/login/oobe_welcome.js b/chrome/browser/resources/chromeos/login/oobe_welcome.js
index 3500dcd..5b48931 100644
--- a/chrome/browser/resources/chromeos/login/oobe_welcome.js
+++ b/chrome/browser/resources/chromeos/login/oobe_welcome.js
@@ -2,30 +2,187 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+/**
+ * @fileoverview Polymer element for displaying material design OOBE.
+ */
+
 Polymer({
   is: 'oobe-welcome-md',
 
   properties: {
-    disabled: {
-      type: Boolean,
-      value: false,
-    },
+    /**
+     * Currently selected system language.
+     */
     currentLanguage: {
       type: String,
       value: 'English (US)',
     },
+
+    /**
+     * Flag that switches Welcome screen to Network Selection screen.
+     */
+    networkSelectionScreenShown: {
+      type: Boolean,
+      value: false,
+    },
   },
 
+  /**
+   * GUID of the user-selected network. It is remembered after user taps on
+   * network entry. After we receive event "connected" on this network,
+   * OOBE will proceed.
+   */
+  networkLastSelectedGuid_: '',
+
+  /**
+   * Sets proper focus.
+   */
   focus: function() {
     this.$.welcomeNextButton.focus();
   },
 
+  /**
+   * Handles "visible" event.
+   * @private
+   */
   onAnimationFinish_: function() {
     this.focus();
   },
 
+  /**
+   * Returns custom items for network selector.
+   */
+  _getNetworkCustomItems: function() {
+    var self = this;
+    return [
+      {
+        customItemName: 'proxySettingsMenuName',
+        polymerIcon: 'oobe-welcome:add',
+        customData: {
+          onTap: function() { self.OpenProxySettingsDialog_(); },
+        },
+      },
+      {
+        customItemName: 'addWiFiNetworkMenuName',
+        polymerIcon: 'oobe-welcome:add',
+        customData: {
+          onTap: function() { self.OpenAddWiFiNetworkDialog_(); },
+        },
+      },
+      {
+        customItemName: 'addMobileNetworkMenuName',
+        polymerIcon: 'oobe-welcome:add',
+        customData: {
+          onTap: function() { self.OpenAddWiFiNetworkDialog_(); },
+        },
+      },
+    ];
+  },
+
+  /**
+   * Handle "Next" button for "Welcome" screen.
+   *
+   * @private
+   */
   onWelcomeNextButtonClicked_: function() {
+    this.networkSelectionScreenShown = true;
+  },
+
+  /**
+   * Handle Networwork Setup screen "Proxy settings" button.
+   *
+   * @private
+   */
+  OpenProxySettingsDialog_: function(item) {
+    chrome.send('launchProxySettingsDialog');
+  },
+
+  /**
+   * Handle Networwork Setup screen "Add WiFi network" button.
+   *
+   * @private
+   */
+  OpenAddWiFiNetworkDialog_: function(item) {
+    chrome.send('launchAddWiFiNetworkDialog');
+  },
+
+  /**
+   * Handle Networwork Setup screen "Add cellular network" button.
+   *
+   * @private
+   */
+  OpenAddMobileNetworkDialog_: function(item) {
+    chrome.send('launchAddMobileNetworkDialog');
+  },
+
+  /**
+   * This is called when network setup is done.
+   *
+   * @private
+   */
+  onSelectedNetworkConnected_: function() {
     $('oobe-connect').hidden = false;
     $('oobe-welcome-md').hidden = true;
-  }
+  },
+
+  /**
+   * This gets called when a network enters the 'Connected' state.
+   *
+   * @param {!{detail: !CrOnc.NetworkStateProperties}} event
+   * @private
+   */
+  onNetworkConnected_: function(event) {
+    var state = event.detail;
+    if (state.GUID != this.networkLastSelectedGuid_)
+      return;
+
+    this.onSelectedNetworkConnected_();
+  },
+
+  /**
+   * This is called when user taps on network entry in networks list.
+   *
+   * @param {!{detail: !CrOnc.NetworkStateProperties}} event
+   * @private
+   */
+  onNetworkListNetworkItemSelected_: function(event) {
+    var state = event.detail;
+    // If user has not previously made a selection and selected network
+    // is already connected, just continue to the next screen.
+    if (this.networkLastSelectedGuid_ == '' &&
+        state.ConnectionState == CrOnc.ConnectionState.CONNECTED) {
+      this.onSelectedNetworkConnected_();
+    }
+
+    // If user has previously selected another network, there
+    // is pending connection attempt. So even if new selection is currently
+    // connected, it may get disconnected at any time.
+    // So just send one more connection request to cancel current attempts.
+    this.networkLastSelectedGuid_ = state.GUID;
+
+    var self = this;
+    var networkStateCopy = Object.assign({}, state);
+
+    chrome.networkingPrivate.startConnect(state.GUID, function() {
+      var lastError = chrome.runtime.lastError;
+      if (!lastError)
+        return;
+
+      if (lastError.message == 'connected') {
+        self.onNetworkConnected_({'detail': networkStateCopy});
+        return;
+      }
+
+      if (lastError.message != 'connecting')
+        console.error('networkingPrivate.startConnect error: ' + lastError);
+    });
+  },
+
+  /**
+   * @param {!Event} event
+   */
+  onNetworkListCustomItemSelected_: function(e) {
+    var itemState = e.detail;
+    itemState.customData.onTap();
+  },
 });
diff --git a/chrome/browser/resources/chromeos/quick_unlock/compiled_resources2.gyp b/chrome/browser/resources/chromeos/quick_unlock/compiled_resources2.gyp
index 3de88518..0c166bf 100644
--- a/chrome/browser/resources/chromeos/quick_unlock/compiled_resources2.gyp
+++ b/chrome/browser/resources/chromeos/quick_unlock/compiled_resources2.gyp
@@ -7,7 +7,8 @@
       'target_name': 'pin_keyboard',
       'dependencies': [
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
-      ],
+        '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-button/compiled_resources2.gyp:paper-button-extracted',
+       ],
       'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
     },
   ],
diff --git a/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.js b/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.js
index f9f5873..90b32bb1 100644
--- a/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.js
+++ b/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.js
@@ -69,10 +69,21 @@
     this.$$('#pin-input').focus();
   },
 
-  /** Called when a keypad number has been tapped. */
+  /**
+   * Called when a keypad number has been tapped.
+   * @param {!{target: !PaperButtonElement}} event
+   * @private
+   */
   onNumberTap_: function(event, detail) {
     var numberValue = event.target.getAttribute('value');
     this.value += numberValue;
+
+    // If a number button is clicked, we do not want to switch focus to the
+    // button, therefore we transfer focus back to the input, but if a number
+    // button is tabbed into, it should keep focus, so users can use tab and
+    // spacebar/return to enter their PIN.
+    if (!event.target.receivedFocusFromKeyboard)
+      this.focus();
   },
 
   /** Fires a submit event with the current PIN value. */
diff --git a/chrome/browser/resources/component_extension_resources.grd b/chrome/browser/resources/component_extension_resources.grd
index e87619cf..1910b1c 100644
--- a/chrome/browser/resources/component_extension_resources.grd
+++ b/chrome/browser/resources/component_extension_resources.grd
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- This comment is only here because changes to resources are not picked up
      without changes to the corresponding grd file.  -->
-<grit latest_public_release="0" current_release="1">
+<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
   <outputs>
     <output filename="grit/component_extension_resources.h" type="rc_header">
       <emit emit_type='prepend'></emit>
@@ -146,15 +146,13 @@
         <include name="IDR_FIRST_RUN_DIALOG_ICON_256" file="chromeos/first_run/app/icon/256.png" type="BINDATA" />
         <include name="IDR_ARC_SUPPORT_BACKGROUND_JS" file="chromeos/arc_support/background.js" flattenhtml="true" type="BINDATA" />
         <include name="IDR_ARC_SUPPORT_MAIN_CSS" file="chromeos/arc_support/main.css" type="BINDATA" />
+        <include name="IDR_ARC_SUPPORT_LSO_CSS" file="chromeos/arc_support/lso.css" type="BINDATA" />
         <include name="IDR_ARC_SUPPORT_PLAYSTORE_CSS" file="chromeos/arc_support/playstore.css" type="BINDATA" />
         <include name="IDR_ARC_SUPPORT_PLAYSTORE_JS" file="chromeos/arc_support/playstore.js" type="BINDATA" />
         <include name="IDR_ARC_SUPPORT_MAIN" file="chromeos/arc_support/main.html" allowexternalscript="true" type="BINDATA" />
         <include name="IDR_ARC_SUPPORT_ICON" file="chromeos/arc_support/icon/48.png" type="BINDATA" />
         <include name="IDR_ARC_SUPPORT_ICON_HEADER" file="chromeos/arc_support/images/header.png" type="BINDATA" />
       </if>
-      <if expr="enable_settings_app">
-        <include name="IDR_SETTINGS_APP_JS" file="settings_app/settings_app.js" type="BINDATA" />
-      </if>
       <if expr="enable_plugins">
         <include name="IDR_PDF_INDEX_CSS" file="pdf/index.css" allowexternalscript="true" type="BINDATA" />
         <include name="IDR_PDF_INDEX_HTML" file="pdf/index.html" allowexternalscript="true" type="BINDATA" />
diff --git a/chrome/browser/resources/help/help_content.css b/chrome/browser/resources/help/help_content.css
index b9b7756a..4c47256 100644
--- a/chrome/browser/resources/help/help_content.css
+++ b/chrome/browser/resources/help/help_content.css
@@ -108,13 +108,13 @@
 }
 
 #eol-status-message-container {
-  -webkit-margin-start: 12px;
+  -webkit-margin-start: 8px;
   display: inline-block;
   vertical-align: middle;
 }
 
 #update-status-message-container {
-  -webkit-margin-start: 12px;
+  -webkit-margin-start: 8px;
   display: inline-block;
   vertical-align: middle;
 }
diff --git a/chrome/browser/resources/invalidations_resources.grd b/chrome/browser/resources/invalidations_resources.grd
index 2a394a00..8fdd278a 100644
--- a/chrome/browser/resources/invalidations_resources.grd
+++ b/chrome/browser/resources/invalidations_resources.grd
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="0" current_release="1">
+<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
   <outputs>
     <output filename="grit/invalidations_resources.h" type="rc_header">
       <emit emit_type='prepend'></emit>
diff --git a/chrome/browser/resources/local_ntp/most_visited_single.js b/chrome/browser/resources/local_ntp/most_visited_single.js
index 817fd76..89b6adfd 100644
--- a/chrome/browser/resources/local_ntp/most_visited_single.js
+++ b/chrome/browser/resources/local_ntp/most_visited_single.js
@@ -23,8 +23,8 @@
   // Indicates a tile was rendered, no matter if it's a thumbnail, a gray tile
   // or an external tile.
   NTP_TILE: 2,
-  // A NTP Tile has finished loading (successfully or failing).
-  NTP_TILE_LOADED: 10,
+  // All NTP Tiles have finished loading (successfully or failing).
+  NTP_ALL_TILES_LOADED: 11,
 };
 
 
@@ -133,7 +133,7 @@
   loadedCounter -= 1;
   if (loadedCounter <= 0) {
     showTiles();
-    logEvent(LOG_TYPE.NTP_TILE_LOADED);
+    logEvent(LOG_TYPE.NTP_ALL_TILES_LOADED);
     window.parent.postMessage({cmd: 'loaded'}, DOMAIN_ORIGIN);
     loadedCounter = 1;
   }
diff --git a/chrome/browser/resources/md_history/app.html b/chrome/browser/resources/md_history/app.html
index a3da52df..fb4c2ee1 100644
--- a/chrome/browser/resources/md_history/app.html
+++ b/chrome/browser/resources/md_history/app.html
@@ -52,7 +52,7 @@
     <div id="main-container">
       <iron-pages id="content" attr-for-selected="id"
           selected="[[selectedPage_]]">
-        <history-list-container id="history" query-state="[[queryState_]]"
+        <history-list-container id="history" query-state="{{queryState_}}"
             query-result="[[queryResult_]]" grouped="[[grouped_]]">
         </history-list-container>
         <template is="dom-if" if="[[syncedTabsSelected_(selectedPage_)]]">
diff --git a/chrome/browser/resources/md_history/browser_service.js b/chrome/browser/resources/md_history/browser_service.js
index 4fa10ac..e8790aae 100644
--- a/chrome/browser/resources/md_history/browser_service.js
+++ b/chrome/browser/resources/md_history/browser_service.js
@@ -49,6 +49,10 @@
       chrome.send('removeBookmark', [url]);
     },
 
+    openClearBrowsingData: function() {
+      chrome.send('clearBrowsingData');
+    },
+
     /**
      * @param {boolean} successful
      * @private
diff --git a/chrome/browser/resources/md_history/compiled_resources2.gyp b/chrome/browser/resources/md_history/compiled_resources2.gyp
index cfc189a..52673654 100644
--- a/chrome/browser/resources/md_history/compiled_resources2.gyp
+++ b/chrome/browser/resources/md_history/compiled_resources2.gyp
@@ -106,6 +106,7 @@
       'dependencies': [
         '<(DEPTH)/third_party/polymer/v1_0/components-chromium/app-layout/app-drawer/compiled_resources2.gyp:app-drawer-extracted',
         '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-selector/compiled_resources2.gyp:iron-selector-extracted',
+        'browser_service',
       ],
       'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
     },
diff --git a/chrome/browser/resources/md_history/side_bar.html b/chrome/browser/resources/md_history/side_bar.html
index 9468875..37bdc02 100644
--- a/chrome/browser/resources/md_history/side_bar.html
+++ b/chrome/browser/resources/md_history/side_bar.html
@@ -3,6 +3,7 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-selector/iron-selector.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-item.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
+<link rel="import" href="chrome://history/browser_service.html">
 <link rel="import" href="chrome://history/shared_style.html">
 
 <dom-module id="history-side-bar">
diff --git a/chrome/browser/resources/md_history/side_bar.js b/chrome/browser/resources/md_history/side_bar.js
index 46291206..46cedad3 100644
--- a/chrome/browser/resources/md_history/side_bar.js
+++ b/chrome/browser/resources/md_history/side_bar.js
@@ -36,6 +36,6 @@
    * @private
    */
   onClearBrowsingDataTap_: function() {
-    window.location.href = 'chrome://settings/clearBrowserData';
+    md_history.BrowserService.getInstance().openClearBrowsingData();
   },
 });
diff --git a/chrome/browser/resources/md_policy/policy_resources.grd b/chrome/browser/resources/md_policy/policy_resources.grd
index 50c9bcc..dc76f52 100644
--- a/chrome/browser/resources/md_policy/policy_resources.grd
+++ b/chrome/browser/resources/md_policy/policy_resources.grd
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="0" current_release="1">
+<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
   <outputs>
     <output filename="grit/policy_resources.h" type="rc_header">
       <emit emit_type='prepend'></emit>
diff --git a/chrome/browser/resources/net_internals_resources.grd b/chrome/browser/resources/net_internals_resources.grd
index 6b3aefe..5a00818 100644
--- a/chrome/browser/resources/net_internals_resources.grd
+++ b/chrome/browser/resources/net_internals_resources.grd
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- This comment is only here because changes to resources are not picked up
      without changes to the corresponding grd file. -->
-<grit latest_public_release="0" current_release="1">
+<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
   <outputs>
     <output filename="grit/net_internals_resources.h" type="rc_header">
       <emit emit_type='prepend'></emit>
diff --git a/chrome/browser/resources/options/browser_options.html b/chrome/browser/resources/options/browser_options.html
index f86d32e..553ccef 100644
--- a/chrome/browser/resources/options/browser_options.html
+++ b/chrome/browser/resources/options/browser_options.html
@@ -277,11 +277,6 @@
 </if>
       <div id="profiles-buttons">
         <button id="profiles-create" i18n-content="profilesCreate"></button>
-<if expr="enable_settings_app">
-        <button id="profiles-app-list-switch"
-            i18n-content="profilesAppListSwitch" hidden>
-        </button>
-</if>
         <button id="profiles-manage" i18n-content="profilesManage" disabled>
         </button>
         <button id="profiles-delete" i18n-content="profilesDelete"></button>
diff --git a/chrome/browser/resources/options/browser_options.js b/chrome/browser/resources/options/browser_options.js
index 8d9e0320..1fdaa55 100644
--- a/chrome/browser/resources/options/browser_options.js
+++ b/chrome/browser/resources/options/browser_options.js
@@ -389,12 +389,6 @@
                       ['Options_ShowCreateProfileDlg']);
           ManageProfileOverlay.showCreateDialog();
         };
-        if (OptionsPage.isSettingsApp()) {
-          $('profiles-app-list-switch').onclick = function(event) {
-            var selectedProfile = self.getSelectedProfileItem_();
-            chrome.send('switchAppListProfile', [selectedProfile.filePath]);
-          };
-        }
         $('profiles-manage').onclick = function(event) {
           chrome.send('metricsHandler:recordAction',
                       ['Options_ShowEditProfileDlg']);
@@ -483,7 +477,6 @@
         PageManager.showPageByName('clearBrowserData');
         chrome.send('coreOptionsUserMetricsAction', ['Options_ClearData']);
       };
-      $('privacyClearDataButton').hidden = OptionsPage.isSettingsApp();
 
       if ($('metrics-reporting-enabled')) {
         $('metrics-reporting-enabled').checked =
@@ -1527,10 +1520,6 @@
         $('profiles-manage').title = '';
       $('profiles-delete').disabled = !profilesList.canDeleteItems ||
                                       !hasSelection;
-      if (OptionsPage.isSettingsApp()) {
-        $('profiles-app-list-switch').disabled = !hasSelection ||
-            selectedProfile.isCurrentProfile;
-      }
       var importData = $('import-data');
       if (importData) {
         importData.disabled = $('import-data').disabled = hasSelection &&
@@ -1550,13 +1539,10 @@
       var showSingleProfileView = !usingNewProfilesUI && numProfiles == 1;
       $('profiles-list').hidden = showSingleProfileView;
       $('profiles-single-message').hidden = !showSingleProfileView;
-      $('profiles-manage').hidden =
-          showSingleProfileView || OptionsPage.isSettingsApp();
+      $('profiles-manage').hidden = showSingleProfileView;
       $('profiles-delete').textContent = showSingleProfileView ?
           loadTimeData.getString('profilesDeleteSingle') :
           loadTimeData.getString('profilesDelete');
-      if (OptionsPage.isSettingsApp())
-        $('profiles-app-list-switch').hidden = showSingleProfileView;
     },
 
     /**
diff --git a/chrome/browser/resources/options/options.html b/chrome/browser/resources/options/options.html
index 9318c51..026c99c 100644
--- a/chrome/browser/resources/options/options.html
+++ b/chrome/browser/resources/options/options.html
@@ -71,9 +71,6 @@
 <link rel="stylesheet" href="certificate_manager.css">
 <link rel="stylesheet" href="certificate_tree.css">
 </if>
-<if expr="enable_settings_app">
-<link rel="stylesheet" href="options_settings_app.css">
-</if>
 <script src="chrome://resources/js/action_link.js"></script>
 <script src="chrome://resources/js/cr.js"></script>
 <script src="chrome://resources/js/event_tracker.js"></script>
diff --git a/chrome/browser/resources/options/options_bundle.js b/chrome/browser/resources/options/options_bundle.js
index d6a330c..0c340bc 100644
--- a/chrome/browser/resources/options/options_bundle.js
+++ b/chrome/browser/resources/options/options_bundle.js
@@ -129,6 +129,3 @@
 <include src="../uber/uber_page_manager_observer.js">
 <include src="../uber/uber_utils.js">
 <include src="options.js">
-<if expr="enable_settings_app">
-<include src="options_settings_app.js">
-</if>
diff --git a/chrome/browser/resources/options/options_page.js b/chrome/browser/resources/options/options_page.js
index ecff736..9700c74 100644
--- a/chrome/browser/resources/options/options_page.js
+++ b/chrome/browser/resources/options/options_page.js
@@ -85,24 +85,6 @@
             'enablePepperFlashSettings');
       }
     },
-
-    /**
-     * Sets whether Settings is shown as a standalone page in a window for the
-     * app launcher settings "app".
-     * @param {boolean} isSettingsApp Whether this page is shown standalone.
-     */
-    setIsSettingsApp: function(isSettingsApp) {
-      document.documentElement.classList.toggle('settings-app', isSettingsApp);
-    },
-
-    /**
-     * Returns true if Settings is shown as an "app" (in a window by itself)
-     * for the app launcher settings "app".
-     * @return {boolean} Whether this page is shown standalone.
-     */
-    isSettingsApp: function() {
-      return document.documentElement.classList.contains('settings-app');
-    },
   };
 
   // Export
diff --git a/chrome/browser/resources/options/options_settings_app.css b/chrome/browser/resources/options/options_settings_app.css
deleted file mode 100644
index e1bd6580..0000000
--- a/chrome/browser/resources/options/options_settings_app.css
+++ /dev/null
@@ -1,47 +0,0 @@
-/* Copyright 2012 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. */
-
-/* Don't use the large margin used for the navigation bar. Settings App uses a
- * 20px margin for headings + 18px for sections.
- */
-html.settings-app body.uber-frame {
-  -webkit-margin-start: 38px;
-}
-
-/* There is a tweak in uber_shared.css to improve touch events around the
- * navigation bar (which is not used for the settings app) in reaction to a
- * webkit bug (wk95204). We need to reset back to the original style.
- */
-@media(pointer:coarse) {
-  html.settings-app body.uber-frame section {
-    -webkit-padding-start: 18px;
-  }
-  html.settings-app body.uber-frame section > h3 {
-    -webkit-margin-start: -18px;
-  }
-}
-
-html.settings-app body.uber-frame header {
-  left: 20px;
-  min-width: 400px;
-}
-
-html.settings-app #content-settings-page .content-area {
-  -webkit-margin-start: 18px;
-}
-
-/* Settings App is narrower due to no navigation margin, so the roomy language
- * overlay needs to be trimmed down. 25% is taken off the original height and
- * the width is trimmed proportional to (half) the reduction due to the removal
- * of the left margin.
- */
-html.settings-app .language-options-left {
-  height: 300px;
-  width: 228px;
-}
-
-html.settings-app .language-options-right {
-  height: 300px;
-  width: 288px;
-}
diff --git a/chrome/browser/resources/options/options_settings_app.js b/chrome/browser/resources/options/options_settings_app.js
deleted file mode 100644
index 72d2928..0000000
--- a/chrome/browser/resources/options/options_settings_app.js
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-(function() {
-  if (document.location != 'chrome://settings-frame/options_settings_app.html')
-    return;
-
-  OptionsPage.setIsSettingsApp(true);
-
-  // Override the offset in the options page.
-  PageManager.horizontalOffset = 38;
-
-  document.addEventListener('DOMContentLoaded', function() {
-    // Hide everything by default.
-    var sections = document.querySelectorAll('section');
-    for (var i = 0; i < sections.length; i++)
-      sections[i].hidden = true;
-
-    var whitelistedSections = [
-      'advanced-settings',
-      'downloads-section',
-      'handlers-section',
-      'languages-section',
-      'network-section',
-      'notifications-section',
-      'sync-section'
-    ];
-
-    for (var i = 0; i < whitelistedSections.length; i++)
-      $(whitelistedSections[i]).hidden = false;
-
-    // Avoid showing an empty Users section on ash. Note that profiles-section
-    // is actually a div element, rather than section, so is not hidden after
-    // the querySelectorAll(), above.
-    $('sync-users-section').hidden = $('profiles-section').hidden;
-
-    // Hide Import bookmarks and settings button.
-    $('import-data').hidden = true;
-
-    // Hide create / edit / delete profile buttons.
-    $('profiles-create').hidden = true;
-    $('profiles-delete').hidden = true;
-    $('profiles-manage').hidden = true;
-
-    // Remove the 'X'es on profiles in the profile list.
-    $('profiles-list').canDeleteItems = false;
-  });
-
-  loadTimeData.overrideValues(/** @type {!Object} */(
-      loadTimeData.getValue('settingsApp')));
-}());
diff --git a/chrome/browser/resources/options_resources.grd b/chrome/browser/resources/options_resources.grd
index be34501..f517c41 100644
--- a/chrome/browser/resources/options_resources.grd
+++ b/chrome/browser/resources/options_resources.grd
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="0" current_release="1">
+<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
   <outputs>
     <output filename="grit/options_resources.h" type="rc_header">
       <emit emit_type='prepend'></emit>
diff --git a/chrome/browser/resources/options_test_resources.grd b/chrome/browser/resources/options_test_resources.grd
index 9e79550..a9220f9f 100644
--- a/chrome/browser/resources/options_test_resources.grd
+++ b/chrome/browser/resources/options_test_resources.grd
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="0" current_release="1">
+<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
   <outputs>
     <output filename="grit/options_test_resources.h" type="rc_header">
       <emit emit_type='prepend'></emit>
diff --git a/chrome/browser/resources/password_manager_internals_resources.grd b/chrome/browser/resources/password_manager_internals_resources.grd
index 367acb9..ed63cbb 100644
--- a/chrome/browser/resources/password_manager_internals_resources.grd
+++ b/chrome/browser/resources/password_manager_internals_resources.grd
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="0" current_release="1">
+<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
   <outputs>
     <output filename="grit/password_manager_internals_resources.h" type="rc_header">
       <emit emit_type='prepend'></emit>
diff --git a/chrome/browser/resources/quota_internals_resources.grd b/chrome/browser/resources/quota_internals_resources.grd
index c81a1c1..d077fc8f 100644
--- a/chrome/browser/resources/quota_internals_resources.grd
+++ b/chrome/browser/resources/quota_internals_resources.grd
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="0" current_release="1">
+<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
   <outputs>
     <output filename="grit/quota_internals_resources.h" type="rc_header">
       <emit emit_type='prepend'></emit>
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.html b/chrome/browser/resources/settings/privacy_page/privacy_page.html
index fbd2986..2efb345 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_page.html
+++ b/chrome/browser/resources/settings/privacy_page/privacy_page.html
@@ -11,6 +11,7 @@
 <link rel="import" href="/site_settings/all_sites.html">
 <link rel="import" href="/site_settings/constants.html">
 <link rel="import" href="/site_settings/media_picker.html">
+<link rel="import" href="/site_settings/protocol_handlers.html">
 <link rel="import" href="/site_settings/site_data.html">
 <link rel="import" href="/site_settings_page/site_settings_page.html">
 
@@ -202,6 +203,11 @@
           </site-settings-category>
         </settings-subpage>
       </template>
+      <template is="dom-if" name="protocol-handlers">
+        <settings-subpage page-title="$i18n{siteSettingsCategoryHandlers}">
+          <protocol-handlers></protocol-handlers>
+        </settings-subpage>
+      </template>
       <template is="dom-if" name="site-settings-category-javascript">
         <settings-subpage
             page-title="$i18n{siteSettingsCategoryJavascript}">
diff --git a/chrome/browser/resources/settings/search_engines_page/search_engine_dialog.js b/chrome/browser/resources/settings/search_engines_page/search_engine_dialog.js
index ae28c04..eb272e5 100644
--- a/chrome/browser/resources/settings/search_engines_page/search_engine_dialog.js
+++ b/chrome/browser/resources/settings/search_engines_page/search_engine_dialog.js
@@ -57,7 +57,7 @@
       this.actionButtonText_ = loadTimeData.getString('save');
 
       // If editing an existing search engine, pre-populate the input fields.
-      this.searchEngine_ = this.model.displayName;
+      this.searchEngine_ = this.model.name;
       this.keyword_ = this.model.keyword;
       this.queryUrl_ = this.model.url;
     } else {
diff --git a/chrome/browser/resources/settings/settings_page/settings_router.js b/chrome/browser/resources/settings/settings_page/settings_router.js
index cf98772..d26933e 100644
--- a/chrome/browser/resources/settings/settings_page/settings_router.js
+++ b/chrome/browser/resources/settings/settings_page/settings_router.js
@@ -283,6 +283,18 @@
       subpage: ['site-settings', 'site-settings-category-images'],
     },
     {
+      url: '/siteSettings/handlers',
+      page: 'advanced',
+      section: 'privacy',
+      subpage: ['site-settings', 'protocol-handlers'],
+    },
+    {
+      url: '/siteSettings/javascript',
+      page: 'advanced',
+      section: 'privacy',
+      subpage: ['site-settings', 'site-settings-category-javascript'],
+    },
+    {
       url: '/siteSettings/keygen',
       page: 'advanced',
       section: 'privacy',
@@ -295,12 +307,6 @@
       subpage: ['site-settings', 'site-settings-category-location'],
     },
     {
-      url: '/siteSettings/javascript',
-      page: 'advanced',
-      section: 'privacy',
-      subpage: ['site-settings', 'site-settings-category-javascript'],
-    },
-    {
       url: '/siteSettings/microphone',
       page: 'advanced',
       section: 'privacy',
@@ -380,6 +386,13 @@
           'site-details'],
     },
     {
+      url: '/siteSettings/javascript/details',
+      page: 'advanced',
+      section: 'privacy',
+      subpage: ['site-settings', 'site-settings-category-javascript',
+          'site-details'],
+    },
+    {
       url: '/siteSettings/keygen/details',
       page: 'advanced',
       section: 'privacy',
@@ -394,13 +407,6 @@
           'site-details'],
     },
     {
-      url: '/siteSettings/javascript/details',
-      page: 'advanced',
-      section: 'privacy',
-      subpage: ['site-settings', 'site-settings-category-javascript',
-          'site-details'],
-    },
-    {
       url: '/siteSettings/microphone/details',
       page: 'advanced',
       section: 'privacy',
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd
index 38fb84a9..8e9c6a3c 100644
--- a/chrome/browser/resources/settings/settings_resources.grd
+++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="0" current_release="1">
+<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
   <outputs>
     <output filename="grit/settings_resources.h" type="rc_header">
       <emit emit_type='prepend'></emit>
@@ -647,6 +647,12 @@
                    file="privacy_page/privacy_page_browser_proxy.js"
                    type="chrome_html" />
       </if>
+      <structure name="IDR_SETTINGS_PROTOCOL_HANDLERS_HTML"
+                 file="site_settings/protocol_handlers.html"
+                 type="chrome_html" />
+      <structure name="IDR_SETTINGS_PROTOCOL_HANDLERS_JS"
+                 file="site_settings/protocol_handlers.js"
+                 type="chrome_html" />
       <structure name="IDR_SETTINGS_CR_SETTINGS_ROUTER_HTML"
                  file="settings_page/settings_router.html"
                  type="chrome_html" />
diff --git a/chrome/browser/resources/settings/site_settings/constants.js b/chrome/browser/resources/settings/site_settings/constants.js
index 27a10838..f32a531 100644
--- a/chrome/browser/resources/settings/site_settings/constants.js
+++ b/chrome/browser/resources/settings/site_settings/constants.js
@@ -22,6 +22,7 @@
     FULLSCREEN: 'fullscreen',
     MIC: 'media-stream-mic',
     CAMERA: 'media-stream-camera',
+    PROTOCOL_HANDLERS: 'register-protocol-handler',
     UNSANDBOXED_PLUGINS: 'ppapi-broker',
     AUTOMATIC_DOWNLOADS: 'multiple-automatic-downloads',
     KEYGEN: 'keygen',
diff --git a/chrome/browser/resources/settings/site_settings/protocol_handlers.html b/chrome/browser/resources/settings/site_settings/protocol_handlers.html
new file mode 100644
index 0000000..4e6a31e8
--- /dev/null
+++ b/chrome/browser/resources/settings/site_settings/protocol_handlers.html
@@ -0,0 +1,73 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-item.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-menu/paper-menu.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-menu-button/paper-menu-button.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
+<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
+<link rel="import" href="/i18n_setup.html">
+<link rel="import" href="/settings_shared_css.html">
+<link rel="import" href="/site_settings/site_settings_behavior.html">
+<link rel="import" href="/site_settings/site_settings_prefs_browser_proxy.html">
+
+<dom-module id="protocol-handlers">
+  <template>
+    <style include="settings-shared">
+      :host {
+        display: block;
+      }
+
+      .protocol {
+        -webkit-margin-start: 20px;
+        margin-bottom: 15px;
+        margin-top: 15px;
+      }
+    </style>
+    <div class="settings-box first two-line">
+      <div class="start secondary">
+        [[computeHandlersDescription_(categoryEnabled)]]
+      </div>
+      <paper-toggle-button id="toggle" checked="{{categoryEnabled}}"
+          on-change="onToggleChange_"></paper-toggle-button>
+    </div>
+
+    <template is="dom-repeat" items="[[protocols]]" as="protocol">
+      <div class="protocol">[[protocol.protocol]]</div>
+
+      <div class="list-frame menu-content vertical-list">
+        <template is="dom-repeat" items="[[protocol.handlers]]">
+
+          <div class="list-item underscore">
+            <div class="middle" >
+              <div>[[item.host]]</div>
+              <div class="secondary"
+                  hidden$="[[!isDefault_(index, protocol.default_handler)]]">
+                $i18n{handlerIsDefault}
+              </div>
+            </div>
+
+            <paper-menu-button>
+              <paper-icon-button icon="cr:more-vert"
+                  class="dropdown-trigger">
+              </paper-icon-button>
+              <paper-menu id="actionMenu" class="dropdown-content"
+                  on-iron-activate="onActionMenuIronActivate_"
+                  attr-for-selected="menu-value">
+                <paper-item menu-value$="[[menuActions_.SET_DEFAULT]]"
+                    hidden$="[[isDefault_(index, protocol.default_handler)]]">
+                  $i18n{handlerSetDefault}
+                </paper-item>
+                <paper-item menu-value$="[[menuActions_.REMOVE]]">
+                  $i18n{handlerRemove}
+                </paper-item>
+              </paper-menu>
+            </paper-menu-button>
+          </div>
+
+        </template>
+      </div>
+    </template>
+  </template>
+  <script src="protocol_handlers.js"></script>
+</dom-module>
diff --git a/chrome/browser/resources/settings/site_settings/protocol_handlers.js b/chrome/browser/resources/settings/site_settings/protocol_handlers.js
new file mode 100644
index 0000000..2f37b29
--- /dev/null
+++ b/chrome/browser/resources/settings/site_settings/protocol_handlers.js
@@ -0,0 +1,142 @@
+// 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.
+
+/**
+ * @fileoverview
+ * 'protocol-handlers' is the polymer element for showing the
+ * protocol handlers category under Site Settings.
+ */
+
+var MenuActions = {
+  SET_DEFAULT: 'SetDefault',
+  REMOVE: 'Remove',
+};
+
+/**
+ * @typedef {{host: string,
+ *            protocol: string,
+ *            spec: string}}
+ */
+var HandlerEntry;
+
+/**
+ * @typedef {{default_handler: number,
+ *            handlers: !Array<!HandlerEntry>,
+ *            has_policy_recommendations: boolean,
+ *            is_default_handler_set_by_user: boolean,
+ *            protocol: string}}
+ */
+var ProtocolEntry;
+
+Polymer({
+  is: 'protocol-handlers',
+
+  behaviors: [SiteSettingsBehavior, WebUIListenerBehavior],
+
+  properties: {
+    /**
+     * Represents the state of the main toggle shown for the category.
+     */
+    categoryEnabled: Boolean,
+
+    /**
+     * Array of protocols and their handlers.
+     * @type {!Array<!ProtocolEntry>}
+     */
+    protocols: Array,
+
+    /**
+     * The possible menu actions.
+     * @type {MenuActions}
+     */
+    menuActions_: {
+      type: Object,
+      value: MenuActions,
+      readOnly: true,
+    },
+  },
+
+  ready: function() {
+    this.addWebUIListener('setHandlersEnabled',
+        this.setHandlersEnabled_.bind(this));
+    this.addWebUIListener('setProtocolHandlers',
+        this.setProtocolHandlers_.bind(this));
+    this.addWebUIListener('setIgnoredProtocolHandlers',
+        this.setIgnoredProtocolHandlers_.bind(this));
+    this.browserProxy.initializeProtocolHandlerList();
+  },
+
+  /**
+   * Obtains the description for the main toggle.
+   * @param {number} categoryEnabled Whether the main toggle is enabled.
+   * @return {string} The description to use.
+   * @private
+   */
+  computeHandlersDescription_: function(categoryEnabled) {
+    return this.computeCategoryDesc(
+        settings.ContentSettingsTypes.PROTOCOL_HANDLERS, categoryEnabled, true);
+  },
+
+  /**
+   * Returns whether the given index matches the default handler.
+   * @param {number} index The index to evaluate.
+   * @param {number} defaultHandler The default handler index.
+   * @return {boolean} Whether the item is default.
+   * @private
+   */
+  isDefault_: function(index, defaultHandler) {
+    return defaultHandler == index;
+  },
+
+  /**
+   * Updates the main toggle to set it enabled/disabled.
+   * @param {boolean} enabled The state to set.
+   * @private
+   */
+  setHandlersEnabled_: function(enabled) {
+    this.categoryEnabled = enabled;
+  },
+
+  /**
+   * Updates the list of protocol handlers.
+   * @param {!Array<!ProtocolEntry>} protocols The new protocol handler list.
+   * @private
+   */
+  setProtocolHandlers_: function(protocols) {
+    this.protocols = protocols;
+  },
+
+  /**
+   * Updates the list of ignored protocol handlers.
+   * @param {!Array<!ProtocolEntry>} args The new (ignored) protocol handler
+   *     list.
+   * @private
+   */
+  setIgnoredProtocolHandlers_: function(args) {
+    // TODO(finnur): Figure this out. Have yet to be able to trigger the C++
+    // side to send this.
+  },
+
+  /**
+   * A handler when the toggle is flipped.
+   * @private
+   */
+  onToggleChange_: function(event) {
+    this.browserProxy.setProtocolHandlerDefault(this.categoryEnabled);
+  },
+
+  /**
+   * A handler when an action is selected in the action menu.
+   * @private
+   */
+  onActionMenuIronActivate_: function(event) {
+    var protocol = event.model.item.protocol;
+    var url = event.model.item.spec;
+    if (event.detail.selected == MenuActions.SET_DEFAULT) {
+      this.browserProxy.setProtocolDefault(protocol, url);
+    } else if (event.detail.selected == MenuActions.REMOVE) {
+      this.browserProxy.removeProtocolHandler(protocol, url);
+    }
+  },
+});
diff --git a/chrome/browser/resources/settings/site_settings/site_list.js b/chrome/browser/resources/settings/site_settings/site_list.js
index 4c249642..3020f519 100644
--- a/chrome/browser/resources/settings/site_settings/site_list.js
+++ b/chrome/browser/resources/settings/site_settings/site_list.js
@@ -243,6 +243,13 @@
   getAllSitesList_: function() {
     var promiseList = [];
     for (var type in settings.ContentSettingsTypes) {
+      if (settings.ContentSettingsTypes[type] ==
+          settings.ContentSettingsTypes.PROTOCOL_HANDLERS) {
+        // Protocol handlers don't have data stored the way all the other
+        // categories do.
+        continue;
+      }
+
       promiseList.push(
           this.browserProxy_.getExceptionList(
               settings.ContentSettingsTypes[type]));
diff --git a/chrome/browser/resources/settings/site_settings/site_settings_behavior.js b/chrome/browser/resources/settings/site_settings/site_settings_behavior.js
index 86ee14b3..7b05396 100644
--- a/chrome/browser/resources/settings/site_settings/site_settings_behavior.js
+++ b/chrome/browser/resources/settings/site_settings/site_settings_behavior.js
@@ -96,6 +96,8 @@
         return 'plugins';
       case settings.ContentSettingsTypes.POPUPS:
         return 'popups';
+      case settings.ContentSettingsTypes.PROTOCOL_HANDLERS:
+        return 'handlers';
       case settings.ContentSettingsTypes.UNSANDBOXED_PLUGINS:
         return 'unsandboxed-plugins';
       default:
@@ -139,6 +141,8 @@
         return 'cr:extension';
       case settings.ContentSettingsTypes.POPUPS:
         return 'settings:open-in-new';
+      case settings.ContentSettingsTypes.PROTOCOL_HANDLERS:
+        return 'settings:open-with';
       case settings.ContentSettingsTypes.UNSANDBOXED_PLUGINS:
         return 'cr:extension';
       default:
@@ -183,6 +187,8 @@
         return loadTimeData.getString('siteSettingsPlugins');
       case settings.ContentSettingsTypes.POPUPS:
         return loadTimeData.getString('siteSettingsPopups');
+      case settings.ContentSettingsTypes.PROTOCOL_HANDLERS:
+        return loadTimeData.getString('siteSettingsHandlers');
       case settings.ContentSettingsTypes.UNSANDBOXED_PLUGINS:
         return loadTimeData.getString('siteSettingsUnsandboxedPlugins');
       default:
@@ -245,6 +251,14 @@
         return showRecommendation ?
             loadTimeData.getString('siteSettingsCookiesAllowedRecommended') :
             loadTimeData.getString('siteSettingsCookiesAllowed');
+      case settings.ContentSettingsTypes.PROTOCOL_HANDLERS:
+        // "Allow sites to ask to become default handlers" vs "Blocked".
+        if (!categoryEnabled) {
+          return loadTimeData.getString('siteSettingsHandlersBlocked');
+        }
+        return showRecommendation ?
+            loadTimeData.getString('siteSettingsHandlersAskRecommended') :
+            loadTimeData.getString('siteSettingsHandlersAsk');
       case settings.ContentSettingsTypes.IMAGES:
         if (!categoryEnabled) {
           return loadTimeData.getString('siteSettingsDontShowImages');
diff --git a/chrome/browser/resources/settings/site_settings/site_settings_category.js b/chrome/browser/resources/settings/site_settings/site_settings_category.js
index 9012e4a..81672e8e 100644
--- a/chrome/browser/resources/settings/site_settings/site_settings_category.js
+++ b/chrome/browser/resources/settings/site_settings/site_settings_category.js
@@ -77,6 +77,7 @@
       case settings.ContentSettingsTypes.JAVASCRIPT:
       case settings.ContentSettingsTypes.KEYGEN:
       case settings.ContentSettingsTypes.POPUPS:
+      case settings.ContentSettingsTypes.PROTOCOL_HANDLERS:
         // "Allowed" vs "Blocked".
         this.browserProxy.setDefaultValueForContentType(
             this.category,
@@ -85,8 +86,8 @@
                 settings.PermissionValues.BLOCK);
         break;
       case settings.ContentSettingsTypes.AUTOMATIC_DOWNLOADS:
-      case settings.ContentSettingsTypes.GEOLOCATION:
       case settings.ContentSettingsTypes.CAMERA:
+      case settings.ContentSettingsTypes.GEOLOCATION:
       case settings.ContentSettingsTypes.MIC:
       case settings.ContentSettingsTypes.NOTIFICATIONS:
       case settings.ContentSettingsTypes.UNSANDBOXED_PLUGINS:
diff --git a/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js b/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js
index 99af3cd..c944ccdc 100644
--- a/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js
+++ b/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js
@@ -127,6 +127,33 @@
      * @param {string} path The path to the parent cookie.
      */
     removeCookie: function(path) {},
+
+    /**
+     * Initializes the protocol handler list. List is returned through JS calls
+     * to setHandlersEnabled, setProtocolHandlers & setIgnoredProtocolHandlers.
+     */
+    initializeProtocolHandlerList: function() {},
+
+    /**
+     * Enables or disables the ability for sites to ask to become the default
+     * protocol handlers.
+     * @param {boolean} enabled Whether sites can ask to become default.
+     */
+    setProtocolHandlerDefault: function(enabled) {},
+
+    /**
+     * Sets a certain url as default for a given protocol handler.
+     * @param {string} protocol The protocol to set a default for.
+     * @param {string} url The url to use as the default.
+     */
+    setProtocolDefault: function(protocol, url) {},
+
+    /**
+     * Deletes a certain protocol handler by url.
+     * @param {string} protocol The protocol to delete the url from.
+     * @param {string} url The url to delete.
+     */
+    removeProtocolHandler: function(protocol, url) {},
   };
 
   /**
@@ -197,7 +224,26 @@
     /** @override */
     removeCookie: function(path) {
       chrome.send('removeCookie', [path]);
-    }
+    },
+
+    initializeProtocolHandlerList: function() {
+      chrome.send('initializeProtocolHandlerList');
+    },
+
+    /** @override */
+    setProtocolHandlerDefault: function(enabled) {
+      chrome.send('setHandlersEnabled', [enabled]);
+    },
+
+    /** @override */
+    setProtocolDefault: function(protocol, url) {
+      chrome.send('setDefault', [[protocol, url]]);
+    },
+
+    /** @override */
+    removeProtocolHandler: function(protocol, url) {
+      chrome.send('removeHandler', [[protocol, url]]);
+    },
   };
 
   return {
diff --git a/chrome/browser/resources/settings/site_settings_page/site_settings_page.html b/chrome/browser/resources/settings/site_settings_page/site_settings_page.html
index 16afa796..fc3e621 100644
--- a/chrome/browser/resources/settings/site_settings_page/site_settings_page.html
+++ b/chrome/browser/resources/settings/site_settings_page/site_settings_page.html
@@ -147,6 +147,17 @@
         <div id="unsandboxedPlugins" class="secondary"></div>
       </div>
     </div>
+    <div class="settings-box two-line"
+        category$="[[ContentSettingsTypes.PROTOCOL_HANDLERS]]"
+        on-tap="onTapCategory">
+      <iron-icon icon="[[computeIconForContentCategory(
+          ContentSettingsTypes.PROTOCOL_HANDLERS)]]" item-icon=""></iron-icon>
+      <div class="middle">
+        [[computeTitleForContentCategory(
+            ContentSettingsTypes.PROTOCOL_HANDLERS)]]
+        <div id="handlers" class="secondary"></div>
+      </div>
+    </div>
   </template>
   <script src="site_settings_page.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/settings/site_settings_page/site_settings_page.js b/chrome/browser/resources/settings/site_settings_page/site_settings_page.js
index a757f08..f44f0b3 100644
--- a/chrome/browser/resources/settings/site_settings_page/site_settings_page.js
+++ b/chrome/browser/resources/settings/site_settings_page/site_settings_page.js
@@ -52,6 +52,8 @@
         '#notifications');
     this.setDefaultValue_(this.ContentSettingsTypes.PLUGINS, '#plugins');
     this.setDefaultValue_(this.ContentSettingsTypes.POPUPS, '#popups');
+    this.setDefaultValue_(this.ContentSettingsTypes.PROTOCOL_HANDLERS,
+        '#handlers');
     this.setDefaultValue_(this.ContentSettingsTypes.UNSANDBOXED_PLUGINS,
         '#unsandboxedPlugins');
   },
@@ -77,6 +79,12 @@
         section: 'privacy',
         subpage: ['site-settings', 'all-sites'],
       };
+    } else if (category == this.ContentSettingsTypes.PROTOCOL_HANDLERS) {
+      this.currentRoute = {
+        page: this.currentRoute.page,
+        section: 'privacy',
+        subpage: ['site-settings', 'protocol-handlers'],
+      };
     } else {
       this.categorySelected = this.computeCategoryTextId(category);
       this.currentRoute = {
diff --git a/chrome/browser/resources/settings_app/manifest.json b/chrome/browser/resources/settings_app/manifest.json
deleted file mode 100644
index b382801..0000000
--- a/chrome/browser/resources/settings_app/manifest.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-  //chrome-extension://ennkphjdgehloodpbhlhldgbnhmacadg
-  "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDoVDPGX6fvKPVVgc+gnkYlGqHuuapgFDyKhsy4z7UzRLO/95zXPv8h8e5EacqbAQJLUbP6DERH5jowyNEYVxq9GJyntJMwP1ejvoz/52hnY3CCGGCmttmKzzpp5zwLuq3iZf8bslwywfflNUYtaCFSDa0TtrBZz0aOPrAAd/AhNwIDAQAB",
-  "name": "Settings",
-  "version": "0.2",
-  "manifest_version": 2,
-  "description": "Settings",
-
-  "icons": {
-    "16": "settings_app_icon_16.png",
-    "32": "settings_app_icon_32.png",
-    "48": "settings_app_icon_48.png",
-    "128": "settings_app_icon_128.png"
-  },
-  "app": {
-    "background": {
-      "scripts": [ "settings_app.js" ]
-    }
-  },
-  "permissions": [
-    "chrome://settings-frame/"
-  ],
-  "display_in_launcher": false
-}
diff --git a/chrome/browser/resources/settings_app/settings_app.js b/chrome/browser/resources/settings_app/settings_app.js
deleted file mode 100644
index 8b82ec4..0000000
--- a/chrome/browser/resources/settings_app/settings_app.js
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2012 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(
-      'chrome://settings-frame/options_settings_app.html',
-      {'id': 'settings_app', 'height': 550, 'width': 750});
-});
diff --git a/chrome/browser/resources/sync_file_system_internals_resources.grd b/chrome/browser/resources/sync_file_system_internals_resources.grd
index 62f685d6..6c730ce 100644
--- a/chrome/browser/resources/sync_file_system_internals_resources.grd
+++ b/chrome/browser/resources/sync_file_system_internals_resources.grd
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="0" current_release="1">
+<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
   <outputs>
     <output filename="grit/sync_file_system_internals_resources.h" type="rc_header">
       <emit emit_type='prepend'></emit>
diff --git a/chrome/browser/resources/translate_internals_resources.grd b/chrome/browser/resources/translate_internals_resources.grd
index 1ad9abf3d..02cc177 100644
--- a/chrome/browser/resources/translate_internals_resources.grd
+++ b/chrome/browser/resources/translate_internals_resources.grd
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="0" current_release="1">
+<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
   <outputs>
     <output filename="grit/translate_internals_resources.h" type="rc_header">
       <emit emit_type='prepend'></emit>
diff --git a/chrome/browser/safe_browsing/download_feedback.cc b/chrome/browser/safe_browsing/download_feedback.cc
index 2356900..501f6a40f 100644
--- a/chrome/browser/safe_browsing/download_feedback.cc
+++ b/chrome/browser/safe_browsing/download_feedback.cc
@@ -7,9 +7,11 @@
 #include "base/bind.h"
 #include "base/files/file_util_proxy.h"
 #include "base/macros.h"
+#include "base/memory/ptr_util.h"
 #include "base/metrics/histogram.h"
 #include "base/task_runner.h"
 #include "chrome/common/safe_browsing/csd.pb.h"
+#include "content/public/browser/browser_thread.h"
 #include "net/base/net_errors.h"
 
 namespace safe_browsing {
@@ -89,12 +91,13 @@
       file_size_(-1),
       ping_request_(ping_request),
       ping_response_(ping_response) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DVLOG(1) << "DownloadFeedback constructed " << this << " for "
            << file_path.AsUTF8Unsafe();
 }
 
 DownloadFeedbackImpl::~DownloadFeedbackImpl() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DVLOG(1) << "DownloadFeedback destructed " << this;
 
   if (uploader_) {
@@ -110,7 +113,7 @@
 }
 
 void DownloadFeedbackImpl::Start(const base::Closure& finish_callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(!uploader_);
 
   ClientDownloadReport report_metadata;
@@ -126,16 +129,12 @@
   std::string metadata_string;
   bool ok = report_metadata.SerializeToString(&metadata_string);
   DCHECK(ok);
-  uploader_.reset(
-      TwoPhaseUploader::Create(request_context_getter_.get(),
-                               file_task_runner_.get(),
-                               GURL(kSbFeedbackURL),
-                               metadata_string,
-                               file_path_,
-                               TwoPhaseUploader::ProgressCallback(),
-                               base::Bind(&DownloadFeedbackImpl::FinishedUpload,
-                                          base::Unretained(this),
-                                          finish_callback)));
+  uploader_ = TwoPhaseUploader::Create(
+      request_context_getter_.get(), file_task_runner_.get(),
+      GURL(kSbFeedbackURL), metadata_string, file_path_,
+      TwoPhaseUploader::ProgressCallback(),
+      base::Bind(&DownloadFeedbackImpl::FinishedUpload, base::Unretained(this),
+                 finish_callback));
   uploader_->Start();
 }
 
@@ -144,33 +143,31 @@
                                           int net_error,
                                           int response_code,
                                           const std::string& response_data) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DVLOG(1) << __FUNCTION__ << " " << state << " rlen=" << response_data.size();
 
   switch (state) {
     case TwoPhaseUploader::STATE_SUCCESS: {
       ClientUploadResponse response;
       if (!response.ParseFromString(response_data) ||
-          response.status() != ClientUploadResponse::SUCCESS)
+          response.status() != ClientUploadResponse::SUCCESS) {
         RecordUploadResult(UPLOAD_COMPLETE_RESPONSE_ERROR);
-      else
+      } else {
         RecordUploadResult(UPLOAD_SUCCESS);
+      }
       break;
     }
     case TwoPhaseUploader::UPLOAD_FILE:
-      if (net_error != net::OK)
-        RecordUploadResult(UPLOAD_FILE_NET_ERROR);
-      else
-        RecordUploadResult(UPLOAD_FILE_RESPONSE_ERROR);
+      RecordUploadResult(net_error != net::OK ? UPLOAD_FILE_NET_ERROR
+                                              : UPLOAD_FILE_RESPONSE_ERROR);
       break;
     case TwoPhaseUploader::UPLOAD_METADATA:
-      if (net_error != net::OK)
-        RecordUploadResult(UPLOAD_METADATA_NET_ERROR);
-      else
-        RecordUploadResult(UPLOAD_METADATA_RESPONSE_ERROR);
+      RecordUploadResult(net_error != net::OK ? UPLOAD_METADATA_NET_ERROR
+                                              : UPLOAD_METADATA_RESPONSE_ERROR);
       break;
     default:
       NOTREACHED();
+      break;
   }
 
   uploader_.reset();
@@ -180,12 +177,13 @@
 }
 
 void DownloadFeedbackImpl::RecordUploadResult(UploadResultType result) {
-  if (result == UPLOAD_SUCCESS)
+  if (result == UPLOAD_SUCCESS) {
     UMA_HISTOGRAM_CUSTOM_COUNTS(
         "SBDownloadFeedback.SizeSuccess", file_size_, 1, kMaxUploadSize, 50);
-  else
+  } else {
     UMA_HISTOGRAM_CUSTOM_COUNTS(
         "SBDownloadFeedback.SizeFailure", file_size_, 1, kMaxUploadSize, 50);
+  }
   UMA_HISTOGRAM_ENUMERATION(
       "SBDownloadFeedback.UploadResult", result, UPLOAD_RESULT_MAX);
 }
@@ -200,19 +198,20 @@
     "https://safebrowsing.google.com/safebrowsing/uploads/chrome";
 
 // static
-DownloadFeedbackFactory* DownloadFeedback::factory_ = NULL;
+DownloadFeedbackFactory* DownloadFeedback::factory_ = nullptr;
 
 // static
-DownloadFeedback* DownloadFeedback::Create(
+std::unique_ptr<DownloadFeedback> DownloadFeedback::Create(
     net::URLRequestContextGetter* request_context_getter,
     base::TaskRunner* file_task_runner,
     const base::FilePath& file_path,
     const std::string& ping_request,
     const std::string& ping_response) {
-  if (!DownloadFeedback::factory_)
-    return new DownloadFeedbackImpl(
-        request_context_getter, file_task_runner, file_path, ping_request,
-        ping_response);
+  if (!factory_) {
+    return base::WrapUnique(
+        new DownloadFeedbackImpl(request_context_getter, file_task_runner,
+                                 file_path, ping_request, ping_response));
+  }
   return DownloadFeedback::factory_->CreateDownloadFeedback(
         request_context_getter, file_task_runner, file_path, ping_request,
         ping_response);
diff --git a/chrome/browser/safe_browsing/download_feedback.h b/chrome/browser/safe_browsing/download_feedback.h
index 90734eb..cd8adf5e 100644
--- a/chrome/browser/safe_browsing/download_feedback.h
+++ b/chrome/browser/safe_browsing/download_feedback.h
@@ -14,10 +14,6 @@
 #include "base/threading/non_thread_safe.h"
 #include "chrome/browser/safe_browsing/two_phase_uploader.h"
 
-namespace content {
-class DownloadItem;
-}
-
 namespace safe_browsing {
 
 class DownloadFeedbackFactory;
@@ -28,7 +24,7 @@
  public:
   // Takes ownership of the file pointed to be |file_path|, it will be deleted
   // when the DownloadFeedback is destructed.
-  static DownloadFeedback* Create(
+  static std::unique_ptr<DownloadFeedback> Create(
       net::URLRequestContextGetter* request_context_getter,
       base::TaskRunner* file_task_runner,
       const base::FilePath& file_path,
@@ -70,7 +66,7 @@
  public:
   virtual ~DownloadFeedbackFactory() {}
 
-  virtual DownloadFeedback* CreateDownloadFeedback(
+  virtual std::unique_ptr<DownloadFeedback> CreateDownloadFeedback(
       net::URLRequestContextGetter* request_context_getter,
       base::TaskRunner* file_task_runner,
       const base::FilePath& file_path,
diff --git a/chrome/browser/safe_browsing/download_feedback_service.cc b/chrome/browser/safe_browsing/download_feedback_service.cc
index 9eb9b09..ca50fd24 100644
--- a/chrome/browser/safe_browsing/download_feedback_service.cc
+++ b/chrome/browser/safe_browsing/download_feedback_service.cc
@@ -81,10 +81,11 @@
     : request_context_getter_(request_context_getter),
       file_task_runner_(file_task_runner),
       weak_ptr_factory_(this) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 }
 
 DownloadFeedbackService::~DownloadFeedbackService() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 }
 
 // static
@@ -142,7 +143,7 @@
 
 void DownloadFeedbackService::BeginFeedbackForDownload(
     content::DownloadItem* download) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   UMA_HISTOGRAM_ENUMERATION("SBDownloadFeedback.Activations",
                             download->GetDangerType(),
@@ -186,11 +187,11 @@
     const std::string& ping_request,
     const std::string& ping_response,
     const base::FilePath& path) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   std::unique_ptr<DownloadFeedback> feedback(DownloadFeedback::Create(
       request_context_getter_.get(), file_task_runner_.get(), path,
       ping_request, ping_response));
-  active_feedback_.push_back(std::move(feedback));
+  active_feedback_.push(std::move(feedback));
   UMA_HISTOGRAM_COUNTS_100("SBDownloadFeedback.ActiveFeedbacks",
                            active_feedback_.size());
 
@@ -200,9 +201,9 @@
 
 void DownloadFeedbackService::FeedbackComplete() {
   DVLOG(1) << __FUNCTION__;
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(!active_feedback_.empty());
-  active_feedback_.erase(active_feedback_.begin());
+  active_feedback_.pop();
   if (!active_feedback_.empty())
     StartPendingFeedback();
 }
diff --git a/chrome/browser/safe_browsing/download_feedback_service.h b/chrome/browser/safe_browsing/download_feedback_service.h
index 35058ea..48b1ee8 100644
--- a/chrome/browser/safe_browsing/download_feedback_service.h
+++ b/chrome/browser/safe_browsing/download_feedback_service.h
@@ -6,12 +6,11 @@
 #define CHROME_BROWSER_SAFE_BROWSING_DOWNLOAD_FEEDBACK_SERVICE_H_
 
 #include <memory>
+#include <queue>
 #include <string>
-#include <vector>
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/threading/non_thread_safe.h"
 #include "chrome/browser/safe_browsing/download_protection_service.h"
 #include "content/public/browser/download_danger_type.h"
 
@@ -33,7 +32,8 @@
 
 // Tracks active DownloadFeedback objects, provides interface for storing ping
 // data for malicious downloads.
-class DownloadFeedbackService : public base::NonThreadSafe {
+// Lives on the UI thread.
+class DownloadFeedbackService {
  public:
   DownloadFeedbackService(net::URLRequestContextGetter* request_context_getter,
                           base::TaskRunner* file_task_runner);
@@ -86,7 +86,7 @@
 
   // Currently active & pending uploads. The first item is active, remaining
   // items are pending.
-  std::vector<std::unique_ptr<DownloadFeedback>> active_feedback_;
+  std::queue<std::unique_ptr<DownloadFeedback>> active_feedback_;
 
   base::WeakPtrFactory<DownloadFeedbackService> weak_ptr_factory_;
 
diff --git a/chrome/browser/safe_browsing/download_feedback_service_unittest.cc b/chrome/browser/safe_browsing/download_feedback_service_unittest.cc
index 5bb379f..1c11e93 100644
--- a/chrome/browser/safe_browsing/download_feedback_service_unittest.cc
+++ b/chrome/browser/safe_browsing/download_feedback_service_unittest.cc
@@ -11,6 +11,7 @@
 
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
+#include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "chrome/browser/safe_browsing/download_feedback.h"
@@ -82,7 +83,7 @@
  public:
   ~FakeDownloadFeedbackFactory() override {}
 
-  DownloadFeedback* CreateDownloadFeedback(
+  std::unique_ptr<DownloadFeedback> CreateDownloadFeedback(
       net::URLRequestContextGetter* request_context_getter,
       base::TaskRunner* file_task_runner,
       const base::FilePath& file_path,
@@ -98,12 +99,10 @@
                    base::Unretained(this),
                    feedbacks_.size()));
     feedbacks_.push_back(feedback);
-    return feedback;
+    return base::WrapUnique(feedback);
   }
 
-  void DownloadFeedbackDeleted(size_t n) {
-    feedbacks_[n] = NULL;
-  }
+  void DownloadFeedbackDeleted(size_t n) { feedbacks_[n] = nullptr; }
 
   FakeDownloadFeedback* feedback(size_t n) const {
     return feedbacks_[n];
@@ -144,7 +143,7 @@
     DownloadFeedback::RegisterFactory(&download_feedback_factory_);
   }
 
-  void TearDown() override { DownloadFeedback::RegisterFactory(NULL); }
+  void TearDown() override { DownloadFeedback::RegisterFactory(nullptr); }
 
   base::FilePath CreateTestFile(int n) const {
     base::FilePath upload_file_path(
@@ -235,14 +234,14 @@
 TEST_F(DownloadFeedbackServiceTest, MultiplePendingFeedbackComplete) {
   const std::string ping_request = "ping";
   const std::string ping_response = "resp";
-  const size_t num_downloads = 3;
+  const size_t kNumDownloads = 3;
 
   content::DownloadItem::AcquireFileCallback
-      download_discarded_callback[num_downloads];
+      download_discarded_callback[kNumDownloads];
 
-  base::FilePath file_path[num_downloads];
-  content::MockDownloadItem item[num_downloads];
-  for (size_t i = 0; i < num_downloads; ++i) {
+  base::FilePath file_path[kNumDownloads];
+  content::MockDownloadItem item[kNumDownloads];
+  for (size_t i = 0; i < kNumDownloads; ++i) {
     file_path[i] = CreateTestFile(i);
     EXPECT_CALL(item[i], GetDangerType())
         .WillRepeatedly(Return(content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT));
@@ -258,14 +257,14 @@
   {
     DownloadFeedbackService service(request_context_getter_.get(),
                                     file_task_runner_.get());
-    for (size_t i = 0; i < num_downloads; ++i) {
+    for (size_t i = 0; i < kNumDownloads; ++i) {
       SCOPED_TRACE(i);
       service.BeginFeedbackForDownload(&item[i]);
       ASSERT_FALSE(download_discarded_callback[i].is_null());
     }
     EXPECT_EQ(0U, num_feedbacks());
 
-    for (size_t i = 0; i < num_downloads; ++i) {
+    for (size_t i = 0; i < kNumDownloads; ++i) {
       download_discarded_callback[i].Run(file_path[i]);
     }
 
@@ -304,14 +303,14 @@
 TEST_F(DownloadFeedbackServiceTest, MultiFeedbackWithIncomplete) {
   const std::string ping_request = "ping";
   const std::string ping_response = "resp";
-  const size_t num_downloads = 3;
+  const size_t kNumDownloads = 3;
 
   content::DownloadItem::AcquireFileCallback
-      download_discarded_callback[num_downloads];
+      download_discarded_callback[kNumDownloads];
 
-  base::FilePath file_path[num_downloads];
-  content::MockDownloadItem item[num_downloads];
-  for (size_t i = 0; i < num_downloads; ++i) {
+  base::FilePath file_path[kNumDownloads];
+  content::MockDownloadItem item[kNumDownloads];
+  for (size_t i = 0; i < kNumDownloads; ++i) {
     file_path[i] = CreateTestFile(i);
     EXPECT_CALL(item[i], GetDangerType())
         .WillRepeatedly(Return(content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT));
@@ -327,7 +326,7 @@
   {
     DownloadFeedbackService service(request_context_getter_.get(),
                                     file_task_runner_.get());
-    for (size_t i = 0; i < num_downloads; ++i) {
+    for (size_t i = 0; i < kNumDownloads; ++i) {
       SCOPED_TRACE(i);
       service.BeginFeedbackForDownload(&item[i]);
       ASSERT_FALSE(download_discarded_callback[i].is_null());
diff --git a/chrome/browser/safe_browsing/download_feedback_unittest.cc b/chrome/browser/safe_browsing/download_feedback_unittest.cc
index 2ce8b49..6c7979ff 100644
--- a/chrome/browser/safe_browsing/download_feedback_unittest.cc
+++ b/chrome/browser/safe_browsing/download_feedback_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
+#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
@@ -64,10 +65,10 @@
 
 class FakeUploaderFactory : public TwoPhaseUploaderFactory {
  public:
-  FakeUploaderFactory() : uploader_(NULL) {}
+  FakeUploaderFactory() : uploader_(nullptr) {}
   ~FakeUploaderFactory() override {}
 
-  TwoPhaseUploader* CreateTwoPhaseUploader(
+  std::unique_ptr<TwoPhaseUploader> CreateTwoPhaseUploader(
       net::URLRequestContextGetter* url_request_context_getter,
       base::TaskRunner* file_task_runner,
       const GURL& base_url,
@@ -79,7 +80,7 @@
   FakeUploader* uploader_;
 };
 
-TwoPhaseUploader* FakeUploaderFactory::CreateTwoPhaseUploader(
+std::unique_ptr<TwoPhaseUploader> FakeUploaderFactory::CreateTwoPhaseUploader(
     net::URLRequestContextGetter* url_request_context_getter,
     base::TaskRunner* file_task_runner,
     const GURL& base_url,
@@ -92,7 +93,7 @@
   uploader_ = new FakeUploader(url_request_context_getter, file_task_runner,
                                base_url, metadata, file_path, progress_callback,
                                finish_callback);
-  return uploader_;
+  return base::WrapUnique(uploader_);
 }
 
 }  // namespace
@@ -120,16 +121,15 @@
     TwoPhaseUploader::RegisterFactory(&two_phase_uploader_factory_);
   }
 
-  void TearDown() override { TwoPhaseUploader::RegisterFactory(NULL); }
+  void TearDown() override { TwoPhaseUploader::RegisterFactory(nullptr); }
 
   FakeUploader* uploader() const {
     return two_phase_uploader_factory_.uploader_;
   }
 
-  void FinishCallback(DownloadFeedback* feedback) {
+  void FinishCallback() {
     EXPECT_FALSE(feedback_finish_called_);
     feedback_finish_called_ = true;
-    delete feedback;
   }
 
  protected:
@@ -147,11 +147,10 @@
 
 TEST_F(DownloadFeedbackTest, CompleteUpload) {
   ClientDownloadReport expected_report_metadata;
-  expected_report_metadata.mutable_download_request()->set_url("http://test");
-  expected_report_metadata.mutable_download_request()->set_length(
-      upload_file_data_.size());
-  expected_report_metadata.mutable_download_request()->mutable_digests(
-      )->set_sha1("hi");
+  auto* request = expected_report_metadata.mutable_download_request();
+  request->set_url("http://test");
+  request->set_length(upload_file_data_.size());
+  request->mutable_digests()->set_sha1("hi");
   expected_report_metadata.mutable_download_response()->set_verdict(
       ClientDownloadResponse::DANGEROUS_HOST);
   std::string ping_request(
@@ -159,17 +158,13 @@
   std::string ping_response(
       expected_report_metadata.download_response().SerializeAsString());
 
-  DownloadFeedback* feedback =
-      DownloadFeedback::Create(url_request_context_getter_.get(),
-                               file_task_runner_.get(),
-                               upload_file_path_,
-                               ping_request,
-                               ping_response);
+  std::unique_ptr<DownloadFeedback> feedback = DownloadFeedback::Create(
+      url_request_context_getter_.get(), file_task_runner_.get(),
+      upload_file_path_, ping_request, ping_response);
   EXPECT_FALSE(uploader());
 
   feedback->Start(base::Bind(&DownloadFeedbackTest::FinishCallback,
-                             base::Unretained(this),
-                             feedback));
+                             base::Unretained(this)));
   ASSERT_TRUE(uploader());
   EXPECT_FALSE(feedback_finish_called_);
   EXPECT_TRUE(uploader()->start_called_);
@@ -188,17 +183,17 @@
   uploader()->finish_callback_.Run(
       TwoPhaseUploader::STATE_SUCCESS, net::OK, 0, "");
   EXPECT_TRUE(feedback_finish_called_);
+  feedback.reset();
   base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(base::PathExists(upload_file_path_));
 }
 
 TEST_F(DownloadFeedbackTest, CancelUpload) {
   ClientDownloadReport expected_report_metadata;
-  expected_report_metadata.mutable_download_request()->set_url("http://test");
-  expected_report_metadata.mutable_download_request()->set_length(
-      upload_file_data_.size());
-  expected_report_metadata.mutable_download_request()->mutable_digests(
-      )->set_sha1("hi");
+  auto* request = expected_report_metadata.mutable_download_request();
+  request->set_url("http://test");
+  request->set_length(upload_file_data_.size());
+  request->mutable_digests()->set_sha1("hi");
   expected_report_metadata.mutable_download_response()->set_verdict(
       ClientDownloadResponse::DANGEROUS_HOST);
   std::string ping_request(
@@ -206,23 +201,19 @@
   std::string ping_response(
       expected_report_metadata.download_response().SerializeAsString());
 
-  DownloadFeedback* feedback =
-      DownloadFeedback::Create(url_request_context_getter_.get(),
-                               file_task_runner_.get(),
-                               upload_file_path_,
-                               ping_request,
-                               ping_response);
+  std::unique_ptr<DownloadFeedback> feedback = DownloadFeedback::Create(
+      url_request_context_getter_.get(), file_task_runner_.get(),
+      upload_file_path_, ping_request, ping_response);
   EXPECT_FALSE(uploader());
 
   feedback->Start(base::Bind(&DownloadFeedbackTest::FinishCallback,
-                             base::Unretained(this),
-                             feedback));
+                             base::Unretained(this)));
   ASSERT_TRUE(uploader());
   EXPECT_FALSE(feedback_finish_called_);
   EXPECT_TRUE(uploader()->start_called_);
   EXPECT_TRUE(base::PathExists(upload_file_path_));
 
-  delete feedback;
+  feedback.reset();
   EXPECT_FALSE(feedback_finish_called_);
 
   base::RunLoop().RunUntilIdle();
diff --git a/chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner.cc b/chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner.cc
index 142da45a..ebc14d2f 100644
--- a/chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner.cc
+++ b/chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner.h"
 
 #include "base/location.h"
+#include "content/public/browser/browser_thread.h"
 
 namespace safe_browsing {
 
@@ -12,27 +13,29 @@
     base::TimeDelta delay,
     const scoped_refptr<base::TaskRunner>& task_runner)
     : task_runner_(task_runner),
-      next_callback_(callbacks_.end()),
+      has_work_(false),
       timer_(FROM_HERE, delay, this, &DelayedCallbackRunner::OnTimer) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 }
 
 DelayedCallbackRunner::~DelayedCallbackRunner() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 }
 
 void DelayedCallbackRunner::RegisterCallback(const base::Closure& callback) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  callbacks_.push_back(callback);
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  callbacks_.push(callback);
 }
 
 void DelayedCallbackRunner::Start() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   // Nothing to do if the runner is already running or nothing has been added.
-  if (next_callback_ != callbacks_.end() || callbacks_.empty())
+  if (has_work_ || callbacks_.empty())
     return;
 
   // Prime the system with the first callback.
-  next_callback_ = callbacks_.begin();
+  has_work_ = true;
 
   // Point the starter pistol in the air and pull the trigger.
   timer_.Reset();
@@ -40,11 +43,13 @@
 
 void DelayedCallbackRunner::OnTimer() {
   // Run the next callback on the task runner.
-  task_runner_->PostTask(FROM_HERE, *next_callback_);
+  auto callback = callbacks_.front();
+  callbacks_.pop();
+  task_runner_->PostTask(FROM_HERE, callback);
 
   // Remove this callback and get ready for the next if there is one.
-  next_callback_ = callbacks_.erase(next_callback_);
-  if (next_callback_ != callbacks_.end())
+  has_work_ = !callbacks_.empty();
+  if (has_work_)
     timer_.Reset();
 }
 
diff --git a/chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner.h b/chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner.h
index 19e3f6c1..db95bc55e 100644
--- a/chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner.h
+++ b/chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner.h
@@ -5,13 +5,12 @@
 #ifndef CHROME_BROWSER_SAFE_BROWSING_INCIDENT_REPORTING_DELAYED_CALLBACK_RUNNER_H_
 #define CHROME_BROWSER_SAFE_BROWSING_INCIDENT_REPORTING_DELAYED_CALLBACK_RUNNER_H_
 
-#include <list>
+#include <queue>
 
 #include "base/callback_forward.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/task_runner.h"
-#include "base/threading/thread_checker.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 
@@ -22,6 +21,7 @@
 // the first callback will be run some time after Start() is invoked). Callbacks
 // are deleted after they are run. Start() is idempotent: calling it while the
 // runner is doing its job has no effect.
+// Lives on the UI thread.
 class DelayedCallbackRunner {
  public:
   // Constructs an instance that runs tasks on |callback_runner|, waiting for
@@ -38,22 +38,20 @@
   void Start();
 
  private:
-  typedef std::list<base::Closure> CallbackList;
+  using CallbackList = std::queue<base::Closure>;
 
   // A callback invoked by the timer to run the next callback. The timer is
   // restarted to process the next callback if there is one.
   void OnTimer();
 
-  base::ThreadChecker thread_checker_;
-
   // The runner on which callbacks are to be run.
   scoped_refptr<base::TaskRunner> task_runner_;
 
   // The list of callbacks to run. Callbacks are removed when run.
   CallbackList callbacks_;
 
-  // callbacks_.end() when no work is being done. Any other value otherwise.
-  CallbackList::iterator next_callback_;
+  // Whethere there is work to be done from |callbacks_|.
+  bool has_work_;
 
   // A timer upon the firing of which the next callback will be run.
   base::DelayTimer timer_;
diff --git a/chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner_unittest.cc
index 863b599..2d284dd 100644
--- a/chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner_unittest.cc
+++ b/chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner_unittest.cc
@@ -11,8 +11,10 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/test/test_simple_task_runner.h"
+#include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
@@ -45,14 +47,11 @@
   }
 
  protected:
-  DelayedCallbackRunnerTest()
-      : task_runner_(new base::TestSimpleTaskRunner),
-        thread_task_runner_handle_(task_runner_) {}
+  DelayedCallbackRunnerTest() {}
 
   void SetUp() override {
     instance_.reset(new safe_browsing::DelayedCallbackRunner(
-        base::TimeDelta::FromMilliseconds(1),  // ignored by simple runner.
-        task_runner_));
+        base::TimeDelta(), base::ThreadTaskRunnerHandle::Get()));
   }
 
   void TearDown() override { instance_.reset(); }
@@ -90,8 +89,7 @@
     return callbacks_[name].deleted;
   }
 
-  scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
-  base::ThreadTaskRunnerHandle thread_task_runner_handle_;
+  content::TestBrowserThreadBundle thread_bundle_;
   std::unique_ptr<safe_browsing::DelayedCallbackRunner> instance_;
 
  private:
@@ -118,7 +116,7 @@
   const std::string name("one");
   RegisterTestCallback(name);
   instance_->Start();
-  task_runner_->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(CallbackWasRun(name));
   EXPECT_TRUE(CallbackWasDeleted(name));
 }
@@ -130,15 +128,13 @@
   const std::string name2("two");
 
   // Post a task to register a new callback after Start() is called.
-  task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&DelayedCallbackRunnerTest::RegisterTestCallback,
-                 base::Unretained(this),
-                 name2));
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::Bind(&DelayedCallbackRunnerTest::RegisterTestCallback,
+                            base::Unretained(this), name2));
 
   RegisterTestCallback(name);
   instance_->Start();
-  task_runner_->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(CallbackWasRun(name));
   EXPECT_TRUE(CallbackWasDeleted(name));
   EXPECT_TRUE(CallbackWasRun(name2));
@@ -151,13 +147,13 @@
 
   RegisterTestCallback(name);
   instance_->Start();
-  task_runner_->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(CallbackWasRun(name));
   EXPECT_TRUE(CallbackWasDeleted(name));
 
   RegisterTestCallback(name2);
   instance_->Start();
-  task_runner_->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(CallbackWasRun(name2));
   EXPECT_TRUE(CallbackWasDeleted(name2));
 }
diff --git a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc
index 4e30cf3..2de8eb7 100644
--- a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc
+++ b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc
@@ -241,7 +241,7 @@
 void IncidentReportingService::Receiver::AddIncidentForProfile(
     Profile* profile,
     std::unique_ptr<Incident> incident) {
-  DCHECK(thread_runner_->BelongsToCurrentThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(profile);
   AddIncidentOnMainThread(service_, profile, std::move(incident));
 }
@@ -361,6 +361,7 @@
       download_metadata_manager_(content::BrowserThread::GetBlockingPool()),
       receiver_weak_ptr_factory_(this),
       weak_ptr_factory_(this) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   notification_registrar_.Add(this,
                               chrome::NOTIFICATION_PROFILE_ADDED,
                               content::NotificationService::AllSources());
@@ -368,9 +369,9 @@
                               chrome::NOTIFICATION_PROFILE_DESTROYED,
                               content::NotificationService::AllSources());
   DownloadProtectionService* download_protection_service =
-      (safe_browsing_service ?
-       safe_browsing_service->download_protection_service() :
-       NULL);
+      (safe_browsing_service
+           ? safe_browsing_service->download_protection_service()
+           : nullptr);
   if (download_protection_service) {
     client_download_request_subscription_ =
         download_protection_service->RegisterClientDownloadRequestCallback(
@@ -382,7 +383,7 @@
 }
 
 IncidentReportingService::~IncidentReportingService() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   CancelIncidentCollection();
 
   // Cancel all internal asynchronous tasks.
@@ -403,7 +404,7 @@
 
 std::unique_ptr<TrackedPreferenceValidationDelegate>
 IncidentReportingService::CreatePreferenceValidationDelegate(Profile* profile) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   if (profile->IsOffTheRecord())
     return std::unique_ptr<TrackedPreferenceValidationDelegate>();
@@ -413,7 +414,7 @@
 
 void IncidentReportingService::RegisterDelayedAnalysisCallback(
     const DelayedAnalysisCallback& callback) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   // |callback| will be run on the blocking pool. The receiver will bounce back
   // to the origin thread if needed.
@@ -430,7 +431,7 @@
 void IncidentReportingService::
     RegisterExtendedReportingOnlyDelayedAnalysisCallback(
         const DelayedAnalysisCallback& callback) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   // |callback| will be run on the blocking pool. The receiver will bounce back
   // to the origin thread if needed.
@@ -460,7 +461,7 @@
     const scoped_refptr<base::TaskRunner>& delayed_task_runner)
     : database_manager_(safe_browsing_service
                             ? safe_browsing_service->database_manager()
-                            : NULL),
+                            : nullptr),
       url_request_context_getter_(request_context_getter),
       collect_environment_data_fn_(&CollectEnvironmentData),
       environment_collection_task_runner_(
@@ -508,7 +509,7 @@
 }
 
 void IncidentReportingService::OnProfileAdded(Profile* profile) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   // Track the addition of all profiles even when no report is being assembled
   // so that the service can determine whether or not it can evaluate a
@@ -584,13 +585,13 @@
 }
 
 bool IncidentReportingService::IsProcessingReport() const {
-  return report_ != NULL;
+  return report_ != nullptr;
 }
 
 IncidentReportingService::ProfileContext*
 IncidentReportingService::GetOrCreateProfileContext(Profile* profile) {
   ProfileContextCollection::iterator it =
-      profiles_.insert(ProfileContextCollection::value_type(profile, NULL))
+      profiles_.insert(ProfileContextCollection::value_type(profile, nullptr))
           .first;
   if (!it->second)
     it->second = new ProfileContext();
@@ -600,11 +601,11 @@
 IncidentReportingService::ProfileContext*
 IncidentReportingService::GetProfileContext(Profile* profile) {
   ProfileContextCollection::iterator it = profiles_.find(profile);
-  return it == profiles_.end() ? NULL : it->second;
+  return it != profiles_.end() ? it->second : nullptr;
 }
 
 void IncidentReportingService::OnProfileDestroyed(Profile* profile) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   ProfileContextCollection::iterator it = profiles_.find(profile);
   if (it == profiles_.end())
@@ -626,7 +627,7 @@
 }
 
 Profile* IncidentReportingService::FindEligibleProfile() const {
-  Profile* candidate = NULL;
+  Profile* candidate = nullptr;
   for (ProfileContextCollection::const_iterator scan = profiles_.begin();
        scan != profiles_.end();
        ++scan) {
@@ -654,7 +655,7 @@
 
 void IncidentReportingService::AddIncident(Profile* profile,
                                            std::unique_ptr<Incident> incident) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   // Ignore incidents from off-the-record profiles.
   if (profile && profile->IsOffTheRecord())
@@ -705,7 +706,7 @@
 }
 
 void IncidentReportingService::BeginReportProcessing() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   // Creates a new report if needed.
   if (!report_)
@@ -734,7 +735,7 @@
 }
 
 void IncidentReportingService::OnCollationTimeout() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   // Exit early if collection was cancelled.
   if (!collation_timeout_pending_)
@@ -756,7 +757,7 @@
 }
 
 void IncidentReportingService::BeginEnvironmentCollection() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(report_);
   // Nothing to do if environment collection is pending or has already
   // completed, if there are no incidents to process, or if there is no eligible
@@ -794,7 +795,7 @@
 
 void IncidentReportingService::OnEnvironmentDataCollected(
     std::unique_ptr<ClientIncidentReport_EnvironmentData> environment_data) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(environment_collection_pending_);
   DCHECK(report_ && !report_->has_environment());
   environment_collection_pending_ = false;
@@ -816,7 +817,7 @@
 }
 
 void IncidentReportingService::BeginDownloadCollection() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(report_);
   // Nothing to do if a search for the most recent download is already pending,
   // if one has already been found, or if there are no incidents to process.
@@ -870,7 +871,7 @@
     std::unique_ptr<ClientIncidentReport_DownloadDetails> last_binary_download,
     std::unique_ptr<ClientIncidentReport_NonBinaryDownloadDetails>
         last_non_binary_download) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(report_);
 
   UMA_HISTOGRAM_TIMES("SBIRS.FindDownloadedBinaryTime",
@@ -923,7 +924,7 @@
   // Associate process-wide incidents with the profile that benefits from the
   // strongest safe browsing protections. If there is no such profile, drop the
   // incidents.
-  ProfileContext* null_context = GetProfileContext(NULL);
+  ProfileContext* null_context = GetProfileContext(nullptr);
   if (null_context && null_context->HasIncidents()) {
     if (eligible_profile) {
       ProfileContext* eligible_context = GetProfileContext(eligible_profile);
@@ -1063,7 +1064,7 @@
   }
 #endif
 
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!is_killswitch_on) {
     // Initiate the upload.
     context->uploader = StartReportUpload(
@@ -1095,7 +1096,7 @@
     UploadContext* context,
     IncidentReportUploader::Result result,
     std::unique_ptr<ClientIncidentResponse> response) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   UMA_HISTOGRAM_ENUMERATION(
       "SBIRS.UploadResult", result, IncidentReportUploader::NUM_UPLOAD_RESULTS);
diff --git a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.h b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.h
index c692814..38e6d16 100644
--- a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.h
+++ b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.h
@@ -16,7 +16,6 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
-#include "base/threading/thread_checker.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "chrome/browser/safe_browsing/download_protection_service.h"
@@ -74,6 +73,7 @@
 // a bit. Additional incidents that arrive during this time are collated with
 // the initial incident. Finally, already-reported incidents are pruned and any
 // remaining are uploaded in an incident report.
+// Lives on the UI thread.
 class IncidentReportingService : public content::NotificationObserver {
  public:
   explicit IncidentReportingService(SafeBrowsingService* safe_browsing_service);
@@ -277,8 +277,6 @@
                const content::NotificationSource& source,
                const content::NotificationDetails& details) override;
 
-  base::ThreadChecker thread_checker_;
-
   // The safe browsing database manager, through which the whitelist killswitch
   // is checked.
   scoped_refptr<SafeBrowsingDatabaseManager> database_manager_;
diff --git a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service_unittest.cc
index 3ed7947..6f6c229 100644
--- a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service_unittest.cc
+++ b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service_unittest.cc
@@ -35,6 +35,7 @@
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
 #include "components/syncable_prefs/testing_pref_service_syncable.h"
+#include "content/public/test/test_browser_thread.h"
 #include "extensions/browser/quota_service.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -53,22 +54,20 @@
   class TestIncidentReportingService
       : public safe_browsing::IncidentReportingService {
    public:
-    typedef base::Callback<void(Profile*)> PreProfileAddCallback;
+    using PreProfileAddCallback = base::Callback<void(Profile*)>;
 
-    typedef base::Callback<
-        void(safe_browsing::ClientIncidentReport_EnvironmentData*)>
-        CollectEnvironmentCallback;
+    using CollectEnvironmentCallback = base::Callback<void(
+        safe_browsing::ClientIncidentReport_EnvironmentData*)>;
 
-    typedef base::Callback<std::unique_ptr<safe_browsing::LastDownloadFinder>(
-        const safe_browsing::LastDownloadFinder::LastDownloadCallback&
-            callback)>
-        CreateDownloadFinderCallback;
+    using CreateDownloadFinderCallback =
+        base::Callback<std::unique_ptr<safe_browsing::LastDownloadFinder>(
+            const safe_browsing::LastDownloadFinder::LastDownloadCallback&
+                callback)>;
 
-    typedef base::Callback<
-        std::unique_ptr<safe_browsing::IncidentReportUploader>(
+    using StartUploadCallback =
+        base::Callback<std::unique_ptr<safe_browsing::IncidentReportUploader>(
             const safe_browsing::IncidentReportUploader::OnResultCallback&,
-            const safe_browsing::ClientIncidentReport& report)>
-        StartUploadCallback;
+            const safe_browsing::ClientIncidentReport& report)>;
 
     TestIncidentReportingService(
         const scoped_refptr<base::TaskRunner>& task_runner,
@@ -76,8 +75,8 @@
         const CollectEnvironmentCallback& collect_environment_callback,
         const CreateDownloadFinderCallback& create_download_finder_callback,
         const StartUploadCallback& start_upload_callback)
-        : IncidentReportingService(NULL,
-                                   NULL,
+        : IncidentReportingService(nullptr,
+                                   nullptr,
                                    base::TimeDelta::FromMilliseconds(5),
                                    task_runner),
           pre_profile_add_callback_(pre_profile_add_callback),
@@ -89,7 +88,9 @@
       test_instance_.Get().Set(this);
     }
 
-    ~TestIncidentReportingService() override { test_instance_.Get().Set(NULL); }
+    ~TestIncidentReportingService() override {
+      test_instance_.Get().Set(nullptr);
+    }
 
     bool IsProcessingReport() const {
       return IncidentReportingService::IsProcessingReport();
@@ -195,6 +196,7 @@
   IncidentReportingServiceTest()
       : task_runner_(new base::TestSimpleTaskRunner),
         thread_task_runner_handle_(task_runner_),
+        ui_thread_(content::BrowserThread::UI),
         profile_manager_(TestingBrowserProcess::GetGlobal()),
         on_create_download_finder_action_(
             ON_CREATE_DOWNLOAD_FINDER_DOWNLOADS_FOUND),
@@ -344,6 +346,7 @@
       disable_purge_for_testing_;
   scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
   base::ThreadTaskRunnerHandle thread_task_runner_handle_;
+  content::TestBrowserThread ui_thread_;
   TestingProfileManager profile_manager_;
   std::unique_ptr<TestIncidentReportingService> instance_;
   base::Closure on_start_upload_callback_;
@@ -508,9 +511,7 @@
   // operation.
   void CollectEnvironmentData(
       safe_browsing::ClientIncidentReport_EnvironmentData* data) {
-    ASSERT_NE(
-        static_cast<safe_browsing::ClientIncidentReport_EnvironmentData*>(NULL),
-        data);
+    ASSERT_TRUE(data);
     data->mutable_os()->set_os_name(kFakeOsName);
     environment_collected_ = true;
   }
@@ -1069,7 +1070,7 @@
 TEST_F(IncidentReportingServiceTest, ProcessWideNoProfileNoUpload) {
   SetFieldTrialAndCreateService(true);
   // Add the test incident.
-  AddTestIncident(NULL);
+  AddTestIncident(nullptr);
 
   // Let all tasks run.
   task_runner_->RunUntilIdle();
@@ -1090,7 +1091,7 @@
                 ON_PROFILE_ADDITION_NO_ACTION, nullptr);
 
   // Add the test incident.
-  AddTestIncident(NULL);
+  AddTestIncident(nullptr);
 
   // Let all tasks run.
   task_runner_->RunUntilIdle();
@@ -1099,7 +1100,7 @@
   ExpectTestIncidentUploadWithBinaryDownload(1);
 
   // Add the incident to the service again.
-  AddTestIncident(NULL);
+  AddTestIncident(nullptr);
 
   // Let all tasks run.
   task_runner_->RunUntilIdle();
@@ -1148,7 +1149,7 @@
 TEST_F(IncidentReportingServiceTest, ProcessWideNoUploadAfterProfile) {
   SetFieldTrialAndCreateService(false);
   // Add the test incident.
-  AddTestIncident(NULL);
+  AddTestIncident(nullptr);
 
   // Let all tasks run.
   task_runner_->RunUntilIdle();
@@ -1294,7 +1295,7 @@
   ExpectTestIncidentUploadWithBinaryDownload(1);
 
   // Add the incident to the service again.
-  AddTestIncident(NULL);
+  AddTestIncident(nullptr);
 
   // Let all tasks run.
   task_runner_->RunUntilIdle();
diff --git a/chrome/browser/safe_browsing/local_database_manager.cc b/chrome/browser/safe_browsing/local_database_manager.cc
index e2430a7..2ec9325 100644
--- a/chrome/browser/safe_browsing/local_database_manager.cc
+++ b/chrome/browser/safe_browsing/local_database_manager.cc
@@ -804,7 +804,7 @@
     return database_;
 
   const base::TimeTicks before = base::TimeTicks::Now();
-  SafeBrowsingDatabase* database = SafeBrowsingDatabase::Create(
+  std::unique_ptr<SafeBrowsingDatabase> database = SafeBrowsingDatabase::Create(
       safe_browsing_task_runner_, enable_download_protection_,
       enable_csd_whitelist_, enable_download_whitelist_,
       enable_extension_blacklist_, enable_ip_blacklist_,
@@ -815,7 +815,7 @@
     // Acquiring the lock here guarantees correct ordering between the writes to
     // the new database object above, and the setting of |database_| below.
     base::AutoLock lock(database_lock_);
-    database_ = database;
+    database_ = database.release();
   }
 
   BrowserThread::PostTask(
diff --git a/chrome/browser/safe_browsing/ping_manager.cc b/chrome/browser/safe_browsing/ping_manager.cc
index f24cf859..f75ed23e 100644
--- a/chrome/browser/safe_browsing/ping_manager.cc
+++ b/chrome/browser/safe_browsing/ping_manager.cc
@@ -7,9 +7,11 @@
 #include <utility>
 
 #include "base/logging.h"
+#include "base/memory/ptr_util.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
+#include "chrome/browser/safe_browsing/permission_reporter.h"
 #include "components/certificate_reporting/error_reporter.h"
 #include "content/public/browser/browser_thread.h"
 #include "google_apis/google_api_keys.h"
@@ -38,11 +40,12 @@
 // SafeBrowsingPingManager implementation ----------------------------------
 
 // static
-SafeBrowsingPingManager* SafeBrowsingPingManager::Create(
+std::unique_ptr<SafeBrowsingPingManager> SafeBrowsingPingManager::Create(
     net::URLRequestContextGetter* request_context_getter,
     const SafeBrowsingProtocolConfig& config) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  return new SafeBrowsingPingManager(request_context_getter, config);
+  return base::WrapUnique(
+      new SafeBrowsingPingManager(request_context_getter, config));
 }
 
 SafeBrowsingPingManager::SafeBrowsingPingManager(
@@ -62,6 +65,9 @@
     certificate_error_reporter_.reset(new certificate_reporting::ErrorReporter(
         request_context_getter->GetURLRequestContext(), certificate_upload_url,
         cookies_preference));
+
+    permission_reporter_.reset(
+        new PermissionReporter(request_context_getter->GetURLRequestContext()));
   }
 
   version_ = SafeBrowsingProtocolManagerHelper::Version();
@@ -129,6 +135,13 @@
   certificate_error_reporter_ = std::move(certificate_error_reporter);
 }
 
+void SafeBrowsingPingManager::ReportPermissionAction(
+    const GURL& origin,
+    content::PermissionType permission,
+    PermissionAction action) {
+  permission_reporter_->SendReport(origin, permission, action);
+}
+
 GURL SafeBrowsingPingManager::SafeBrowsingHitUrl(
     const safe_browsing::HitReport& hit_report) const {
   DCHECK(hit_report.threat_type == SB_THREAT_TYPE_URL_MALWARE ||
diff --git a/chrome/browser/safe_browsing/ping_manager.h b/chrome/browser/safe_browsing/ping_manager.h
index f8730ba..f07252c 100644
--- a/chrome/browser/safe_browsing/ping_manager.h
+++ b/chrome/browser/safe_browsing/ping_manager.h
@@ -14,9 +14,11 @@
 
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
+#include "chrome/browser/permissions/permission_uma_util.h"
 #include "chrome/browser/safe_browsing/protocol_manager_helper.h"
 #include "components/safe_browsing_db/hit_report.h"
 #include "components/safe_browsing_db/util.h"
+#include "content/public/browser/permission_type.h"
 #include "net/url_request/url_fetcher_delegate.h"
 #include "url/gurl.h"
 
@@ -31,12 +33,14 @@
 
 namespace safe_browsing {
 
+class PermissionReporter;
+
 class SafeBrowsingPingManager : public net::URLFetcherDelegate {
  public:
   ~SafeBrowsingPingManager() override;
 
   // Create an instance of the safe browsing ping manager.
-  static SafeBrowsingPingManager* Create(
+  static std::unique_ptr<SafeBrowsingPingManager> Create(
       net::URLRequestContextGetter* request_context_getter,
       const SafeBrowsingProtocolConfig& config);
 
@@ -60,6 +64,11 @@
       std::unique_ptr<certificate_reporting::ErrorReporter>
           certificate_error_reporter);
 
+  // Report permission action to SafeBrowsing servers.
+  void ReportPermissionAction(const GURL& origin,
+                              content::PermissionType permission,
+                              PermissionAction action);
+
  private:
   FRIEND_TEST_ALL_PREFIXES(SafeBrowsingPingManagerTest,
                            TestSafeBrowsingHitUrl);
@@ -100,6 +109,9 @@
   std::unique_ptr<certificate_reporting::ErrorReporter>
       certificate_error_reporter_;
 
+  // Sends reports of permission actions.
+  std::unique_ptr<PermissionReporter> permission_reporter_;
+
   DISALLOW_COPY_AND_ASSIGN(SafeBrowsingPingManager);
 };
 
diff --git a/chrome/browser/safe_browsing/protocol_manager.cc b/chrome/browser/safe_browsing/protocol_manager.cc
index e9c561a..5ba83b1 100644
--- a/chrome/browser/safe_browsing/protocol_manager.cc
+++ b/chrome/browser/safe_browsing/protocol_manager.cc
@@ -9,6 +9,7 @@
 #include "base/environment.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/sparse_histogram.h"
 #include "base/profiler/scoped_tracker.h"
@@ -22,6 +23,7 @@
 #include "chrome/common/env_vars.h"
 #include "components/safe_browsing_db/util.h"
 #include "components/variations/variations_associated_data.h"
+#include "content/public/browser/browser_thread.h"
 #include "google_apis/google_api_keys.h"
 #include "net/base/escape.h"
 #include "net/base/load_flags.h"
@@ -98,12 +100,13 @@
  public:
   SBProtocolManagerFactoryImpl() {}
   ~SBProtocolManagerFactoryImpl() override {}
-  SafeBrowsingProtocolManager* CreateProtocolManager(
+
+  std::unique_ptr<SafeBrowsingProtocolManager> CreateProtocolManager(
       SafeBrowsingProtocolManagerDelegate* delegate,
       net::URLRequestContextGetter* request_context_getter,
       const SafeBrowsingProtocolConfig& config) override {
-    return new SafeBrowsingProtocolManager(delegate, request_context_getter,
-                                           config);
+    return base::WrapUnique(new SafeBrowsingProtocolManager(
+        delegate, request_context_getter, config));
   }
 
  private:
@@ -113,17 +116,14 @@
 // SafeBrowsingProtocolManager implementation ----------------------------------
 
 // static
-SBProtocolManagerFactory* SafeBrowsingProtocolManager::factory_ = NULL;
+SBProtocolManagerFactory* SafeBrowsingProtocolManager::factory_ = nullptr;
 
 // static
-SafeBrowsingProtocolManager* SafeBrowsingProtocolManager::Create(
+std::unique_ptr<SafeBrowsingProtocolManager>
+SafeBrowsingProtocolManager::Create(
     SafeBrowsingProtocolManagerDelegate* delegate,
     net::URLRequestContextGetter* request_context_getter,
     const SafeBrowsingProtocolConfig& config) {
-  // TODO(cbentzel): Remove ScopedTracker below once crbug.com/483689 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "483689 SafeBrowsingProtocolManager::Create"));
   if (!factory_)
     factory_ = new SBProtocolManagerFactoryImpl();
   return factory_->CreateProtocolManager(delegate, request_context_getter,
@@ -206,7 +206,7 @@
     FullHashCallback callback,
     bool is_download,
     bool is_extended_reporting) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   // If we are in GetHash backoff, we need to check if we're past the next
   // allowed time. If we are, we can proceed with the request. If not, we are
   // required to return empty results (i.e. treat the page as safe).
@@ -232,7 +232,7 @@
 }
 
 void SafeBrowsingProtocolManager::GetNextUpdate() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   if (request_.get() || request_type_ != NO_REQUEST)
     return;
 
@@ -251,7 +251,7 @@
 //              required, the SafeBrowsing servers will tell us to get it again.
 void SafeBrowsingProtocolManager::OnURLFetchComplete(
     const net::URLFetcher* source) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   std::unique_ptr<const net::URLFetcher> fetcher;
 
   HashRequests::iterator it = hash_requests_.find(source);
@@ -409,7 +409,7 @@
 bool SafeBrowsingProtocolManager::HandleServiceResponse(const GURL& url,
                                                         const char* data,
                                                         size_t length) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
   switch (request_type_) {
     case UPDATE_REQUEST:
@@ -490,11 +490,7 @@
 }
 
 void SafeBrowsingProtocolManager::Initialize() {
-  DCHECK(CalledOnValidThread());
-  // TODO(cbentzel): Remove ScopedTracker below once crbug.com/483689 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "483689 SafeBrowsingProtocolManager::Initialize"));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   // Don't want to hit the safe browsing servers on build/chrome bots.
   std::unique_ptr<base::Environment> env(base::Environment::Create());
   if (env->HasVar(env_vars::kHeadless))
@@ -503,7 +499,7 @@
 }
 
 void SafeBrowsingProtocolManager::ScheduleNextUpdate(bool back_off) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   if (disable_auto_update_) {
     // Unschedule any current timer.
     update_timer_.Stop();
@@ -516,7 +512,7 @@
 
 void SafeBrowsingProtocolManager::ForceScheduleNextUpdate(
     base::TimeDelta interval) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   DCHECK(interval >= base::TimeDelta());
   // Unschedule any current timer.
   update_timer_.Stop();
@@ -529,7 +525,7 @@
 // when we receive a response from the SafeBrowsing service.
 base::TimeDelta SafeBrowsingProtocolManager::GetNextUpdateInterval(
     bool back_off) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   DCHECK(next_update_interval_ > base::TimeDelta());
   base::TimeDelta next = next_update_interval_;
   if (back_off) {
@@ -545,7 +541,7 @@
 base::TimeDelta SafeBrowsingProtocolManager::GetNextBackOffInterval(
     size_t* error_count,
     size_t* multiplier) const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   DCHECK(multiplier && error_count);
   (*error_count)++;
   if (*error_count > 1 && *error_count < 6) {
@@ -569,7 +565,7 @@
 //              otherhand, this request will only occur ~20-30 minutes so there
 //              isn't that much overhead. Measure!
 void SafeBrowsingProtocolManager::IssueUpdateRequest() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   request_type_ = UPDATE_REQUEST;
   delegate_->UpdateStarted();
   delegate_->GetChunks(
@@ -581,7 +577,7 @@
 // retrieved from the DB.
 bool SafeBrowsingProtocolManager::IssueBackupUpdateRequest(
     BackupUpdateReason backup_update_reason) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   DCHECK_EQ(request_type_, UPDATE_REQUEST);
   DCHECK(backup_update_reason >= 0 &&
          backup_update_reason < BACKUP_UPDATE_REASON_MAX);
@@ -607,7 +603,7 @@
 }
 
 void SafeBrowsingProtocolManager::IssueChunkRequest() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   // We are only allowed to have one request outstanding at any time.  Also,
   // don't get the next url until the previous one has been written to disk so
   // that we don't use too much memory.
@@ -630,7 +626,7 @@
     const std::vector<SBListChunkRanges>& lists,
     bool database_error,
     bool is_extended_reporting) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   DCHECK_EQ(request_type_, UPDATE_REQUEST);
   DCHECK(update_list_data_.empty());
   if (database_error) {
@@ -685,7 +681,7 @@
 // If we haven't heard back from the server with an update response, this method
 // will run. Close the current update session and schedule another update.
 void SafeBrowsingProtocolManager::UpdateResponseTimeout() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   DCHECK(request_type_ == UPDATE_REQUEST ||
          request_type_ == BACKUP_UPDATE_REQUEST);
   request_.reset();
@@ -697,7 +693,7 @@
 }
 
 void SafeBrowsingProtocolManager::OnAddChunksComplete() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   chunk_pending_to_write_ = false;
 
   if (chunk_request_urls_.empty()) {
@@ -709,7 +705,7 @@
 }
 
 void SafeBrowsingProtocolManager::HandleGetHashError(const Time& now) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   base::TimeDelta next =
       GetNextBackOffInterval(&gethash_error_count_, &gethash_back_off_mult_);
   next_gethash_time_ = now + next;
@@ -720,7 +716,7 @@
 }
 
 void SafeBrowsingProtocolManager::UpdateFinished(bool success, bool back_off) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   UMA_HISTOGRAM_COUNTS("SB2.UpdateSize", update_size_);
   update_size_ = 0;
   bool update_success = success || request_type_ == CHUNK_REQUEST;
@@ -766,7 +762,7 @@
 }
 
 GURL SafeBrowsingProtocolManager::NextChunkUrl(const std::string& url) const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   std::string next_url;
   if (!base::StartsWith(url, "http://", base::CompareCase::INSENSITIVE_ASCII) &&
       !base::StartsWith(url, "https://",
diff --git a/chrome/browser/safe_browsing/protocol_manager.h b/chrome/browser/safe_browsing/protocol_manager.h
index aecf832..d1f8f50 100644
--- a/chrome/browser/safe_browsing/protocol_manager.h
+++ b/chrome/browser/safe_browsing/protocol_manager.h
@@ -24,7 +24,6 @@
 #include "base/containers/hash_tables.h"
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
-#include "base/threading/non_thread_safe.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "chrome/browser/safe_browsing/chunk_range.h"
@@ -47,8 +46,8 @@
 class SBProtocolManagerFactory;
 class SafeBrowsingProtocolManagerDelegate;
 
-class SafeBrowsingProtocolManager : public net::URLFetcherDelegate,
-                                    public base::NonThreadSafe {
+// Lives on the IO thread.
+class SafeBrowsingProtocolManager : public net::URLFetcherDelegate {
  public:
   // FullHashCallback is invoked when GetFullHash completes.
   // Parameters:
@@ -56,8 +55,9 @@
   //     were no matches, and that the resource is safe.
   //   - The cache lifetime of the result. A lifetime of 0 indicates the results
   //     should not be cached.
-  typedef base::Callback<void(const std::vector<SBFullHashResult>&,
-                              const base::TimeDelta&)> FullHashCallback;
+  using FullHashCallback =
+      base::Callback<void(const std::vector<SBFullHashResult>&,
+                          const base::TimeDelta&)>;
 
   ~SafeBrowsingProtocolManager() override;
 
@@ -68,7 +68,7 @@
   }
 
   // Create an instance of the safe browsing protocol manager.
-  static SafeBrowsingProtocolManager* Create(
+  static std::unique_ptr<SafeBrowsingProtocolManager> Create(
       SafeBrowsingProtocolManagerDelegate* delegate,
       net::URLRequestContextGetter* request_context_getter,
       const SafeBrowsingProtocolConfig& config);
@@ -290,7 +290,7 @@
     FullHashCallback callback;
     bool is_download;
   };
-  typedef base::hash_map<const net::URLFetcher*, FullHashDetails> HashRequests;
+  using HashRequests = base::hash_map<const net::URLFetcher*, FullHashDetails>;
 
   // The factory that controls the creation of SafeBrowsingProtocolManager.
   // This is used by tests.
@@ -392,10 +392,12 @@
  public:
   SBProtocolManagerFactory() {}
   virtual ~SBProtocolManagerFactory() {}
-  virtual SafeBrowsingProtocolManager* CreateProtocolManager(
+
+  virtual std::unique_ptr<SafeBrowsingProtocolManager> CreateProtocolManager(
       SafeBrowsingProtocolManagerDelegate* delegate,
       net::URLRequestContextGetter* request_context_getter,
       const SafeBrowsingProtocolConfig& config) = 0;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(SBProtocolManagerFactory);
 };
@@ -403,12 +405,11 @@
 // Delegate interface for the SafeBrowsingProtocolManager.
 class SafeBrowsingProtocolManagerDelegate {
  public:
-  typedef base::Callback<void(
+  using GetChunksCallback = base::Callback<void(
       const std::vector<SBListChunkRanges>&, /* List of chunks */
       bool,                                  /* database_error */
-      bool                                   /* is_extended_reporting */
-      )> GetChunksCallback;
-  typedef base::Callback<void(void)> AddChunksCallback;
+      bool                                   /* is_extended_reporting */)>;
+  using AddChunksCallback = base::Closure;
 
   virtual ~SafeBrowsingProtocolManagerDelegate();
 
diff --git a/chrome/browser/safe_browsing/protocol_manager_unittest.cc b/chrome/browser/safe_browsing/protocol_manager_unittest.cc
index 70e240b..b08d01a9 100644
--- a/chrome/browser/safe_browsing/protocol_manager_unittest.cc
+++ b/chrome/browser/safe_browsing/protocol_manager_unittest.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/safe_browsing/chunk.pb.h"
 #include "components/safe_browsing_db/safebrowsing.pb.h"
 #include "components/safe_browsing_db/util.h"
+#include "content/public/test/test_browser_thread.h"
 #include "google_apis/google_api_keys.h"
 #include "net/base/escape.h"
 #include "net/base/load_flags.h"
@@ -70,7 +71,12 @@
 
 class SafeBrowsingProtocolManagerTest : public testing::Test {
  protected:
-  std::string key_param_;
+  SafeBrowsingProtocolManagerTest()
+      : runner_(new base::TestSimpleTaskRunner),
+        runner_handler_(runner_),
+        io_thread_(content::BrowserThread::IO) {}
+
+  ~SafeBrowsingProtocolManagerTest() override {}
 
   void SetUp() override {
     std::string key = google_apis::GetAPIKey();
@@ -91,7 +97,7 @@
     config.backup_network_error_url_prefix = kBackupNetworkUrlPrefix;
     config.version = kAppVer;
     return std::unique_ptr<SafeBrowsingProtocolManager>(
-        SafeBrowsingProtocolManager::Create(delegate, NULL, config));
+        SafeBrowsingProtocolManager::Create(delegate, nullptr, config));
   }
 
   void ValidateUpdateFetcherRequest(const net::TestURLFetcher* url_fetcher,
@@ -121,11 +127,17 @@
     EXPECT_EQ("", url_fetcher->upload_data());
     EXPECT_EQ(GURL(expected_url), url_fetcher->GetOriginalURL());
   }
+
+  scoped_refptr<base::TestSimpleTaskRunner> runner_;
+  base::ThreadTaskRunnerHandle runner_handler_;
+  content::TestBrowserThread io_thread_;
+  std::string key_param_;
 };
 
 // Ensure that we respect section 5 of the SafeBrowsing protocol specification.
 TEST_F(SafeBrowsingProtocolManagerTest, TestBackOffTimes) {
-  std::unique_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
+  std::unique_ptr<SafeBrowsingProtocolManager> pm(
+      CreateProtocolManager(nullptr));
 
   pm->next_update_interval_ = TimeDelta::FromSeconds(1800);
   ASSERT_TRUE(pm->back_off_fuzz_ >= 0.0 && pm->back_off_fuzz_ <= 1.0);
@@ -174,7 +186,8 @@
 }
 
 TEST_F(SafeBrowsingProtocolManagerTest, TestChunkStrings) {
-  std::unique_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
+  std::unique_ptr<SafeBrowsingProtocolManager> pm(
+      CreateProtocolManager(nullptr));
 
   // Add and Sub chunks.
   SBListChunkRanges phish(kDefaultPhishList);
@@ -202,7 +215,8 @@
 }
 
 TEST_F(SafeBrowsingProtocolManagerTest, TestGetHashBackOffTimes) {
-  std::unique_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
+  std::unique_ptr<SafeBrowsingProtocolManager> pm(
+      CreateProtocolManager(nullptr));
 
   // No errors or back off time yet.
   EXPECT_EQ(0U, pm->gethash_error_count_);
@@ -254,7 +268,8 @@
 }
 
 TEST_F(SafeBrowsingProtocolManagerTest, TestGetHashUrl) {
-  std::unique_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
+  std::unique_ptr<SafeBrowsingProtocolManager> pm(
+      CreateProtocolManager(nullptr));
 
   EXPECT_EQ(
       "https://prefix.com/foo/gethash?client=unittest&appver=1.0&"
@@ -271,7 +286,8 @@
 }
 
 TEST_F(SafeBrowsingProtocolManagerTest, TestUpdateUrl) {
-  std::unique_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
+  std::unique_ptr<SafeBrowsingProtocolManager> pm(
+      CreateProtocolManager(nullptr));
 
   EXPECT_EQ(
       "https://prefix.com/foo/downloads?client=unittest&appver=1.0&"
@@ -288,7 +304,8 @@
 }
 
 TEST_F(SafeBrowsingProtocolManagerTest, TestNextChunkUrl) {
-  std::unique_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
+  std::unique_ptr<SafeBrowsingProtocolManager> pm(
+      CreateProtocolManager(nullptr));
 
   std::string url_partial = "localhost:1234/foo/bar?foo";
   std::string url_http_full = "http://localhost:1234/foo/bar?foo";
@@ -381,10 +398,6 @@
 // Tests that the Update protocol will be skipped if there are problems
 // accessing the database.
 TEST_F(SafeBrowsingProtocolManagerTest, ProblemAccessingDatabase) {
-  scoped_refptr<base::TestSimpleTaskRunner> runner(
-      new base::TestSimpleTaskRunner());
-  base::ThreadTaskRunnerHandle runner_handler(runner);
-
   testing::StrictMock<MockProtocolDelegate> test_delegate;
   EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
   EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
@@ -397,7 +410,7 @@
       CreateProtocolManager(&test_delegate));
 
   pm->ForceScheduleNextUpdate(TimeDelta());
-  runner->RunPendingTasks();
+  runner_->RunPendingTasks();
 
   EXPECT_TRUE(pm->IsUpdateScheduled());
 }
@@ -406,9 +419,6 @@
 // local database. This is not exhaustive, as the actual list formatting
 // is covered by SafeBrowsingProtocolManagerTest.TestChunkStrings.
 TEST_F(SafeBrowsingProtocolManagerTest, ExistingDatabase) {
-  scoped_refptr<base::TestSimpleTaskRunner> runner(
-      new base::TestSimpleTaskRunner());
-  base::ThreadTaskRunnerHandle runner_handler(runner);
   net::TestURLFetcherFactory url_fetcher_factory;
 
   std::vector<SBListChunkRanges> ranges;
@@ -435,7 +445,7 @@
 
   // Kick off initialization. This returns chunks from the DB synchronously.
   pm->ForceScheduleNextUpdate(TimeDelta());
-  runner->RunPendingTasks();
+  runner_->RunPendingTasks();
 
   // We should have an URLFetcher at this point in time.
   net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
@@ -460,9 +470,6 @@
 }
 
 TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseBadBodyBackupSuccess) {
-  scoped_refptr<base::TestSimpleTaskRunner> runner(
-      new base::TestSimpleTaskRunner());
-  base::ThreadTaskRunnerHandle runner_handler(runner);
   net::TestURLFetcherFactory url_fetcher_factory;
 
   testing::StrictMock<MockProtocolDelegate> test_delegate;
@@ -478,7 +485,7 @@
 
   // Kick off initialization. This returns chunks from the DB synchronously.
   pm->ForceScheduleNextUpdate(TimeDelta());
-  runner->RunPendingTasks();
+  runner_->RunPendingTasks();
 
   // We should have an URLFetcher at this point in time.
   net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
@@ -507,9 +514,6 @@
 // Tests what happens when there is an HTTP error response to the update
 // request, as well as an error response to the backup update request.
 TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseHttpErrorBackupError) {
-  scoped_refptr<base::TestSimpleTaskRunner> runner(
-      new base::TestSimpleTaskRunner());
-  base::ThreadTaskRunnerHandle runner_handler(runner);
   net::TestURLFetcherFactory url_fetcher_factory;
 
   testing::StrictMock<MockProtocolDelegate> test_delegate;
@@ -525,7 +529,7 @@
 
   // Kick off initialization. This returns chunks from the DB synchronously.
   pm->ForceScheduleNextUpdate(TimeDelta());
-  runner->RunPendingTasks();
+  runner_->RunPendingTasks();
 
   // We should have an URLFetcher at this point in time.
   net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
@@ -554,9 +558,6 @@
 // Tests what happens when there is an HTTP error response to the update
 // request, followed by a successful response to the backup update request.
 TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseHttpErrorBackupSuccess) {
-  scoped_refptr<base::TestSimpleTaskRunner> runner(
-      new base::TestSimpleTaskRunner());
-  base::ThreadTaskRunnerHandle runner_handler(runner);
   net::TestURLFetcherFactory url_fetcher_factory;
 
   testing::StrictMock<MockProtocolDelegate> test_delegate;
@@ -572,7 +573,7 @@
 
   // Kick off initialization. This returns chunks from the DB synchronously.
   pm->ForceScheduleNextUpdate(TimeDelta());
-  runner->RunPendingTasks();
+  runner_->RunPendingTasks();
 
   // We should have an URLFetcher at this point in time.
   net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
@@ -601,9 +602,6 @@
 // Tests what happens when there is an HTTP error response to the update
 // request, and a timeout on the backup update request.
 TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseHttpErrorBackupTimeout) {
-  scoped_refptr<base::TestSimpleTaskRunner> runner(
-      new base::TestSimpleTaskRunner());
-  base::ThreadTaskRunnerHandle runner_handler(runner);
   net::TestURLFetcherFactory url_fetcher_factory;
 
   testing::StrictMock<MockProtocolDelegate> test_delegate;
@@ -619,7 +617,7 @@
 
   // Kick off initialization. This returns chunks from the DB synchronously.
   pm->ForceScheduleNextUpdate(TimeDelta());
-  runner->RunPendingTasks();
+  runner_->RunPendingTasks();
 
   // We should have an URLFetcher at this point in time.
   net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
@@ -642,9 +640,9 @@
   // call the timeout task from the backup request, or schedule another task
   // to run that in the future.
   // TODO(cbentzel): Less fragile approach.
-  runner->RunPendingTasks();
+  runner_->RunPendingTasks();
   if (!pm->IsUpdateScheduled())
-    runner->RunPendingTasks();
+    runner_->RunPendingTasks();
   EXPECT_TRUE(pm->IsUpdateScheduled());
 }
 
@@ -652,9 +650,6 @@
 // request, and an error with the backup update request.
 TEST_F(SafeBrowsingProtocolManagerTest,
        UpdateResponseConnectionErrorBackupError) {
-  scoped_refptr<base::TestSimpleTaskRunner> runner(
-      new base::TestSimpleTaskRunner());
-  base::ThreadTaskRunnerHandle runner_handler(runner);
   net::TestURLFetcherFactory url_fetcher_factory;
 
   testing::StrictMock<MockProtocolDelegate> test_delegate;
@@ -670,7 +665,7 @@
 
   // Kick off initialization. This returns chunks from the DB synchronously.
   pm->ForceScheduleNextUpdate(TimeDelta());
-  runner->RunPendingTasks();
+  runner_->RunPendingTasks();
 
   // We should have an URLFetcher at this point in time.
   net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
@@ -699,9 +694,6 @@
 // request, and a successful response to the backup update request.
 TEST_F(SafeBrowsingProtocolManagerTest,
        UpdateResponseConnectionErrorBackupSuccess) {
-  scoped_refptr<base::TestSimpleTaskRunner> runner(
-      new base::TestSimpleTaskRunner());
-  base::ThreadTaskRunnerHandle runner_handler(runner);
   net::TestURLFetcherFactory url_fetcher_factory;
 
   testing::StrictMock<MockProtocolDelegate> test_delegate;
@@ -717,7 +709,7 @@
 
   // Kick off initialization. This returns chunks from the DB synchronously.
   pm->ForceScheduleNextUpdate(TimeDelta());
-  runner->RunPendingTasks();
+  runner_->RunPendingTasks();
 
   // We should have an URLFetcher at this point in time.
   net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
@@ -745,9 +737,6 @@
 // update request, and an error with the backup update request.
 TEST_F(SafeBrowsingProtocolManagerTest,
        UpdateResponseNetworkErrorBackupError) {
-  scoped_refptr<base::TestSimpleTaskRunner> runner(
-      new base::TestSimpleTaskRunner());
-  base::ThreadTaskRunnerHandle runner_handler(runner);
   net::TestURLFetcherFactory url_fetcher_factory;
 
   testing::StrictMock<MockProtocolDelegate> test_delegate;
@@ -763,7 +752,7 @@
 
   // Kick off initialization. This returns chunks from the DB synchronously.
   pm->ForceScheduleNextUpdate(TimeDelta());
-  runner->RunPendingTasks();
+  runner_->RunPendingTasks();
 
   // We should have an URLFetcher at this point in time.
   net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
@@ -793,9 +782,6 @@
 // update request, and a successful response to the backup update request.
 TEST_F(SafeBrowsingProtocolManagerTest,
        UpdateResponseNetworkErrorBackupSuccess) {
-  scoped_refptr<base::TestSimpleTaskRunner> runner(
-      new base::TestSimpleTaskRunner());
-  base::ThreadTaskRunnerHandle runner_handler(runner);
   net::TestURLFetcherFactory url_fetcher_factory;
 
   testing::StrictMock<MockProtocolDelegate> test_delegate;
@@ -811,7 +797,7 @@
 
   // Kick off initialization. This returns chunks from the DB synchronously.
   pm->ForceScheduleNextUpdate(TimeDelta());
-  runner->RunPendingTasks();
+  runner_->RunPendingTasks();
 
   // We should have an URLFetcher at this point in time.
   net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
@@ -839,9 +825,6 @@
 
 // Tests what happens when there is a timeout before an update response.
 TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseTimeoutBackupSuccess) {
-  scoped_refptr<base::TestSimpleTaskRunner> runner(
-      new base::TestSimpleTaskRunner());
-  base::ThreadTaskRunnerHandle runner_handler(runner);
   net::TestURLFetcherFactory url_fetcher_factory;
 
   testing::StrictMock<MockProtocolDelegate> test_delegate;
@@ -857,7 +840,7 @@
 
   // Kick off initialization. This returns chunks from the DB synchronously.
   pm->ForceScheduleNextUpdate(TimeDelta());
-  runner->RunPendingTasks();
+  runner_->RunPendingTasks();
 
   // We should have an URLFetcher at this point in time.
   net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
@@ -865,7 +848,7 @@
 
   // The first time RunPendingTasks is called above, the update timeout timer is
   // not handled. This call of RunPendingTasks will handle the update.
-  runner->RunPendingTasks();
+  runner_->RunPendingTasks();
 
   // There should be a backup URLFetcher now.
   net::TestURLFetcher* backup_url_fetcher =
@@ -883,9 +866,6 @@
 
 // Tests what happens when there is a reset command in the response.
 TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseReset) {
-  scoped_refptr<base::TestSimpleTaskRunner> runner(
-      new base::TestSimpleTaskRunner());
-  base::ThreadTaskRunnerHandle runner_handler(runner);
   net::TestURLFetcherFactory url_fetcher_factory;
 
   testing::StrictMock<MockProtocolDelegate> test_delegate;
@@ -902,7 +882,7 @@
 
   // Kick off initialization. This returns chunks from the DB synchronously.
   pm->ForceScheduleNextUpdate(TimeDelta());
-  runner->RunPendingTasks();
+  runner_->RunPendingTasks();
 
   net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
   ValidateUpdateFetcherRequest(url_fetcher);
@@ -919,9 +899,6 @@
 // Tests a single valid update response, followed by a single redirect response
 // that has an valid, but empty body.
 TEST_F(SafeBrowsingProtocolManagerTest, EmptyRedirectResponse) {
-  scoped_refptr<base::TestSimpleTaskRunner> runner(
-      new base::TestSimpleTaskRunner());
-  base::ThreadTaskRunnerHandle runner_handler(runner);
   net::TestURLFetcherFactory url_fetcher_factory;
 
   testing::StrictMock<MockProtocolDelegate> test_delegate;
@@ -937,7 +914,7 @@
 
   // Kick off initialization. This returns chunks from the DB synchronously.
   pm->ForceScheduleNextUpdate(TimeDelta());
-  runner->RunPendingTasks();
+  runner_->RunPendingTasks();
 
   // The update response contains a single redirect command.
   net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
@@ -966,9 +943,6 @@
 // Tests a single valid update response, followed by a single redirect response
 // that has an invalid body.
 TEST_F(SafeBrowsingProtocolManagerTest, InvalidRedirectResponse) {
-  scoped_refptr<base::TestSimpleTaskRunner> runner(
-      new base::TestSimpleTaskRunner());
-  base::ThreadTaskRunnerHandle runner_handler(runner);
   net::TestURLFetcherFactory url_fetcher_factory;
 
   testing::StrictMock<MockProtocolDelegate> test_delegate;
@@ -984,7 +958,7 @@
 
   // Kick off initialization. This returns chunks from the DB synchronously.
   pm->ForceScheduleNextUpdate(TimeDelta());
-  runner->RunPendingTasks();
+  runner_->RunPendingTasks();
 
   // The update response contains a single redirect command.
   net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
@@ -1013,9 +987,6 @@
 // Tests a single valid update response, followed by a single redirect response
 // containing chunks.
 TEST_F(SafeBrowsingProtocolManagerTest, SingleRedirectResponseWithChunks) {
-  scoped_refptr<base::TestSimpleTaskRunner> runner(
-      new base::TestSimpleTaskRunner());
-  base::ThreadTaskRunnerHandle runner_handler(runner);
   net::TestURLFetcherFactory url_fetcher_factory;
 
   testing::StrictMock<MockProtocolDelegate> test_delegate;
@@ -1033,7 +1004,7 @@
 
   // Kick off initialization. This returns chunks from the DB synchronously.
   pm->ForceScheduleNextUpdate(TimeDelta());
-  runner->RunPendingTasks();
+  runner_->RunPendingTasks();
 
   // The update response contains a single redirect command.
   net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
@@ -1059,7 +1030,7 @@
   EXPECT_FALSE(pm->IsUpdateScheduled());
 
   // The AddChunksCallback needs to be invoked.
-  runner->RunPendingTasks();
+  runner_->RunPendingTasks();
 
   EXPECT_TRUE(pm->IsUpdateScheduled());
 }
@@ -1067,9 +1038,6 @@
 // Tests a single valid update response, followed by multiple redirect responses
 // containing chunks.
 TEST_F(SafeBrowsingProtocolManagerTest, MultipleRedirectResponsesWithChunks) {
-  scoped_refptr<base::TestSimpleTaskRunner> runner(
-      new base::TestSimpleTaskRunner());
-  base::ThreadTaskRunnerHandle runner_handler(runner);
   net::TestURLFetcherFactory url_fetcher_factory;
 
   testing::StrictMock<MockProtocolDelegate> test_delegate;
@@ -1087,7 +1055,7 @@
 
   // Kick off initialization. This returns chunks from the DB synchronously.
   pm->ForceScheduleNextUpdate(TimeDelta());
-  runner->RunPendingTasks();
+  runner_->RunPendingTasks();
 
   // The update response contains multiple redirect commands.
   net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
@@ -1113,7 +1081,7 @@
       first_chunk_url_fetcher);
 
   // Invoke the AddChunksCallback to trigger the second request.
-  runner->RunPendingTasks();
+  runner_->RunPendingTasks();
 
   EXPECT_FALSE(pm->IsUpdateScheduled());
 
@@ -1131,7 +1099,7 @@
   EXPECT_FALSE(pm->IsUpdateScheduled());
 
   // Invoke the AddChunksCallback to finish the update.
-  runner->RunPendingTasks();
+  runner_->RunPendingTasks();
 
   EXPECT_TRUE(pm->IsUpdateScheduled());
 }
diff --git a/chrome/browser/safe_browsing/safe_browsing_database.cc b/chrome/browser/safe_browsing/safe_browsing_database.cc
index d1bc5486..a824223 100644
--- a/chrome/browser/safe_browsing/safe_browsing_database.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_database.cc
@@ -280,7 +280,7 @@
 // The default SafeBrowsingDatabaseFactory.
 class SafeBrowsingDatabaseFactoryImpl : public SafeBrowsingDatabaseFactory {
  public:
-  SafeBrowsingDatabase* CreateSafeBrowsingDatabase(
+  std::unique_ptr<SafeBrowsingDatabase> CreateSafeBrowsingDatabase(
       const scoped_refptr<base::SequencedTaskRunner>& db_task_runner,
       bool enable_download_protection,
       bool enable_client_side_whitelist,
@@ -289,7 +289,7 @@
       bool enable_ip_blacklist,
       bool enable_unwanted_software_list,
       bool enable_module_whitelist) override {
-    return new SafeBrowsingDatabaseNew(
+    return base::WrapUnique(new SafeBrowsingDatabaseNew(
         db_task_runner, CreateStore(true, db_task_runner),  // browse_store
         CreateStore(enable_download_protection, db_task_runner),
         CreateStore(enable_client_side_whitelist, db_task_runner),
@@ -298,7 +298,7 @@
         CreateStore(enable_ip_blacklist, db_task_runner),
         CreateStore(enable_unwanted_software_list, db_task_runner),
         CreateStore(enable_module_whitelist, db_task_runner),
-        CreateStore(true, db_task_runner));  // resource_blacklist_store
+        CreateStore(true, db_task_runner)));  // resource_blacklist_store
   }
 
   SafeBrowsingDatabaseFactoryImpl() {}
@@ -315,7 +315,7 @@
 // TODO(shess): There's no need for a factory any longer.  Convert
 // SafeBrowsingDatabaseNew to SafeBrowsingDatabase, and have Create()
 // callers just construct things directly.
-SafeBrowsingDatabase* SafeBrowsingDatabase::Create(
+std::unique_ptr<SafeBrowsingDatabase> SafeBrowsingDatabase::Create(
     const scoped_refptr<base::SequencedTaskRunner>& current_task_runner,
     bool enable_download_protection,
     bool enable_client_side_whitelist,
diff --git a/chrome/browser/safe_browsing/safe_browsing_database.h b/chrome/browser/safe_browsing/safe_browsing_database.h
index 9b1d7ff..67f75b39 100644
--- a/chrome/browser/safe_browsing/safe_browsing_database.h
+++ b/chrome/browser/safe_browsing/safe_browsing_database.h
@@ -36,7 +36,7 @@
  public:
   SafeBrowsingDatabaseFactory() { }
   virtual ~SafeBrowsingDatabaseFactory() { }
-  virtual SafeBrowsingDatabase* CreateSafeBrowsingDatabase(
+  virtual std::unique_ptr<SafeBrowsingDatabase> CreateSafeBrowsingDatabase(
       const scoped_refptr<base::SequencedTaskRunner>& db_task_runner,
       bool enable_download_protection,
       bool enable_client_side_whitelist,
@@ -68,7 +68,7 @@
   // It is not thread safe.
   // The browse list and off-domain inclusion whitelist are always on;
   // availability of other lists is controlled by the flags on this method.
-  static SafeBrowsingDatabase* Create(
+  static std::unique_ptr<SafeBrowsingDatabase> Create(
       const scoped_refptr<base::SequencedTaskRunner>& db_task_runner,
       bool enable_download_protection,
       bool enable_client_side_whitelist,
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.cc b/chrome/browser/safe_browsing/safe_browsing_service.cc
index ae689f3..19158a2a7 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_service.cc
@@ -281,8 +281,6 @@
 
 SafeBrowsingService::SafeBrowsingService()
     : services_delegate_(ServicesDelegate::Create(this)),
-      protocol_manager_(nullptr),
-      ping_manager_(nullptr),
       enabled_(false),
       enabled_by_prefs_(false) {}
 
@@ -390,12 +388,16 @@
 
 SafeBrowsingProtocolManager* SafeBrowsingService::protocol_manager() const {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  return protocol_manager_;
+#if defined(SAFE_BROWSING_DB_LOCAL)
+  return protocol_manager_.get();
+#else
+  return nullptr;
+#endif
 }
 
 SafeBrowsingPingManager* SafeBrowsingService::ping_manager() const {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  return ping_manager_;
+  return ping_manager_.get();
 }
 
 std::unique_ptr<TrackedPreferenceValidationDelegate>
@@ -569,11 +571,9 @@
     // This cancels all in-flight GetHash requests. Note that
     // |database_manager_| relies on |protocol_manager_| so if the latter is
     // destroyed, the former must be stopped.
-    delete protocol_manager_;
-    protocol_manager_ = nullptr;
+    protocol_manager_.reset();
 #endif
-    delete ping_manager_;
-    ping_manager_ = NULL;
+    ping_manager_.reset();
   }
 }
 
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.h b/chrome/browser/safe_browsing/safe_browsing_service.h
index 0d85341..0ac36a33 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service.h
+++ b/chrome/browser/safe_browsing/safe_browsing_service.h
@@ -244,11 +244,13 @@
   scoped_refptr<SafeBrowsingURLRequestContextGetter>
       url_request_context_getter_;
 
+#if defined(SAFE_BROWSING_DB_LOCAL)
   // Handles interaction with SafeBrowsing servers. Accessed on IO thread.
-  SafeBrowsingProtocolManager* protocol_manager_;
+  std::unique_ptr<SafeBrowsingProtocolManager> protocol_manager_;
+#endif
 
   // Provides phishing and malware statistics. Accessed on IO thread.
-  SafeBrowsingPingManager* ping_manager_;
+  std::unique_ptr<SafeBrowsingPingManager> ping_manager_;
 
   // Whether the service is running. 'enabled_' is used by SafeBrowsingService
   // on the IO thread during normal operations.
diff --git a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
index e24a4a5..5a041c2 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
@@ -345,10 +345,10 @@
 // Factory that creates TestSafeBrowsingDatabase instances.
 class TestSafeBrowsingDatabaseFactory : public SafeBrowsingDatabaseFactory {
  public:
-  TestSafeBrowsingDatabaseFactory() : db_(NULL) {}
+  TestSafeBrowsingDatabaseFactory() : db_(nullptr) {}
   ~TestSafeBrowsingDatabaseFactory() override {}
 
-  SafeBrowsingDatabase* CreateSafeBrowsingDatabase(
+  std::unique_ptr<SafeBrowsingDatabase> CreateSafeBrowsingDatabase(
       const scoped_refptr<base::SequencedTaskRunner>& db_task_runner,
       bool enable_download_protection,
       bool enable_client_side_whitelist,
@@ -358,7 +358,7 @@
       bool enabled_unwanted_software_list,
       bool enable_module_whitelist) override {
     db_ = new TestSafeBrowsingDatabase();
-    return db_;
+    return base::WrapUnique(db_);
   }
   TestSafeBrowsingDatabase* GetDb() { return db_; }
 
@@ -420,15 +420,15 @@
 // Factory that creates TestProtocolManager instances.
 class TestSBProtocolManagerFactory : public SBProtocolManagerFactory {
  public:
-  TestSBProtocolManagerFactory() : pm_(NULL) {}
+  TestSBProtocolManagerFactory() : pm_(nullptr) {}
   ~TestSBProtocolManagerFactory() override {}
 
-  SafeBrowsingProtocolManager* CreateProtocolManager(
+  std::unique_ptr<SafeBrowsingProtocolManager> CreateProtocolManager(
       SafeBrowsingProtocolManagerDelegate* delegate,
       net::URLRequestContextGetter* request_context_getter,
       const SafeBrowsingProtocolConfig& config) override {
     pm_ = new TestProtocolManager(delegate, request_context_getter, config);
-    return pm_;
+    return base::WrapUnique(pm_);
   }
 
   TestProtocolManager* GetProtocolManager() { return pm_; }
@@ -484,7 +484,7 @@
                                    SBFullHashResult* full_hash) {
     std::string host;
     std::string path;
-    CanonicalizeUrl(url, &host, &path, NULL);
+    CanonicalizeUrl(url, &host, &path, nullptr);
     full_hash->hash = SBFullHashForString(host + path);
     full_hash->list_id = list_id;
   }
@@ -516,9 +516,9 @@
 
     // Unregister test factories after InProcessBrowserTest::TearDown
     // (which destructs SafeBrowsingService).
-    SafeBrowsingDatabase::RegisterFactory(NULL);
-    SafeBrowsingProtocolManager::RegisterFactory(NULL);
-    SafeBrowsingService::RegisterFactory(NULL);
+    SafeBrowsingDatabase::RegisterFactory(nullptr);
+    SafeBrowsingProtocolManager::RegisterFactory(nullptr);
+    SafeBrowsingService::RegisterFactory(nullptr);
   }
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
@@ -573,7 +573,7 @@
     WebContents* contents =
         browser()->tab_strip_model()->GetActiveWebContents();
     InterstitialPage* interstitial_page = contents->GetInterstitialPage();
-    return interstitial_page != NULL;
+    return interstitial_page != nullptr;
   }
 
   void IntroduceGetHashDelay(const base::TimeDelta& delay) {
@@ -1473,9 +1473,9 @@
       sb_service->safe_browsing_detection_service();
   PrefService* pref_service = browser()->profile()->GetPrefs();
 
-  ASSERT_TRUE(sb_service != NULL);
-  ASSERT_TRUE(csd_service != NULL);
-  ASSERT_TRUE(pref_service != NULL);
+  ASSERT_TRUE(sb_service);
+  ASSERT_TRUE(csd_service);
+  ASSERT_TRUE(pref_service);
 
   EXPECT_TRUE(pref_service->GetBoolean(prefs::kSafeBrowsingEnabled));
 
@@ -1487,8 +1487,8 @@
   // Add a new Profile. SBS should keep running.
   ASSERT_TRUE(temp_profile_dir_.CreateUniqueTempDir());
   std::unique_ptr<Profile> profile2(Profile::CreateProfile(
-      temp_profile_dir_.path(), NULL, Profile::CREATE_MODE_SYNCHRONOUS));
-  ASSERT_TRUE(profile2.get() != NULL);
+      temp_profile_dir_.path(), nullptr, Profile::CREATE_MODE_SYNCHRONOUS));
+  ASSERT_TRUE(profile2);
   StartupTaskRunnerServiceFactory::GetForProfile(profile2.get())->
       StartDeferredTaskRunners();
   PrefService* pref_service2 = profile2->GetPrefs();
@@ -1530,7 +1530,7 @@
   EXPECT_TRUE(csd_service->enabled());
 
   // Delete the Profile. SBS stops again.
-  pref_service2 = NULL;
+  pref_service2 = nullptr;
   profile2.reset();
   EXPECT_FALSE(sb_service->enabled_by_prefs());
   WaitForIOAndCheckEnabled(sb_service, false);
@@ -1570,9 +1570,9 @@
       sb_service->safe_browsing_detection_service();
   PrefService* pref_service = browser()->profile()->GetPrefs();
 
-  ASSERT_TRUE(sb_service != NULL);
-  ASSERT_TRUE(csd_service != NULL);
-  ASSERT_TRUE(pref_service != NULL);
+  ASSERT_TRUE(sb_service);
+  ASSERT_TRUE(csd_service);
+  ASSERT_TRUE(pref_service);
 
   EXPECT_TRUE(pref_service->GetBoolean(prefs::kSafeBrowsingEnabled));
 
@@ -1629,7 +1629,7 @@
   void TearDown() override {
     InProcessBrowserTest::TearDown();
 
-    SafeBrowsingService::RegisterFactory(NULL);
+    SafeBrowsingService::RegisterFactory(nullptr);
   }
 
   bool SetUpUserDataDirectory() override {
@@ -1743,6 +1743,7 @@
     return std::move(http_response);
   }
 
+ private:
   DISALLOW_COPY_AND_ASSIGN(SafeBrowsingDatabaseManagerCookieTest);
 };
 
diff --git a/chrome/browser/safe_browsing/srt_fetcher_win.cc b/chrome/browser/safe_browsing/srt_fetcher_win.cc
index ccba9a6..62996ec1 100644
--- a/chrome/browser/safe_browsing/srt_fetcher_win.cc
+++ b/chrome/browser/safe_browsing/srt_fetcher_win.cc
@@ -22,7 +22,6 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task_runner_util.h"
-#include "base/threading/thread_checker.h"
 #include "base/time/time.h"
 #include "base/win/registry.h"
 #include "chrome/browser/browser_process.h"
@@ -472,7 +471,7 @@
       const scoped_refptr<base::TaskRunner>& blocking_task_runner) {
     if (!instance_)
       instance_ = new ReporterRunner;
-    DCHECK(instance_->thread_checker_.CalledOnValidThread());
+    DCHECK_CURRENTLY_ON(BrowserThread::UI);
     // There's nothing to do if the path and version of the reporter has not
     // changed, we just keep running the tasks that are running now.
     if (instance_->exe_path_ == exe_path && instance_->version_.IsValid() &&
@@ -497,7 +496,7 @@
   void OnBrowserSetLastActive(Browser* browser) override {}
   void OnBrowserRemoved(Browser* browser) override {}
   void OnBrowserAdded(Browser* browser) override {
-    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK_CURRENTLY_ON(BrowserThread::UI);
     DCHECK(browser);
     MaybeFetchSRT(browser, version_);
     BrowserList::RemoveObserver(this);
@@ -509,7 +508,7 @@
   void ReporterDone(const base::Time& reporter_start_time,
                     const base::Version& version,
                     int exit_code) {
-    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
     base::TimeDelta reporter_running_time =
         base::Time::Now() - reporter_start_time;
@@ -565,7 +564,7 @@
   }
 
   void TryToRun() {
-    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK_CURRENTLY_ON(BrowserThread::UI);
     PrefService* local_state = g_browser_process->local_state();
     if (!version_.IsValid() || !local_state) {
       DCHECK(exe_path_.empty());
@@ -622,7 +621,6 @@
   // A single leaky instance.
   static ReporterRunner* instance_;
 
-  base::ThreadChecker thread_checker_;
   DISALLOW_COPY_AND_ASSIGN(ReporterRunner);
 };
 
diff --git a/chrome/browser/safe_browsing/two_phase_uploader.cc b/chrome/browser/safe_browsing/two_phase_uploader.cc
index eaabab9..242326d7 100644
--- a/chrome/browser/safe_browsing/two_phase_uploader.cc
+++ b/chrome/browser/safe_browsing/two_phase_uploader.cc
@@ -10,7 +10,9 @@
 
 #include "base/bind.h"
 #include "base/macros.h"
+#include "base/memory/ptr_util.h"
 #include "base/task_runner.h"
+#include "content/public/browser/browser_thread.h"
 #include "net/base/net_errors.h"
 #include "net/http/http_response_headers.h"
 #include "net/url_request/url_fetcher.h"
@@ -20,12 +22,12 @@
 namespace {
 
 // Header sent on initial request to start the two phase upload process.
-const char* kStartHeader = "x-goog-resumable: start";
+const char kStartHeader[] = "x-goog-resumable: start";
 
 // Header returned on initial response with URL to use for the second phase.
-const char* kLocationHeader = "Location";
+const char kLocationHeader[] = "Location";
 
-const char* kUploadContentType = "application/octet-stream";
+const char kUploadContentType[] = "application/octet-stream";
 
 class TwoPhaseUploaderImpl : public net::URLFetcherDelegate,
                              public TwoPhaseUploader {
@@ -84,21 +86,22 @@
       file_path_(file_path),
       progress_callback_(progress_callback),
       finish_callback_(finish_callback) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 }
 
 TwoPhaseUploaderImpl::~TwoPhaseUploaderImpl() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 }
 
 void TwoPhaseUploaderImpl::Start() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK_EQ(STATE_NONE, state_);
 
   UploadMetadata();
 }
 
 void TwoPhaseUploaderImpl::OnURLFetchComplete(const net::URLFetcher* source) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   net::URLRequestStatus status = source->GetStatus();
   int response_code = source->GetResponseCode();
 
@@ -126,7 +129,7 @@
         }
         std::string location;
         if (!source->GetResponseHeaders()->EnumerateHeader(
-              NULL, kLocationHeader, &location)) {
+                nullptr, kLocationHeader, &location)) {
           LOG(ERROR) << "no location header";
           Finish(net::OK, response_code, std::string());
           return;
@@ -154,7 +157,7 @@
     const net::URLFetcher* source,
     int64_t current,
     int64_t total) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DVLOG(3) << __FUNCTION__ << " " << source->GetURL().spec()
            << " " << current << "/" << total;
   if (state_ == UPLOAD_FILE && !progress_callback_.is_null())
@@ -162,7 +165,7 @@
 }
 
 void TwoPhaseUploaderImpl::UploadMetadata() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   state_ = UPLOAD_METADATA;
   url_fetcher_ =
       net::URLFetcher::Create(base_url_, net::URLFetcher::POST, this);
@@ -173,7 +176,7 @@
 }
 
 void TwoPhaseUploaderImpl::UploadFile() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   state_ = UPLOAD_FILE;
 
   url_fetcher_ =
@@ -188,17 +191,17 @@
 void TwoPhaseUploaderImpl::Finish(int net_error,
                                   int response_code,
                                   const std::string& response) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   finish_callback_.Run(state_, net_error, response_code, response);
 }
 
 }  // namespace
 
 // static
-TwoPhaseUploaderFactory* TwoPhaseUploader::factory_ = NULL;
+TwoPhaseUploaderFactory* TwoPhaseUploader::factory_ = nullptr;
 
 // static
-TwoPhaseUploader* TwoPhaseUploader::Create(
+std::unique_ptr<TwoPhaseUploader> TwoPhaseUploader::Create(
     net::URLRequestContextGetter* url_request_context_getter,
     base::TaskRunner* file_task_runner,
     const GURL& base_url,
@@ -206,10 +209,11 @@
     const base::FilePath& file_path,
     const ProgressCallback& progress_callback,
     const FinishCallback& finish_callback) {
-  if (!TwoPhaseUploader::factory_)
-    return new TwoPhaseUploaderImpl(
+  if (!factory_) {
+    return base::WrapUnique(new TwoPhaseUploaderImpl(
         url_request_context_getter, file_task_runner, base_url, metadata,
-        file_path, progress_callback, finish_callback);
+        file_path, progress_callback, finish_callback));
+  }
   return TwoPhaseUploader::factory_->CreateTwoPhaseUploader(
       url_request_context_getter, file_task_runner, base_url, metadata,
       file_path, progress_callback, finish_callback);
diff --git a/chrome/browser/safe_browsing/two_phase_uploader.h b/chrome/browser/safe_browsing/two_phase_uploader.h
index f7c2d5f..12325003 100644
--- a/chrome/browser/safe_browsing/two_phase_uploader.h
+++ b/chrome/browser/safe_browsing/two_phase_uploader.h
@@ -12,7 +12,6 @@
 
 #include "base/callback.h"
 #include "base/files/file_path.h"
-#include "base/threading/non_thread_safe.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "url/gurl.h"
 
@@ -33,7 +32,8 @@
 // supports sending metadata in the POST request body. We also do not need the
 // api-version and authorization headers.
 // TODO(mattm): support retry / resume.
-class TwoPhaseUploader : public base::NonThreadSafe {
+// Lives on the UI thread.
+class TwoPhaseUploader {
  public:
   enum State {
     STATE_NONE,
@@ -41,11 +41,11 @@
     UPLOAD_FILE,
     STATE_SUCCESS,
   };
-  typedef base::Callback<void(int64_t sent, int64_t total)> ProgressCallback;
-  typedef base::Callback<void(State state,
-                              int net_error,
-                              int response_code,
-                              const std::string& response_data)> FinishCallback;
+  using ProgressCallback = base::Callback<void(int64_t sent, int64_t total)>;
+  using FinishCallback = base::Callback<void(State state,
+                                             int net_error,
+                                             int response_code,
+                                             const std::string& response_data)>;
 
   virtual ~TwoPhaseUploader() {}
 
@@ -62,7 +62,7 @@
   // response_data will specify information about the error. |finish_callback|
   // will not be called if the upload is cancelled by destructing the
   // TwoPhaseUploader object before completion.
-  static TwoPhaseUploader* Create(
+  static std::unique_ptr<TwoPhaseUploader> Create(
       net::URLRequestContextGetter* url_request_context_getter,
       base::TaskRunner* file_task_runner,
       const GURL& base_url,
@@ -90,7 +90,7 @@
  public:
   virtual ~TwoPhaseUploaderFactory() {}
 
-  virtual TwoPhaseUploader* CreateTwoPhaseUploader(
+  virtual std::unique_ptr<TwoPhaseUploader> CreateTwoPhaseUploader(
       net::URLRequestContextGetter* url_request_context_getter,
       base::TaskRunner* file_task_runner,
       const GURL& base_url,
diff --git a/chrome/browser/safe_browsing/two_phase_uploader_unittest.cc b/chrome/browser/safe_browsing/two_phase_uploader_unittest.cc
index dbb22b0..f845a173 100644
--- a/chrome/browser/safe_browsing/two_phase_uploader_unittest.cc
+++ b/chrome/browser/safe_browsing/two_phase_uploader_unittest.cc
@@ -51,10 +51,10 @@
 base::FilePath GetTestFilePath() {
   base::FilePath file_path;
   PathService::Get(base::DIR_SOURCE_ROOT, &file_path);
-  file_path = file_path.Append(FILE_PATH_LITERAL("net"));
-  file_path = file_path.Append(FILE_PATH_LITERAL("data"));
-  file_path = file_path.Append(FILE_PATH_LITERAL("url_request_unittest"));
-  file_path = file_path.Append(FILE_PATH_LITERAL("BullRunSpeech.txt"));
+  file_path = file_path.AppendASCII("net");
+  file_path = file_path.AppendASCII("data");
+  file_path = file_path.AppendASCII("url_request_unittest");
+  file_path = file_path.AppendASCII("BullRunSpeech.txt");
   return file_path;
 }
 
diff --git a/chrome/browser/safe_browsing/ui_manager.cc b/chrome/browser/safe_browsing/ui_manager.cc
index 8543c38..ab4769e 100644
--- a/chrome/browser/safe_browsing/ui_manager.cc
+++ b/chrome/browser/safe_browsing/ui_manager.cc
@@ -280,6 +280,17 @@
       callback);
 }
 
+void SafeBrowsingUIManager::ReportPermissionAction(
+    const GURL& origin,
+    content::PermissionType permission,
+    PermissionAction action) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  BrowserThread::PostTask(
+      BrowserThread::IO, FROM_HERE,
+      base::Bind(&SafeBrowsingUIManager::ReportPermissionActionOnIOThread, this,
+                 origin, permission, action));
+}
+
 void SafeBrowsingUIManager::AddObserver(Observer* observer) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   observer_list_.AddObserver(observer);
@@ -302,6 +313,21 @@
   sb_service_->ping_manager()->ReportInvalidCertificateChain(serialized_report);
 }
 
+void SafeBrowsingUIManager::ReportPermissionActionOnIOThread(
+    const GURL& origin,
+    content::PermissionType permission,
+    PermissionAction action) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  // The service may delete the ping manager (i.e. when user disabling service,
+  // etc). This happens on the IO thread.
+  if (!sb_service_ || !sb_service_->ping_manager())
+    return;
+
+  sb_service_->ping_manager()->ReportPermissionAction(origin, permission,
+                                                      action);
+}
+
 // If the user had opted-in to send ThreatDetails, this gets called
 // when the report is ready.
 void SafeBrowsingUIManager::SendSerializedThreatDetails(
diff --git a/chrome/browser/safe_browsing/ui_manager.h b/chrome/browser/safe_browsing/ui_manager.h
index b9b7e528..4b39b65 100644
--- a/chrome/browser/safe_browsing/ui_manager.h
+++ b/chrome/browser/safe_browsing/ui_manager.h
@@ -16,9 +16,11 @@
 #include "base/memory/ref_counted.h"
 #include "base/observer_list.h"
 #include "base/time/time.h"
+#include "chrome/browser/permissions/permission_uma_util.h"
 #include "components/safe_browsing_db/hit_report.h"
 #include "components/safe_browsing_db/util.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/permission_type.h"
 #include "url/gurl.h"
 
 namespace base {
@@ -148,6 +150,12 @@
   void ReportInvalidCertificateChain(const std::string& serialized_report,
                                      const base::Closure& callback);
 
+  // Report permission action to SafeBrowsing servers. Can only be called on UI
+  // thread.
+  void ReportPermissionAction(const GURL& origin,
+                              content::PermissionType permission,
+                              PermissionAction action);
+
   // Add and remove observers.  These methods must be invoked on the UI thread.
   void AddObserver(Observer* observer);
   void RemoveObserver(Observer* remove);
@@ -168,6 +176,11 @@
   void ReportInvalidCertificateChainOnIOThread(
       const std::string& serialized_report);
 
+  // Report permission action to SafeBrowsing servers.
+  void ReportPermissionActionOnIOThread(const GURL& origin,
+                                        content::PermissionType permission,
+                                        PermissionAction action);
+
   // Updates the whitelist state.  Called on the UI thread.
   void AddToWhitelist(const UnsafeResource& resource);
 
diff --git a/chrome/browser/search/local_ntp_source.cc b/chrome/browser/search/local_ntp_source.cc
index c54ae62..70a21ab 100644
--- a/chrome/browser/search/local_ntp_source.cc
+++ b/chrome/browser/search/local_ntp_source.cc
@@ -148,8 +148,7 @@
 // Returns a JS dictionary of configuration data for the local NTP.
 std::string GetConfigData(Profile* profile) {
   base::DictionaryValue config_data;
-  bool is_google = DefaultSearchProviderIsGoogle(profile) &&
-                   search::ShouldShowGoogleLocalNTP();
+  bool is_google = DefaultSearchProviderIsGoogle(profile);
   config_data.Set("translatedStrings",
                   GetTranslatedStrings(is_google).release());
   config_data.SetBoolean("isGooglePage", is_google);
diff --git a/chrome/browser/search/search.cc b/chrome/browser/search/search.cc
index 60f2cd3..c2ac4fe 100644
--- a/chrome/browser/search/search.cc
+++ b/chrome/browser/search/search.cc
@@ -61,8 +61,6 @@
 const char kAltInstantURLPath[] = "search";
 const char kAltInstantURLQueryParams[] = "&qbp=1";
 
-const char kShouldShowGoogleLocalNTPFlagName[] = "google_local_ntp";
-
 // Status of the New Tab URL for the default Search provider. NOTE: Used in a
 // UMA histogram so values should only be added at the end and not reordered.
 enum NewTabURLState {
@@ -502,12 +500,6 @@
       kPrerenderInstantUrlOnOmniboxFocus, false, flags);
 }
 
-bool ShouldShowGoogleLocalNTP() {
-  FieldTrialFlags flags;
-  return !GetFieldTrialInfo(&flags) || GetBoolValueForFlagWithDefault(
-      kShouldShowGoogleLocalNTPFlagName, true, flags);
-}
-
 GURL GetEffectiveURLForInstant(const GURL& url, Profile* profile) {
   CHECK(ShouldAssignURLToInstantRenderer(url, profile))
       << "Error granting Instant access.";
diff --git a/chrome/browser/search/search.h b/chrome/browser/search/search.h
index 2b33dbb..4466ef2 100644
--- a/chrome/browser/search/search.h
+++ b/chrome/browser/search/search.h
@@ -134,10 +134,6 @@
 // focused.
 bool ShouldPrerenderInstantUrlOnOmniboxFocus();
 
-// Returns true if the local new tab page should show a Google logo and search
-// box for users whose default search provider is Google, or false if not.
-bool ShouldShowGoogleLocalNTP();
-
 // Transforms the input |url| into its "effective URL". The returned URL
 // facilitates grouping process-per-site. The |url| is transformed, for
 // example, from
diff --git a/chrome/browser/search/search_unittest.cc b/chrome/browser/search/search_unittest.cc
index baa19152..72b12f4a 100644
--- a/chrome/browser/search/search_unittest.cc
+++ b/chrome/browser/search/search_unittest.cc
@@ -596,23 +596,6 @@
 }
 
 
-TEST_F(SearchTest, ShouldShowGoogleLocalNTP_Default) {
-  EXPECT_TRUE(ShouldShowGoogleLocalNTP());
-}
-
-TEST_F(SearchTest, ShouldShowGoogleLocalNTP_EnabledViaFinch) {
-  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
-      "EmbeddedSearch", "Group1 espv:2 google_local_ntp:1"));
-  EXPECT_TRUE(ShouldShowGoogleLocalNTP());
-}
-
-TEST_F(SearchTest, ShouldShowGoogleLocalNTP_DisabledViaFinch) {
-  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
-      "EmbeddedSearch", "Group1 espv:2 google_local_ntp:0"));
-  EXPECT_FALSE(ShouldShowGoogleLocalNTP());
-}
-
-
 TEST_F(SearchTest, IsNTPURL) {
   GURL invalid_url;
   GURL ntp_url(chrome::kChromeUINewTabURL);
diff --git a/chrome/browser/status_icons/status_icon_menu_model.cc b/chrome/browser/status_icons/status_icon_menu_model.cc
index eee644e..5f36040 100644
--- a/chrome/browser/status_icons/status_icon_menu_model.cc
+++ b/chrome/browser/status_icons/status_icon_menu_model.cc
@@ -113,7 +113,7 @@
 }
 
 bool StatusIconMenuModel::GetAcceleratorForCommandId(
-    int command_id, ui::Accelerator* accelerator) {
+    int command_id, ui::Accelerator* accelerator) const {
   ItemStateMap::const_iterator iter = item_states_.find(command_id);
   if (iter != item_states_.end() &&
       iter->second.accelerator.key_code() != ui::VKEY_UNKNOWN) {
diff --git a/chrome/browser/status_icons/status_icon_menu_model.h b/chrome/browser/status_icons/status_icon_menu_model.h
index 57967a5..672ff35d 100644
--- a/chrome/browser/status_icons/status_icon_menu_model.h
+++ b/chrome/browser/status_icons/status_icon_menu_model.h
@@ -82,7 +82,7 @@
   bool IsCommandIdEnabled(int command_id) const override;
   bool IsCommandIdVisible(int command_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   bool IsItemForCommandIdDynamic(int command_id) const override;
   base::string16 GetLabelForCommandId(int command_id) const override;
   base::string16 GetSublabelForCommandId(int command_id) const override;
diff --git a/chrome/browser/supervised_user/supervised_user_pref_store.cc b/chrome/browser/supervised_user/supervised_user_pref_store.cc
index 921fbe13..3f144a4 100644
--- a/chrome/browser/supervised_user/supervised_user_pref_store.cc
+++ b/chrome/browser/supervised_user/supervised_user_pref_store.cc
@@ -76,7 +76,7 @@
   // TODO(peconn): Remove this once SupervisedUserPrefStore is (partially at
   // least) a KeyedService. The user_settings_subscription_ must be reset or
   // destroyed before the SupervisedUserSettingsService is.
-  if (supervised_user_settings_service->GetProfile() != nullptr){
+  if (supervised_user_settings_service->GetProfile()) {
     unsubscriber_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
         content::Source<Profile>(
           supervised_user_settings_service->GetProfile()));
@@ -85,10 +85,6 @@
 
 bool SupervisedUserPrefStore::GetValue(const std::string& key,
                                        const base::Value** value) const {
-  // TODO(bauerb): Temporary CHECK to force a clean crash while investigating
-  // https://crbug.com/425785. Remove (or change back to DCHECK) once the bug
-  // is fixed.
-  CHECK(prefs_);
   return prefs_->GetValue(key, value);
 }
 
diff --git a/chrome/browser/supervised_user/supervised_user_settings_service.cc b/chrome/browser/supervised_user/supervised_user_settings_service.cc
index cf8dc89..6561085 100644
--- a/chrome/browser/supervised_user/supervised_user_settings_service.cc
+++ b/chrome/browser/supervised_user/supervised_user_settings_service.cc
@@ -75,9 +75,8 @@
   Init(store);
   if (load_synchronously) {
     store_->ReadPrefs();
-    // TODO(bauerb): Temporary CHECK while investigating
-    // https://crbug.com/425785. Remove (or change to DCHECK) once the bug
-    // is fixed.
+    // This should be a DCHECK, but it is triggering in the wild.
+    // https://crbug.com/627031
     CHECK(store_->IsInitializationComplete());
   } else {
     store_->ReadPrefsAsync(nullptr);
@@ -102,7 +101,7 @@
   return callback_list_.Add(callback);
 }
 
-Profile* SupervisedUserSettingsService::GetProfile(){
+Profile* SupervisedUserSettingsService::GetProfile() {
   return profile_;
 }
 
@@ -111,7 +110,7 @@
   InformSubscribers();
 }
 
-bool SupervisedUserSettingsService::IsReady() {
+bool SupervisedUserSettingsService::IsReady() const {
   // Initialization cannot be complete but have failed at the same time.
   DCHECK(!(store_->IsInitializationComplete() && initialization_failed_));
   return initialization_failed_ || store_->IsInitializationComplete();
@@ -404,9 +403,7 @@
     initialization_failed_ = true;
   }
 
-  // TODO(bauerb): Temporary CHECK while investigating https://crbug.com/425785.
-  // Remove (or change back to DCHECK) once the bug is fixed.
-  CHECK(IsReady());
+  DCHECK(IsReady());
   InformSubscribers();
 }
 
diff --git a/chrome/browser/supervised_user/supervised_user_settings_service.h b/chrome/browser/supervised_user/supervised_user_settings_service.h
index fc0a06b..6903fd4 100644
--- a/chrome/browser/supervised_user/supervised_user_settings_service.h
+++ b/chrome/browser/supervised_user/supervised_user_settings_service.h
@@ -95,7 +95,7 @@
   void SetActive(bool active);
 
   // Whether supervised user settings are available.
-  bool IsReady();
+  bool IsReady() const;
 
   // Clears all supervised user settings and items.
   void Clear();
@@ -172,7 +172,7 @@
   // directly hooked up to the PrefService.
   scoped_refptr<PersistentPrefStore> store_;
 
-  Profile* profile_;
+  Profile* const profile_;
 
   bool active_;
 
diff --git a/chrome/browser/task_management/providers/arc/arc_process_task.cc b/chrome/browser/task_management/providers/arc/arc_process_task.cc
index 8f179109..435eee3 100644
--- a/chrome/browser/task_management/providers/arc/arc_process_task.cc
+++ b/chrome/browser/task_management/providers/arc/arc_process_task.cc
@@ -42,10 +42,8 @@
     default:
       break;
   }
-  base::string16 title =
-      l10n_util::GetStringFUTF16(
-          name_template,
-          base::UTF8ToUTF16(process_name));
+  base::string16 title = l10n_util::GetStringFUTF16(
+      name_template, base::UTF8ToUTF16(process_name));
   base::i18n::AdjustStringForLocaleDirection(&title);
   return title;
 }
@@ -69,8 +67,10 @@
                                const std::string& process_name,
                                arc::mojom::ProcessState process_state,
                                const std::vector<std::string>& packages)
-    : Task(MakeTitle(process_name, process_state), process_name,
-           nullptr /* icon */, pid),
+    : Task(MakeTitle(process_name, process_state),
+           process_name,
+           nullptr /* icon */,
+           pid),
       nspid_(nspid),
       process_name_(process_name),
       process_state_(process_state),
@@ -103,12 +103,12 @@
 
   if (result == arc::ActivityIconLoader::GetResult::FAILED_ARC_NOT_READY) {
     // Need to retry loading the icon.
-    arc::ArcBridgeService::Get()->AddObserver(this);
+    arc::ArcBridgeService::Get()->intent_helper()->AddObserver(this);
   }
 }
 
 ArcProcessTask::~ArcProcessTask() {
-  arc::ArcBridgeService::Get()->RemoveObserver(this);
+  arc::ArcBridgeService::Get()->intent_helper()->RemoveObserver(this);
 }
 
 Task::Type ArcProcessTask::GetType() const {
@@ -127,25 +127,25 @@
 
 void ArcProcessTask::Kill() {
   arc::mojom::ProcessInstance* arc_process_instance =
-      arc::ArcBridgeService::Get()->process_instance();
+      arc::ArcBridgeService::Get()->process()->instance();
   if (!arc_process_instance) {
     LOG(ERROR) << "ARC process instance is not ready.";
     return;
   }
-  if (arc::ArcBridgeService::Get()->process_version() < 1) {
+  if (arc::ArcBridgeService::Get()->process()->version() < 1) {
     LOG(ERROR) << "ARC KillProcess IPC is unavailable.";
     return;
   }
-  arc_process_instance->KillProcess(
-      nspid_, "Killed manually from Task Manager");
+  arc_process_instance->KillProcess(nspid_,
+                                    "Killed manually from Task Manager");
 }
 
-void ArcProcessTask::OnIntentHelperInstanceReady() {
+void ArcProcessTask::OnInstanceReady() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   VLOG(2) << "intent_helper instance is ready. Fetching the icon for "
           << package_name_;
-  arc::ArcBridgeService::Get()->RemoveObserver(this);
+  arc::ArcBridgeService::Get()->intent_helper()->RemoveObserver(this);
 
   // Instead of calling into StartIconLoading() directly, return to the main
   // loop first to make sure other ArcBridgeService observers are notified.
diff --git a/chrome/browser/task_management/providers/arc/arc_process_task.h b/chrome/browser/task_management/providers/arc/arc_process_task.h
index 9cae4d86..3edf6538 100644
--- a/chrome/browser/task_management/providers/arc/arc_process_task.h
+++ b/chrome/browser/task_management/providers/arc/arc_process_task.h
@@ -14,12 +14,15 @@
 #include "chrome/browser/task_management/providers/task.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/common/process.mojom.h"
+#include "components/arc/instance_holder.h"
 #include "components/arc/intent_helper/activity_icon_loader.h"
 
 namespace task_management {
 
 // Defines a task that represents an ARC process.
-class ArcProcessTask : public Task, public arc::ArcBridgeService::Observer {
+class ArcProcessTask
+    : public Task,
+      public arc::InstanceHolder<arc::mojom::IntentHelperInstance>::Observer {
  public:
   ArcProcessTask(base::ProcessId pid,
                  base::ProcessId nspid,
@@ -34,8 +37,8 @@
   bool IsKillable() override;
   void Kill() override;
 
-  // arc::ArcBridgeService::Observer:
-  void OnIntentHelperInstanceReady() override;
+  // arc::InstanceHolder<arc::mojom::IntentHelperInstance>::Observer:
+  void OnInstanceReady() override;
 
   void SetProcessState(arc::mojom::ProcessState process_state);
 
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index a982d5b9..031d9ae 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -484,7 +484,6 @@
       "//ui/views/controls/webview",
     ]
     deps += [
-      "//chrome/installer/util:strings",
       "//components/search_engines",
       "//google_update",
       "//third_party/iaccessible2",
diff --git a/chrome/browser/ui/app_list/app_context_menu.cc b/chrome/browser/ui/app_list/app_context_menu.cc
index 5836e8c..5e85a6e 100644
--- a/chrome/browser/ui/app_list/app_context_menu.cc
+++ b/chrome/browser/ui/app_list/app_context_menu.cc
@@ -84,8 +84,9 @@
   return true;
 }
 
-bool AppContextMenu::GetAcceleratorForCommandId(int command_id,
-                                                ui::Accelerator* accelerator) {
+bool AppContextMenu::GetAcceleratorForCommandId(
+    int command_id,
+    ui::Accelerator* accelerator) const {
   return false;
 }
 
diff --git a/chrome/browser/ui/app_list/app_context_menu.h b/chrome/browser/ui/app_list/app_context_menu.h
index 4d80cd2..aea36ff1 100644
--- a/chrome/browser/ui/app_list/app_context_menu.h
+++ b/chrome/browser/ui/app_list/app_context_menu.h
@@ -52,7 +52,7 @@
   bool IsCommandIdChecked(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
 
  protected:
diff --git a/chrome/browser/ui/app_list/app_list_view_delegate.cc b/chrome/browser/ui/app_list/app_list_view_delegate.cc
index 814fddb..37188e3ea 100644
--- a/chrome/browser/ui/app_list/app_list_view_delegate.cc
+++ b/chrome/browser/ui/app_list/app_list_view_delegate.cc
@@ -567,18 +567,6 @@
   }
 }
 
-void AppListViewDelegate::OpenSettings() {
-  const extensions::Extension* extension =
-      extensions::ExtensionRegistry::Get(profile_)->GetExtensionById(
-          extension_misc::kSettingsAppId,
-          extensions::ExtensionRegistry::EVERYTHING);
-  DCHECK(extension);
-  controller_->ActivateApp(profile_,
-                           extension,
-                           AppListControllerDelegate::LAUNCH_FROM_UNKNOWN,
-                           0);
-}
-
 void AppListViewDelegate::OpenHelp() {
   chrome::ScopedTabbedBrowserDisplayer displayer(profile_);
   content::OpenURLParams params(GURL(chrome::kAppLauncherHelpURL),
diff --git a/chrome/browser/ui/app_list/app_list_view_delegate.h b/chrome/browser/ui/app_list/app_list_view_delegate.h
index a1d4d2e1..3346029 100644
--- a/chrome/browser/ui/app_list/app_list_view_delegate.h
+++ b/chrome/browser/ui/app_list/app_list_view_delegate.h
@@ -101,7 +101,6 @@
   void ViewInitialized() override;
   void Dismiss() override;
   void ViewClosing() override;
-  void OpenSettings() override;
   void OpenHelp() override;
   void OpenFeedback() override;
   void StartSpeechRecognition() override;
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
index fa58150..823ce65d 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
@@ -108,9 +108,9 @@
 
   base::CreateDirectory(icon_path.DirName());
 
-  int wrote = base::WriteFile(icon_path,
-                              reinterpret_cast<const char*>(&content_png[0]),
-                              content_png.size());
+  int wrote =
+      base::WriteFile(icon_path, reinterpret_cast<const char*>(&content_png[0]),
+                      content_png.size());
   if (wrote != static_cast<int>(content_png.size())) {
     VLOG(2) << "Failed to write ARC icon file: " << icon_path.MaybeAsASCII()
             << ".";
@@ -234,6 +234,7 @@
   arc::ArcBridgeService* bridge_service = arc::ArcBridgeService::Get();
   DCHECK(bridge_service);
 
+  bridge_service->app()->AddObserver(this);
   bridge_service->AddObserver(this);
   if (!bridge_service->ready())
     OnBridgeStopped();
@@ -241,8 +242,10 @@
 
 ArcAppListPrefs::~ArcAppListPrefs() {
   arc::ArcBridgeService* bridge_service = arc::ArcBridgeService::Get();
-  if (bridge_service)
+  if (bridge_service) {
     bridge_service->RemoveObserver(this);
+    bridge_service->app()->RemoveObserver(this);
+  }
 
   arc::ArcAuthService* auth_service = arc::ArcAuthService::Get();
   if (auth_service)
@@ -258,35 +261,34 @@
     ui::ScaleFactor scale_factor) const {
   const base::FilePath app_path = GetAppPath(app_id);
   switch (scale_factor) {
-  case ui::SCALE_FACTOR_100P:
-    return app_path.AppendASCII("icon_100p.png");
-  case ui::SCALE_FACTOR_125P:
-    return app_path.AppendASCII("icon_125p.png");
-  case ui::SCALE_FACTOR_133P:
-    return app_path.AppendASCII("icon_133p.png");
-  case ui::SCALE_FACTOR_140P:
-    return app_path.AppendASCII("icon_140p.png");
-  case ui::SCALE_FACTOR_150P:
-    return app_path.AppendASCII("icon_150p.png");
-  case ui::SCALE_FACTOR_180P:
-    return app_path.AppendASCII("icon_180p.png");
-  case ui::SCALE_FACTOR_200P:
-    return app_path.AppendASCII("icon_200p.png");
-  case ui::SCALE_FACTOR_250P:
-    return app_path.AppendASCII("icon_250p.png");
-  case ui::SCALE_FACTOR_300P:
-    return app_path.AppendASCII("icon_300p.png");
-  default:
-    NOTREACHED();
-    return base::FilePath();
+    case ui::SCALE_FACTOR_100P:
+      return app_path.AppendASCII("icon_100p.png");
+    case ui::SCALE_FACTOR_125P:
+      return app_path.AppendASCII("icon_125p.png");
+    case ui::SCALE_FACTOR_133P:
+      return app_path.AppendASCII("icon_133p.png");
+    case ui::SCALE_FACTOR_140P:
+      return app_path.AppendASCII("icon_140p.png");
+    case ui::SCALE_FACTOR_150P:
+      return app_path.AppendASCII("icon_150p.png");
+    case ui::SCALE_FACTOR_180P:
+      return app_path.AppendASCII("icon_180p.png");
+    case ui::SCALE_FACTOR_200P:
+      return app_path.AppendASCII("icon_200p.png");
+    case ui::SCALE_FACTOR_250P:
+      return app_path.AppendASCII("icon_250p.png");
+    case ui::SCALE_FACTOR_300P:
+      return app_path.AppendASCII("icon_300p.png");
+    default:
+      NOTREACHED();
+      return base::FilePath();
   }
 }
 
 void ArcAppListPrefs::RequestIcon(const std::string& app_id,
                                   ui::ScaleFactor scale_factor) {
   if (!IsRegistered(app_id)) {
-    VLOG(2) << "Request to load icon for non-registered app: "
-            <<  app_id << ".";
+    VLOG(2) << "Request to load icon for non-registered app: " << app_id << ".";
     return;
   }
 
@@ -302,7 +304,7 @@
     NOTREACHED();
     return;
   }
-  arc::mojom::AppInstance* app_instance = bridge_service->app_instance();
+  arc::mojom::AppInstance* app_instance = bridge_service->app()->instance();
   if (!app_instance) {
     // AppInstance should be ready since we have app_id in ready_apps_.
     NOTREACHED();
@@ -311,7 +313,7 @@
 
   std::unique_ptr<AppInfo> app_info = GetApp(app_id);
   if (!app_info) {
-    VLOG(2) << "Failed to get app info: " <<  app_id << ".";
+    VLOG(2) << "Failed to get app info: " << app_id << ".";
     return;
   }
 
@@ -345,9 +347,9 @@
   // In case app is not ready, defer this request.
   if (!ready_apps_.count(app_id)) {
     SetNotificationsEnabledDeferred(prefs_).Put(app_id, enabled);
-    FOR_EACH_OBSERVER(Observer, observer_list_,
-                      OnNotificationsEnabledChanged(
-                          app_info->package_name, enabled));
+    FOR_EACH_OBSERVER(
+        Observer, observer_list_,
+        OnNotificationsEnabledChanged(app_info->package_name, enabled));
     return;
   }
 
@@ -357,14 +359,14 @@
     return;
   }
 
-  arc::mojom::AppInstance* app_instance = bridge_service->app_instance();
+  arc::mojom::AppInstance* app_instance = bridge_service->app()->instance();
   if (!app_instance) {
     // AppInstance should be ready since we have app_id in ready_apps_.
     NOTREACHED();
     return;
   }
 
-  if (bridge_service->app_version() < kSetNotificationsEnabledMinVersion) {
+  if (bridge_service->app()->version() < kSetNotificationsEnabledMinVersion) {
     VLOG(2) << "app version is too small to set notifications enabled.";
     return;
   }
@@ -425,8 +427,8 @@
 
   // crx_file::id_util is de-facto utility for id generation.
   const base::DictionaryValue* apps = prefs_->GetDictionary(prefs::kArcApps);
-  for (base::DictionaryValue::Iterator app_id(*apps);
-       !app_id.IsAtEnd(); app_id.Advance()) {
+  for (base::DictionaryValue::Iterator app_id(*apps); !app_id.IsAtEnd();
+       app_id.Advance()) {
     if (!crx_file::id_util::IdIsValid(app_id.key()))
       continue;
 
@@ -524,8 +526,7 @@
   std::set<std::string> old_ready_apps;
   old_ready_apps.swap(ready_apps_);
   for (auto& app_id : old_ready_apps) {
-    FOR_EACH_OBSERVER(Observer,
-                      observer_list_,
+    FOR_EACH_OBSERVER(Observer, observer_list_,
                       OnAppReadyChanged(app_id, false));
   }
 }
@@ -542,8 +543,7 @@
       NOTREACHED();
       continue;
     }
-    FOR_EACH_OBSERVER(Observer,
-                      observer_list_,
+    FOR_EACH_OBSERVER(Observer, observer_list_,
                       OnAppRegistered(app_id, *app_info));
   }
 
@@ -567,13 +567,13 @@
   DisableAllApps();
 }
 
-void ArcAppListPrefs::OnAppInstanceReady() {
+void ArcAppListPrefs::OnInstanceReady() {
   arc::ArcBridgeService* bridge_service = arc::ArcBridgeService::Get();
   if (!bridge_service) {
     NOTREACHED();
     return;
   }
-  arc::mojom::AppInstance* app_instance = bridge_service->app_instance();
+  arc::mojom::AppInstance* app_instance = bridge_service->app()->instance();
   if (!app_instance) {
     VLOG(2) << "Request to refresh app list when bridge service is not ready.";
     return;
@@ -583,7 +583,7 @@
   app_instance->RefreshAppList();
 }
 
-void ArcAppListPrefs::OnAppInstanceClosed() {
+void ArcAppListPrefs::OnInstanceClosed() {
   ready_apps_.clear();
 }
 
@@ -626,8 +626,7 @@
     ready_apps_.insert(app_id);
 
   if (was_registered) {
-    FOR_EACH_OBSERVER(Observer,
-                      observer_list_,
+    FOR_EACH_OBSERVER(Observer, observer_list_,
                       OnAppReadyChanged(app_id, true));
   } else {
     AppInfo app_info(name, package_name, activity, intent_uri, icon_resource_id,
@@ -674,14 +673,11 @@
   // app_id may be released by observers, get the path first.
   const base::FilePath app_path = GetAppPath(app_id);
 
-  FOR_EACH_OBSERVER(Observer,
-                    observer_list_,
-                    OnAppRemoved(app_id));
+  FOR_EACH_OBSERVER(Observer, observer_list_, OnAppRemoved(app_id));
 
   // Remove local data on file system.
   content::BrowserThread::GetBlockingPool()->PostTask(
-      FROM_HERE,
-      base::Bind(&DeleteAppFolderFromFileThread, app_path));
+      FROM_HERE, base::Bind(&DeleteAppFolderFromFileThread, app_path));
 }
 
 void ArcAppListPrefs::OnAppListRefreshed(
@@ -755,8 +751,8 @@
 void ArcAppListPrefs::OnPackageRemoved(const mojo::String& package_name) {
   const base::DictionaryValue* apps = prefs_->GetDictionary(prefs::kArcApps);
   std::vector<std::string> apps_to_remove;
-  for (base::DictionaryValue::Iterator app_it(*apps);
-       !app_it.IsAtEnd(); app_it.Advance()) {
+  for (base::DictionaryValue::Iterator app_it(*apps); !app_it.IsAtEnd();
+       app_it.Advance()) {
     const base::Value* value = &app_it.value();
     const base::DictionaryValue* app;
     if (!value->GetAsDictionary(&app)) {
@@ -817,8 +813,7 @@
 void ArcAppListPrefs::OnTaskCreated(int32_t task_id,
                                     const mojo::String& package_name,
                                     const mojo::String& activity) {
-  FOR_EACH_OBSERVER(Observer,
-                    observer_list_,
+  FOR_EACH_OBSERVER(Observer, observer_list_,
                     OnTaskCreated(task_id, package_name, activity));
 }
 
@@ -831,10 +826,11 @@
 }
 
 void ArcAppListPrefs::OnNotificationsEnabledChanged(
-    const mojo::String& package_name, bool enabled) {
+    const mojo::String& package_name,
+    bool enabled) {
   const base::DictionaryValue* apps = prefs_->GetDictionary(prefs::kArcApps);
-  for (base::DictionaryValue::Iterator app(*apps);
-       !app.IsAtEnd(); app.Advance()) {
+  for (base::DictionaryValue::Iterator app(*apps); !app.IsAtEnd();
+       app.Advance()) {
     const base::DictionaryValue* app_dict;
     std::string app_package_name;
     if (!app.value().GetAsDictionary(&app_dict) ||
@@ -902,17 +898,12 @@
                                   ui::ScaleFactor scale_factor,
                                   const std::vector<uint8_t>& content_png) {
   base::FilePath icon_path = GetIconPath(app_id, scale_factor);
-  base::PostTaskAndReplyWithResult(content::BrowserThread::GetBlockingPool(),
-                                   FROM_HERE,
-                                   base::Bind(&InstallIconFromFileThread,
-                                              app_id,
-                                              scale_factor,
-                                              icon_path,
-                                              content_png),
-                                   base::Bind(&ArcAppListPrefs::OnIconInstalled,
-                                              weak_ptr_factory_.GetWeakPtr(),
-                                              app_id,
-                                              scale_factor));
+  base::PostTaskAndReplyWithResult(
+      content::BrowserThread::GetBlockingPool(), FROM_HERE,
+      base::Bind(&InstallIconFromFileThread, app_id, scale_factor, icon_path,
+                 content_png),
+      base::Bind(&ArcAppListPrefs::OnIconInstalled,
+                 weak_ptr_factory_.GetWeakPtr(), app_id, scale_factor));
 }
 
 void ArcAppListPrefs::OnIconInstalled(const std::string& app_id,
@@ -922,8 +913,7 @@
   if (!install_succeed)
     return;
 
-  FOR_EACH_OBSERVER(Observer,
-                    observer_list_,
+  FOR_EACH_OBSERVER(Observer, observer_list_,
                     OnAppIconUpdated(app_id, scale_factor));
 }
 
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h
index 173843c5..2fccad76 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h
+++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h
@@ -21,6 +21,7 @@
 #include "chrome/browser/chromeos/arc/arc_auth_service.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/common/app.mojom.h"
+#include "components/arc/instance_holder.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "ui/base/layout.h"
@@ -44,10 +45,12 @@
 // information is used to pre-create non-ready app items while ARC bridge
 // service is not ready to provide information about available ARC apps.
 // NOTE: ArcAppListPrefs is only created for the primary user.
-class ArcAppListPrefs : public KeyedService,
-                        public arc::mojom::AppHost,
-                        public arc::ArcBridgeService::Observer,
-                        public arc::ArcAuthService::Observer {
+class ArcAppListPrefs
+    : public KeyedService,
+      public arc::mojom::AppHost,
+      public arc::ArcBridgeService::Observer,
+      public arc::InstanceHolder<arc::mojom::AppInstance>::Observer,
+      public arc::ArcAuthService::Observer {
  public:
   struct AppInfo {
     AppInfo(const std::string& name,
@@ -207,8 +210,10 @@
 
   // arc::ArcBridgeService::Observer:
   void OnBridgeStopped() override;
-  void OnAppInstanceReady() override;
-  void OnAppInstanceClosed() override;
+
+  // arc::InstanceHolder<arc::mojom::AppInstance>::Observer:
+  void OnInstanceReady() override;
+  void OnInstanceClosed() override;
 
   // arc::mojom::AppHost:
   void OnAppListRefreshed(mojo::Array<arc::mojom::AppInfoPtr> apps) override;
diff --git a/chrome/browser/ui/app_list/arc/arc_app_utils.cc b/chrome/browser/ui/app_list/arc/arc_app_utils.cc
index 273c104..651bbb8 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_utils.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_utils.cc
@@ -53,14 +53,14 @@
     return nullptr;
   }
 
-  arc::mojom::AppInstance* app_instance = bridge_service->app_instance();
+  arc::mojom::AppInstance* app_instance = bridge_service->app()->instance();
   if (!app_instance) {
     VLOG(2) << "Request to " << service_name
             << " when mojom::app_instance is not ready.";
     return nullptr;
   }
 
-  int bridge_version = bridge_service->app_version();
+  int bridge_version = bridge_service->app()->version();
   if (bridge_version < required_version) {
     VLOG(2) << "Request to " << service_name << " when Arc version "
             << bridge_version << " does not support it.";
@@ -109,10 +109,8 @@
  public:
   LaunchAppWithoutSize(content::BrowserContext* context,
                        const std::string& app_id,
-                       bool landscape_mode) :
-      context_(context),
-      app_id_(app_id),
-      landscape_mode_(landscape_mode) {}
+                       bool landscape_mode)
+      : context_(context), app_id_(app_id), landscape_mode_(landscape_mode) {}
 
   // This will launch the request and after the return the creator does not
   // need to delete the object anymore.
@@ -130,7 +128,8 @@
     // capability flags like [PHONE/TABLET]_[LANDSCAPE/PORTRAIT] and which
     // might also return the used DP->PIX conversion constant to do better
     // size calculations.
-    bool result = CanHandleResolution(context_, app_id_, landscape_,
+    bool result = CanHandleResolution(
+        context_, app_id_, landscape_,
         base::Bind(&LaunchAppWithoutSize::Callback, base::Unretained(this)));
     if (!result)
       delete this;
@@ -200,9 +199,8 @@
 }
 
 bool LaunchAndroidSettingsApp(content::BrowserContext* context) {
-  return arc::LaunchApp(context,
-                        kSettingsAppId,
-                        true);  // landscape_layout
+  constexpr bool kUseLandscapeLayout = true;
+  return arc::LaunchApp(context, kSettingsAppId, kUseLandscapeLayout);
 }
 
 bool LaunchApp(content::BrowserContext* context, const std::string& app_id) {
@@ -225,15 +223,14 @@
     return true;
   }
 
-  return (new LaunchAppWithoutSize(context,
-                                   app_id,
-                                   landscape_layout))->LaunchAndRelease();
+  return (new LaunchAppWithoutSize(context, app_id, landscape_layout))
+      ->LaunchAndRelease();
 }
 
 bool CanHandleResolution(content::BrowserContext* context,
-    const std::string& app_id,
-    const gfx::Rect& rect,
-    const CanHandleResolutionCallback& callback) {
+                         const std::string& app_id,
+                         const gfx::Rect& rect,
+                         const CanHandleResolutionCallback& callback) {
   const ArcAppListPrefs* prefs = ArcAppListPrefs::Get(context);
   DCHECK(prefs);
   std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = prefs->GetApp(app_id);
diff --git a/chrome/browser/ui/app_list/search/search_controller_factory.cc b/chrome/browser/ui/app_list/search/search_controller_factory.cc
index 3776d469..bbe518c 100644
--- a/chrome/browser/ui/app_list/search/search_controller_factory.cc
+++ b/chrome/browser/ui/app_list/search/search_controller_factory.cc
@@ -34,7 +34,6 @@
 
 // Maximum number of results to show in each mixer group.
 const size_t kMaxAppsGroupResults = 4;
-// Ignored unless AppListMixer field trial is "Blended".
 const size_t kMaxOmniboxResults = 4;
 const size_t kMaxWebstoreResults = 2;
 const size_t kMaxSuggestionsResults = 6;
@@ -67,18 +66,12 @@
                            HistoryFactory::GetForBrowserContext(profile)));
 
   // Add mixer groups. There are three main groups: apps, webstore and
-  // omnibox. The behaviour depends on the AppListMixer field trial:
-  // - If default: The apps and webstore groups each have a fixed
-  //   maximum number of results. The omnibox group fills the remaining slots
-  //   (with a minimum of one result).
-  // - If "Blended": Each group has a "soft" maximum number of results. However,
-  //   if a query turns up very few results, the mixer may take more than this
-  //   maximum from a particular group.
-  size_t apps_group_id = controller->AddGroup(kMaxAppsGroupResults, 3.0, 1.0);
-  size_t omnibox_group_id =
-      controller->AddOmniboxGroup(kMaxOmniboxResults, 2.0, 1.0);
-  size_t webstore_group_id =
-      controller->AddGroup(kMaxWebstoreResults, 1.0, 0.4);
+  // omnibox. Each group has a "soft" maximum number of results. However, if
+  // a query turns up very few results, the mixer may take more than this
+  // maximum from a particular group.
+  size_t apps_group_id = controller->AddGroup(kMaxAppsGroupResults, 1.0);
+  size_t omnibox_group_id = controller->AddGroup(kMaxOmniboxResults, 1.0);
+  size_t webstore_group_id = controller->AddGroup(kMaxWebstoreResults, 0.4);
 
   // Add search providers.
   controller->AddProvider(
@@ -94,7 +87,7 @@
                               new WebstoreProvider(profile, list_controller)));
   if (IsSuggestionsSearchProviderEnabled()) {
     size_t suggestions_group_id =
-        controller->AddGroup(kMaxSuggestionsResults, 3.0, 1.0);
+        controller->AddGroup(kMaxSuggestionsResults, 1.0);
     controller->AddProvider(
         suggestions_group_id,
         std::unique_ptr<SearchProvider>(
@@ -107,7 +100,7 @@
   if (app_list::switches::IsDriveSearchInChromeLauncherEnabled() &&
       !profile->IsGuestSession()) {
     size_t search_api_group_id =
-        controller->AddGroup(kMaxLauncherSearchResults, 0.0, 1.0);
+        controller->AddGroup(kMaxLauncherSearchResults, 1.0);
     controller->AddProvider(
         search_api_group_id,
         std::unique_ptr<SearchProvider>(new LauncherSearchProvider(profile)));
diff --git a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc
index cf5a14a7..ae4fedff 100644
--- a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc
+++ b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc
@@ -3,8 +3,11 @@
 // found in the LICENSE file.
 #include "chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.h"
 
+#include <string>
+
 #include "ash/common/wm/maximize_mode/maximize_mode_controller.h"
 #include "ash/common/wm/window_state.h"
+#include "ash/common/wm_lookup.h"
 #include "ash/common/wm_shell.h"
 #include "ash/display/display_manager.h"
 #include "ash/display/screen_orientation_controller_chromeos.h"
@@ -211,15 +214,15 @@
   arc::mojom::AppInstance* GetAppInstance() {
     arc::ArcBridgeService* bridge_service = arc::ArcBridgeService::Get();
     arc::mojom::AppInstance* app_instance =
-        bridge_service ? bridge_service->app_instance() : nullptr;
+        bridge_service ? bridge_service->app()->instance() : nullptr;
     if (!app_instance) {
       VLOG(2) << "Arc Bridge is not available.";
       return nullptr;
     }
 
-    if (bridge_service->app_version() < 3) {
+    if (bridge_service->app()->version() < 3) {
       VLOG(2) << "Arc Bridge has old version for apps."
-              << bridge_service->app_version();
+              << bridge_service->app()->version();
       return nullptr;
     }
     return app_instance;
@@ -580,8 +583,8 @@
 
 void ArcAppWindowLauncherController::SetOrientationLockForAppWindow(
     AppWindow* app_window) {
-  ash::Shell* shell = ash::Shell::GetInstance();
-  aura::Window* window = app_window->widget()->GetNativeWindow();
+  ash::WmWindow* window =
+      ash::WmLookup::Get()->GetWindowForWidget(app_window->widget());
   if (!window)
     return;
   arc::mojom::OrientationLock orientation_lock;
@@ -602,6 +605,7 @@
     app_window->set_requested_orientation_lock(orientation_lock);
   }
 
+  ash::Shell* shell = ash::Shell::GetInstance();
   shell->screen_orientation_controller()->LockOrientationForWindow(
       window, BlinkOrientationLockFromMojom(orientation_lock));
 }
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 929bc24..984adf5 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc
@@ -1669,7 +1669,12 @@
 // ash::WindowTreeHostManager::Observer:
 
 void ChromeLauncherControllerImpl::OnDisplayConfigurationChanged() {
-  SetShelfBehaviorsFromPrefs();
+  // In BOTTOM_LOCKED state, ignore the call of SetShelfBehaviorsFromPrefs.
+  // Because it might be called by some operations, like crbug.com/627040
+  // rotating screen.
+  ash::Shelf* shelf = ash::Shelf::ForPrimaryDisplay();
+  if (!shelf || shelf->alignment() != ash::SHELF_ALIGNMENT_BOTTOM_LOCKED)
+    SetShelfBehaviorsFromPrefs();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.cc b/chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.cc
index dbc2535..7f89b3a 100644
--- a/chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.cc
+++ b/chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.cc
@@ -48,7 +48,7 @@
 
 bool LauncherApplicationMenuItemModel::GetAcceleratorForCommandId(
     int command_id,
-    ui::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) const {
   return false;
 }
 
diff --git a/chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.h b/chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.h
index ba9b533..583554b 100644
--- a/chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.h
+++ b/chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.h
@@ -33,7 +33,7 @@
   bool IsCommandIdChecked(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
 
  private:
diff --git a/chrome/browser/ui/ash/launcher/launcher_context_menu.cc b/chrome/browser/ui/ash/launcher/launcher_context_menu.cc
index f050a3b5..388f3aa 100644
--- a/chrome/browser/ui/ash/launcher/launcher_context_menu.cc
+++ b/chrome/browser/ui/ash/launcher/launcher_context_menu.cc
@@ -109,8 +109,8 @@
 }
 
 bool LauncherContextMenu::GetAcceleratorForCommandId(
-      int command_id,
-      ui::Accelerator* accelerator) {
+    int command_id,
+    ui::Accelerator* accelerator) const {
   return false;
 }
 
diff --git a/chrome/browser/ui/ash/launcher/launcher_context_menu.h b/chrome/browser/ui/ash/launcher/launcher_context_menu.h
index 773ddeb..8a380db9 100644
--- a/chrome/browser/ui/ash/launcher/launcher_context_menu.h
+++ b/chrome/browser/ui/ash/launcher/launcher_context_menu.h
@@ -36,7 +36,7 @@
   bool IsCommandIdChecked(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
 
  protected:
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_context_menu_chromeos.cc b/chrome/browser/ui/ash/multi_user/multi_user_context_menu_chromeos.cc
index 702517f..df2cbebc 100644
--- a/chrome/browser/ui/ash/multi_user/multi_user_context_menu_chromeos.cc
+++ b/chrome/browser/ui/ash/multi_user/multi_user_context_menu_chromeos.cc
@@ -41,7 +41,7 @@
   bool IsCommandIdChecked(int command_id) const override { return false; }
   bool IsCommandIdEnabled(int command_id) const override { return true; }
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override {
+                                  ui::Accelerator* accelerator) const override {
     return false;
   }
   void ExecuteCommand(int command_id, int event_flags) override;
diff --git a/chrome/browser/ui/autofill/autofill_dialog_models.cc b/chrome/browser/ui/autofill/autofill_dialog_models.cc
index 036e5ce..b2fbce6 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_models.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_models.cc
@@ -112,7 +112,7 @@
 
 bool SuggestionsMenuModel::GetAcceleratorForCommandId(
     int command_id,
-    ui::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) const {
   return false;
 }
 
diff --git a/chrome/browser/ui/autofill/autofill_dialog_models.h b/chrome/browser/ui/autofill/autofill_dialog_models.h
index 3b5b33d..101a1743 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_models.h
+++ b/chrome/browser/ui/autofill/autofill_dialog_models.h
@@ -85,7 +85,7 @@
   bool IsCommandIdChecked(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
 
  private:
diff --git a/chrome/browser/ui/bluetooth/bluetooth_chooser_controller.cc b/chrome/browser/ui/bluetooth/bluetooth_chooser_controller.cc
index 447778f1..0998ec1 100644
--- a/chrome/browser/ui/bluetooth/bluetooth_chooser_controller.cc
+++ b/chrome/browser/ui/bluetooth/bluetooth_chooser_controller.cc
@@ -33,6 +33,11 @@
 
 BluetoothChooserController::~BluetoothChooserController() {}
 
+base::string16 BluetoothChooserController::GetOkButtonLabel() const {
+  return l10n_util::GetStringUTF16(
+      IDS_BLUETOOTH_DEVICE_CHOOSER_PAIR_BUTTON_TEXT);
+}
+
 size_t BluetoothChooserController::NumOptions() const {
   return device_names_and_ids_.size();
 }
diff --git a/chrome/browser/ui/bluetooth/bluetooth_chooser_controller.h b/chrome/browser/ui/bluetooth/bluetooth_chooser_controller.h
index 0ec12e9..deb2caa 100644
--- a/chrome/browser/ui/bluetooth/bluetooth_chooser_controller.h
+++ b/chrome/browser/ui/bluetooth/bluetooth_chooser_controller.h
@@ -28,6 +28,7 @@
   ~BluetoothChooserController() override;
 
   // ChooserController:
+  base::string16 GetOkButtonLabel() const override;
   size_t NumOptions() const override;
   base::string16 GetOption(size_t index) const override;
   void Select(size_t index) override;
diff --git a/chrome/browser/ui/bookmarks/bookmark_context_menu_controller.cc b/chrome/browser/ui/bookmarks/bookmark_context_menu_controller.cc
index cb8461f..d05b36e 100644
--- a/chrome/browser/ui/bookmarks/bookmark_context_menu_controller.cc
+++ b/chrome/browser/ui/bookmarks/bookmark_context_menu_controller.cc
@@ -434,7 +434,7 @@
 
 bool BookmarkContextMenuController::GetAcceleratorForCommandId(
     int command_id,
-    ui::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) const {
   return false;
 }
 
diff --git a/chrome/browser/ui/bookmarks/bookmark_context_menu_controller.h b/chrome/browser/ui/bookmarks/bookmark_context_menu_controller.h
index 274cdd0..c020f733 100644
--- a/chrome/browser/ui/bookmarks/bookmark_context_menu_controller.h
+++ b/chrome/browser/ui/bookmarks/bookmark_context_menu_controller.h
@@ -68,7 +68,7 @@
   bool IsCommandIdEnabled(int command_id) const override;
   bool IsCommandIdVisible(int command_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
   bool IsItemForCommandIdDynamic(int command_id) const override;
   base::string16 GetLabelForCommandId(int command_id) const override;
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index 0e77ef3b..3951954 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -68,6 +68,7 @@
 #include "chrome/browser/memory/tab_manager_web_contents_data.h"
 #include "chrome/browser/notifications/notification_ui_manager.h"
 #include "chrome/browser/pepper_broker_infobar_delegate.h"
+#include "chrome/browser/permissions/permission_request_manager.h"
 #include "chrome/browser/prefs/incognito_mode_prefs.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_destroyer.h"
@@ -143,7 +144,6 @@
 #include "chrome/browser/ui/unload_controller.h"
 #include "chrome/browser/ui/validation_message_bubble.h"
 #include "chrome/browser/ui/website_settings/chooser_bubble_delegate.h"
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
 #include "chrome/browser/ui/webui/signin/login_ui_service.h"
 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
 #include "chrome/browser/ui/window_sizer/window_sizer.h"
@@ -1763,10 +1763,10 @@
     window_->GetLocationBar()->UpdateContentSettingsIcons();
   }
 
-  PermissionBubbleManager* bubble_manager =
-      PermissionBubbleManager::FromWebContents(web_contents);
-  if (bubble_manager) {
-    bubble_manager->AddRequest(
+  PermissionRequestManager* permission_request_manager =
+      PermissionRequestManager::FromWebContents(web_contents);
+  if (permission_request_manager) {
+    permission_request_manager->AddRequest(
         new RegisterProtocolHandlerPermissionRequest(registry, handler,
                                                      url, user_gesture));
   }
diff --git a/chrome/browser/ui/browser_instant_controller.cc b/chrome/browser/ui/browser_instant_controller.cc
index 1a95c98..08b8d6f 100644
--- a/chrome/browser/ui/browser_instant_controller.cc
+++ b/chrome/browser/ui/browser_instant_controller.cc
@@ -154,8 +154,6 @@
 }
 
 void BrowserInstantController::TabDeactivated(content::WebContents* contents) {
-  instant_.TabDeactivated(contents);
-
   InstantSearchPrerenderer* prerenderer =
       GetInstantSearchPrerenderer(profile());
   if (prerenderer)
diff --git a/chrome/browser/ui/cocoa/app_menu/app_menu_controller.mm b/chrome/browser/ui/cocoa/app_menu/app_menu_controller.mm
index 36818e2..bc4f35f 100644
--- a/chrome/browser/ui/cocoa/app_menu/app_menu_controller.mm
+++ b/chrome/browser/ui/cocoa/app_menu/app_menu_controller.mm
@@ -79,8 +79,9 @@
 // A C++ delegate that handles the accelerators in the app menu.
 class AcceleratorDelegate : public ui::AcceleratorProvider {
  public:
-  bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* out_accelerator) override {
+  bool GetAcceleratorForCommandId(
+      int command_id,
+      ui::Accelerator* out_accelerator) const override {
     AcceleratorsCocoa* keymap = AcceleratorsCocoa::GetInstance();
     const ui::Accelerator* accelerator =
         keymap->GetAcceleratorForCommand(command_id);
diff --git a/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.h b/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.h
index 850e275..e8dffcb 100644
--- a/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.h
+++ b/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.h
@@ -72,7 +72,7 @@
 
   // ui::AcceleratorProvider:
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
 
   // ExclusiveAccessBubbleViewsContext:
   ExclusiveAccessManager* GetExclusiveAccessManager() override;
diff --git a/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.mm b/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.mm
index a3498ae..75f67caf 100644
--- a/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.mm
+++ b/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.mm
@@ -154,7 +154,7 @@
 
 bool ExclusiveAccessController::GetAcceleratorForCommandId(
     int cmd_id,
-    ui::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) const {
   *accelerator =
       *AcceleratorsCocoa::GetInstance()->GetAcceleratorForCommand(cmd_id);
   return true;
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm
index 0f9b729..fe57b6095 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller.mm
+++ b/chrome/browser/ui/cocoa/browser_window_controller.mm
@@ -21,6 +21,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/devtools/devtools_window.h"
 #include "chrome/browser/extensions/extension_commands_global_registry.h"
+#include "chrome/browser/permissions/permission_request_manager.h"
 #include "chrome/browser/profiles/avatar_menu.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_attributes_storage.h"
@@ -77,7 +78,6 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/tabs/tab_strip_model_delegate.h"
 #include "chrome/browser/ui/translate/translate_bubble_model_impl.h"
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
 #include "chrome/browser/ui/window_sizer/window_sizer.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/command.h"
@@ -1016,15 +1016,15 @@
 - (void)onActiveTabChanged:(content::WebContents*)oldContents
                         to:(content::WebContents*)newContents {
   // No need to remove previous bubble. It will close itself.
-  PermissionBubbleManager* manager(nullptr);
+  PermissionRequestManager* manager(nullptr);
   if (oldContents) {
-    manager = PermissionBubbleManager::FromWebContents(oldContents);
+    manager = PermissionRequestManager::FromWebContents(oldContents);
     if (manager)
       manager->HideBubble();
   }
 
   if (newContents) {
-    manager = PermissionBubbleManager::FromWebContents(newContents);
+    manager = PermissionRequestManager::FromWebContents(newContents);
     if (manager)
       manager->DisplayPendingRequests();
   }
@@ -1634,7 +1634,7 @@
 }
 
 - (void)dismissPermissionBubble {
-  PermissionBubbleManager* manager = [self permissionBubbleManager];
+  PermissionRequestManager* manager = [self permissionRequestManager];
   if (manager)
     manager->HideBubble();
 }
diff --git a/chrome/browser/ui/cocoa/browser_window_controller_private.h b/chrome/browser/ui/cocoa/browser_window_controller_private.h
index 61a96e86..d754669 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller_private.h
+++ b/chrome/browser/ui/cocoa/browser_window_controller_private.h
@@ -10,7 +10,7 @@
 #import "chrome/browser/ui/cocoa/fullscreen_toolbar_controller.h"
 
 @class BrowserWindowLayout;
-class PermissionBubbleManager;
+class PermissionRequestManager;
 
 namespace content {
 class WebContents;
@@ -176,7 +176,7 @@
 - (void)resetCustomAppKitFullscreenVariables;
 
 - (content::WebContents*)webContents;
-- (PermissionBubbleManager*)permissionBubbleManager;
+- (PermissionRequestManager*)permissionRequestManager;
 
 // Hides or unhides any displayed modal sheet for fullscreen transition.
 // Modal sheets should be hidden at the beginning and then shown at the end.
diff --git a/chrome/browser/ui/cocoa/browser_window_controller_private.mm b/chrome/browser/ui/cocoa/browser_window_controller_private.mm
index 0eba308..bc844c8 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller_private.mm
+++ b/chrome/browser/ui/cocoa/browser_window_controller_private.mm
@@ -15,6 +15,7 @@
 #import "base/mac/sdk_forward_declarations.h"
 #include "base/metrics/histogram.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/permissions/permission_request_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
 #include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h"
@@ -45,7 +46,6 @@
 #import "chrome/browser/ui/cocoa/website_settings/permission_bubble_cocoa.h"
 #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
 #include "chrome/common/chrome_switches.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/scoped_user_pref_update.h"
@@ -268,7 +268,7 @@
 
   // Will update the location of the permission bubble when showing/hiding the
   // top level toolbar in fullscreen.
-  PermissionBubbleManager* manager = [self permissionBubbleManager];
+  PermissionRequestManager* manager = [self permissionRequestManager];
   if (manager)
     manager->UpdateAnchorPosition();
 
@@ -421,7 +421,7 @@
     statusBubble_->SwitchParentWindow(destWindow);
 
   // Updates the bubble position.
-  PermissionBubbleManager* manager = [self permissionBubbleManager];
+  PermissionRequestManager* manager = [self permissionRequestManager];
   if (manager)
     manager->UpdateAnchorPosition();
 
@@ -468,7 +468,7 @@
   BOOL showDropdown =
       !fullscreenForTab && !kioskMode && ([self floatingBarHasFocus]);
 
-  PermissionBubbleManager* manager = [self permissionBubbleManager];
+  PermissionRequestManager* manager = [self permissionRequestManager];
   if (manager && manager->IsBubbleVisible()) {
     NSWindow* bubbleWindow = manager->GetBubbleWindow();
     DCHECK(bubbleWindow);
@@ -815,7 +815,7 @@
   [self resetCustomAppKitFullscreenVariables];
 
   // Ensures that the permission bubble shows up properly at the front.
-  PermissionBubbleManager* manager = [self permissionBubbleManager];
+  PermissionRequestManager* manager = [self permissionRequestManager];
   if (manager && manager->IsBubbleVisible()) {
     NSWindow* bubbleWindow = manager->GetBubbleWindow();
     DCHECK(bubbleWindow);
@@ -1274,9 +1274,9 @@
   return browser_->tab_strip_model()->GetActiveWebContents();
 }
 
-- (PermissionBubbleManager*)permissionBubbleManager {
+- (PermissionRequestManager*)permissionRequestManager {
   if (WebContents* contents = [self webContents])
-    return PermissionBubbleManager::FromWebContents(contents);
+    return PermissionRequestManager::FromWebContents(contents);
   return nil;
 }
 
diff --git a/chrome/browser/ui/cocoa/chooser_content_view_cocoa.mm b/chrome/browser/ui/cocoa/chooser_content_view_cocoa.mm
index 73a7379f..d97c3ef 100644
--- a/chrome/browser/ui/cocoa/chooser_content_view_cocoa.mm
+++ b/chrome/browser/ui/cocoa/chooser_content_view_cocoa.mm
@@ -264,7 +264,7 @@
 
 - (base::scoped_nsobject<NSButton>)createConnectButton {
   NSString* connectTitle =
-      l10n_util::GetNSString(IDS_DEVICE_CHOOSER_CONNECT_BUTTON_TEXT);
+      base::SysUTF16ToNSString(chooserController_->GetOkButtonLabel());
   return [self createButtonWithTitle:connectTitle];
 }
 
diff --git a/chrome/browser/ui/cocoa/extensions/chooser_dialog_cocoa_controller.mm b/chrome/browser/ui/cocoa/extensions/chooser_dialog_cocoa_controller.mm
index 668929e1..0ef8a21 100644
--- a/chrome/browser/ui/cocoa/extensions/chooser_dialog_cocoa_controller.mm
+++ b/chrome/browser/ui/cocoa/extensions/chooser_dialog_cocoa_controller.mm
@@ -5,17 +5,9 @@
 #import "chrome/browser/ui/cocoa/extensions/chooser_dialog_cocoa_controller.h"
 
 #include "base/strings/sys_string_conversions.h"
-#include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/chooser_controller/chooser_controller.h"
 #import "chrome/browser/ui/cocoa/chooser_content_view_cocoa.h"
 #import "chrome/browser/ui/cocoa/extensions/chooser_dialog_cocoa.h"
-#include "chrome/grit/generated_resources.h"
-#include "components/url_formatter/elide_url.h"
-#include "content/public/browser/web_contents.h"
-#include "extensions/browser/extension_registry.h"
-#import "ui/base/l10n/l10n_util_mac.h"
-#include "url/gurl.h"
-#include "url/origin.h"
 
 @implementation ChooserDialogCocoaController
 
@@ -28,28 +20,9 @@
   if ((self = [super init]))
     chooserDialogCocoa_ = chooserDialogCocoa;
 
-  base::string16 chooserTitle;
-  url::Origin origin = chooserController->GetOrigin();
-  content::WebContents* web_contents = chooserDialogCocoa_->web_contents();
-  content::BrowserContext* browser_context = web_contents->GetBrowserContext();
-  extensions::ExtensionRegistry* extension_registry =
-      extensions::ExtensionRegistry::Get(browser_context);
-  if (extension_registry) {
-    const extensions::Extension* extension =
-        extension_registry->enabled_extensions().GetExtensionOrAppByURL(
-            GURL(origin.Serialize()));
-    if (extension)
-      chooserTitle = base::UTF8ToUTF16(extension->name());
-  }
-
-  if (chooserTitle.empty()) {
-    chooserTitle = url_formatter::FormatOriginForSecurityDisplay(
-        origin, url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC);
-  }
-
+  base::string16 chooserTitle = chooserController->GetTitle();
   chooserContentView_.reset([[ChooserContentViewCocoa alloc]
-      initWithChooserTitle:l10n_util::GetNSStringF(IDS_DEVICE_CHOOSER_PROMPT,
-                                                   chooserTitle)
+      initWithChooserTitle:base::SysUTF16ToNSString(chooserTitle)
          chooserController:std::move(chooserController)]);
 
   tableView_ = [chooserContentView_ tableView];
diff --git a/chrome/browser/ui/cocoa/passwords/signin_promo_view_controller.mm b/chrome/browser/ui/cocoa/passwords/signin_promo_view_controller.mm
index 769992b..83ceb3c 100644
--- a/chrome/browser/ui/cocoa/passwords/signin_promo_view_controller.mm
+++ b/chrome/browser/ui/cocoa/passwords/signin_promo_view_controller.mm
@@ -9,6 +9,7 @@
 #import "chrome/browser/ui/cocoa/hover_close_button.h"
 #include "chrome/browser/ui/cocoa/passwords/passwords_bubble_utils.h"
 #include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h"
+#include "content/public/browser/user_metrics.h"
 #include "grit/generated_resources.h"
 #import "ui/base/cocoa/controls/hyperlink_text_view.h"
 #include "ui/base/l10n/l10n_util_mac.h"
@@ -99,6 +100,8 @@
   [_closeButton setFrameOrigin:closeButtonOrigin];
   [view setFrame:NSMakeRect(0, 0, kDesiredBubbleWidth, height)];
   [self setView:view];
+  content::RecordAction(
+      base::UserMetricsAction("Signin_Impression_FromPasswordBubble"));
 }
 
 - (void)onSignInClicked:(id)sender {
diff --git a/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.h b/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.h
index 94b9fd9f..ef790db 100644
--- a/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.h
+++ b/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.h
@@ -34,7 +34,7 @@
  protected:
   // RenderViewContextMenu implementation.
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   void AppendPlatformEditableItems() override;
 
  private:
diff --git a/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.mm b/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.mm
index 21963a0..833b3317 100644
--- a/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.mm
+++ b/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.mm
@@ -333,7 +333,7 @@
 
 bool RenderViewContextMenuMac::GetAcceleratorForCommandId(
     int command_id,
-    ui::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) const {
   return false;
 }
 
diff --git a/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h b/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h
index d729f79..3801260 100644
--- a/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h
+++ b/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h
@@ -20,10 +20,9 @@
 // display of the WebContents view.
 //
 // Client code that inserts [controller view] into the view hierarchy needs to
-// beforehand call the |-ensureContentsSizeDoesNotChange| method. This will
-// avoid multiple resize messages being sent to the renderer and triggering
-// redundant and costly layouts. After the view has been inserted, client code
-// calls |-ensureContentsVisible| to display the WebContents view.
+// call -ensureContentsVisibleInSuperview:(NSView*)superview to match the
+// container to the [superview bounds] and avoid multiple resize messages being
+// sent to the renderer, which triggers redundant and costly layouts.
 //
 // AutoEmbedFullscreen mode: When enabled, TabContentsController will observe
 // for WebContents fullscreen changes and automatically swap the normal
@@ -57,15 +56,10 @@
 // Create the contents of a tab represented by |contents|.
 - (id)initWithContents:(content::WebContents*)contents isPopup:(BOOL)popup;
 
-// Call when the container view owned by TabContentsController is about to be
-// resized and inserted into the view hierarchy, so as to not trigger
-// unnecessary content re-layout.
-- (void)ensureContentsSizeDoesNotChange;
-
-// Call after the container view is inserted into the view hierarchy and
-// properly sized. Then, this method will select either the WebContents view or
-// the fullscreen view and swap it into the view hierarchy for display.
-- (void)ensureContentsVisible;
+// Call to insert the container view into the view hierarchy, sizing it to match
+// |superview|. Then, this method will select either the WebContents view or
+// the fullscreen view and swap it into the container for display.
+- (void)ensureContentsVisibleInSuperview:(NSView*)superview;
 
 // Called after we enter fullscreen to ensure that the fullscreen widget will
 // have the right frame.
diff --git a/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm b/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm
index 706f370..5bf3298 100644
--- a/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm
+++ b/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm
@@ -71,9 +71,9 @@
 
 @interface TabContentsController (TabContentsContainerViewDelegate)
 - (BOOL)contentsInFullscreenCaptureMode;
-// Computes and returns the frame to use for the contents view within the
-// container view.
-- (NSRect)frameForContentsView;
+// Computes and returns the frame to use for the contents view using the size of
+// |container| as the target size.
+- (NSRect)frameForContentsViewIn:(NSView*)container;
 
 // Returns YES if the content view should be resized.
 - (BOOL)shouldResizeContentView;
@@ -130,7 +130,7 @@
   }
 
   ScopedCAActionDisabler disabler;
-  [contentsView setFrame:[delegate_ frameForContentsView]];
+  [contentsView setFrame:[delegate_ frameForContentsViewIn:self]];
 }
 
 // Update the background layer's color whenever the view needs to repaint.
@@ -217,18 +217,10 @@
   [self setView:view];
 }
 
-- (void)ensureContentsSizeDoesNotChange {
-  NSView* contentsContainer = [self view];
-  NSArray* subviews = [contentsContainer subviews];
-  if ([subviews count] > 0) {
-    NSView* currentSubview = [subviews objectAtIndex:0];
-    [currentSubview setAutoresizingMask:NSViewNotSizable];
-  }
-}
-
-- (void)ensureContentsVisible {
+- (void)ensureContentsVisibleInSuperview:(NSView*)superview {
   if (!contents_)
     return;
+
   ScopedCAActionDisabler disabler;
   NSView* contentsContainer = [self view];
   NSArray* subviews = [contentsContainer subviews];
@@ -244,7 +236,7 @@
   }
 
   if ([self shouldResizeContentView])
-    [contentsNativeView setFrame:[self frameForContentsView]];
+    [contentsNativeView setFrame:[self frameForContentsViewIn:superview]];
 
   if ([subviews count] == 0) {
     [contentsContainer addSubview:contentsNativeView];
@@ -252,6 +244,10 @@
     [contentsContainer replaceSubview:[subviews objectAtIndex:0]
                                  with:contentsNativeView];
   }
+
+  [contentsNativeView setAutoresizingMask:NSViewNotSizable];
+  [contentsContainer setFrame:[superview bounds]];
+  [superview addSubview:contentsContainer];
   [contentsNativeView setAutoresizingMask:NSViewWidthSizable|
                                           NSViewHeightSizable];
 
@@ -276,8 +272,10 @@
 
   content::RenderWidgetHostView* const fullscreenView =
       contents_->GetFullscreenRenderWidgetHostView();
-  if (fullscreenView)
-    [fullscreenView->GetNativeView() setFrame:[self frameForContentsView]];
+  if (fullscreenView) {
+    [fullscreenView->GetNativeView()
+        setFrame:[self frameForContentsViewIn:[self view]]];
+  }
 }
 
 - (void)changeWebContents:(WebContents*)newContents {
@@ -329,14 +327,14 @@
   // the view is different.
   if ([self webContents] != updatedContents) {
     [self changeWebContents:updatedContents];
-    [self ensureContentsVisible];
+    [self ensureContentsVisibleInSuperview:[[self view] superview]];
   }
 }
 
 - (void)toggleFullscreenWidget:(BOOL)enterFullscreen {
   isEmbeddingFullscreenWidget_ = enterFullscreen &&
       contents_ && contents_->GetFullscreenRenderWidgetHostView();
-  [self ensureContentsVisible];
+  [self ensureContentsVisibleInSuperview:[[self view] superview]];
 }
 
 - (BOOL)contentsInFullscreenCaptureMode {
@@ -353,11 +351,8 @@
   return YES;
 }
 
-- (NSRect)frameForContentsView {
-  const NSSize containerSize = [[self view] frame].size;
-  gfx::Rect rect;
-  rect.set_width(containerSize.width);
-  rect.set_height(containerSize.height);
+- (NSRect)frameForContentsViewIn:(NSView*)container {
+  gfx::Rect rect([container bounds]);
 
   // In most cases, the contents view is simply sized to fill the container
   // view's bounds. Only WebContentses that are in fullscreen mode and being
diff --git a/chrome/browser/ui/cocoa/tabs/tab_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_controller.mm
index eb31514..224ef9b7 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_controller.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_controller.mm
@@ -48,7 +48,7 @@
     return [target_ isCommandEnabled:command forController:owner_];
   }
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override {
+                                  ui::Accelerator* accelerator) const override {
     return false;
   }
   void ExecuteCommand(int command_id, int event_flags) override {
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
index 44d1d98..3a19757 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
@@ -580,43 +580,22 @@
   // positions.
   ScopedCAActionDisabler ca_disabler;
 
-  // Resize the new view to fit the window. Calling |view| may lazily
-  // instantiate the TabContentsController from the nib. Until we call
-  // |-ensureContentsVisible|, the controller doesn't install the RWHVMac into
-  // the view hierarchy. This is in order to avoid sending the renderer a
-  // spurious default size loaded from the nib during the call to |-view|.
-  NSView* newView = [controller view];
+  // Ensure the nib is loaded. Sizing won't occur until it's added to the view
+  // hierarchy with -ensureContentsVisibleInSuperview:.
+  [controller view];
 
-  // Turns content autoresizing off, so removing and inserting views won't
-  // trigger unnecessary content relayout.
-  [controller ensureContentsSizeDoesNotChange];
+  // Remove the old view from the view hierarchy to suppress resizes. We know
+  // there's only one child of |switchView_| because we're the one who put it
+  // there. There may not be any children in the case of a tab that's been
+  // closed, in which case there's nothing removed.
+  [[[switchView_ subviews] firstObject] removeFromSuperview];
 
-  // Remove the old view from the view hierarchy. We know there's only one
-  // child of |switchView_| because we're the one who put it there. There
-  // may not be any children in the case of a tab that's been closed, in
-  // which case there's no swapping going on.
-  NSArray* subviews = [switchView_ subviews];
-  if ([subviews count]) {
-    NSView* oldView = [subviews objectAtIndex:0];
-    // Set newView frame to the oldVew frame to prevent NSSplitView hosting
-    // sidebar and tab content from resizing sidebar's content view.
-    // ensureContentsVisible (see below) sets content size and autoresizing
-    // properties.
-    [newView setFrame:[oldView frame]];
-    // Remove the old view first, to ensure ConstrainedWindowSheets keyed to the
-    // old WebContents are removed before adding new ones.
-    [oldView removeFromSuperview];
-    [switchView_ addSubview:newView];
-  } else {
-    [newView setFrame:[switchView_ bounds]];
-    [switchView_ addSubview:newView];
-  }
-
-  // New content is in place, delegate should adjust itself accordingly.
+  // Prepare the container with any infobars or docked devtools it wants.
   [delegate_ onActivateTabWithContents:[controller webContents]];
 
-  // It also restores content autoresizing properties.
-  [controller ensureContentsVisible];
+  // Sizes the WebContents to match the possibly updated size of |switchView_|,
+  // then adds it and starts auto-resizing again.
+  [controller ensureContentsVisibleInSuperview:switchView_];
 }
 
 // Create a new tab view and set its cell correctly so it draws the way we want
diff --git a/chrome/browser/ui/cocoa/website_settings/chooser_bubble_ui_cocoa.mm b/chrome/browser/ui/cocoa/website_settings/chooser_bubble_ui_cocoa.mm
index 2e89087a..8ee3153 100644
--- a/chrome/browser/ui/cocoa/website_settings/chooser_bubble_ui_cocoa.mm
+++ b/chrome/browser/ui/cocoa/website_settings/chooser_bubble_ui_cocoa.mm
@@ -11,7 +11,7 @@
 
 #include "base/mac/scoped_nsobject.h"
 #include "base/memory/ptr_util.h"
-#include "base/strings/utf_string_conversions.h"
+#include "base/strings/sys_string_conversions.h"
 #include "chrome/browser/chooser_controller/chooser_controller.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
@@ -23,15 +23,10 @@
 #import "chrome/browser/ui/cocoa/info_bubble_window.h"
 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
 #include "chrome/browser/ui/website_settings/chooser_bubble_delegate.h"
-#include "chrome/grit/generated_resources.h"
 #include "components/bubble/bubble_controller.h"
-#include "components/url_formatter/elide_url.h"
 #include "content/public/browser/native_web_keyboard_event.h"
 #include "ui/base/cocoa/cocoa_base_utils.h"
 #include "ui/base/cocoa/window_size_constants.h"
-#include "ui/base/l10n/l10n_util_mac.h"
-#include "url/gurl.h"
-#include "url/origin.h"
 
 std::unique_ptr<BubbleUi> ChooserBubbleDelegate::BuildBubbleUi() {
   return base::WrapUnique(
@@ -120,13 +115,9 @@
                    name:NSWindowDidMoveNotification
                  object:[self getExpectedParentWindow]];
 
-    url::Origin origin = chooserController->GetOrigin();
+    base::string16 chooserTitle = chooserController->GetTitle();
     chooserContentView_.reset([[ChooserContentViewCocoa alloc]
-        initWithChooserTitle:
-            l10n_util::GetNSStringF(
-                IDS_DEVICE_CHOOSER_PROMPT,
-                url_formatter::FormatOriginForSecurityDisplay(
-                    origin, url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC))
+        initWithChooserTitle:base::SysUTF16ToNSString(chooserTitle)
            chooserController:std::move(chooserController)]);
 
     tableView_ = [chooserContentView_ tableView];
diff --git a/chrome/browser/ui/cocoa/website_settings/permission_bubble_controller.mm b/chrome/browser/ui/cocoa/website_settings/permission_bubble_controller.mm
index 6067243..d29878d43 100644
--- a/chrome/browser/ui/cocoa/website_settings/permission_bubble_controller.mm
+++ b/chrome/browser/ui/cocoa/website_settings/permission_bubble_controller.mm
@@ -623,7 +623,7 @@
                previousContents:(content::WebContents*)oldContents
                         atIndex:(NSInteger)index
                          reason:(int)reason {
-  // The show/hide of this bubble is handled by the PermissionBubbleManager.
+  // The show/hide of this bubble is handled by the PermissionRequestManager.
   // So bypass the base class, which would close the bubble here.
 }
 
diff --git a/chrome/browser/ui/content_settings/content_setting_media_menu_model.cc b/chrome/browser/ui/content_settings/content_setting_media_menu_model.cc
index 1b7cc3f..87c214e 100644
--- a/chrome/browser/ui/content_settings/content_setting_media_menu_model.cc
+++ b/chrome/browser/ui/content_settings/content_setting_media_menu_model.cc
@@ -47,7 +47,7 @@
 
 bool ContentSettingMediaMenuModel::GetAcceleratorForCommandId(
     int command_id,
-    ui::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) const {
   return false;
 }
 
diff --git a/chrome/browser/ui/content_settings/content_setting_media_menu_model.h b/chrome/browser/ui/content_settings/content_setting_media_menu_model.h
index f2bfb30..280ae7b 100644
--- a/chrome/browser/ui/content_settings/content_setting_media_menu_model.h
+++ b/chrome/browser/ui/content_settings/content_setting_media_menu_model.h
@@ -35,7 +35,7 @@
   bool IsCommandIdChecked(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
 
  private:
diff --git a/chrome/browser/ui/panels/panel_extension_browsertest.cc b/chrome/browser/ui/panels/panel_extension_browsertest.cc
index fe70e98..54cc05645 100644
--- a/chrome/browser/ui/panels/panel_extension_browsertest.cc
+++ b/chrome/browser/ui/panels/panel_extension_browsertest.cc
@@ -129,7 +129,7 @@
  protected:
   // RenderViewContextMenu implementation.
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override {
+                                  ui::Accelerator* accelerator) const override {
     return false;
   }
 };
diff --git a/chrome/browser/ui/search/instant_controller.cc b/chrome/browser/ui/search/instant_controller.cc
index d1f628f..607a29c 100644
--- a/chrome/browser/ui/search/instant_controller.cc
+++ b/chrome/browser/ui/search/instant_controller.cc
@@ -8,34 +8,27 @@
 #include <utility>
 
 #include "base/location.h"
-#include "base/single_thread_task_runner.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/platform_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search/instant_service.h"
 #include "chrome/browser/search/instant_service_factory.h"
 #include "chrome/browser/search/search.h"
-#include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/ui/browser_instant_controller.h"
 #include "chrome/browser/ui/search/instant_tab.h"
 #include "chrome/browser/ui/search/search_tab_helper.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/search/search_urls.h"
-#include "chrome/common/url_constants.h"
-#include "components/prefs/pref_service.h"
-#include "components/search_engines/template_url_service.h"
 #include "components/sessions/core/serialized_navigation_entry.h"
+#include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/notification_service.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents.h"
-#include "net/base/escape.h"
-#include "net/base/network_change_notifier.h"
 #include "url/gurl.h"
 
+// Macro used for logging debug events. |message| should be a std::string.
+#define LOG_INSTANT_DEBUG_EVENT(controller, message) \
+    controller->LogDebugEvent(message)
+
 namespace {
 
 bool IsContentsFrom(const InstantPage* page,
@@ -107,12 +100,6 @@
   ResetInstantTab();
 }
 
-void InstantController::TabDeactivated(content::WebContents* contents) {
-  // If user is deactivating an NTP tab, give it a change to log stats.
-  if (search::IsInstantNTP(contents))
-    InstantTab::TabDeactivated(contents);
-}
-
 void InstantController::LogDebugEvent(const std::string& info) const {
   DVLOG(1) << info;
 
@@ -175,7 +162,7 @@
   if (!search_mode_.is_origin_default()) {
     content::WebContents* active_tab = browser_->GetActiveWebContents();
     if (!instant_tab_ || active_tab != instant_tab_->web_contents()) {
-      instant_tab_.reset(new InstantTab(this, browser_->profile()));
+      instant_tab_.reset(new InstantTab(this));
       instant_tab_->Init(active_tab);
       UpdateInfoForInstantTab();
     }
diff --git a/chrome/browser/ui/search/instant_controller.h b/chrome/browser/ui/search/instant_controller.h
index 9a099ff..b051956 100644
--- a/chrome/browser/ui/search/instant_controller.h
+++ b/chrome/browser/ui/search/instant_controller.h
@@ -11,14 +11,12 @@
 #include <memory>
 #include <string>
 #include <utility>
-#include <vector>
 
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "base/strings/string16.h"
 #include "chrome/browser/ui/search/instant_page.h"
 #include "chrome/common/search/search_types.h"
-#include "ui/gfx/native_widget_types.h"
 
 class BrowserInstantController;
 class GURL;
@@ -31,10 +29,6 @@
 class WebContents;
 }
 
-// Macro used for logging debug events. |message| should be a std::string.
-#define LOG_INSTANT_DEBUG_EVENT(controller, message) \
-    controller->LogDebugEvent(message)
-
 // InstantController drives Chrome Instant, i.e., the browser implementation of
 // the Embedded Search API (see http://dev.chromium.org/embeddedsearch).
 //
@@ -64,9 +58,6 @@
   // Instant search results page.
   void ActiveTabChanged();
 
-  // The user is about to switch tabs.
-  void TabDeactivated(content::WebContents* contents);
-
   // Adds a new event to |debug_events_| and also DVLOG's it. Ensures that
   // |debug_events_| doesn't get too large.
   void LogDebugEvent(const std::string& info) const;
@@ -121,18 +112,11 @@
   void InstantPageAboutToNavigateMainFrame(const content::WebContents* contents,
                                            const GURL& url) override;
 
-  // Helper function to navigate the given contents to the local fallback
-  // Instant URL and trim the history correctly.
-  void RedirectToLocalNTP(content::WebContents* contents);
-
-  // Helper for OmniboxFocusChanged. Commit or discard the overlay.
-  void OmniboxLostFocus(gfx::NativeView view_gaining_focus);
-
   // If the active tab is an Instant search results page, sets |instant_tab_| to
   // point to it. Else, deletes any existing |instant_tab_|.
   void ResetInstantTab();
 
-  // Sends theme info, omnibox bounds, etc. down to the Instant tab.
+  // Sends theme info and most visited items to the Instant tab.
   void UpdateInfoForInstantTab();
 
   // Returns the InstantService for the browser profile.
diff --git a/chrome/browser/ui/search/instant_page.cc b/chrome/browser/ui/search/instant_page.cc
index 9b4625d..fce80b3 100644
--- a/chrome/browser/ui/search/instant_page.cc
+++ b/chrome/browser/ui/search/instant_page.cc
@@ -4,19 +4,11 @@
 
 #include "chrome/browser/ui/search/instant_page.h"
 
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/search/search.h"
 #include "chrome/browser/ui/search/search_model.h"
 #include "chrome/browser/ui/search/search_tab_helper.h"
 #include "chrome/common/url_constants.h"
-#include "content/public/browser/navigation_controller.h"
-#include "content/public/browser/navigation_details.h"
-#include "content/public/browser/navigation_entry.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_source.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/common/frame_navigate_params.h"
 
 InstantPage::Delegate::~Delegate() {
 }
@@ -33,21 +25,13 @@
       SearchTabHelper::FromWebContents(web_contents())->SupportsInstant();
 }
 
-const std::string& InstantPage::instant_url() const {
-  return instant_url_;
-}
-
 bool InstantPage::IsLocal() const {
   return web_contents() &&
       web_contents()->GetURL() == GURL(chrome::kChromeSearchLocalNtpUrl);
 }
 
-InstantPage::InstantPage(Delegate* delegate,
-                         const std::string& instant_url,
-                         Profile* profile)
-    : profile_(profile),
-      delegate_(delegate),
-      instant_url_(instant_url) {
+InstantPage::InstantPage(Delegate* delegate)
+    : delegate_(delegate) {
 }
 
 void InstantPage::SetContents(content::WebContents* new_web_contents) {
@@ -75,8 +59,9 @@
     const GURL& url,
     ui::PageTransition /* transition_type */) {
   if (!render_frame_host->GetParent() &&
-      ShouldProcessAboutToNavigateMainFrame())
+      ShouldProcessAboutToNavigateMainFrame()) {
     delegate_->InstantPageAboutToNavigateMainFrame(web_contents(), url);
+  }
 }
 
 void InstantPage::ModelChanged(const SearchModel::State& old_state,
diff --git a/chrome/browser/ui/search/instant_page.h b/chrome/browser/ui/search/instant_page.h
index 23fef3f5..0a04f1b 100644
--- a/chrome/browser/ui/search/instant_page.h
+++ b/chrome/browser/ui/search/instant_page.h
@@ -5,33 +5,23 @@
 #ifndef CHROME_BROWSER_UI_SEARCH_INSTANT_PAGE_H_
 #define CHROME_BROWSER_UI_SEARCH_INSTANT_PAGE_H_
 
-#include <vector>
-
 #include "base/compiler_specific.h"
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
-#include "base/strings/string16.h"
 #include "chrome/browser/ui/search/search_model_observer.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "ui/base/page_transition_types.h"
 
 class GURL;
-class Profile;
 
 namespace content {
-struct FrameNavigateParams;
-struct LoadCommittedDetails;
+class RenderFrameHost;
 class WebContents;
 }
 
-namespace gfx {
-class Rect;
-}
-
 // InstantPage is used to exchange messages with a page that implements the
 // Instant/Embedded Search API (http://dev.chromium.org/embeddedsearch).
-// InstantPage is not used directly but via one of its derived classes,
-// InstantNTP and InstantTab.
+// InstantPage is not used directly but via its derived class, InstantTab.
 class InstantPage : public content::WebContentsObserver,
                     public SearchModelObserver {
  public:
@@ -56,24 +46,18 @@
 
   ~InstantPage() override;
 
-  // Returns the Instant URL that was loaded for this page. Returns the empty
-  // string if no URL was explicitly loaded as is the case for InstantTab.
-  virtual const std::string& instant_url() const;
-
   // Returns true if the page is known to support the Instant API. This starts
   // out false, and is set to true whenever we get any message from the page.
   // Once true, it never becomes false (the page isn't expected to drop API
   // support suddenly).
-  virtual bool supports_instant() const;
+  bool supports_instant() const;
 
   // Returns true if the page is the local NTP (i.e. its URL is
   // chrome::kChromeSearchLocalNTPURL).
-  virtual bool IsLocal() const;
+  bool IsLocal() const;
 
  protected:
-  InstantPage(Delegate* delegate,
-              const std::string& instant_url,
-              Profile* profile);
+  explicit InstantPage(Delegate* delegate);
 
   // Sets |web_contents| as the page to communicate with. |web_contents| may be
   // NULL, which effectively stops all communication.
@@ -81,12 +65,7 @@
 
   Delegate* delegate() const { return delegate_; }
 
-  Profile* profile() const { return profile_; }
-
-  // These functions are called before processing messages received from the
-  // page. By default, all messages are handled, but any derived classes may
-  // choose to ignore some or all of the received messages by overriding these
-  // methods.
+  // This method is called before processing messages received from the page.
   virtual bool ShouldProcessAboutToNavigateMainFrame();
 
  private:
@@ -114,12 +93,7 @@
 
   void ClearContents();
 
-  // TODO(kmadhusu): Remove |profile_| from here and update InstantNTP to get
-  // |profile| from InstantNTPPrerenderer.
-  Profile* profile_;
-
   Delegate* const delegate_;
-  const std::string instant_url_;
 
   DISALLOW_COPY_AND_ASSIGN(InstantPage);
 };
diff --git a/chrome/browser/ui/search/instant_page_unittest.cc b/chrome/browser/ui/search/instant_page_unittest.cc
index c9b57f1..c028d77 100644
--- a/chrome/browser/ui/search/instant_page_unittest.cc
+++ b/chrome/browser/ui/search/instant_page_unittest.cc
@@ -68,7 +68,7 @@
 }
 
 TEST_F(InstantPageTest, IsLocal) {
-  page.reset(new InstantPage(&delegate, "", NULL));
+  page.reset(new InstantPage(&delegate));
   EXPECT_FALSE(page->supports_instant());
   EXPECT_FALSE(page->IsLocal());
   page->SetContents(web_contents());
@@ -79,7 +79,7 @@
 }
 
 TEST_F(InstantPageTest, DetermineIfPageSupportsInstant_Local) {
-  page.reset(new InstantPage(&delegate, "", NULL));
+  page.reset(new InstantPage(&delegate));
   EXPECT_FALSE(page->supports_instant());
   page->SetContents(web_contents());
   NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl));
@@ -92,7 +92,7 @@
 }
 
 TEST_F(InstantPageTest, DetermineIfPageSupportsInstant_NonLocal) {
-  page.reset(new InstantPage(&delegate, "", NULL));
+  page.reset(new InstantPage(&delegate));
   EXPECT_FALSE(page->supports_instant());
   page->SetContents(web_contents());
   NavigateAndCommit(GURL("chrome-search://foo/bar"));
@@ -107,7 +107,7 @@
 }
 
 TEST_F(InstantPageTest, PageURLDoesntBelongToInstantRenderer) {
-  page.reset(new InstantPage(&delegate, "", NULL));
+  page.reset(new InstantPage(&delegate));
   EXPECT_FALSE(page->supports_instant());
   NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl));
   page->SetContents(web_contents());
@@ -132,7 +132,7 @@
 // Test to verify that ChromeViewMsg_DetermineIfPageSupportsInstant message
 // reply handler updates the instant support state in InstantPage.
 TEST_F(InstantPageTest, PageSupportsInstant) {
-  page.reset(new InstantPage(&delegate, "", NULL));
+  page.reset(new InstantPage(&delegate));
   EXPECT_FALSE(page->supports_instant());
   page->SetContents(web_contents());
   NavigateAndCommit(GURL("chrome-search://foo/bar"));
diff --git a/chrome/browser/ui/search/instant_tab.cc b/chrome/browser/ui/search/instant_tab.cc
index 7c60de47..3d8e7923 100644
--- a/chrome/browser/ui/search/instant_tab.cc
+++ b/chrome/browser/ui/search/instant_tab.cc
@@ -4,13 +4,11 @@
 
 #include "chrome/browser/ui/search/instant_tab.h"
 
-#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/webui/ntp/ntp_user_data_logger.h"
 #include "content/public/browser/web_contents.h"
 
-InstantTab::InstantTab(InstantPage::Delegate* delegate,
-                       Profile* profile)
-    : InstantPage(delegate, "", profile) {
+InstantTab::InstantTab(InstantPage::Delegate* delegate)
+    : InstantPage(delegate) {
 }
 
 InstantTab::~InstantTab() {
@@ -20,17 +18,6 @@
   SetContents(contents);
 }
 
-// static
-void InstantTab::TabDeactivated(content::WebContents* contents) {
-  NTPUserDataLogger::GetOrCreateFromWebContents(contents)->TabDeactivated();
-}
-
-// static
-void InstantTab::MostVisitedItemsChanged(content::WebContents* contents) {
-  NTPUserDataLogger::GetOrCreateFromWebContents(contents)
-      ->MostVisitedItemsChanged();
-}
-
 bool InstantTab::ShouldProcessAboutToNavigateMainFrame() {
   return true;
 }
diff --git a/chrome/browser/ui/search/instant_tab.h b/chrome/browser/ui/search/instant_tab.h
index e879cbae..e3a6d9b 100644
--- a/chrome/browser/ui/search/instant_tab.h
+++ b/chrome/browser/ui/search/instant_tab.h
@@ -9,23 +9,17 @@
 #include "base/macros.h"
 #include "chrome/browser/ui/search/instant_page.h"
 
-class Profile;
-
 // InstantTab represents a committed page (i.e. an actual tab on the tab strip)
 // that supports the Instant API.
 class InstantTab : public InstantPage {
  public:
-  InstantTab(InstantPage::Delegate* delegate, Profile* profile);
+  explicit InstantTab(InstantPage::Delegate* delegate);
   ~InstantTab() override;
 
   // Start observing |contents| for messages. Sends a message to determine if
   // the page supports the Instant API.
   void Init(content::WebContents* contents);
 
-  // Logs statistics regarding the NTP.
-  static void TabDeactivated(content::WebContents* contents);
-  static void MostVisitedItemsChanged(content::WebContents* contents);
-
  private:
   // Overridden from InstantPage:
   bool ShouldProcessAboutToNavigateMainFrame() override;
diff --git a/chrome/browser/ui/search/search_tab_helper.cc b/chrome/browser/ui/search/search_tab_helper.cc
index 2ba04505..3ff3225 100644
--- a/chrome/browser/ui/search/search_tab_helper.cc
+++ b/chrome/browser/ui/search/search_tab_helper.cc
@@ -385,28 +385,7 @@
 
 void SearchTabHelper::MostVisitedItemsChanged(
     const std::vector<InstantMostVisitedItem>& items) {
-  // When most visited change, the NTP usually reloads the tiles. This means
-  // our metrics get inconsistent. So we'd rather emit stats now.
-  InstantTab::MostVisitedItemsChanged(web_contents_);
   ipc_router_.SendMostVisitedItems(items);
-  LogMostVisitedItemsSource(items);
-}
-
-void SearchTabHelper::LogMostVisitedItemsSource(
-    const std::vector<InstantMostVisitedItem>& items) {
-  for (auto item : items) {
-    NTPLoggingEventType event;
-    if (item.is_server_side_suggestion) {
-      event = NTP_SERVER_SIDE_SUGGESTION;
-    } else {
-      event = NTP_CLIENT_SIDE_SUGGESTION;
-    }
-    // The metrics are emitted for each suggestion as the design requirement
-    // even the ntp_user_data_logger.cc now only supports the scenario:
-    // all suggestions are provided by server OR
-    // all suggestions are provided by client.
-    this->OnLogEvent(event, base::TimeDelta());
-  }
 }
 
 void SearchTabHelper::FocusOmnibox(OmniboxFocusState state) {
diff --git a/chrome/browser/ui/search/search_tab_helper.h b/chrome/browser/ui/search/search_tab_helper.h
index 6543142..b6ef66c 100644
--- a/chrome/browser/ui/search/search_tab_helper.h
+++ b/chrome/browser/ui/search/search_tab_helper.h
@@ -201,10 +201,6 @@
   // Returns the OmniboxView for |web_contents_| or NULL if not available.
   OmniboxView* GetOmniboxView() const;
 
-  // Record whether each suggestion comes from server or client.
-  void LogMostVisitedItemsSource(
-      const std::vector<InstantMostVisitedItem>& items);
-
   typedef bool (*OmniboxHasFocusFn)(OmniboxView*);
 
   void set_omnibox_has_focus_fn(OmniboxHasFocusFn fn) {
diff --git a/chrome/browser/ui/search/search_tab_helper_unittest.cc b/chrome/browser/ui/search/search_tab_helper_unittest.cc
index eda53e3..357c77eb 100644
--- a/chrome/browser/ui/search/search_tab_helper_unittest.cc
+++ b/chrome/browser/ui/search/search_tab_helper_unittest.cc
@@ -320,46 +320,6 @@
   ASSERT_FALSE(std::get<0>(params));
 }
 
-TEST_F(SearchTabHelperTest, OnMostVisitedItemsChangedFromServer) {
-  InstantMostVisitedItem item;
-  item.is_server_side_suggestion = true;
-  std::vector<InstantMostVisitedItem> items;
-  items.push_back(item);
-
-  SearchTabHelper* search_tab_helper =
-      SearchTabHelper::FromWebContents(web_contents());
-  ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper);
-
-  auto logger = NTPUserDataLogger::GetOrCreateFromWebContents(web_contents());
-  ASSERT_FALSE(logger->has_server_side_suggestions_);
-  ASSERT_FALSE(logger->has_client_side_suggestions_);
-
-  search_tab_helper->MostVisitedItemsChanged(items);
-
-  ASSERT_TRUE(logger->has_server_side_suggestions_);
-  ASSERT_FALSE(logger->has_client_side_suggestions_);
-}
-
-TEST_F(SearchTabHelperTest, OnMostVisitedItemsChangedFromClient) {
-  InstantMostVisitedItem item;
-  item.is_server_side_suggestion = false;
-  std::vector<InstantMostVisitedItem> items;
-  items.push_back(item);
-
-  SearchTabHelper* search_tab_helper =
-      SearchTabHelper::FromWebContents(web_contents());
-  ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper);
-
-  auto logger = NTPUserDataLogger::GetOrCreateFromWebContents(web_contents());
-  ASSERT_FALSE(logger->has_server_side_suggestions_);
-  ASSERT_FALSE(logger->has_client_side_suggestions_);
-
-  search_tab_helper->MostVisitedItemsChanged(items);
-
-  ASSERT_FALSE(logger->has_server_side_suggestions_);
-  ASSERT_TRUE(logger->has_client_side_suggestions_);
-}
-
 class TabTitleObserver : public content::WebContentsObserver {
  public:
   explicit TabTitleObserver(content::WebContents* contents)
diff --git a/chrome/browser/ui/startup/default_browser_infobar_delegate.cc b/chrome/browser/ui/startup/default_browser_infobar_delegate.cc
index bab51d9..b9175c7 100644
--- a/chrome/browser/ui/startup/default_browser_infobar_delegate.cc
+++ b/chrome/browser/ui/startup/default_browser_infobar_delegate.cc
@@ -57,6 +57,7 @@
     : ConfirmInfoBarDelegate(),
       profile_(profile),
       should_expire_(false),
+      action_taken_(false),
       weak_factory_(this) {
   // We want the info-bar to stick-around for few seconds and then be hidden
   // on the next navigation after that.
@@ -66,7 +67,13 @@
       base::TimeDelta::FromSeconds(8));
 }
 
-DefaultBrowserInfoBarDelegate::~DefaultBrowserInfoBarDelegate() = default;
+DefaultBrowserInfoBarDelegate::~DefaultBrowserInfoBarDelegate() {
+  if (!action_taken_) {
+    UMA_HISTOGRAM_ENUMERATION("DefaultBrowser.InfoBar.UserInteraction",
+                              IGNORE_INFO_BAR,
+                              NUM_INFO_BAR_USER_INTERACTION_TYPES);
+  }
+}
 
 void DefaultBrowserInfoBarDelegate::AllowExpiry() {
   should_expire_ = true;
@@ -127,10 +134,11 @@
 }
 
 void DefaultBrowserInfoBarDelegate::InfoBarDismissed() {
+  action_taken_ = true;
   content::RecordAction(
       base::UserMetricsAction("DefaultBrowserInfoBar_Dismiss"));
   UMA_HISTOGRAM_ENUMERATION("DefaultBrowser.InfoBar.UserInteraction",
-                            IGNORE_INFO_BAR,
+                            DISMISS_INFO_BAR,
                             NUM_INFO_BAR_USER_INTERACTION_TYPES);
 }
 
@@ -164,6 +172,7 @@
 }
 
 bool DefaultBrowserInfoBarDelegate::Accept() {
+  action_taken_ = true;
   content::RecordAction(
       base::UserMetricsAction("DefaultBrowserInfoBar_Accept"));
   UMA_HISTOGRAM_ENUMERATION("DefaultBrowser.InfoBar.UserInteraction",
@@ -190,6 +199,7 @@
 }
 
 bool DefaultBrowserInfoBarDelegate::Cancel() {
+  action_taken_ = true;
   // This can get reached in tests where profile_ is null.
   if (profile_)
     chrome::DefaultBrowserPromptDeclined(profile_);
diff --git a/chrome/browser/ui/startup/default_browser_infobar_delegate.h b/chrome/browser/ui/startup/default_browser_infobar_delegate.h
index 99b7ffd6..9b56c47 100644
--- a/chrome/browser/ui/startup/default_browser_infobar_delegate.h
+++ b/chrome/browser/ui/startup/default_browser_infobar_delegate.h
@@ -46,6 +46,8 @@
     CANCEL_INFO_BAR = 1,
     // The user did not interact with the info bar.
     IGNORE_INFO_BAR = 2,
+    // The user explicitly closed the infobar.
+    DISMISS_INFO_BAR = 3,
     NUM_INFO_BAR_USER_INTERACTION_TYPES
   };
 
@@ -85,6 +87,9 @@
   // Whether the info bar should be dismissed on the next navigation.
   bool should_expire_;
 
+  // Indicates if the user interacted with the infobar.
+  bool action_taken_;
+
   // Used to delay the expiration of the info-bar.
   base::WeakPtrFactory<DefaultBrowserInfoBarDelegate> weak_factory_;
 
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc
index 2981c67..85c3e1d 100644
--- a/chrome/browser/ui/tab_helpers.cc
+++ b/chrome/browser/ui/tab_helpers.cc
@@ -53,6 +53,7 @@
 #include "content/public/browser/web_contents.h"
 
 #if BUILDFLAG(ANDROID_JAVA_UI)
+#include "chrome/browser/android/banners/app_banner_manager_android.h"
 #include "chrome/browser/android/data_usage/data_use_tab_helper.h"
 #include "chrome/browser/android/offline_pages/offline_page_tab_helper.h"
 #include "chrome/browser/android/offline_pages/recent_tab_helper.h"
@@ -63,6 +64,7 @@
 #include "components/offline_pages/offline_page_feature.h"
 #else
 #include "chrome/browser/banners/app_banner_manager_desktop.h"
+#include "chrome/browser/permissions/permission_request_manager.h"
 #include "chrome/browser/plugins/plugin_observer.h"
 #include "chrome/browser/safe_browsing/safe_browsing_tab_observer.h"
 #include "chrome/browser/thumbnails/thumbnail_tab_helper.h"
@@ -71,7 +73,6 @@
 #include "chrome/browser/ui/sad_tab_helper.h"
 #include "chrome/browser/ui/search_engines/search_engine_tab_helper.h"
 #include "chrome/browser/ui/sync/tab_contents_synced_tab_delegate.h"
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
 #include "components/pdf/browser/pdf_web_contents_helper.h"
 #include "components/web_modal/web_contents_modal_dialog_manager.h"
 #include "components/zoom/zoom_controller.h"
@@ -182,6 +183,7 @@
   // --- Platform-specific tab helpers ---
 
 #if BUILDFLAG(ANDROID_JAVA_UI)
+  banners::AppBannerManagerAndroid::CreateForWebContents(web_contents);
   ContextMenuHelper::CreateForWebContents(web_contents);
   DataUseTabHelper::CreateForWebContents(web_contents);
 
@@ -202,7 +204,7 @@
   pdf::PDFWebContentsHelper::CreateForWebContentsWithClient(
       web_contents, std::unique_ptr<pdf::PDFWebContentsHelperClient>(
                         new ChromePDFWebContentsHelperClient()));
-  PermissionBubbleManager::CreateForWebContents(web_contents);
+  PermissionRequestManager::CreateForWebContents(web_contents);
   PluginObserver::CreateForWebContents(web_contents);
   SadTabHelper::CreateForWebContents(web_contents);
   safe_browsing::SafeBrowsingTabObserver::CreateForWebContents(web_contents);
@@ -212,9 +214,8 @@
   ThumbnailTabHelper::CreateForWebContents(web_contents);
   web_modal::WebContentsModalDialogManager::CreateForWebContents(web_contents);
 
-  if (banners::AppBannerManagerDesktop::IsEnabled()) {
+  if (banners::AppBannerManagerDesktop::IsEnabled())
     banners::AppBannerManagerDesktop::CreateForWebContents(web_contents);
-  }
 #endif
 
   // --- Feature tab helpers behind flags ---
diff --git a/chrome/browser/ui/toolbar/app_menu_model.cc b/chrome/browser/ui/toolbar/app_menu_model.cc
index 19f6fef..9209ab16 100644
--- a/chrome/browser/ui/toolbar/app_menu_model.cc
+++ b/chrome/browser/ui/toolbar/app_menu_model.cc
@@ -171,7 +171,7 @@
 
 bool EncodingMenuModel::GetAcceleratorForCommandId(
     int command_id,
-    ui::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) const {
   return false;
 }
 
@@ -721,8 +721,9 @@
   }
 }
 
-bool AppMenuModel::GetAcceleratorForCommandId(int command_id,
-                                              ui::Accelerator* accelerator) {
+bool AppMenuModel::GetAcceleratorForCommandId(
+    int command_id,
+    ui::Accelerator* accelerator) const {
   return provider_->GetAcceleratorForCommandId(command_id, accelerator);
 }
 
diff --git a/chrome/browser/ui/toolbar/app_menu_model.h b/chrome/browser/ui/toolbar/app_menu_model.h
index 11afa0c..96349154 100644
--- a/chrome/browser/ui/toolbar/app_menu_model.h
+++ b/chrome/browser/ui/toolbar/app_menu_model.h
@@ -86,7 +86,7 @@
   bool IsCommandIdChecked(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
 
  private:
@@ -148,7 +148,7 @@
   bool IsCommandIdEnabled(int command_id) const override;
   bool IsCommandIdVisible(int command_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
 
   // Overridden from TabStripModelObserver:
   void ActiveTabChanged(content::WebContents* old_contents,
diff --git a/chrome/browser/ui/toolbar/app_menu_model_unittest.cc b/chrome/browser/ui/toolbar/app_menu_model_unittest.cc
index 5397452..c0d0e98 100644
--- a/chrome/browser/ui/toolbar/app_menu_model_unittest.cc
+++ b/chrome/browser/ui/toolbar/app_menu_model_unittest.cc
@@ -59,7 +59,7 @@
  public:
   // Don't handle accelerators.
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override {
+                                  ui::Accelerator* accelerator) const override {
     return false;
   }
 
diff --git a/chrome/browser/ui/toolbar/media_router_contextual_menu.cc b/chrome/browser/ui/toolbar/media_router_contextual_menu.cc
index 50558b9..8caf084b7 100644
--- a/chrome/browser/ui/toolbar/media_router_contextual_menu.cc
+++ b/chrome/browser/ui/toolbar/media_router_contextual_menu.cc
@@ -85,7 +85,7 @@
 
 bool MediaRouterContextualMenu::GetAcceleratorForCommandId(
     int command_id,
-    ui::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) const {
   return false;
 }
 
diff --git a/chrome/browser/ui/toolbar/media_router_contextual_menu.h b/chrome/browser/ui/toolbar/media_router_contextual_menu.h
index 060e4738..42b57ed 100644
--- a/chrome/browser/ui/toolbar/media_router_contextual_menu.h
+++ b/chrome/browser/ui/toolbar/media_router_contextual_menu.h
@@ -25,7 +25,7 @@
   bool IsCommandIdEnabled(int command_id) const override;
   bool IsCommandIdVisible(int command_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
 
   void ReportIssue();
diff --git a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
index dac90372..9e478df 100644
--- a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
+++ b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
@@ -252,7 +252,8 @@
 }
 
 bool RecentTabsSubMenuModel::GetAcceleratorForCommandId(
-    int command_id, ui::Accelerator* accelerator) {
+    int command_id,
+    ui::Accelerator* accelerator) const {
   // If there are no recently closed items, we show the accelerator beside
   // the header, otherwise, we show it beside the first item underneath it.
   int index_in_menu = GetIndexOfCommandId(command_id);
diff --git a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h
index 895a2a8..ca5b0be 100644
--- a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h
+++ b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h
@@ -67,7 +67,7 @@
   bool IsCommandIdChecked(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
   const gfx::FontList* GetLabelFontListAt(int index) const override;
 
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc
index 1b80cf7..50d190f5 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc
@@ -190,7 +190,7 @@
 
 bool BookmarkEditorView::GetAcceleratorForCommandId(
     int command_id,
-    ui::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) const {
   return GetWidget()->GetAccelerator(command_id, accelerator);
 }
 
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.h b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.h
index a601c30..0bd8f63 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.h
+++ b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.h
@@ -109,7 +109,7 @@
   bool IsCommandIdChecked(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
 
   // Creates a Window and adds the BookmarkEditorView to it. When the window is
diff --git a/chrome/browser/ui/views/chooser_content_view.cc b/chrome/browser/ui/views/chooser_content_view.cc
index ad6a040a..24b0e254 100644
--- a/chrome/browser/ui/views/chooser_content_view.cc
+++ b/chrome/browser/ui/views/chooser_content_view.cc
@@ -143,11 +143,15 @@
   return gfx::Size(kChooserWidth, kChooserHeight);
 }
 
+base::string16 ChooserContentView::GetWindowTitle() const {
+  return chooser_controller_->GetTitle();
+}
+
 base::string16 ChooserContentView::GetDialogButtonLabel(
     ui::DialogButton button) const {
-  return l10n_util::GetStringUTF16(button == ui::DIALOG_BUTTON_OK
-                                       ? IDS_DEVICE_CHOOSER_CONNECT_BUTTON_TEXT
-                                       : IDS_DEVICE_CHOOSER_CANCEL_BUTTON_TEXT);
+  return button == ui::DIALOG_BUTTON_OK
+             ? chooser_controller_->GetOkButtonLabel()
+             : l10n_util::GetStringUTF16(IDS_DEVICE_CHOOSER_CANCEL_BUTTON_TEXT);
 }
 
 bool ChooserContentView::IsDialogButtonEnabled(ui::DialogButton button) const {
diff --git a/chrome/browser/ui/views/chooser_content_view.h b/chrome/browser/ui/views/chooser_content_view.h
index 57c5dd1..2a9c45a 100644
--- a/chrome/browser/ui/views/chooser_content_view.h
+++ b/chrome/browser/ui/views/chooser_content_view.h
@@ -37,6 +37,7 @@
   // views::View:
   gfx::Size GetPreferredSize() const override;
 
+  base::string16 GetWindowTitle() const;
   base::string16 GetDialogButtonLabel(ui::DialogButton button) const;
   bool IsDialogButtonEnabled(ui::DialogButton button) const;
   // Ownership of the view is passed to the caller.
diff --git a/chrome/browser/ui/views/constrained_web_dialog_delegate_views.cc b/chrome/browser/ui/views/constrained_web_dialog_delegate_views.cc
index 662c976..0644dbc 100644
--- a/chrome/browser/ui/views/constrained_web_dialog_delegate_views.cc
+++ b/chrome/browser/ui/views/constrained_web_dialog_delegate_views.cc
@@ -154,6 +154,8 @@
         max_size_(max_size) {
     SetWebContents(GetWebContents());
     AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE));
+    if (!max_size_.IsEmpty())
+      EnableAutoResize();
   }
   ~ConstrainedWebDialogDelegateViewViews() override {}
 
@@ -235,13 +237,10 @@
       EnableAutoResize();
   }
   void DocumentOnLoadCompletedInMainFrame() override {
-    if (!max_size_.IsEmpty()) {
-      EnableAutoResize();
-      if (initiator_observer_.web_contents()) {
-        web_modal::WebContentsModalDialogManager::FromWebContents(
-            initiator_observer_.web_contents())
-            ->ShowModalDialog(GetWidget()->GetNativeWindow());
-      }
+    if (!max_size_.IsEmpty() && initiator_observer_.web_contents()) {
+      web_modal::WebContentsModalDialogManager::FromWebContents(
+          initiator_observer_.web_contents())
+          ->ShowModalDialog(GetWidget()->GetNativeWindow());
     }
   }
 
diff --git a/chrome/browser/ui/views/extensions/chooser_dialog_view.cc b/chrome/browser/ui/views/extensions/chooser_dialog_view.cc
index 51dae6b..b7d0215d 100644
--- a/chrome/browser/ui/views/extensions/chooser_dialog_view.cc
+++ b/chrome/browser/ui/views/extensions/chooser_dialog_view.cc
@@ -10,18 +10,13 @@
 #include "chrome/browser/ui/views/chooser_content_view.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/constrained_window/constrained_window_views.h"
-#include "components/url_formatter/elide_url.h"
 #include "components/web_modal/web_contents_modal_dialog_manager.h"
 #include "content/public/browser/browser_thread.h"
-#include "extensions/browser/extension_registry.h"
-#include "ui/base/l10n/l10n_util.h"
 #include "ui/views/controls/styled_label.h"
 #include "ui/views/window/dialog_client_view.h"
 
 ChooserDialogView::ChooserDialogView(
-    content::WebContents* web_contents,
-    std::unique_ptr<ChooserController> chooser_controller)
-    : web_contents_(web_contents), chooser_content_view_(nullptr) {
+    std::unique_ptr<ChooserController> chooser_controller) {
   // ------------------------------------
   // | Chooser dialog title             |
   // | -------------------------------- |
@@ -37,9 +32,7 @@
   // | Not seeing your device? Get help |
   // ------------------------------------
 
-  DCHECK(web_contents_);
   DCHECK(chooser_controller);
-  origin_ = chooser_controller->GetOrigin();
   chooser_content_view_ =
       new ChooserContentView(this, std::move(chooser_controller));
 }
@@ -47,24 +40,7 @@
 ChooserDialogView::~ChooserDialogView() {}
 
 base::string16 ChooserDialogView::GetWindowTitle() const {
-  base::string16 chooser_title;
-  content::BrowserContext* browser_context = web_contents_->GetBrowserContext();
-  extensions::ExtensionRegistry* extension_registry =
-      extensions::ExtensionRegistry::Get(browser_context);
-  if (extension_registry) {
-    const extensions::Extension* extension =
-        extension_registry->enabled_extensions().GetExtensionOrAppByURL(
-            GURL(origin_.Serialize()));
-    if (extension)
-      chooser_title = base::UTF8ToUTF16(extension->name());
-  }
-
-  if (chooser_title.empty()) {
-    chooser_title = url_formatter::FormatOriginForSecurityDisplay(
-        origin_, url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC);
-  }
-
-  return l10n_util::GetStringFUTF16(IDS_DEVICE_CHOOSER_PROMPT, chooser_title);
+  return chooser_content_view_->GetWindowTitle();
 }
 
 bool ChooserDialogView::ShouldShowCloseButton() const {
@@ -138,7 +114,6 @@
       web_modal::WebContentsModalDialogManager::FromWebContents(web_contents_);
   if (manager) {
     constrained_window::ShowWebModalDialogViews(
-        new ChooserDialogView(web_contents_, std::move(chooser_controller)),
-        web_contents_);
+        new ChooserDialogView(std::move(chooser_controller)), web_contents_);
   }
 }
diff --git a/chrome/browser/ui/views/extensions/chooser_dialog_view.h b/chrome/browser/ui/views/extensions/chooser_dialog_view.h
index b33100a..f68d01ab 100644
--- a/chrome/browser/ui/views/extensions/chooser_dialog_view.h
+++ b/chrome/browser/ui/views/extensions/chooser_dialog_view.h
@@ -11,15 +11,10 @@
 #include "ui/views/controls/styled_label_listener.h"
 #include "ui/views/controls/table/table_view_observer.h"
 #include "ui/views/window/dialog_delegate.h"
-#include "url/origin.h"
 
 class ChooserContentView;
 class ChooserController;
 
-namespace content {
-class WebContents;
-}
-
 namespace views {
 class TableView;
 }
@@ -30,8 +25,8 @@
                           public views::StyledLabelListener,
                           public views::TableViewObserver {
  public:
-  ChooserDialogView(content::WebContents* web_contents,
-                    std::unique_ptr<ChooserController> chooser_controller);
+  explicit ChooserDialogView(
+      std::unique_ptr<ChooserController> chooser_controller);
   ~ChooserDialogView() override;
 
   // views::WidgetDelegate:
@@ -63,8 +58,6 @@
   views::TableView* table_view_for_test() const;
 
  private:
-  content::WebContents* web_contents_;
-  url::Origin origin_;
   ChooserContentView* chooser_content_view_;
 
   DISALLOW_COPY_AND_ASSIGN(ChooserDialogView);
diff --git a/chrome/browser/ui/views/extensions/chooser_dialog_view_browsertest.cc b/chrome/browser/ui/views/extensions/chooser_dialog_view_browsertest.cc
index 2ef2625a..1b65c6c 100644
--- a/chrome/browser/ui/views/extensions/chooser_dialog_view_browsertest.cc
+++ b/chrome/browser/ui/views/extensions/chooser_dialog_view_browsertest.cc
@@ -9,7 +9,6 @@
 #include "chrome/browser/extensions/extension_browsertest.h"
 #include "chrome/browser/platform_util.h"
 #include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/grit/generated_resources.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -25,14 +24,11 @@
   ~ChooserDialogViewTest() override {}
 
   void SetUpOnMainThread() override {
-    content::WebContents* web_contents =
-        browser()->tab_strip_model()->GetWebContentsAt(0);
     std::unique_ptr<MockChooserController> mock_chooser_controller(
         new MockChooserController(nullptr));
     mock_chooser_controller_ = mock_chooser_controller.get();
     std::unique_ptr<ChooserDialogView> chooser_dialog_view(
-        new ChooserDialogView(web_contents,
-                              std::move(mock_chooser_controller)));
+        new ChooserDialogView(std::move(mock_chooser_controller)));
     chooser_dialog_view_ = chooser_dialog_view.get();
     table_view_ = chooser_dialog_view_->table_view_for_test();
     ASSERT_TRUE(table_view_);
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index 31581e1..34aaf62 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -31,6 +31,7 @@
 #include "chrome/browser/extensions/tab_helper.h"
 #include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/browser/native_window_notification_source.h"
+#include "chrome/browser/permissions/permission_request_manager.h"
 #include "chrome/browser/profiles/avatar_menu.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_attributes_entry.h"
@@ -99,7 +100,6 @@
 #include "chrome/browser/ui/views/update_recommended_message_box.h"
 #include "chrome/browser/ui/views/website_settings/permissions_bubble_view.h"
 #include "chrome/browser/ui/views/website_settings/website_settings_popup_view.h"
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
 #include "chrome/browser/ui/window_sizer/window_sizer.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/command.h"
@@ -844,11 +844,11 @@
   infobar_container_->ChangeInfoBarManager(
       InfoBarService::FromWebContents(new_contents));
 
-  if (old_contents && PermissionBubbleManager::FromWebContents(old_contents))
-    PermissionBubbleManager::FromWebContents(old_contents)->HideBubble();
+  if (old_contents && PermissionRequestManager::FromWebContents(old_contents))
+    PermissionRequestManager::FromWebContents(old_contents)->HideBubble();
 
-  if (new_contents && PermissionBubbleManager::FromWebContents(new_contents)) {
-    PermissionBubbleManager::FromWebContents(new_contents)
+  if (new_contents && PermissionRequestManager::FromWebContents(new_contents)) {
+    PermissionRequestManager::FromWebContents(new_contents)
         ->DisplayPendingRequests();
   }
 
@@ -1562,8 +1562,8 @@
 }
 
 void BrowserView::TabDetachedAt(WebContents* contents, int index) {
-  if (PermissionBubbleManager::FromWebContents(contents))
-    PermissionBubbleManager::FromWebContents(contents)->HideBubble();
+  if (PermissionRequestManager::FromWebContents(contents))
+    PermissionRequestManager::FromWebContents(contents)->HideBubble();
 
   // We use index here rather than comparing |contents| because by this time
   // the model has already removed |contents| from its list, so
@@ -1580,8 +1580,8 @@
 }
 
 void BrowserView::TabDeactivated(WebContents* contents) {
-  if (PermissionBubbleManager::FromWebContents(contents))
-    PermissionBubbleManager::FromWebContents(contents)->HideBubble();
+  if (PermissionRequestManager::FromWebContents(contents))
+    PermissionRequestManager::FromWebContents(contents)->HideBubble();
 
   // We do not store the focus when closing the tab to work-around bug 4633.
   // Some reports seem to show that the focus manager and/or focused view can
@@ -1608,8 +1608,9 @@
 ///////////////////////////////////////////////////////////////////////////////
 // BrowserView, ui::AcceleratorProvider implementation:
 
-bool BrowserView::GetAcceleratorForCommandId(int command_id,
-                                             ui::Accelerator* accelerator) {
+bool BrowserView::GetAcceleratorForCommandId(
+    int command_id,
+    ui::Accelerator* accelerator) const {
   // Let's let the ToolbarView own the canonical implementation of this method.
   return toolbar_->GetAcceleratorForCommandId(command_id, accelerator);
 }
@@ -2359,8 +2360,8 @@
   ToolbarSizeChanged(false);
 
   WebContents* contents = browser_->tab_strip_model()->GetActiveWebContents();
-  if (contents && PermissionBubbleManager::FromWebContents(contents))
-    PermissionBubbleManager::FromWebContents(contents)->UpdateAnchorPosition();
+  if (contents && PermissionRequestManager::FromWebContents(contents))
+    PermissionRequestManager::FromWebContents(contents)->UpdateAnchorPosition();
 }
 
 bool BrowserView::ShouldUseImmersiveFullscreenForUrl(const GURL& url) const {
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h
index 7c9c94d..92bbc40 100644
--- a/chrome/browser/ui/views/frame/browser_view.h
+++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -383,7 +383,7 @@
 
   // Overridden from ui::AcceleratorProvider:
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
 
   // Overridden from views::WidgetDelegate:
   bool CanResize() const override;
diff --git a/chrome/browser/ui/views/frame/system_menu_model_delegate.cc b/chrome/browser/ui/views/frame/system_menu_model_delegate.cc
index 77849cb3..aa6e7055 100644
--- a/chrome/browser/ui/views/frame/system_menu_model_delegate.cc
+++ b/chrome/browser/ui/views/frame/system_menu_model_delegate.cc
@@ -59,8 +59,9 @@
   return true;
 }
 
-bool SystemMenuModelDelegate::GetAcceleratorForCommandId(int command_id,
-                                             ui::Accelerator* accelerator) {
+bool SystemMenuModelDelegate::GetAcceleratorForCommandId(
+    int command_id,
+    ui::Accelerator* accelerator) const {
   return provider_->GetAcceleratorForCommandId(command_id, accelerator);
 }
 
diff --git a/chrome/browser/ui/views/frame/system_menu_model_delegate.h b/chrome/browser/ui/views/frame/system_menu_model_delegate.h
index 49b0d8f..bd5b810 100644
--- a/chrome/browser/ui/views/frame/system_menu_model_delegate.h
+++ b/chrome/browser/ui/views/frame/system_menu_model_delegate.h
@@ -24,7 +24,7 @@
   bool IsCommandIdChecked(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   bool IsItemForCommandIdDynamic(int command_id) const override;
   base::string16 GetLabelForCommandId(int command_id) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
diff --git a/chrome/browser/ui/views/new_task_manager_view.cc b/chrome/browser/ui/views/new_task_manager_view.cc
index 01a5d3c7..a73d48a 100644
--- a/chrome/browser/ui/views/new_task_manager_view.cc
+++ b/chrome/browser/ui/views/new_task_manager_view.cc
@@ -280,7 +280,7 @@
 
 bool NewTaskManagerView::GetAcceleratorForCommandId(
     int command_id,
-    ui::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) const {
   return false;
 }
 
diff --git a/chrome/browser/ui/views/new_task_manager_view.h b/chrome/browser/ui/views/new_task_manager_view.h
index fe94e35..1f9543a6d 100644
--- a/chrome/browser/ui/views/new_task_manager_view.h
+++ b/chrome/browser/ui/views/new_task_manager_view.h
@@ -89,7 +89,7 @@
   bool IsCommandIdChecked(int id) const override;
   bool IsCommandIdEnabled(int id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   void ExecuteCommand(int id, int event_flags) override;
 
  private:
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc
index 10dcaab..74c2694 100644
--- a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc
+++ b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc
@@ -17,6 +17,7 @@
 #include "chrome/browser/ui/views/passwords/manage_password_items_view.h"
 #include "chrome/browser/ui/views/passwords/manage_passwords_icon_views.h"
 #include "chrome/grit/generated_resources.h"
+#include "content/public/browser/user_metrics.h"
 #include "grit/components_strings.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/material_design/material_design_controller.h"
@@ -593,6 +594,8 @@
   layout->AddView(no_button_);
 
   parent_->set_initially_focused_view(signin_button_);
+  content::RecordAction(
+      base::UserMetricsAction("Signin_Impression_FromPasswordBubble"));
 }
 
 void ManagePasswordsBubbleView::SignInPromoView::ButtonPressed(
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.cc b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
index 7ea8a87..5500499 100644
--- a/chrome/browser/ui/views/profiles/profile_chooser_view.cc
+++ b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
@@ -765,6 +765,7 @@
   delete_account_button_map_.clear();
   reauth_account_button_map_.clear();
   manage_accounts_link_ = nullptr;
+  manage_accounts_button_ = nullptr;
   signin_current_profile_button_ = nullptr;
   auth_error_email_button_ = nullptr;
   current_profile_photo_ = nullptr;
diff --git a/chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.cc b/chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.cc
index 6cf6659..639219ea 100644
--- a/chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.cc
+++ b/chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.cc
@@ -62,7 +62,7 @@
 
 bool RenderViewContextMenuViews::GetAcceleratorForCommandId(
     int command_id,
-    ui::Accelerator* accel) {
+    ui::Accelerator* accel) const {
   // There are no formally defined accelerators we can query so we assume
   // that Ctrl+C, Ctrl+V, Ctrl+X, Ctrl-A, etc do what they normally do.
   ui::AcceleratorProvider* accelerator_provider = nullptr;
diff --git a/chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.h b/chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.h
index 29b4263..3e052117 100644
--- a/chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.h
+++ b/chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.h
@@ -49,7 +49,7 @@
 
   // RenderViewContextMenu implementation.
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
 
  private:
   void AppendPlatformEditableItems() override;
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
index d7ff874..0d00ebe 100644
--- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
+++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
@@ -132,7 +132,7 @@
         tab_);
   }
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override {
+                                  ui::Accelerator* accelerator) const override {
     int browser_cmd;
     return TabStripModel::ContextMenuCommandToBrowserCommand(command_id,
                                                              &browser_cmd) ?
diff --git a/chrome/browser/ui/views/toolbar/reload_button.cc b/chrome/browser/ui/views/toolbar/reload_button.cc
index 4d9b593..bfa4fae 100644
--- a/chrome/browser/ui/views/toolbar/reload_button.cc
+++ b/chrome/browser/ui/views/toolbar/reload_button.cc
@@ -181,8 +181,9 @@
   return true;
 }
 
-bool ReloadButton::GetAcceleratorForCommandId(int command_id,
-    ui::Accelerator* accelerator) {
+bool ReloadButton::GetAcceleratorForCommandId(
+    int command_id,
+    ui::Accelerator* accelerator) const {
   switch (command_id) {
     case IDS_RELOAD_MENU_NORMAL_RELOAD_ITEM:
       GetWidget()->GetAccelerator(IDC_RELOAD, accelerator);
diff --git a/chrome/browser/ui/views/toolbar/reload_button.h b/chrome/browser/ui/views/toolbar/reload_button.h
index b9e8bf2..31717773 100644
--- a/chrome/browser/ui/views/toolbar/reload_button.h
+++ b/chrome/browser/ui/views/toolbar/reload_button.h
@@ -63,7 +63,7 @@
   bool IsCommandIdEnabled(int command_id) const override;
   bool IsCommandIdVisible(int command_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
 
  private:
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc
index c4785ea..1bb235c 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -463,7 +463,7 @@
 // ToolbarView, ui::AcceleratorProvider implementation:
 
 bool ToolbarView::GetAcceleratorForCommandId(int command_id,
-    ui::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) const {
   return GetWidget()->GetAccelerator(command_id, accelerator);
 }
 
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.h b/chrome/browser/ui/views/toolbar/toolbar_view.h
index 9276225..d8a12a50 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.h
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.h
@@ -137,7 +137,7 @@
 
   // ui::AcceleratorProvider:
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
 
   // views::View:
   gfx::Size GetPreferredSize() const override;
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view.cc b/chrome/browser/ui/views/translate/translate_bubble_view.cc
index a864fc1..29f24e21 100644
--- a/chrome/browser/ui/views/translate/translate_bubble_view.cc
+++ b/chrome/browser/ui/views/translate/translate_bubble_view.cc
@@ -318,7 +318,7 @@
 
 bool TranslateBubbleView::GetAcceleratorForCommandId(
     int command_id,
-    ui::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) const {
   return false;
 }
 
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view.h b/chrome/browser/ui/views/translate/translate_bubble_view.h
index 7bf93806..ec8f744 100644
--- a/chrome/browser/ui/views/translate/translate_bubble_view.h
+++ b/chrome/browser/ui/views/translate/translate_bubble_view.h
@@ -109,7 +109,7 @@
   bool IsCommandIdChecked(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
 
   // views::StyledLabelListener method.
diff --git a/chrome/browser/ui/views/website_settings/chooser_bubble_ui_view.cc b/chrome/browser/ui/views/website_settings/chooser_bubble_ui_view.cc
index b247e10..c6cb2d1 100644
--- a/chrome/browser/ui/views/website_settings/chooser_bubble_ui_view.cc
+++ b/chrome/browser/ui/views/website_settings/chooser_bubble_ui_view.cc
@@ -21,15 +21,11 @@
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/browser/ui/views/location_bar/location_icon_view.h"
 #include "chrome/browser/ui/website_settings/chooser_bubble_delegate.h"
-#include "chrome/grit/generated_resources.h"
 #include "components/bubble/bubble_controller.h"
-#include "components/url_formatter/elide_url.h"
-#include "ui/base/l10n/l10n_util.h"
 #include "ui/views/controls/styled_label.h"
 #include "ui/views/controls/styled_label_listener.h"
 #include "ui/views/controls/table/table_view_observer.h"
 #include "ui/views/window/dialog_client_view.h"
-#include "url/origin.h"
 
 std::unique_ptr<BubbleUi> ChooserBubbleDelegate::BuildBubbleUi() {
   return base::WrapUnique(
@@ -81,7 +77,6 @@
   void UpdateTableModel() const;
 
  private:
-  url::Origin origin_;
   ChooserContentView* chooser_content_view_;
   BubbleReference bubble_reference_;
 
@@ -109,7 +104,6 @@
   // | Not seeing your device? Get help |
   // ------------------------------------
 
-  origin_ = chooser_controller->GetOrigin();
   chooser_content_view_ =
       new ChooserContentView(this, std::move(chooser_controller));
 }
@@ -117,10 +111,7 @@
 ChooserBubbleUiViewDelegate::~ChooserBubbleUiViewDelegate() {}
 
 base::string16 ChooserBubbleUiViewDelegate::GetWindowTitle() const {
-  return l10n_util::GetStringFUTF16(
-      IDS_DEVICE_CHOOSER_PROMPT,
-      url_formatter::FormatOriginForSecurityDisplay(
-          origin_, url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC));
+  return chooser_content_view_->GetWindowTitle();
 }
 
 base::string16 ChooserBubbleUiViewDelegate::GetDialogButtonLabel(
diff --git a/chrome/browser/ui/website_settings/mock_permission_bubble_factory.cc b/chrome/browser/ui/website_settings/mock_permission_bubble_factory.cc
index 94955902..fc135d73 100644
--- a/chrome/browser/ui/website_settings/mock_permission_bubble_factory.cc
+++ b/chrome/browser/ui/website_settings/mock_permission_bubble_factory.cc
@@ -7,16 +7,16 @@
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
+#include "chrome/browser/permissions/permission_request_manager.h"
 #include "chrome/browser/ui/website_settings/mock_permission_bubble_view.h"
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
 
 MockPermissionBubbleFactory::MockPermissionBubbleFactory(
-    PermissionBubbleManager* manager)
+    PermissionRequestManager* manager)
     : can_update_ui_(false),
       show_count_(0),
       requests_count_(0),
       total_requests_count_(0),
-      response_type_(PermissionBubbleManager::NONE),
+      response_type_(PermissionRequestManager::NONE),
       manager_(manager) {
   manager->view_factory_ =
       base::Bind(&MockPermissionBubbleFactory::Create, base::Unretained(this));
diff --git a/chrome/browser/ui/website_settings/mock_permission_bubble_factory.h b/chrome/browser/ui/website_settings/mock_permission_bubble_factory.h
index 471039f..5574e0d 100644
--- a/chrome/browser/ui/website_settings/mock_permission_bubble_factory.h
+++ b/chrome/browser/ui/website_settings/mock_permission_bubble_factory.h
@@ -8,8 +8,7 @@
 #include <memory>
 #include <vector>
 
-#include "base/callback.h"
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
+#include "chrome/browser/permissions/permission_request_manager.h"
 
 class Browser;
 class PermissionBubbleView;
@@ -19,10 +18,10 @@
 // test the bubble manager logic. Should not be used for anything that requires
 // actual UI.
 // See example usage in
-// chrome/browser/ui/website_settings/permission_bubble_manager_unittest.cc
+// chrome/browser/permissions/permission_request_manager_unittest.cc
 class MockPermissionBubbleFactory {
  public:
-  explicit MockPermissionBubbleFactory(PermissionBubbleManager* manager);
+  explicit MockPermissionBubbleFactory(PermissionRequestManager* manager);
   ~MockPermissionBubbleFactory();
 
   // Create method called by the PBM to show a bubble.
@@ -34,7 +33,7 @@
 
   void DocumentOnLoadCompletedInMainFrame();
 
-  void set_response_type(PermissionBubbleManager::AutoResponseType type) {
+  void set_response_type(PermissionRequestManager::AutoResponseType type) {
     response_type_ = type;
   }
 
@@ -65,12 +64,12 @@
   int requests_count_;
   int total_requests_count_;
   std::vector<MockPermissionBubbleView*> views_;
-  PermissionBubbleManager::AutoResponseType response_type_;
+  PermissionRequestManager::AutoResponseType response_type_;
 
   base::Closure show_bubble_quit_closure_;
 
   // The bubble manager that will be associated with this factory.
-  PermissionBubbleManager* manager_;
+  PermissionRequestManager* manager_;
 
   DISALLOW_COPY_AND_ASSIGN(MockPermissionBubbleFactory);
 };
diff --git a/chrome/browser/ui/website_settings/mock_permission_bubble_view.cc b/chrome/browser/ui/website_settings/mock_permission_bubble_view.cc
index 470ac0a4..598375e 100644
--- a/chrome/browser/ui/website_settings/mock_permission_bubble_view.cc
+++ b/chrome/browser/ui/website_settings/mock_permission_bubble_view.cc
@@ -6,8 +6,8 @@
 
 #include "base/bind.h"
 #include "base/run_loop.h"
+#include "chrome/browser/permissions/permission_request_manager.h"
 #include "chrome/browser/ui/website_settings/mock_permission_bubble_factory.h"
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
 
 MockPermissionBubbleView::~MockPermissionBubbleView() {
   Hide();
@@ -48,7 +48,7 @@
 
 MockPermissionBubbleView::MockPermissionBubbleView(
     MockPermissionBubbleFactory* factory,
-    PermissionBubbleManager* manager)
+    PermissionRequestManager* manager)
     : factory_(factory),
       manager_(manager),
       can_update_ui_(true),
diff --git a/chrome/browser/ui/website_settings/mock_permission_bubble_view.h b/chrome/browser/ui/website_settings/mock_permission_bubble_view.h
index 2a27f997..dd29f8b7 100644
--- a/chrome/browser/ui/website_settings/mock_permission_bubble_view.h
+++ b/chrome/browser/ui/website_settings/mock_permission_bubble_view.h
@@ -8,7 +8,7 @@
 #include "chrome/browser/ui/website_settings/permission_bubble_view.h"
 
 class MockPermissionBubbleFactory;
-class PermissionBubbleManager;
+class PermissionRequestManager;
 
 // Provides a skeleton class for unit and browser testing when trying to test
 // the bubble manager logic. Should not be used for anything that requires
@@ -32,10 +32,10 @@
   friend class MockPermissionBubbleFactory;
 
   MockPermissionBubbleView(MockPermissionBubbleFactory* factory,
-                           PermissionBubbleManager* manager);
+                           PermissionRequestManager* manager);
 
   MockPermissionBubbleFactory* factory_;
-  PermissionBubbleManager* manager_;
+  PermissionRequestManager* manager_;
   bool can_update_ui_;
   bool is_visible_;
 };
diff --git a/chrome/browser/ui/website_settings/permission_bubble_view.h b/chrome/browser/ui/website_settings/permission_bubble_view.h
index 2c6cabd..15afc8f 100644
--- a/chrome/browser/ui/website_settings/permission_bubble_view.h
+++ b/chrome/browser/ui/website_settings/permission_bubble_view.h
@@ -12,7 +12,7 @@
 #include "ui/gfx/native_widget_types.h"
 
 class Browser;
-class PermissionBubbleManager;
+class PermissionRequestManager;
 class PermissionBubbleRequest;
 
 // This class is the platform-independent interface through which the permission
diff --git a/chrome/browser/ui/website_settings/permission_menu_model.cc b/chrome/browser/ui/website_settings/permission_menu_model.cc
index 7a6ff0d..9944b12 100644
--- a/chrome/browser/ui/website_settings/permission_menu_model.cc
+++ b/chrome/browser/ui/website_settings/permission_menu_model.cc
@@ -121,7 +121,7 @@
 
 bool PermissionMenuModel::GetAcceleratorForCommandId(
     int command_id,
-    ui::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) const {
   // Accelerators are not supported.
   return false;
 }
diff --git a/chrome/browser/ui/website_settings/permission_menu_model.h b/chrome/browser/ui/website_settings/permission_menu_model.h
index 7ec2ad2..8a28b1a 100644
--- a/chrome/browser/ui/website_settings/permission_menu_model.h
+++ b/chrome/browser/ui/website_settings/permission_menu_model.h
@@ -35,7 +35,7 @@
   bool IsCommandIdChecked(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
 
  private:
diff --git a/chrome/browser/ui/website_settings/website_settings.cc b/chrome/browser/ui/website_settings/website_settings.cc
index eb8ff4b..b6d3012d 100644
--- a/chrome/browser/ui/website_settings/website_settings.cc
+++ b/chrome/browser/ui/website_settings/website_settings.cc
@@ -293,8 +293,8 @@
     // in the permissions layer. See crbug.com/469221.
     content::PermissionType permission_type;
     if (PermissionUtil::GetPermissionType(type, &permission_type)) {
-      PermissionUmaUtil::PermissionRevoked(permission_type,
-                                           this->site_url_);
+      PermissionUmaUtil::PermissionRevoked(permission_type, this->site_url_,
+                                           this->profile_);
     }
   }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/network_dropdown_handler.cc b/chrome/browser/ui/webui/chromeos/login/network_dropdown_handler.cc
index bdbf7fc..b8bb9d6 100644
--- a/chrome/browser/ui/webui/chromeos/login/network_dropdown_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/network_dropdown_handler.cc
@@ -5,9 +5,12 @@
 #include "chrome/browser/ui/webui/chromeos/login/network_dropdown_handler.h"
 
 #include "chrome/browser/chromeos/login/ui/webui_login_display.h"
+#include "chrome/browser/chromeos/options/network_config_view.h"
+#include "chrome/browser/chromeos/ui/choose_mobile_network_dialog.h"
 #include "chrome/browser/ui/webui/chromeos/login/network_dropdown.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/login/localized_values_builder.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
 
 namespace {
 
@@ -18,6 +21,10 @@
 const char kJsApiNetworkDropdownShow[] = "networkDropdownShow";
 const char kJsApiNetworkDropdownHide[] = "networkDropdownHide";
 const char kJsApiNetworkDropdownRefresh[] = "networkDropdownRefresh";
+const char kJsApiLaunchProxySettingsDialog[] = "launchProxySettingsDialog";
+const char kJsApiLaunchAddWiFiNetworkDialog[] = "launchAddWiFiNetworkDialog";
+const char kJsApiLaunchAddMobileNetworkDialog[] =
+    "launchAddMobileNetworkDialog";
 
 }  // namespace
 
@@ -57,6 +64,28 @@
               &NetworkDropdownHandler::HandleNetworkDropdownHide);
   AddCallback(kJsApiNetworkDropdownRefresh,
               &NetworkDropdownHandler::HandleNetworkDropdownRefresh);
+
+  // MD-OOBE
+  AddCallback(kJsApiLaunchProxySettingsDialog,
+              &NetworkDropdownHandler::HandleLaunchProxySettingsDialog);
+  AddCallback(kJsApiLaunchAddWiFiNetworkDialog,
+              &NetworkDropdownHandler::HandleLaunchAddWiFiNetworkDialog);
+  AddCallback(kJsApiLaunchAddMobileNetworkDialog,
+              &NetworkDropdownHandler::HandleLaunchAddMobileNetworkDialog);
+}
+
+void NetworkDropdownHandler::HandleLaunchProxySettingsDialog() {
+  dropdown_->OpenButtonOptions();
+}
+
+void NetworkDropdownHandler::HandleLaunchAddWiFiNetworkDialog() {
+  gfx::NativeWindow native_window = GetNativeWindow();
+  NetworkConfigView::ShowForType(shill::kTypeWifi, native_window);
+}
+
+void NetworkDropdownHandler::HandleLaunchAddMobileNetworkDialog() {
+  gfx::NativeWindow native_window = GetNativeWindow();
+  ChooseMobileNetworkDialog::ShowDialog(native_window);
 }
 
 void NetworkDropdownHandler::OnConnectToNetworkRequested() {
diff --git a/chrome/browser/ui/webui/chromeos/login/network_dropdown_handler.h b/chrome/browser/ui/webui/chromeos/login/network_dropdown_handler.h
index 6a707f7..6c70b655 100644
--- a/chrome/browser/ui/webui/chromeos/login/network_dropdown_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/network_dropdown_handler.h
@@ -52,6 +52,10 @@
   // Handles network drop-down refresh.
   void HandleNetworkDropdownRefresh();
 
+  void HandleLaunchProxySettingsDialog();
+  void HandleLaunchAddWiFiNetworkDialog();
+  void HandleLaunchAddMobileNetworkDialog();
+
   std::unique_ptr<NetworkDropdown> dropdown_;
 
   base::ObserverList<Observer> observers_;
diff --git a/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc
index 2f69776..483fc906 100644
--- a/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc
@@ -162,6 +162,13 @@
   builder->Add("proxySettings", IDS_OPTIONS_PROXIES_CONFIGURE_BUTTON);
   builder->Add("continueButton", IDS_NETWORK_SELECTION_CONTINUE_BUTTON);
   builder->Add("debuggingFeaturesLink", IDS_NETWORK_ENABLE_DEV_FEATURES_LINK);
+
+  // MD-OOBE
+  builder->Add("networkSectionTitle", IDS_NETWORK_SECTION_TITE);
+  builder->Add("networkSectionHint", IDS_NETWORK_SECTION_HINT);
+  builder->Add("proxySettingsMenuName", IDS_PROXY_SETTINGS_MENU_NAME);
+  builder->Add("addWiFiNetworkMenuName", IDS_ADD_WI_FI_NETWORK_MENU_NAME);
+  builder->Add("addMobileNetworkMenuName", IDS_ADD_MOBILE_NETWORK_MENU_NAME);
 }
 
 void NetworkScreenHandler::GetAdditionalParameters(
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
index 71d86f2..d06042f 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -499,8 +499,9 @@
 
   bool new_kiosk_ui = KioskAppMenuHandler::EnableNewKioskUI();
   localized_strings->SetString("newKioskUI", new_kiosk_ui ? "on" : "off");
-
   localized_strings->SetString("newOobeUI", UseMDOobe() ? "on" : "off");
+
+  NetworkUI::GetLocalizedStrings(localized_strings);
 }
 
 void OobeUI::AddScreenHandler(BaseScreenHandler* handler) {
diff --git a/chrome/browser/ui/webui/chromeos/network_ui.cc b/chrome/browser/ui/webui/chromeos/network_ui.cc
index c6593376..29f0eaac 100644
--- a/chrome/browser/ui/webui/chromeos/network_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/network_ui.cc
@@ -23,6 +23,7 @@
 #include "content/public/browser/web_ui_message_handler.h"
 #include "grit/browser_resources.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "ui/chromeos/strings/grit/ui_chromeos_strings.h"
 
 namespace chromeos {
@@ -137,6 +138,74 @@
 
 }  // namespace
 
+// static
+void NetworkUI::GetLocalizedStrings(base::DictionaryValue* localized_strings) {
+  localized_strings->SetString("titleText",
+                               l10n_util::GetStringUTF16(IDS_NETWORK_UI_TITLE));
+
+  localized_strings->SetString("titleText",
+                               l10n_util::GetStringUTF16(IDS_NETWORK_UI_TITLE));
+  localized_strings->SetString(
+      "autoRefreshText",
+      l10n_util::GetStringUTF16(IDS_NETWORK_UI_AUTO_REFRESH));
+  localized_strings->SetString(
+      "deviceLogLinkText", l10n_util::GetStringUTF16(IDS_DEVICE_LOG_LINK_TEXT));
+  localized_strings->SetString(
+      "networkRefreshText", l10n_util::GetStringUTF16(IDS_NETWORK_UI_REFRESH));
+  localized_strings->SetString(
+      "clickToExpandText", l10n_util::GetStringUTF16(IDS_NETWORK_UI_EXPAND));
+  localized_strings->SetString(
+      "propertyFormatText",
+      l10n_util::GetStringUTF16(IDS_NETWORK_UI_PROPERTY_FORMAT));
+
+  localized_strings->SetString(
+      "normalFormatOption",
+      l10n_util::GetStringUTF16(IDS_NETWORK_UI_FORMAT_NORMAL));
+  localized_strings->SetString(
+      "managedFormatOption",
+      l10n_util::GetStringUTF16(IDS_NETWORK_UI_FORMAT_MANAGED));
+  localized_strings->SetString(
+      "stateFormatOption",
+      l10n_util::GetStringUTF16(IDS_NETWORK_UI_FORMAT_STATE));
+  localized_strings->SetString(
+      "shillFormatOption",
+      l10n_util::GetStringUTF16(IDS_NETWORK_UI_FORMAT_SHILL));
+
+  localized_strings->SetString(
+      "visibleNetworksLabel",
+      l10n_util::GetStringUTF16(IDS_NETWORK_UI_VISIBLE_NETWORKS));
+  localized_strings->SetString(
+      "favoriteNetworksLabel",
+      l10n_util::GetStringUTF16(IDS_NETWORK_UI_FAVORITE_NETWORKS));
+
+  localized_strings->SetString(
+      "networkConnected",
+      l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_CONNECTED));
+  localized_strings->SetString(
+      "networkConnecting",
+      l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_CONNECTING));
+  localized_strings->SetString(
+      "networkDisabled",
+      l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_NETWORK_DISABLED));
+  localized_strings->SetString(
+      "networkNotConnected",
+      l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_NOT_CONNECTED));
+  localized_strings->SetString(
+      "OncTypeCellular", l10n_util::GetStringUTF16(IDS_NETWORK_TYPE_CELLULAR));
+  localized_strings->SetString(
+      "OncTypeEthernet", l10n_util::GetStringUTF16(IDS_NETWORK_TYPE_ETHERNET));
+  localized_strings->SetString("OncTypeVPN",
+                               l10n_util::GetStringUTF16(IDS_NETWORK_TYPE_VPN));
+  localized_strings->SetString(
+      "OncTypeWiFi", l10n_util::GetStringUTF16(IDS_NETWORK_TYPE_WIFI));
+  localized_strings->SetString(
+      "OncTypeWimax", l10n_util::GetStringUTF16(IDS_NETWORK_TYPE_WIMAX));
+  localized_strings->SetString(
+      "vpnNameTemplate",
+      l10n_util::GetStringUTF16(
+          IDS_OPTIONS_SETTINGS_SECTION_THIRD_PARTY_VPN_NAME_TEMPLATE));
+}
+
 NetworkUI::NetworkUI(content::WebUI* web_ui)
     : content::WebUIController(web_ui) {
   web_ui->AddMessageHandler(new NetworkConfigMessageHandler());
@@ -144,44 +213,12 @@
   // Enable extension API calls in the WebUI.
   extensions::TabHelper::CreateForWebContents(web_ui->GetWebContents());
 
+  base::DictionaryValue localized_strings;
+  GetLocalizedStrings(&localized_strings);
+
   content::WebUIDataSource* html =
       content::WebUIDataSource::Create(chrome::kChromeUINetworkHost);
-
-  html->AddLocalizedString("titleText", IDS_NETWORK_UI_TITLE);
-  html->AddLocalizedString("autoRefreshText", IDS_NETWORK_UI_AUTO_REFRESH);
-  html->AddLocalizedString("deviceLogLinkText", IDS_DEVICE_LOG_LINK_TEXT);
-  html->AddLocalizedString("networkRefreshText", IDS_NETWORK_UI_REFRESH);
-  html->AddLocalizedString("clickToExpandText", IDS_NETWORK_UI_EXPAND);
-  html->AddLocalizedString("propertyFormatText",
-                           IDS_NETWORK_UI_PROPERTY_FORMAT);
-
-  html->AddLocalizedString("normalFormatOption", IDS_NETWORK_UI_FORMAT_NORMAL);
-  html->AddLocalizedString("managedFormatOption",
-                           IDS_NETWORK_UI_FORMAT_MANAGED);
-  html->AddLocalizedString("stateFormatOption", IDS_NETWORK_UI_FORMAT_STATE);
-  html->AddLocalizedString("shillFormatOption", IDS_NETWORK_UI_FORMAT_SHILL);
-
-  html->AddLocalizedString("visibleNetworksLabel",
-                           IDS_NETWORK_UI_VISIBLE_NETWORKS);
-  html->AddLocalizedString("favoriteNetworksLabel",
-                           IDS_NETWORK_UI_FAVORITE_NETWORKS);
-
-  html->AddLocalizedString("networkConnected",
-                           IDS_ASH_STATUS_TRAY_NETWORK_CONNECTED);
-  html->AddLocalizedString("networkConnecting",
-                           IDS_ASH_STATUS_TRAY_NETWORK_CONNECTING);
-  html->AddLocalizedString("networkDisabled",
-                           IDS_OPTIONS_SETTINGS_NETWORK_DISABLED);
-  html->AddLocalizedString("networkNotConnected",
-                           IDS_ASH_STATUS_TRAY_NETWORK_NOT_CONNECTED);
-  html->AddLocalizedString("OncTypeCellular", IDS_NETWORK_TYPE_CELLULAR);
-  html->AddLocalizedString("OncTypeEthernet", IDS_NETWORK_TYPE_ETHERNET);
-  html->AddLocalizedString("OncTypeVPN", IDS_NETWORK_TYPE_VPN);
-  html->AddLocalizedString("OncTypeWiFi", IDS_NETWORK_TYPE_WIFI);
-  html->AddLocalizedString("OncTypeWimax", IDS_NETWORK_TYPE_WIMAX);
-  html->AddLocalizedString(
-      "vpnNameTemplate",
-      IDS_OPTIONS_SETTINGS_SECTION_THIRD_PARTY_VPN_NAME_TEMPLATE);
+  html->AddLocalizedStrings(localized_strings);
 
   html->SetJsonPath("strings.js");
   html->AddResourcePath("network_ui.css", IDR_NETWORK_UI_CSS);
diff --git a/chrome/browser/ui/webui/chromeos/network_ui.h b/chrome/browser/ui/webui/chromeos/network_ui.h
index 72d7863..e06e6344 100644
--- a/chrome/browser/ui/webui/chromeos/network_ui.h
+++ b/chrome/browser/ui/webui/chromeos/network_ui.h
@@ -8,6 +8,10 @@
 #include "base/macros.h"
 #include "content/public/browser/web_ui_controller.h"
 
+namespace base {
+class DictionaryValue;
+};
+
 namespace chromeos {
 
 class NetworkUI : public content::WebUIController {
@@ -15,6 +19,8 @@
   explicit NetworkUI(content::WebUI* web_ui);
   ~NetworkUI() override;
 
+  static void GetLocalizedStrings(base::DictionaryValue* localized_strings);
+
  private:
   DISALLOW_COPY_AND_ASSIGN(NetworkUI);
 };
diff --git a/chrome/browser/ui/webui/ntp/ntp_user_data_logger.cc b/chrome/browser/ui/webui/ntp/ntp_user_data_logger.cc
index 6773db8..16f07de 100644
--- a/chrome/browser/ui/webui/ntp/ntp_user_data_logger.cc
+++ b/chrome/browser/ui/webui/ntp/ntp_user_data_logger.cc
@@ -100,27 +100,21 @@
 void NTPUserDataLogger::LogEvent(NTPLoggingEventType event,
                                  base::TimeDelta time) {
   switch (event) {
-    // It is possible that our page gets update with a different set of
-    // suggestions if the NTP is left open enough time.
-    // In either case, we want to flush our stats before recounting again.
     case NTP_SERVER_SIDE_SUGGESTION:
-      if (has_client_side_suggestions_)
-        EmitNtpStatistics(EmitReason::INTERNAL_FLUSH);
       has_server_side_suggestions_ = true;
       break;
     case NTP_CLIENT_SIDE_SUGGESTION:
-      if (has_server_side_suggestions_)
-        EmitNtpStatistics(EmitReason::INTERNAL_FLUSH);
       has_client_side_suggestions_ = true;
       break;
     case NTP_TILE:
+      // TODO(sfiera): remove NTP_TILE and use NTP_*_SIDE_SUGGESTION.
       number_of_tiles_++;
       break;
     case NTP_TILE_LOADED:
-      // The time at which the last tile has loaded (title, thumbnail or single)
-      // is a good proxy for the total load time of the NTP, therefore we keep
-      // the max as the load time.
-      load_time_ = std::max(load_time_, time);
+      // We no longer emit statistics for the multi-iframe NTP.
+      break;
+    case NTP_ALL_TILES_LOADED:
+      EmitNtpStatistics(time);
       break;
     default:
       NOTREACHED();
@@ -165,17 +159,8 @@
   content::RecordAction(base::UserMetricsAction("MostVisited_Clicked"));
 }
 
-void NTPUserDataLogger::TabDeactivated() {
-  EmitNtpStatistics(EmitReason::CLOSED);
-}
-
-void NTPUserDataLogger::MostVisitedItemsChanged() {
-  EmitNtpStatistics(EmitReason::MV_CHANGED);
-}
-
 NTPUserDataLogger::NTPUserDataLogger(content::WebContents* contents)
-    : content::WebContentsObserver(contents),
-      has_server_side_suggestions_(false),
+    : has_server_side_suggestions_(false),
       has_client_side_suggestions_(false),
       number_of_tiles_(0),
       has_emitted_(false),
@@ -201,40 +186,25 @@
   }
 }
 
-// content::WebContentsObserver override
-void NTPUserDataLogger::NavigationEntryCommitted(
-    const content::LoadCommittedDetails& load_details) {
-  if (!load_details.previous_url.is_valid())
-    return;
-
-  if (search::MatchesOriginAndPath(ntp_url_, load_details.previous_url))
-    EmitNtpStatistics(EmitReason::NAVIGATED_AWAY);
-}
-
-void NTPUserDataLogger::EmitNtpStatistics(EmitReason reason) {
+void NTPUserDataLogger::EmitNtpStatistics(base::TimeDelta load_time) {
   // We only send statistics once per page.
-  // And we don't send if there are no tiles recorded.
-  if (has_emitted_ || !number_of_tiles_)
+  if (has_emitted_)
     return;
 
-  // LoadTime only gets update once per page, so we don't have it on reloads.
-  if (load_time_ > base::TimeDelta::FromMilliseconds(0)) {
-    logLoadTimeHistogram("NewTabPage.LoadTime", load_time_);
+  logLoadTimeHistogram("NewTabPage.LoadTime", load_time);
 
-    // Split between ML and MV.
-    std::string type = has_server_side_suggestions_ ?
-        "MostLikely" : "MostVisited";
-    logLoadTimeHistogram("NewTabPage.LoadTime." + type, load_time_);
-    // Split between Web and Local.
-    std::string source = ntp_url_.SchemeIsHTTPOrHTTPS() ? "Web" : "LocalNTP";
-    logLoadTimeHistogram("NewTabPage.LoadTime." + source, load_time_);
+  // Split between ML and MV.
+  std::string type = has_server_side_suggestions_ ?
+      "MostLikely" : "MostVisited";
+  logLoadTimeHistogram("NewTabPage.LoadTime." + type, load_time);
+  // Split between Web and Local.
+  std::string source = ntp_url_.SchemeIsHTTPOrHTTPS() ? "Web" : "LocalNTP";
+  logLoadTimeHistogram("NewTabPage.LoadTime." + source, load_time);
 
-    // Split between Startup and non-startup.
-    std::string status = during_startup_ ? "Startup" : "NewTab";
-    logLoadTimeHistogram("NewTabPage.LoadTime." + status, load_time_);
+  // Split between Startup and non-startup.
+  std::string status = during_startup_ ? "Startup" : "NewTab";
+  logLoadTimeHistogram("NewTabPage.LoadTime." + status, load_time);
 
-    load_time_ = base::TimeDelta::FromMilliseconds(0);
-  }
   has_server_side_suggestions_ = false;
   has_client_side_suggestions_ = false;
   UMA_HISTOGRAM_CUSTOM_COUNTS(
diff --git a/chrome/browser/ui/webui/ntp/ntp_user_data_logger.h b/chrome/browser/ui/webui/ntp/ntp_user_data_logger.h
index 6e6f965..bb96075 100644
--- a/chrome/browser/ui/webui/ntp/ntp_user_data_logger.h
+++ b/chrome/browser/ui/webui/ntp/ntp_user_data_logger.h
@@ -11,7 +11,6 @@
 #include "base/macros.h"
 #include "base/time/time.h"
 #include "chrome/common/search/ntp_logging_events.h"
-#include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
 
 namespace content {
@@ -20,8 +19,7 @@
 
 // Helper class for logging data from the NTP. Attached to each NTP instance.
 class NTPUserDataLogger
-    : public content::WebContentsObserver,
-      public content::WebContentsUserData<NTPUserDataLogger> {
+    : public content::WebContentsUserData<NTPUserDataLogger> {
  public:
   ~NTPUserDataLogger() override;
 
@@ -39,12 +37,6 @@
   // Logs a navigation on one of the NTP tiles by a given source.
   void LogMostVisitedNavigation(int position, NTPLoggingTileSource tile_source);
 
-  // Called when the tab is closed. Logs statistics.
-  void TabDeactivated();
-
-  // Called when the set of most visited sites changes. Flushes statistics.
-  void MostVisitedItemsChanged();
-
  protected:
   explicit NTPUserDataLogger(content::WebContents* contents);
 
@@ -58,20 +50,10 @@
   FRIEND_TEST_ALL_PREFIXES(NTPUserDataLoggerTest,
                            TestLogging);
 
-  // content::WebContentsObserver override
-  void NavigationEntryCommitted(
-      const content::LoadCommittedDetails& load_details) override;
-
-  // To clarify at the call site whether we are calling EmitNtpStatistics() for
-  // a good reason (CLOSED, NAVIGATED_AWAY) or a questionable one (MV_CHANGED,
-  // INTERNAL_FLUSH).
-  // TODO(sfiera): remove MV_CHANGED, INTERNAL_FLUSH.
-  enum class EmitReason { CLOSED, NAVIGATED_AWAY, MV_CHANGED, INTERNAL_FLUSH };
-
   // Logs a number of statistics regarding the NTP. Called when an NTP tab is
   // about to be deactivated (be it by switching tabs, losing focus or closing
   // the tab/shutting down Chrome), or when the user navigates to a URL.
-  void EmitNtpStatistics(EmitReason reason);
+  void EmitNtpStatistics(base::TimeDelta load_time);
 
   // True if at least one iframe came from a server-side suggestion.
   bool has_server_side_suggestions_;
@@ -83,9 +65,6 @@
   // or an external tile.
   size_t number_of_tiles_;
 
-  // Time from navigation start it took to load the NTP in milliseconds.
-  base::TimeDelta load_time_;
-
   // Whether we have already emitted NTP stats for this web contents.
   bool has_emitted_;
 
diff --git a/chrome/browser/ui/webui/ntp/ntp_user_data_logger_unittest.cc b/chrome/browser/ui/webui/ntp/ntp_user_data_logger_unittest.cc
index dbdedeb..43d9cbc7 100644
--- a/chrome/browser/ui/webui/ntp/ntp_user_data_logger_unittest.cc
+++ b/chrome/browser/ui/webui/ntp/ntp_user_data_logger_unittest.cc
@@ -52,13 +52,13 @@
     logger.LogEvent(NTP_TILE, delta);
   logger.LogEvent(NTP_SERVER_SIDE_SUGGESTION, delta);
 
-  logger.EmitNtpStatistics(NTPUserDataLogger::EmitReason::NAVIGATED_AWAY);
+  logger.LogEvent(NTP_ALL_TILES_LOADED, delta);
 
   EXPECT_EQ(1, GetTotalCount("NewTabPage.NumberOfTiles"));
   EXPECT_EQ(1, GetBinCount("NewTabPage.NumberOfTiles", 8));
 
   // Statistics should be reset to 0, so we should not log anything else.
-  logger.EmitNtpStatistics(NTPUserDataLogger::EmitReason::NAVIGATED_AWAY);
+  logger.LogEvent(NTP_ALL_TILES_LOADED, delta);
   EXPECT_EQ(1, GetTotalCount("NewTabPage.NumberOfTiles"));
 }
 
diff --git a/chrome/browser/ui/webui/options/browser_options_handler.cc b/chrome/browser/ui/webui/options/browser_options_handler.cc
index f0366fd..c745a6fa 100644
--- a/chrome/browser/ui/webui/options/browser_options_handler.cc
+++ b/chrome/browser/ui/webui/options/browser_options_handler.cc
@@ -537,10 +537,6 @@
     { "backgroundModeCheckbox", IDS_OPTIONS_SYSTEM_ENABLE_BACKGROUND_MODE },
 #endif  // defined(OS_MACOSX) && !defined(OS_CHROMEOS)
 
-#if defined(ENABLE_SETTINGS_APP)
-    { "profilesAppListSwitch", IDS_SETTINGS_APP_PROFILES_SWITCH_BUTTON_LABEL },
-#endif  // defined(ENABLE_SETTINGS_APP)
-
 #if defined(ENABLE_SERVICE_DISCOVERY)
     { "cloudPrintDevicesPageButton", IDS_LOCAL_DISCOVERY_DEVICES_PAGE_BUTTON },
     { "cloudPrintEnableNotificationsLabel",
@@ -548,23 +544,6 @@
 #endif  // defined(ENABLE_SERVICE_DISCOVERY)
   };
 
-#if defined(ENABLE_SETTINGS_APP)
-  static OptionsStringResource app_resources[] = {
-    { "syncOverview", IDS_SETTINGS_APP_SYNC_OVERVIEW },
-    { "syncButtonTextStart", IDS_SYNC_START_SYNC_BUTTON_LABEL,
-      IDS_SETTINGS_APP_LAUNCHER_PRODUCT_NAME },
-    { "profilesSingleUser", IDS_PROFILES_SINGLE_USER_MESSAGE,
-      IDS_SETTINGS_APP_LAUNCHER_PRODUCT_NAME },
-    { "languageSectionLabel", IDS_OPTIONS_ADVANCED_LANGUAGE_LABEL,
-      IDS_SETTINGS_APP_LAUNCHER_PRODUCT_NAME },
-    { "proxiesLabelSystem", IDS_OPTIONS_SYSTEM_PROXIES_LABEL,
-      IDS_SETTINGS_APP_LAUNCHER_PRODUCT_NAME },
-  };
-  base::DictionaryValue* app_values = NULL;
-  CHECK(values->GetDictionary(kSettingsAppKey, &app_values));
-  RegisterStrings(app_values, app_resources, arraysize(app_resources));
-#endif
-
   RegisterStrings(values, resources, arraysize(resources));
   RegisterTitle(values, "doNotTrackConfirmOverlay",
                 IDS_OPTIONS_ENABLE_DO_NOT_TRACK_BUBBLE_TITLE);
diff --git a/chrome/browser/ui/webui/options/chromeos/storage_manager_handler.cc b/chrome/browser/ui/webui/options/chromeos/storage_manager_handler.cc
index 6aa8e1f..c49798d 100644
--- a/chrome/browser/ui/webui/options/chromeos/storage_manager_handler.cc
+++ b/chrome/browser/ui/webui/options/chromeos/storage_manager_handler.cc
@@ -371,6 +371,13 @@
         base::Bind(&StorageManagerHandler::OnGetOtherUserSize,
                    weak_ptr_factory_.GetWeakPtr()));
   }
+  // We should show "0 B" if there is no other user.
+  if (other_users_.empty()) {
+    updating_other_users_size_ = false;
+    web_ui()->CallJavascriptFunctionUnsafe(
+        "options.StorageManager.setOtherUsersSize",
+        base::StringValue(ui::FormatBytes(0)));
+  }
 }
 
 void StorageManagerHandler::OnGetOtherUserSize(bool success, int64_t size) {
diff --git a/chrome/browser/ui/webui/options/cookies_view_handler.cc b/chrome/browser/ui/webui/options/cookies_view_handler.cc
index 0d2fb42c..2737f661 100644
--- a/chrome/browser/ui/webui/options/cookies_view_handler.cc
+++ b/chrome/browser/ui/webui/options/cookies_view_handler.cc
@@ -216,10 +216,8 @@
         new BrowsingDataServiceWorkerHelper(service_worker_context),
         new BrowsingDataCacheStorageHelper(cache_storage_context),
         BrowsingDataFlashLSOHelper::Create(profile));
-    cookies_tree_model_.reset(
-        new CookiesTreeModel(container,
-                             profile->GetExtensionSpecialStoragePolicy(),
-                             false));
+    cookies_tree_model_.reset(new CookiesTreeModel(
+        container, profile->GetExtensionSpecialStoragePolicy()));
     cookies_tree_model_->AddCookiesTreeObserver(this);
   }
 }
diff --git a/chrome/browser/ui/webui/options/language_options_handler_common.cc b/chrome/browser/ui/webui/options/language_options_handler_common.cc
index 579895e..ee249ea 100644
--- a/chrome/browser/ui/webui/options/language_options_handler_common.cc
+++ b/chrome/browser/ui/webui/options/language_options_handler_common.cc
@@ -95,23 +95,6 @@
       IDS_OPTIONS_LANGUAGES_CANNOT_TRANSLATE_IN_THIS_LANGUAGE },
   };
 
-#if defined(ENABLE_SETTINGS_APP)
-  static OptionsStringResource app_resources[] = {
-    { "cannotBeDisplayedInThisLanguage",
-      IDS_OPTIONS_SETTINGS_LANGUAGES_CANNOT_BE_DISPLAYED_IN_THIS_LANGUAGE,
-      IDS_SETTINGS_APP_LAUNCHER_PRODUCT_NAME },
-    { "isDisplayedInThisLanguage",
-      IDS_OPTIONS_SETTINGS_LANGUAGES_IS_DISPLAYED_IN_THIS_LANGUAGE,
-      IDS_SETTINGS_APP_LAUNCHER_PRODUCT_NAME },
-    { "displayInThisLanguage",
-      IDS_OPTIONS_SETTINGS_LANGUAGES_DISPLAY_IN_THIS_LANGUAGE,
-      IDS_SETTINGS_APP_LAUNCHER_PRODUCT_NAME },
-  };
-  base::DictionaryValue* app_values = NULL;
-  CHECK(localized_strings->GetDictionary(kSettingsAppKey, &app_values));
-  RegisterStrings(app_values, app_resources, arraysize(app_resources));
-#endif
-
   RegisterStrings(localized_strings, resources, arraysize(resources));
 
   // The following are resources, rather than local strings.
diff --git a/chrome/browser/ui/webui/options/manage_profile_handler.cc b/chrome/browser/ui/webui/options/manage_profile_handler.cc
index 387e7ce..a1a2493c 100644
--- a/chrome/browser/ui/webui/options/manage_profile_handler.cc
+++ b/chrome/browser/ui/webui/options/manage_profile_handler.cc
@@ -47,11 +47,6 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/webui/web_ui_util.h"
 
-#if defined(ENABLE_SETTINGS_APP)
-#include "chrome/browser/ui/app_list/app_list_service.h"
-#include "content/public/browser/web_contents.h"
-#endif
-
 namespace options {
 
 namespace {
@@ -185,11 +180,6 @@
   web_ui()->RegisterMessageCallback("profileIconSelectionChanged",
       base::Bind(&ManageProfileHandler::ProfileIconSelectionChanged,
                  base::Unretained(this)));
-#if defined(ENABLE_SETTINGS_APP)
-  web_ui()->RegisterMessageCallback("switchAppListProfile",
-      base::Bind(&ManageProfileHandler::SwitchAppListProfile,
-                 base::Unretained(this)));
-#endif
   web_ui()->RegisterMessageCallback("addProfileShortcut",
       base::Bind(&ManageProfileHandler::AddProfileShortcut,
                  base::Unretained(this)));
@@ -413,26 +403,6 @@
   profiles::UpdateProfileName(profile, new_profile_name);
 }
 
-#if defined(ENABLE_SETTINGS_APP)
-void ManageProfileHandler::SwitchAppListProfile(const base::ListValue* args) {
-  DCHECK(args);
-  DCHECK(profiles::IsMultipleProfilesEnabled());
-
-  const base::Value* file_path_value;
-  base::FilePath profile_file_path;
-  if (!args->Get(0, &file_path_value) ||
-      !base::GetValueAsFilePath(*file_path_value, &profile_file_path))
-    return;
-
-  AppListService* app_list_service = AppListService::Get();
-  app_list_service->SetProfilePath(profile_file_path);
-  app_list_service->Show();
-
-  // Close the settings app, since it will now be for the wrong profile.
-  web_ui()->GetWebContents()->Close();
-}
-#endif  // defined(ENABLE_SETTINGS_APP)
-
 void ManageProfileHandler::ProfileIconSelectionChanged(
     const base::ListValue* args) {
   DCHECK(args);
diff --git a/chrome/browser/ui/webui/options/manage_profile_handler.h b/chrome/browser/ui/webui/options/manage_profile_handler.h
index 4407c92..fe6ec6c 100644
--- a/chrome/browser/ui/webui/options/manage_profile_handler.h
+++ b/chrome/browser/ui/webui/options/manage_profile_handler.h
@@ -88,13 +88,6 @@
   // ]
   void SetProfileIconAndName(const base::ListValue* args);
 
-#if defined(ENABLE_SETTINGS_APP)
-  // Callback for the "switchAppListProfile" message. Asks the
-  // app_list_controller to change the profile registered for the AppList.
-  // |args| is of the form: [ {string} profileFilePath ]
-  void SwitchAppListProfile(const base::ListValue* args);
-#endif
-
   // Callback for the 'profileIconSelectionChanged' message. Used to update the
   // name in the manager profile dialog based on the selected icon.
   void ProfileIconSelectionChanged(const base::ListValue* args);
diff --git a/chrome/browser/ui/webui/options/options_ui.cc b/chrome/browser/ui/webui/options/options_ui.cc
index ac1f5d9..9662d5fce 100644
--- a/chrome/browser/ui/webui/options/options_ui.cc
+++ b/chrome/browser/ui/webui/options/options_ui.cc
@@ -207,8 +207,6 @@
 //
 ////////////////////////////////////////////////////////////////////////////////
 
-const char OptionsPageUIHandler::kSettingsAppKey[] = "settingsApp";
-
 OptionsPageUIHandler::OptionsPageUIHandler() {
 }
 
@@ -260,9 +258,6 @@
       WebContentsObserver(web_ui->GetWebContents()),
       initialized_handlers_(false) {
   base::DictionaryValue* localized_strings = new base::DictionaryValue();
-  localized_strings->Set(OptionsPageUIHandler::kSettingsAppKey,
-                         new base::DictionaryValue());
-
   CoreOptionsHandler* core_handler;
 #if defined(OS_CHROMEOS)
   core_handler = new chromeos::options::CoreChromeOSOptionsHandler();
diff --git a/chrome/browser/ui/webui/options/options_ui.h b/chrome/browser/ui/webui/options/options_ui.h
index 1e836f19..a56fbc2 100644
--- a/chrome/browser/ui/webui/options/options_ui.h
+++ b/chrome/browser/ui/webui/options/options_ui.h
@@ -41,9 +41,6 @@
 // The base class handler of Javascript messages of options pages.
 class OptionsPageUIHandler : public content::WebUIMessageHandler {
  public:
-  // Key for identifying the Settings App localized_strings in loadTimeData.
-  static const char kSettingsAppKey[];
-
   OptionsPageUIHandler();
   ~OptionsPageUIHandler() override;
 
diff --git a/chrome/browser/ui/webui/options/settings_app_browsertest.js b/chrome/browser/ui/webui/options/settings_app_browsertest.js
deleted file mode 100644
index 03d11ec6..0000000
--- a/chrome/browser/ui/webui/options/settings_app_browsertest.js
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2013 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.
-
-/**
- * TestFixture for App Launcher's Settings App testing.
- * @extends {testing.Test}
- * @constructor
- */
-function SettingsAppWebUITest() {}
-
-SettingsAppWebUITest.prototype = {
-  __proto__: testing.Test.prototype,
-
-  /**
-   * Browse to Settings App page, in a browser.
-   */
-  browsePreload: 'chrome://settings-frame/options_settings_app.html',
-};
-
-GEN('#if defined(ENABLE_SETTINGS_APP)');
-
-// This test is flaky on Linux and Windows bots. See crbug.com/579666
-GEN('#if defined(OS_LINUX) || defined(OS_WIN)');
-GEN('#define MAYBE_testOpenSettingsApp DISABLED_testOpenSettingsApp');
-GEN('#else');
-GEN('#define MAYBE_testOpenSettingsApp testOpenSettingsApp');
-GEN('#endif  // defined(OS_LINUX) || defined(OS_WIN)');
-// Test opening Settings App, and do some checks on section visibility.
-TEST_F('SettingsAppWebUITest', 'MAYBE_testOpenSettingsApp', function() {
-  // Note there is no location bar in the Settings App.
-
-  // Some things are hidden via a parent, so make a helper function.
-  function isVisible(elementId) {
-    var elem = $(elementId);
-    return elem.offsetWidth > 0 || elem.offsetHeight > 0;
-  }
-  assertTrue(OptionsPage.isSettingsApp());
-  assertTrue(isVisible('sync-users-section'));
-  assertTrue(isVisible('sync-section'));
-
-  // Spot-check some regular settings items that should be hidden.
-  assertFalse(isVisible('change-home-page-section'));
-  assertFalse(isVisible('default-search-engine'));
-  assertFalse(isVisible('hotword-search'));
-  assertFalse(isVisible('privacy-section'));
-  assertFalse(isVisible('startup-section'));
-});
-
-// This test is flaky on Linux and Windows bot. See crbug.com/579666
-GEN('#if defined(OS_LINUX) || defined(OS_WIN)');
-GEN('#define MAYBE_testStrings DISABLED_testStrings');
-GEN('#else');
-GEN('#define MAYBE_testStrings testStrings');
-GEN('#endif  // defined(OS_LINUX) || defined(OS_WIN)');
-// Check functionality of LoadTimeData.overrideValues(), which the Settings App
-// uses. Do spot checks, so the test is not too fragile. Some of the content
-// strings rely on waiting for sync sign-in status, or platform-specifics.
-TEST_F('SettingsAppWebUITest', 'MAYBE_testStrings', function() {
-  // Ensure we check against the override values.
-  assertTrue(!!loadTimeData.getValue('settingsApp'));
-
-  // Check a product-specific label, to ensure it uses "App Launcher", and not
-  // Chrome / Chromium.
-  var languagesLabelElement =
-      document.querySelector('[i18n-content="languageSectionLabel"]');
-  assertNotEquals(-1, languagesLabelElement.innerHTML.indexOf('App Launcher'));
-});
-
-GEN('#endif  // defined(ENABLE_SETTINGS_APP)');
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
index 374fb38..a39c768 100644
--- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -1042,6 +1042,7 @@
       {"siteSettingsCategoryCamera", IDS_SETTINGS_SITE_SETTINGS_CAMERA},
       {"siteSettingsCategoryCookies", IDS_SETTINGS_SITE_SETTINGS_COOKIES},
       {"siteSettingsCategoryFullscreen", IDS_SETTINGS_SITE_SETTINGS_FULLSCREEN},
+      {"siteSettingsCategoryHandlers", IDS_SETTINGS_SITE_SETTINGS_HANDLERS},
       {"siteSettingsCategoryImages", IDS_SETTINGS_SITE_SETTINGS_IMAGES},
       {"siteSettingsCategoryLocation", IDS_SETTINGS_SITE_SETTINGS_LOCATION},
       {"siteSettingsCategoryJavascript", IDS_SETTINGS_SITE_SETTINGS_JAVASCRIPT},
@@ -1058,6 +1059,7 @@
        IDS_SETTINGS_SITE_SETTINGS_BACKGROUND_SYNC},
       {"siteSettingsCamera", IDS_SETTINGS_SITE_SETTINGS_CAMERA},
       {"siteSettingsCookies", IDS_SETTINGS_SITE_SETTINGS_COOKIES},
+      {"siteSettingsHandlers", IDS_SETTINGS_SITE_SETTINGS_HANDLERS},
       {"siteSettingsKeygen", IDS_SETTINGS_SITE_SETTINGS_KEYGEN},
       {"siteSettingsLocation", IDS_SETTINGS_SITE_SETTINGS_LOCATION},
       {"siteSettingsMic", IDS_SETTINGS_SITE_SETTINGS_MIC},
@@ -1095,6 +1097,12 @@
        IDS_SETTINGS_SITE_SETTINGS_BACKGROUND_SYNC_ALLOW_RECENTLY_CLOSED_SITES_RECOMMENDED},
       {"siteSettingsBackgroundSyncBlocked",
        IDS_SETTINGS_SITE_SETTINGS_BACKGROUND_SYNC_BLOCKED},
+      {"siteSettingsHandlersAsk",
+       IDS_SETTINGS_SITE_SETTINGS_HANDLERS_ASK},
+      {"siteSettingsHandlersAskRecommended",
+       IDS_SETTINGS_SITE_SETTINGS_HANDLERS_ASK_RECOMMENDED},
+      {"siteSettingsHandlersBlocked",
+       IDS_SETTINGS_SITE_SETTINGS_HANDLERS_BLOCKED},
       {"siteSettingsKeygenAllow",
        IDS_SETTINGS_SITE_SETTINGS_KEYGEN_ALLOW},
       {"siteSettingsKeygenBlock",
@@ -1153,6 +1161,9 @@
       {"thirdPartyCookie", IDS_SETTINGS_SITE_SETTINGS_THIRD_PARTY_COOKIE},
       {"thirdPartyCookieSublabel",
        IDS_SETTINGS_SITE_SETTINGS_THIRD_PARTY_COOKIE_SUBLABEL},
+      {"handlerIsDefault", IDS_SETTINGS_SITE_SETTINGS_HANDLER_IS_DEFAULT},
+      {"handlerSetDefault", IDS_SETTINGS_SITE_SETTINGS_HANDLER_SET_DEFAULT},
+      {"handlerRemove", IDS_SETTINGS_SITE_SETTINGS_REMOVE},
   };
   AddLocalizedStringsBulk(html_source, localized_strings,
                           arraysize(localized_strings));
diff --git a/chrome/browser/ui/webui/settings/md_settings_ui.cc b/chrome/browser/ui/webui/settings/md_settings_ui.cc
index bd6d743..b8f7380 100644
--- a/chrome/browser/ui/webui/settings/md_settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_ui.cc
@@ -19,6 +19,7 @@
 #include "chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.h"
 #include "chrome/browser/ui/webui/settings/people_handler.h"
 #include "chrome/browser/ui/webui/settings/profile_info_handler.h"
+#include "chrome/browser/ui/webui/settings/protocol_handlers_handler.h"
 #include "chrome/browser/ui/webui/settings/reset_settings_handler.h"
 #include "chrome/browser/ui/webui/settings/search_engines_handler.h"
 #include "chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.h"
@@ -69,6 +70,7 @@
   AddSettingsPageUIHandler(new CookiesViewHandler());
   AddSettingsPageUIHandler(new DownloadsHandler());
   AddSettingsPageUIHandler(new FontHandler(web_ui));
+  AddSettingsPageUIHandler(new ProtocolHandlersHandler());
   AddSettingsPageUIHandler(new LanguagesHandler(web_ui));
   AddSettingsPageUIHandler(new MediaDevicesSelectionHandler(profile));
   AddSettingsPageUIHandler(new PeopleHandler(profile));
diff --git a/chrome/browser/ui/webui/settings/protocol_handlers_handler.cc b/chrome/browser/ui/webui/settings/protocol_handlers_handler.cc
new file mode 100644
index 0000000..1d10197
--- /dev/null
+++ b/chrome/browser/ui/webui/settings/protocol_handlers_handler.cc
@@ -0,0 +1,221 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/settings/protocol_handlers_handler.h"
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/macros.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/google/core/browser/google_util.h"
+#include "components/prefs/pref_service.h"
+#include "content/public/browser/web_ui.h"
+
+namespace settings {
+
+ProtocolHandlersHandler::ProtocolHandlersHandler() {
+}
+
+ProtocolHandlersHandler::~ProtocolHandlersHandler() {
+}
+
+void ProtocolHandlersHandler::OnJavascriptAllowed() {
+  notification_registrar_.Add(
+      this, chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED,
+      content::Source<Profile>(Profile::FromWebUI(web_ui())));
+}
+
+void ProtocolHandlersHandler::OnJavascriptDisallowed() {
+  notification_registrar_.RemoveAll();
+}
+
+void ProtocolHandlersHandler::RegisterMessages() {
+  web_ui()->RegisterMessageCallback("initializeProtocolHandlerList",
+      base::Bind(&ProtocolHandlersHandler::InitializeProtocolHandlerList,
+                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback("clearDefault",
+      base::Bind(&ProtocolHandlersHandler::ClearDefault,
+                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback("removeHandler",
+      base::Bind(&ProtocolHandlersHandler::RemoveHandler,
+                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback("setHandlersEnabled",
+      base::Bind(&ProtocolHandlersHandler::SetHandlersEnabled,
+                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback("setDefault",
+      base::Bind(&ProtocolHandlersHandler::SetDefault,
+                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback("removeIgnoredHandler",
+      base::Bind(&ProtocolHandlersHandler::RemoveIgnoredHandler,
+                 base::Unretained(this)));
+}
+
+ProtocolHandlerRegistry* ProtocolHandlersHandler::GetProtocolHandlerRegistry() {
+  return ProtocolHandlerRegistryFactory::GetForBrowserContext(
+      Profile::FromWebUI(web_ui()));
+}
+
+static void GetHandlersAsListValue(
+    const ProtocolHandlerRegistry::ProtocolHandlerList& handlers,
+    base::ListValue* handler_list) {
+  ProtocolHandlerRegistry::ProtocolHandlerList::const_iterator handler;
+  for (handler = handlers.begin(); handler != handlers.end(); ++handler) {
+    std::unique_ptr<base::DictionaryValue> handler_value(
+        new base::DictionaryValue());
+    handler_value->SetString("protocol", handler->protocol());
+    handler_value->SetString("spec", handler->url().spec());
+    handler_value->SetString("host", handler->url().host());
+    handler_list->Append(std::move(handler_value));
+  }
+}
+
+void ProtocolHandlersHandler::GetHandlersForProtocol(
+    const std::string& protocol,
+    base::DictionaryValue* handlers_value) {
+  ProtocolHandlerRegistry* registry = GetProtocolHandlerRegistry();
+  // The items which are to be written into |handlers_value| are also described
+  // in chrome/browser/resources/options/handler_options.js in @typedef
+  // for Handlers. Please update them whenever you add or remove any keys here.
+  handlers_value->SetString("protocol", protocol);
+  handlers_value->SetInteger("default_handler",
+      registry->GetHandlerIndex(protocol));
+  handlers_value->SetBoolean(
+      "is_default_handler_set_by_user",
+      registry->IsRegisteredByUser(registry->GetHandlerFor(protocol)));
+  handlers_value->SetBoolean("has_policy_recommendations",
+                             registry->HasPolicyRegisteredHandler(protocol));
+
+  base::ListValue* handlers_list = new base::ListValue();
+  GetHandlersAsListValue(registry->GetHandlersFor(protocol), handlers_list);
+  handlers_value->Set("handlers", handlers_list);
+}
+
+void ProtocolHandlersHandler::GetIgnoredHandlers(base::ListValue* handlers) {
+  ProtocolHandlerRegistry* registry = GetProtocolHandlerRegistry();
+  ProtocolHandlerRegistry::ProtocolHandlerList ignored_handlers =
+      registry->GetIgnoredHandlers();
+  return GetHandlersAsListValue(ignored_handlers, handlers);
+}
+
+void ProtocolHandlersHandler::UpdateHandlerList() {
+  ProtocolHandlerRegistry* registry = GetProtocolHandlerRegistry();
+  std::vector<std::string> protocols;
+  registry->GetRegisteredProtocols(&protocols);
+
+  base::ListValue handlers;
+  for (std::vector<std::string>::iterator protocol = protocols.begin();
+       protocol != protocols.end(); protocol++) {
+    std::unique_ptr<base::DictionaryValue> handler_value(
+        new base::DictionaryValue());
+    GetHandlersForProtocol(*protocol, handler_value.get());
+    handlers.Append(std::move(handler_value));
+  }
+
+  std::unique_ptr<base::ListValue> ignored_handlers(new base::ListValue());
+  GetIgnoredHandlers(ignored_handlers.get());
+  CallJavascriptFunction("cr.webUIListenerCallback",
+                         base::StringValue("setProtocolHandlers"),
+                         handlers);
+  CallJavascriptFunction("cr.webUIListenerCallback",
+                         base::StringValue("setIgnoredProtocolHandlers"),
+                         *ignored_handlers);
+}
+
+void ProtocolHandlersHandler::InitializeProtocolHandlerList(
+    const base::ListValue* args) {
+  AllowJavascript();
+  SendHandlersEnabledValue();
+  UpdateHandlerList();
+}
+
+void ProtocolHandlersHandler::SendHandlersEnabledValue() {
+  CallJavascriptFunction("cr.webUIListenerCallback",
+                         base::StringValue("setHandlersEnabled"),
+                         base::FundamentalValue(
+                             GetProtocolHandlerRegistry()->enabled()));
+}
+
+void ProtocolHandlersHandler::RemoveHandler(const base::ListValue* args) {
+  const base::ListValue* list;
+  if (!args->GetList(0, &list)) {
+    NOTREACHED();
+    return;
+  }
+
+  ProtocolHandler handler(ParseHandlerFromArgs(list));
+  GetProtocolHandlerRegistry()->RemoveHandler(handler);
+
+  // No need to call UpdateHandlerList() - we should receive a notification
+  // that the ProtocolHandlerRegistry has changed and we will update the view
+  // then.
+}
+
+void ProtocolHandlersHandler::RemoveIgnoredHandler(
+    const base::ListValue* args) {
+  const base::ListValue* list;
+  if (!args->GetList(0, &list)) {
+    NOTREACHED();
+    return;
+  }
+
+  ProtocolHandler handler(ParseHandlerFromArgs(list));
+  GetProtocolHandlerRegistry()->RemoveIgnoredHandler(handler);
+}
+
+void ProtocolHandlersHandler::SetHandlersEnabled(const base::ListValue* args) {
+  bool enabled = true;
+  CHECK(args->GetBoolean(0, &enabled));
+  if (enabled)
+    GetProtocolHandlerRegistry()->Enable();
+  else
+    GetProtocolHandlerRegistry()->Disable();
+}
+
+void ProtocolHandlersHandler::ClearDefault(const base::ListValue* args) {
+  const base::Value* value;
+  CHECK(args->Get(0, &value));
+  std::string protocol_to_clear;
+  CHECK(value->GetAsString(&protocol_to_clear));
+  GetProtocolHandlerRegistry()->ClearDefault(protocol_to_clear);
+}
+
+void ProtocolHandlersHandler::SetDefault(const base::ListValue* args) {
+  const base::ListValue* list;
+  CHECK(args->GetList(0, &list));
+  const ProtocolHandler& handler(ParseHandlerFromArgs(list));
+  CHECK(!handler.IsEmpty());
+  GetProtocolHandlerRegistry()->OnAcceptRegisterProtocolHandler(handler);
+}
+
+ProtocolHandler ProtocolHandlersHandler::ParseHandlerFromArgs(
+    const base::ListValue* args) const {
+  base::string16 protocol;
+  base::string16 url;
+  bool ok = args->GetString(0, &protocol) && args->GetString(1, &url);
+  if (!ok)
+    return ProtocolHandler::EmptyProtocolHandler();
+  return ProtocolHandler::CreateProtocolHandler(base::UTF16ToUTF8(protocol),
+                                                GURL(base::UTF16ToUTF8(url)));
+}
+
+void ProtocolHandlersHandler::Observe(
+    int type,
+    const content::NotificationSource& source,
+    const content::NotificationDetails& details) {
+  DCHECK_EQ(chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED, type);
+  SendHandlersEnabledValue();
+  UpdateHandlerList();
+}
+
+}  // namespace settings
diff --git a/chrome/browser/ui/webui/settings/protocol_handlers_handler.h b/chrome/browser/ui/webui/settings/protocol_handlers_handler.h
new file mode 100644
index 0000000..87a38241
--- /dev/null
+++ b/chrome/browser/ui/webui/settings/protocol_handlers_handler.h
@@ -0,0 +1,95 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_PROTOCOL_HANDLERS_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_SETTINGS_PROTOCOL_HANDLERS_HANDLER_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "chrome/browser/custom_handlers/protocol_handler_registry.h"
+#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
+#include "chrome/common/custom_handlers/protocol_handler.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// ProtocolHandlersHandler
+
+// Listen for changes to protocol handlers (i.e. registerProtocolHandler()).
+// This get triggered whenever a user allows a specific website or application
+// to handle clicks on a link with a specified protocol (i.e. mailto: -> Gmail).
+
+namespace base {
+class DictionaryValue;
+}
+
+namespace settings {
+
+class ProtocolHandlersHandler : public SettingsPageUIHandler,
+                              public content::NotificationObserver {
+ public:
+  ProtocolHandlersHandler();
+  ~ProtocolHandlersHandler() override;
+
+  // SettingsPageUIHandler:
+  void OnJavascriptAllowed() override;
+  void OnJavascriptDisallowed() override;
+  void RegisterMessages() override;
+
+  // content::NotificationObserver:
+  void Observe(int type,
+               const content::NotificationSource& source,
+               const content::NotificationDetails& details) override;
+
+ private:
+  // Called to fetch the initial list of data to show.
+  void InitializeProtocolHandlerList(const base::ListValue* args);
+
+  // Notifies the JS side whether the handlers are enabled or not.
+  void SendHandlersEnabledValue();
+
+  // Called when the user toggles whether custom handlers are enabled.
+  void SetHandlersEnabled(const base::ListValue* args);
+
+  // Called when the user sets a new default handler for a protocol.
+  void SetDefault(const base::ListValue* args);
+
+  // Called when the user clears the default handler for a protocol.
+  // |args| is the string name of the protocol to clear.
+  void ClearDefault(const base::ListValue* args);
+
+  // Parses a ProtocolHandler out of the arguments passed back from the view.
+  // |args| is a list of [protocol, url, title].
+  ProtocolHandler ParseHandlerFromArgs(const base::ListValue* args) const;
+
+  // Returns a JSON object describing the set of protocol handlers for the
+  // given protocol.
+  void GetHandlersForProtocol(const std::string& protocol,
+                              base::DictionaryValue* value);
+
+  // Returns a JSON list of the ignored protocol handlers.
+  void GetIgnoredHandlers(base::ListValue* handlers);
+
+  // Called when the JS PasswordManager object is initialized.
+  void UpdateHandlerList();
+
+  // Remove a handler.
+  // |args| is a list of [protocol, url, title].
+  void RemoveHandler(const base::ListValue* args);
+
+  // Remove an ignored handler.
+  // |args| is a list of [protocol, url, title].
+  void RemoveIgnoredHandler(const base::ListValue* args);
+
+  ProtocolHandlerRegistry* GetProtocolHandlerRegistry();
+
+  content::NotificationRegistrar notification_registrar_;
+
+  DISALLOW_COPY_AND_ASSIGN(ProtocolHandlersHandler);
+};
+
+}  // namespace settings
+
+#endif  // CHROME_BROWSER_UI_WEBUI_SETTINGS_PROTOCOL_HANDLERS_HANDLER_H_
diff --git a/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc b/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc
index 156ff88..de86c63 100644
--- a/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc
@@ -161,8 +161,7 @@
         BrowsingDataFlashLSOHelper::Create(profile));
     cookies_tree_model_.reset(
         new CookiesTreeModel(container,
-                             profile->GetExtensionSpecialStoragePolicy(),
-                             false));
+                             profile->GetExtensionSpecialStoragePolicy()));
     cookies_tree_model_->AddCookiesTreeObserver(this);
   }
 }
diff --git a/chrome/browser/ui/webui/snippets_internals_message_handler.cc b/chrome/browser/ui/webui/snippets_internals_message_handler.cc
index 89a20ea..f6e7411b 100644
--- a/chrome/browser/ui/webui/snippets_internals_message_handler.cc
+++ b/chrome/browser/ui/webui/snippets_internals_message_handler.cc
@@ -114,14 +114,14 @@
 void SnippetsInternalsMessageHandler::HandleClear(const base::ListValue* args) {
   DCHECK_EQ(0u, args->GetSize());
 
-  ntp_snippets_service_->ClearSnippets();
+  ntp_snippets_service_->ClearCachedSuggestionsForDebugging();
 }
 
 void SnippetsInternalsMessageHandler::HandleClearDiscarded(
     const base::ListValue* args) {
   DCHECK_EQ(0u, args->GetSize());
 
-  ntp_snippets_service_->ClearDiscardedSnippets();
+  ntp_snippets_service_->ClearDiscardedSuggestionsForDebugging();
   SendDiscardedSnippets();
 }
 
diff --git a/chrome/browser/usb/usb_chooser_controller.cc b/chrome/browser/usb/usb_chooser_controller.cc
index e6ce755..b85cad5 100644
--- a/chrome/browser/usb/usb_chooser_controller.cc
+++ b/chrome/browser/usb/usb_chooser_controller.cc
@@ -71,6 +71,10 @@
     callback_.Run(nullptr);
 }
 
+base::string16 UsbChooserController::GetOkButtonLabel() const {
+  return l10n_util::GetStringUTF16(IDS_USB_DEVICE_CHOOSER_CONNECT_BUTTON_TEXT);
+}
+
 size_t UsbChooserController::NumOptions() const {
   return devices_.size();
 }
diff --git a/chrome/browser/usb/usb_chooser_controller.h b/chrome/browser/usb/usb_chooser_controller.h
index 2021a4f..a7e472f 100644
--- a/chrome/browser/usb/usb_chooser_controller.h
+++ b/chrome/browser/usb/usb_chooser_controller.h
@@ -40,6 +40,7 @@
   ~UsbChooserController() override;
 
   // ChooserController:
+  base::string16 GetOkButtonLabel() const override;
   size_t NumOptions() const override;
   base::string16 GetOption(size_t index) const override;
   void Select(size_t index) override;
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index d111a9e..5919bc98 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -2335,6 +2335,8 @@
       'browser/permissions/permission_manager_factory.h',
       'browser/permissions/permission_request_id.cc',
       'browser/permissions/permission_request_id.h',
+      'browser/permissions/permission_request_manager.cc',
+      'browser/permissions/permission_request_manager.h',
       'browser/permissions/permission_uma_util.cc',
       'browser/permissions/permission_uma_util.h',
       'browser/permissions/permission_util.cc',
diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi
index 2a4cc8c..c935e68b 100644
--- a/chrome/chrome_browser_chromeos.gypi
+++ b/chrome/chrome_browser_chromeos.gypi
@@ -57,7 +57,7 @@
         'browser/chromeos/app_mode/startup_app_launcher.cc',
         'browser/chromeos/app_mode/startup_app_launcher.h',
         'browser/chromeos/arc/arc_android_management_checker.cc',
-        'browser/chromeos/arc/arc_android_management_checker.h', 
+        'browser/chromeos/arc/arc_android_management_checker.h',
         'browser/chromeos/arc/arc_android_management_checker_delegate.h',
         'browser/chromeos/arc/arc_auth_context.cc',
         'browser/chromeos/arc/arc_auth_context.h',
@@ -511,6 +511,8 @@
         'browser/chromeos/login/proxy_settings_dialog.h',
         'browser/chromeos/login/reauth_stats.cc',
         'browser/chromeos/login/reauth_stats.h',
+        'browser/chromeos/login/quick_unlock/quick_unlock_notification_controller.cc',
+        'browser/chromeos/login/quick_unlock/quick_unlock_notification_controller.h',
         'browser/chromeos/login/quick_unlock/pin_storage.cc',
         'browser/chromeos/login/quick_unlock/pin_storage.h',
         'browser/chromeos/login/quick_unlock/pin_storage_factory.cc',
diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi
index 25d95b0..34c7830 100644
--- a/chrome/chrome_browser_ui.gypi
+++ b/chrome/chrome_browser_ui.gypi
@@ -1851,8 +1851,6 @@
       'browser/ui/user_manager.h',
       'browser/ui/website_settings/chooser_bubble_delegate.cc',
       'browser/ui/website_settings/chooser_bubble_delegate.h',
-      'browser/ui/website_settings/permission_bubble_manager.cc',
-      'browser/ui/website_settings/permission_bubble_manager.h',
       'browser/ui/website_settings/permission_bubble_view.h',
       'browser/ui/website_settings/permission_menu_model.cc',
       'browser/ui/website_settings/permission_menu_model.h',
@@ -2060,6 +2058,8 @@
       'browser/ui/webui/settings/people_handler.h',
       'browser/ui/webui/settings/profile_info_handler.cc',
       'browser/ui/webui/settings/profile_info_handler.h',
+      'browser/ui/webui/settings/protocol_handlers_handler.cc',
+      'browser/ui/webui/settings/protocol_handlers_handler.h',
       'browser/ui/webui/settings/reset_settings_handler.cc',
       'browser/ui/webui/settings/reset_settings_handler.h',
       'browser/ui/webui/settings/search_engines_handler.cc',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 8a69a728..21f0690 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -385,6 +385,7 @@
       'browser/pdf/pdf_extension_test.cc',
       'browser/pdf/pdf_extension_test_util.cc',
       'browser/pdf/pdf_extension_test_util.h',
+      'browser/permissions/permission_request_manager_browsertest.cc',
       'browser/plugins/plugin_power_saver_browsertest.cc',
       'browser/policy/cloud/cloud_policy_browsertest.cc',
       'browser/policy/cloud/cloud_policy_manager_browsertest.cc',
@@ -522,7 +523,6 @@
       'browser/ui/website_settings/mock_permission_bubble_view.h',
       'browser/ui/website_settings/permission_bubble_browser_test_util.cc',
       'browser/ui/website_settings/permission_bubble_browser_test_util.h',
-      'browser/ui/website_settings/permission_bubble_manager_browsertest.cc',
       'browser/ui/webui/bidi_checker_web_ui_test.cc',
       'browser/ui/webui/bidi_checker_web_ui_test.h',
       'browser/ui/webui/bookmarks_ui_browsertest.cc',
@@ -988,7 +988,6 @@
       'browser/ui/webui/options/password_manager_browsertest.js',
       'browser/ui/webui/options/profile_settings_reset_browsertest.js',
       'browser/ui/webui/options/search_engine_manager_browsertest.js',
-      'browser/ui/webui/options/settings_app_browsertest.js',
       'browser/ui/webui/options/settings_format_browsertest.js',
       'browser/ui/webui/options/startup_page_list_browsertest.js',
       'browser/ui/webui/sync_internals_browsertest.js',
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index 23787082..4bab19ca 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -175,6 +175,7 @@
       'browser/permissions/delegation_tracker_unittest.cc',
       'browser/permissions/permission_context_base_unittest.cc',
       'browser/permissions/permission_manager_unittest.cc',
+      'browser/permissions/permission_uma_util_unittest.cc',
       'browser/permissions/permission_util_unittest.cc',
       'browser/policy/cloud/cloud_policy_invalidator_unittest.cc',
       'browser/policy/cloud/remote_commands_invalidator_unittest.cc',
@@ -278,6 +279,10 @@
       'browser/ui/sync/sync_promo_ui_unittest.cc',
       'browser/ui/tests/ui_gfx_image_unittest.cc',
       'browser/ui/tests/ui_gfx_image_unittest.mm',
+      'browser/ui/website_settings/mock_permission_bubble_factory.cc',
+      'browser/ui/website_settings/mock_permission_bubble_factory.h',
+      'browser/ui/website_settings/mock_permission_bubble_view.cc',
+      'browser/ui/website_settings/mock_permission_bubble_view.h',
       'browser/ui/website_settings/website_settings_unittest.cc',
       'browser/ui/webui/browsing_history_handler_unittest.cc',
       'browser/ui/webui/fileicon_source_unittest.cc',
@@ -360,10 +365,6 @@
       'browser/ui/autofill/country_combobox_model_unittest.cc',
       'browser/ui/autofill/save_card_bubble_controller_impl_unittest.cc',
       'browser/ui/passwords/manage_passwords_ui_controller_unittest.cc',
-      'browser/ui/website_settings/mock_permission_bubble_factory.cc',
-      'browser/ui/website_settings/mock_permission_bubble_factory.h',
-      'browser/ui/website_settings/mock_permission_bubble_view.cc',
-      'browser/ui/website_settings/mock_permission_bubble_view.h',
     ],
     'chrome_unit_tests_spellchecker_sources': [
       'browser/spellchecker/feedback_sender_unittest.cc',
@@ -1499,6 +1500,7 @@
       'browser/memory/tab_manager_unittest.cc',
       'browser/memory/tab_manager_web_contents_data_unittest.cc',
       'browser/net/firefox_proxy_settings_unittest.cc',
+      'browser/permissions/permission_request_manager_unittest.cc',
       'browser/platform_util_unittest.cc',
       'browser/power/process_power_collector_unittest.cc',
       'browser/process_singleton_posix_unittest.cc',
@@ -1566,7 +1568,6 @@
       'browser/ui/toolbar/toolbar_actions_bar_unittest.h',
       'browser/ui/toolbar/toolbar_actions_model_unittest.cc',
       'browser/ui/toolbar/toolbar_model_unittest.cc',
-      'browser/ui/website_settings/permission_bubble_manager_unittest.cc',
       'browser/ui/website_settings/permission_menu_model_unittest.cc',
       'browser/ui/webui/help/version_updater_chromeos_unittest.cc',
       'browser/ui/webui/md_downloads/downloads_list_tracker_unittest.cc',
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 36d3023..9c22d76 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -38,20 +38,6 @@
 // no blocking of requests).
 const char kAllowInsecureLocalhost[] = "allow-insecure-localhost";
 
-#if defined(ENABLE_PLUGINS)
-// Specifies comma-separated list of extension ids or hosts to grant
-// access to CRX file system APIs.
-const char kAllowNaClCrxFsAPI[]             = "allow-nacl-crxfs-api";
-
-// Specifies comma-separated list of extension ids or hosts to grant
-// access to file handle APIs.
-const char kAllowNaClFileHandleAPI[]        = "allow-nacl-file-handle-api";
-
-// Specifies comma-separated list of extension ids or hosts to grant
-// access to TCP/UDP socket APIs.
-const char kAllowNaClSocketAPI[]            = "allow-nacl-socket-api";
-#endif
-
 // Don't block outdated plugins.
 const char kAllowOutdatedPlugins[]          = "allow-outdated-plugins";
 
@@ -66,23 +52,13 @@
 // but less commonly used plugins.
 const char kAlwaysAuthorizePlugins[]        = "always-authorize-plugins";
 
-// Specifies that the extension-app with the specified id should be launched
-// according to its configuration.
-const char kAppId[]                         = "app-id";
-
 // Specifies that the associated value should be launched in "application"
 // mode.
 const char kApp[]                           = "app";
 
-// The URL that the webstore APIs download extensions from.
-// Note: the URL must contain one '%s' for the extension ID.
-const char kAppsGalleryDownloadURL[]        = "apps-gallery-download-url";
-
-// The URL to use for the gallery link in the app launcher.
-const char kAppsGalleryURL[]                = "apps-gallery-url";
-
-// The update url used by gallery/webstore extensions.
-const char kAppsGalleryUpdateURL[]          = "apps-gallery-update-url";
+// Specifies that the extension-app with the specified id should be launched
+// according to its configuration.
+const char kAppId[]                         = "app-id";
 
 // Value of GAIA auth code for --force-app-mode.
 const char kAppModeAuthCode[]               = "app-mode-auth-code";
@@ -90,6 +66,16 @@
 // Value of OAuth2 refresh token for --force-app-mode.
 const char kAppModeOAuth2Token[]            = "app-mode-oauth-token";
 
+// The URL that the webstore APIs download extensions from.
+// Note: the URL must contain one '%s' for the extension ID.
+const char kAppsGalleryDownloadURL[]        = "apps-gallery-download-url";
+
+// The update url used by gallery/webstore extensions.
+const char kAppsGalleryUpdateURL[]          = "apps-gallery-update-url";
+
+// The URL to use for the gallery link in the app launcher.
+const char kAppsGalleryURL[]                = "apps-gallery-url";
+
 // Enables overriding the path for the default authentication extension.
 const char kAuthExtensionPath[]             = "auth-ext-path";
 
@@ -99,8 +85,7 @@
 // This flag makes Chrome auto-open DevTools window for each tab. It is
 // intended to be used by developers and automation to not require user
 // interaction for opening DevTools.
-const char kAutoOpenDevToolsForTabs[] =
-    "auto-open-devtools-for-tabs";
+const char kAutoOpenDevToolsForTabs[]       = "auto-open-devtools-for-tabs";
 
 // This flag makes Chrome auto-select the provided choice when an extension asks
 // permission to start desktop capture. Should only be used for tests. For
@@ -127,8 +112,7 @@
 //   assumed to be HTTPS as required by RFC6962).
 // Multiple logs can be specified by repeating description:key pairs,
 // separated by a comma.
-const char kCertificateTransparencyLog[] =
-    "certificate-transparency-log";
+const char kCertificateTransparencyLog[]    = "certificate-transparency-log";
 
 // How often (in seconds) to check for updates. Should only be used for testing
 // purposes.
@@ -146,13 +130,13 @@
 // unspecified.
 const char kCloudPrintFileType[]            = "cloud-print-file-type";
 
+// Used with kCloudPrintFile to specify a title for the resulting print job.
+const char kCloudPrintJobTitle[]            = "cloud-print-job-title";
+
 // Used with kCloudPrintFile to specify a JSON print ticket for the resulting
 // print job. Defaults to null if unspecified.
 const char kCloudPrintPrintTicket[]         = "cloud-print-print-ticket";
 
-// Used with kCloudPrintFile to specify a title for the resulting print job.
-const char kCloudPrintJobTitle[]            = "cloud-print-job-title";
-
 // Setup cloud print proxy for provided printers. This does not start
 // service or register proxy for autostart.
 const char kCloudPrintSetupProxy[]          = "cloud-print-setup-proxy";
@@ -200,10 +184,6 @@
 // app to their shelf (or platform-specific equivalent)
 const char kDisableAddToShelf[] = "disable-add-to-shelf";
 
-#if defined(OS_ANDROID)
-const char kDisableAppLink[] = "disable-app-link";
-#endif
-
 // Disables the experimental asynchronous DNS client.
 const char kDisableAsyncDns[]               = "disable-async-dns";
 
@@ -280,24 +260,27 @@
 const char kDisableNewBookmarkApps[]        = "disable-new-bookmark-apps";
 
 // Disable auto-reload of error pages if offline.
-const char kDisableOfflineAutoReload[]       = "disable-offline-auto-reload";
+const char kDisableOfflineAutoReload[]      = "disable-offline-auto-reload";
 
 // Disable only auto-reloading error pages when the tab is visible.
 const char kDisableOfflineAutoReloadVisibleOnly[] =
     "disable-offline-auto-reload-visible-only";
 
 // Disable out-of-process V8 proxy resolver.
-const char kDisableOutOfProcessPac[] = "disable-out-of-process-pac";
+const char kDisableOutOfProcessPac[]        = "disable-out-of-process-pac";
 
-// Disables the Permissions Blacklist, which blocks access to permissions
-// for blacklisted sites.
-const char kDisablePermissionsBlacklist[] = "disable-permissions-blacklist";
+// Disables panels (always on-top docked pop-up windows).
+const char kDisablePanels[]                 = "disable-panels";
 
 // Disables permission action reporting to Safe Browsing servers for opted in
 // users.
 const char kDisablePermissionActionReporting[] =
     "disable-permission-action-reporting";
 
+// Disables the Permissions Blacklist, which blocks access to permissions
+// for blacklisted sites.
+const char kDisablePermissionsBlacklist[]   = "disable-permissions-blacklist";
+
 // Disable pop-up blocking.
 const char kDisablePopupBlocking[]          = "disable-popup-blocking";
 
@@ -312,18 +295,20 @@
 // disable that check. This switch is used during automated testing.
 const char kDisablePromptOnRepost[]         = "disable-prompt-on-repost";
 
+// Enable background mode for the Push API.
+const char kDisablePushApiBackgroundMode[] = "disable-push-api-background-mode";
+
 // Disables using bubbles for session restore request.
 const char kDisableSessionCrashedBubble[] = "disable-session-crashed-bubble";
 
+// Disable settings in a separate browser window per profile
+// (see SettingsWindowEnabled() below).
+const char kDisableSettingsWindow[]          = "disable-settings-window";
+
 // Disables the Site Engagement service, which records interaction with sites
 // and allocates certain resources accordingly.
 const char kDisableSiteEngagementService[] = "disable-site-engagement-service";
 
-#if defined(OS_ANDROID)
-// Disable VR UI if supported.
-const char kDisableVrShell[] = "disable-vr-shell";
-#endif
-
 // Disables Web Notification custom layouts.
 const char kDisableWebNotificationCustomLayouts[] =
     "disable-web-notification-custom-layouts";
@@ -365,18 +350,9 @@
 // Enables all bookmarks view in bookmark manager.
 const char kEnableAllBookmarksView[] = "enable-all-bookmarks-view";
 
-#if defined(OS_ANDROID)
-const char kEnableAppLink[] = "enable-app-link";
-#endif
-
 // Enable OS integration for Chrome app file associations.
 const char kEnableAppsFileAssociations[]    = "enable-apps-file-associations";
 
-#if defined(OS_CHROMEOS)
-// Enables the intent picker so the user can handle URL links with ARC apps.
-const char kEnableIntentPicker[] = "enable-intent-picker";
-#endif  // defined(OS_CHROMEOS)
-
 // If the WebRTC logging private API is active, enables audio debug recordings.
 const char kEnableAudioDebugRecordingsFromExtension[] =
     "enable-audio-debug-recordings-from-extension";
@@ -399,13 +375,13 @@
 // Print Proxy component within the service process.
 const char kEnableCloudPrintProxy[]         = "enable-cloud-print-proxy";
 
-// If true devtools experimental settings are enabled.
-const char kEnableDevToolsExperiments[]     = "enable-devtools-experiments";
-
 // Enable device discovery notifications.
 const char kEnableDeviceDiscoveryNotifications[] =
     "enable-device-discovery-notifications";
 
+// If true devtools experimental settings are enabled.
+const char kEnableDevToolsExperiments[]     = "enable-devtools-experiments";
+
 // Enables Domain Reliability Monitoring.
 const char kEnableDomainReliability[] = "enable-domain-reliability";
 
@@ -424,12 +400,6 @@
 // crbug.com/142458 .
 const char kEnableFastUnload[] = "enable-fast-unload";
 
-#if defined(GOOGLE_CHROME_BUILD)
-// Shows a Google icon next to context menu items powered by Google services.
-const char kEnableGoogleBrandedContextMenu[] =
-    "enable-google-branded-context-menu";
-#endif  // defined(GOOGLE_CHROME_BUILD)
-
 // Enables the Material Design version of chrome://extensions.
 const char kEnableMaterialDesignExtensions[] = "enable-md-extensions";
 
@@ -443,11 +413,6 @@
 // (internally adds lEnableGpuPlugin to the command line).
 const char kEnableNaCl[]                    = "enable-nacl";
 
-#if defined(OS_CHROMEOS)
-// Enables native cups integration
-const char kEnableNativeCups[] = "enable-native-cups";
-#endif // defined(OS_CHROMEOS)
-
 // Enables the use of native notifications instead of using the Chrome based
 // ones.
 const char kEnableNativeNotifications[] = "enable-native-notifications";
@@ -470,19 +435,18 @@
 const char kEnableOfflineAutoReloadVisibleOnly[] =
     "enable-offline-auto-reload-visible-only";
 
-// Enables or disables panels (always on-top docked pop-up windows).
+// Enables panels (always on-top docked pop-up windows).
 const char kEnablePanels[]                  = "enable-panels";
-const char kDisablePanels[]                 = "disable-panels";
-
-// Enables the Permissions Blacklist, which blocks access to permissions
-// for blacklisted sites.
-const char kEnablePermissionsBlacklist[] = "enable-permissions-blacklist";
 
 // Enables permission action reporting to Safe Browsing servers for opted in
 // users.
 const char kEnablePermissionActionReporting[] =
     "enable-permission-action-reporting";
 
+// Enables the Permissions Blacklist, which blocks access to permissions
+// for blacklisted sites.
+const char kEnablePermissionsBlacklist[] = "enable-permissions-blacklist";
+
 // Enables a number of potentially annoying security features (strict mixed
 // content mode, powerful feature restrictions, etc.)
 const char kEnablePotentiallyAnnoyingSecurityFeatures[] =
@@ -502,21 +466,15 @@
 // during chrome_browser_main.
 const char kEnableProfiling[]               = "enable-profiling";
 
-// Enable or disable background mode for the Push API.
+// Enable background mode for the Push API.
 const char kEnablePushApiBackgroundMode[] = "enable-push-api-background-mode";
-const char kDisablePushApiBackgroundMode[] = "disable-push-api-background-mode";
-
-// If the WebRTC logging private API is active, enables WebRTC event logging.
-const char kEnableWebRtcEventLoggingFromExtension[] =
-    "enable-webrtc-event-logging-from-extension";
 
 // Enables using bubbles for session restore request instead of infobars.
 const char kEnableSessionCrashedBubble[] = "enable-session-crashed-bubble";
 
-// Enable or disable settings in a separate browser window per profile
+// Enable settings in a separate browser window per profile
 // (see SettingsWindowEnabled() below).
 const char kEnableSettingsWindow[]           = "enable-settings-window";
-const char kDisableSettingsWindow[]          = "disable-settings-window";
 
 // Enable the Site Engagement App Banner which triggers app install banners
 // using the site engagement service rather than a navigation-based heuristic.
@@ -549,34 +507,28 @@
 const char kEnableUserAlternateProtocolPorts[] =
     "enable-user-controlled-alternate-protocol-ports";
 
-#if defined(OS_ANDROID)
-// Enable VR UI if supported.
-const char kEnableVrShell[] = "enable-vr-shell";
-#endif
-
 // Enables a new "web app" style frame for hosted apps (including bookmark
 // apps).
 const char kEnableWebAppFrame[] = "enable-web-app-frame";
 
-#if defined(OS_ANDROID)
-// Enables "Add to Home screen" in the app menu to generate WebAPKs.
-const char kEnableWebApk[] = "enable-webapk";
-#endif
-
 // Enables Web Notification custom layouts.
 const char kEnableWebNotificationCustomLayouts[] =
     "enable-web-notification-custom-layouts";
 
-// Values for the kExtensionContentVerification flag.
-// See ContentVerifierDelegate::Mode for more explanation.
-const char kExtensionContentVerificationBootstrap[] = "bootstrap";
-const char kExtensionContentVerificationEnforceStrict[] = "enforce_strict";
-const char kExtensionContentVerificationEnforce[] = "enforce";
+// If the WebRTC logging private API is active, enables WebRTC event logging.
+const char kEnableWebRtcEventLoggingFromExtension[] =
+    "enable-webrtc-event-logging-from-extension";
 
 // Name of the command line flag to force content verification to be on in one
 // of various modes.
 const char kExtensionContentVerification[] = "extension-content-verification";
 
+// Values for the kExtensionContentVerification flag.
+// See ContentVerifierDelegate::Mode for more explanation.
+const char kExtensionContentVerificationBootstrap[] = "bootstrap";
+const char kExtensionContentVerificationEnforce[] = "enforce";
+const char kExtensionContentVerificationEnforceStrict[] = "enforce_strict";
+
 // Turns on extension install verification if it would not otherwise have been
 // turned on.
 const char kExtensionsInstallVerification[] = "extensions-install-verification";
@@ -611,14 +563,14 @@
 // whether or not it's actually the First Run (this overrides kNoFirstRun).
 const char kForceFirstRun[]                 = "force-first-run";
 
+// Forces Chrome to use localNTP instead of server (GWS) NTP.
+const char kForceLocalNtp[]                 = "force-local-ntp";
+
 // Forces additional Chrome Variation Ids that will be sent in X-Client-Data
 // header, specified as a 64-bit encoded list of numeric experiment ids. Ids
 // prefixed with the character "t" will be treated as Trigger Variation Ids.
 const char kForceVariationIds[]             = "force-variation-ids";
 
-// Forces Chrome to use localNTP instead of server (GWS) NTP.
-const char kForceLocalNtp[]                 = "force-local-ntp";
-
 // Enables grouping websites by domain and filtering them by period.
 const char kHistoryEnableGroupByDomain[]    = "enable-grouped-history";
 
@@ -627,6 +579,10 @@
 // http://google.com.
 const char kHomePage[]                      = "homepage";
 
+// The maximum number of retry attempts to resolve the host. Set this to zero
+// to disable host resolver retry attempts.
+const char kHostResolverRetryAttempts[]     = "host-resolver-retry-attempts";
+
 // Comma-separated list of rules that control how hostnames are mapped.
 //
 // For example:
@@ -644,10 +600,6 @@
 // proxy connection, and the endpoint host in a SOCKS proxy connection).
 const char kHostRules[]                     = "host-rules";
 
-// The maximum number of retry attempts to resolve the host. Set this to zero
-// to disable host resolver retry attempts.
-const char kHostResolverRetryAttempts[]     = "host-resolver-retry-attempts";
-
 // Causes the browser to launch directly in incognito mode.
 const char kIncognito[]                     = "incognito";
 
@@ -681,12 +633,6 @@
 // Loads an extension from the specified directory.
 const char kLoadExtension[]                 = "load-extension";
 
-#if !defined(GOOGLE_CHROME_BUILD)
-// Enables a live-reload for local NTP resources. This only works when Chrome
-// is running from a Chrome source directory.
-const char kLocalNtpReload[]                = "local-ntp-reload";
-#endif
-
 // Makes Chrome default browser
 const char kMakeDefaultBrowser[]            = "make-default-browser";
 
@@ -814,6 +760,7 @@
 // effect when Instant is either disabled or restricted to search, and when
 // prerender is enabled.
 const char kPrerenderFromOmnibox[]          = "prerender-from-omnibox";
+
 // These are the values the kPrerenderFromOmnibox switch may have, as in
 // "--prerender-from-omnibox=auto". auto: Allow field trial selection.
 const char kPrerenderFromOmniboxSwitchValueAuto[] = "auto";
@@ -821,9 +768,11 @@
 const char kPrerenderFromOmniboxSwitchValueDisabled[] = "disabled";
 //   enabled: Guaranteed prerendering.
 const char kPrerenderFromOmniboxSwitchValueEnabled[] = "enabled";
+
 // Controls speculative prerendering of pages, and content prefetching. Both
 // are dispatched from <link rel=prefetch href=...> elements.
 const char kPrerenderMode[]                 = "prerender";
+
 // These are the values the kPrerenderMode switch may have, as in
 // "--prerender=disabled".
 //   disabled: No prerendering.
@@ -922,12 +871,6 @@
 // If true the app list will be shown.
 const char kShowAppList[]                   = "show-app-list";
 
-// Causes SSL key material to be logged to the specified file for debugging
-// purposes. See
-// https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format
-// for the format.
-const char kSSLKeyLogFile[]               = "ssl-key-log-file";
-
 // Does not show an infobar when an extension attaches to a page using
 // chrome.debugger page. Required to attach to extension background pages.
 const char kSilentDebuggerExtensionAPI[]    = "silent-debugger-extension-api";
@@ -936,12 +879,12 @@
 // one wishes to use Chrome as an ash server.
 const char kSilentLaunch[]                  = "silent-launch";
 
-// Simulates that elevation is needed to recover upgrade channel.
-const char kSimulateElevatedRecovery[]      = "simulate-elevated-recovery";
-
 // Simulates a critical update being available.
 const char kSimulateCriticalUpdate[]        = "simulate-critical-update";
 
+// Simulates that elevation is needed to recover upgrade channel.
+const char kSimulateElevatedRecovery[]      = "simulate-elevated-recovery";
+
 // Simulates that current version is outdated.
 const char kSimulateOutdated[]              = "simulate-outdated";
 
@@ -958,38 +901,18 @@
 // Speculative resource prefetching is disabled.
 const char kSpeculativeResourcePrefetchingDisabled[] = "disabled";
 
+// Speculative resource prefetching is enabled.
+const char kSpeculativeResourcePrefetchingEnabled[] = "enabled";
+
 // Speculative resource prefetching will only learn about resources that need to
 // be prefetched but will not prefetch them.
 const char kSpeculativeResourcePrefetchingLearning[] = "learning";
 
-// Speculative resource prefetching is enabled.
-const char kSpeculativeResourcePrefetchingEnabled[] = "enabled";
-
-#if defined(ENABLE_SPELLCHECK)
-#if defined(OS_ANDROID)
-// Enables use of the Android spellchecker.
-const char kEnableAndroidSpellChecker[] = "enable-android-spellchecker";
-#endif
-
-// Enables participation in the field trial for user feedback to spelling
-// service.
-const char kEnableSpellingFeedbackFieldTrial[] =
-    "enable-spelling-feedback-field-trial";
-
-// Specifies the URL where spelling service feedback data will be sent instead
-// of the default URL. This switch is for temporary testing only.
-// TODO(rouslan): Remove this flag when feedback testing is complete. Revisit by
-// August 2013.
-const char kSpellingServiceFeedbackUrl[] = "spelling-service-feedback-url";
-
-// Specifies the number of seconds between sending batches of feedback to
-// spelling service. The default is 30 minutes. The minimum is 5 seconds. This
-// switch is for temporary testing only.
-// TODO(rouslan): Remove this flag when feedback testing is complete. Revisit by
-// August 2013.
-const char kSpellingServiceFeedbackIntervalSeconds[] =
-    "spelling-service-feedback-interval-seconds";
-#endif
+// Causes SSL key material to be logged to the specified file for debugging
+// purposes. See
+// https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format
+// for the format.
+const char kSSLKeyLogFile[]               = "ssl-key-log-file";
 
 // Starts the browser maximized, regardless of any previous settings.
 const char kStartMaximized[]                = "start-maximized";
@@ -1042,9 +965,6 @@
 // all of its state.
 const char kUserDataDir[]                   = "user-data-dir";
 
-// Examines a .crx for validity and prints the result.
-const char kValidateCrx[]                   = "validate-crx";
-
 // Uses experimental simple cache backend if possible.
 const char kUseSimpleCacheBackend[]         = "use-simple-cache-backend";
 
@@ -1054,6 +974,9 @@
 // Enables using an out-of-process Mojo service for the v8 proxy resolver.
 const char kV8PacMojoOutOfProcess[] = "v8-pac-mojo-out-of-process";
 
+// Examines a .crx for validity and prints the result.
+const char kValidateCrx[]                   = "validate-crx";
+
 // Prints version information and quits.
 const char kVersion[]                       = "version";
 
@@ -1074,17 +997,64 @@
 // resulted in a browser startup.
 const char kWinJumplistAction[]             = "win-jumplist-action";
 
+#if defined(ENABLE_SPELLCHECK)
+#if defined(OS_ANDROID)
+// Enables use of the Android spellchecker.
+const char kEnableAndroidSpellChecker[] = "enable-android-spellchecker";
+#endif  // defined(OS_ANDROID)
+
+// Enables participation in the field trial for user feedback to spelling
+// service.
+const char kEnableSpellingFeedbackFieldTrial[] =
+    "enable-spelling-feedback-field-trial";
+
+// Specifies the number of seconds between sending batches of feedback to
+// spelling service. The default is 30 minutes. The minimum is 5 seconds. This
+// switch is for temporary testing only.
+// TODO(rouslan): Remove this flag when feedback testing is complete. Revisit by
+// August 2013.
+const char kSpellingServiceFeedbackIntervalSeconds[] =
+    "spelling-service-feedback-interval-seconds";
+
+// Specifies the URL where spelling service feedback data will be sent instead
+// of the default URL. This switch is for temporary testing only.
+// TODO(rouslan): Remove this flag when feedback testing is complete. Revisit by
+// August 2013.
+const char kSpellingServiceFeedbackUrl[] = "spelling-service-feedback-url";
+#endif  // defined(ENABLE_SPELLCHECK)
+
+#if defined(GOOGLE_CHROME_BUILD)
+// Shows a Google icon next to context menu items powered by Google services.
+const char kEnableGoogleBrandedContextMenu[] =
+    "enable-google-branded-context-menu";
+#endif  // defined(GOOGLE_CHROME_BUILD)
+
+#if !defined(GOOGLE_CHROME_BUILD)
+// Enables a live-reload for local NTP resources. This only works when Chrome
+// is running from a Chrome source directory.
+const char kLocalNtpReload[]                = "local-ntp-reload";
+#endif
+
 #if defined(OS_ANDROID)
 // Android authentication account type for SPNEGO authentication
 const char kAuthAndroidNegotiateAccountType[] = "auth-spnego-account-type";
 
+// Disable App Link.
+const char kDisableAppLink[] = "disable-app-link";
+
 // Disables Contextual Search.
 const char kDisableContextualSearch[]        = "disable-contextual-search";
 
+// Disable VR UI if supported.
+const char kDisableVrShell[] = "disable-vr-shell";
+
 // Enable the accessibility tab switcher.
 const char kEnableAccessibilityTabSwitcher[] =
     "enable-accessibility-tab-switcher";
 
+// Enable App Link.
+const char kEnableAppLink[] = "enable-app-link";
+
 // Enables Contextual Search.
 const char kEnableContextualSearch[]        = "enable-contextual-search";
 
@@ -1095,20 +1065,67 @@
 // unresponsive web content.
 const char kEnableHungRendererInfoBar[] = "enable-hung-renderer-infobar";
 
-// Specifies Android phone page loading progress bar animation.
-const char kProgressBarAnimation[]          = "progress-bar-animation";
-
 // Enabled tab switcher in document mode.
 const char kEnableTabSwitcherInDocumentMode[] =
     "enable-tab-switcher-in-document-mode";
 
+// Enable theme colors in the tab switcher.
+const char kEnableTabSwitcherThemeColors[] = "enable-tab-switcher-theme-colors";
+
+// Enable VR UI if supported.
+const char kEnableVrShell[] = "enable-vr-shell";
+
+// Enables "Add to Home screen" in the app menu to generate WebAPKs.
+const char kEnableWebApk[] = "enable-webapk";
+
+// Forces the update menu badge to show.
+const char kForceShowUpdateMenuBadge[] = "force-show-update-menu-badge";
+
+// Forces the update menu item to show.
+const char kForceShowUpdateMenuItem[] = "force-show-update-menu-item";
+
+// Forces a custom summary to be displayed below the update menu item.
+const char kForceShowUpdateMenuItemCustomSummary[] = "custom_summary";
+
+// Forces the new features summary to be displayed below the update menu item.
+const char kForceShowUpdateMenuItemNewFeaturesSummary[] =
+    "use_new_features_summary";
+
+// Forces a summary to be displayed below the update menu item.
+const char kForceShowUpdateMenuItemSummary[] = "show_summary";
+
+// Sets the market URL for Chrome for use in testing.
+const char kMarketUrlForTesting[] = "market-url-for-testing";
+
 // Switch to an existing tab for a suggestion opened from the New Tab Page.
 const char kNtpSwitchToExistingTab[] = "ntp-switch-to-existing-tab";
 
-// Enable theme colors in the tab switcher.
-const char kEnableTabSwitcherThemeColors[] = "enable-tab-switcher-theme-colors";
+// Specifies Android phone page loading progress bar animation.
+const char kProgressBarAnimation[]          = "progress-bar-animation";
+
+// Specifies a particular tab management experiment to enable.
+const char kTabManagementExperimentTypeAnise[] =
+    "tab-management-experiment-type-anise";
+const char kTabManagementExperimentTypeBasil[] =
+    "tab-management-experiment-type-basil";
+const char kTabManagementExperimentTypeChive[] =
+    "tab-management-experiment-type-chive";
+const char kTabManagementExperimentTypeDill[] =
+    "tab-management-experiment-type-dill";
+const char kTabManagementExperimentTypeDisabled[] =
+    "tab-management-experiment-type-disabled";
+const char kTabManagementExperimentTypeElderberry[] =
+    "tab-management-experiment-type-elderberry";
 #endif  // defined(OS_ANDROID)
 
+#if defined(OS_CHROMEOS)
+// Enables the intent picker so the user can handle URL links with ARC apps.
+const char kEnableIntentPicker[] = "enable-intent-picker";
+
+// Enables native cups integration
+const char kEnableNativeCups[] = "enable-native-cups";
+#endif // defined(OS_CHROMEOS)
+
 #if defined(USE_ASH)
 const char kOpenAsh[]                       = "open-ash";
 #endif
@@ -1130,10 +1147,6 @@
 // Prevents Chrome from quitting when Chrome Apps are open.
 const char kAppsKeepChromeAliveInTests[]    = "apps-keep-chrome-alive-in-tests";
 
-// Shows a notification when quitting Chrome with hosted apps running. Default
-// behavior is to also quit all hosted apps.
-const char kHostedAppQuitNotification[] = "enable-hosted-app-quit-notification";
-
 // Disable the toolkit-views App Info dialog for Mac.
 const char kDisableAppInfoDialogMac[] = "disable-app-info-dialog-mac";
 
@@ -1171,6 +1184,10 @@
 // Enables tab detaching in fullscreen mode on Mac.
 const char kEnableFullscreenTabDetaching[] = "enable-fullscreen-tab-detaching";
 
+// Enables the fullscreen toolbar to reveal itself for tab strip changes.
+const char kEnableFullscreenToolbarReveal[] =
+    "enable-fullscreen-toolbar-reveal";
+
 // Allows hosted apps to be opened in windows on Mac.
 const char kEnableHostedAppsInWindows[] = "enable-hosted-apps-in-windows";
 
@@ -1178,13 +1195,13 @@
 const char kEnableMacViewsNativeAppWindows[] =
     "enable-mac-views-native-app-windows";
 
-// Enables the fullscreen toolbar to reveal itself for tab strip changes.
-const char kEnableFullscreenToolbarReveal[] =
-    "enable-fullscreen-toolbar-reveal";
-
 // Enables Translate experimental new UX which replaces the infobar.
 const char kEnableTranslateNewUX[] = "enable-translate-new-ux";
 
+// Shows a notification when quitting Chrome with hosted apps running. Default
+// behavior is to also quit all hosted apps.
+const char kHostedAppQuitNotification[] = "enable-hosted-app-quit-notification";
+
 // This is how the metrics client ID is passed from the browser process to its
 // children. With Crashpad, the metrics client ID is distinct from the crash
 // client ID.
@@ -1216,6 +1233,12 @@
 // they use a custom-user-data-dir which disables this.
 const char kEnableProfileShortcutManager[]  = "enable-profile-shortcut-manager";
 
+// Makes Windows happy by allowing it to show "Enable access to this program"
+// checkbox in Add/Remove Programs->Set Program Access and Defaults. This only
+// shows an error box because the only way to hide Chrome is by uninstalling
+// it.
+const char kHideIcons[]                     = "hide-icons";
+
 // Whether or not the browser should warn if the profile is on a network share.
 // This flag is only relevant for Windows currently.
 const char kNoNetworkProfileWarning[]       = "no-network-profile-warning";
@@ -1228,12 +1251,6 @@
 // /prefetch:7 is used by crashpad, which can't depend on constants defined
 // here. See crashpad_win.cc for more details.
 
-// Makes Windows happy by allowing it to show "Enable access to this program"
-// checkbox in Add/Remove Programs->Set Program Access and Defaults. This only
-// shows an error box because the only way to hide Chrome is by uninstalling
-// it.
-const char kHideIcons[]                     = "hide-icons";
-
 // See kHideIcons.
 const char kShowIcons[]                     = "show-icons";
 
@@ -1257,49 +1274,28 @@
 const char kDebugPrint[] = "debug-print";
 #endif
 
+#if defined(ENABLE_PLUGINS)
+// Specifies comma-separated list of extension ids or hosts to grant
+// access to CRX file system APIs.
+const char kAllowNaClCrxFsAPI[]             = "allow-nacl-crxfs-api";
+
+// Specifies comma-separated list of extension ids or hosts to grant
+// access to file handle APIs.
+const char kAllowNaClFileHandleAPI[]        = "allow-nacl-file-handle-api";
+
+// Specifies comma-separated list of extension ids or hosts to grant
+// access to TCP/UDP socket APIs.
+const char kAllowNaClSocketAPI[]            = "allow-nacl-socket-api";
+#endif
+
 #if defined(ENABLE_WAYLAND_SERVER)
 // Enables Wayland display server support.
 const char kEnableWaylandServer[] = "enable-wayland-server";
 #endif
 
-#if defined(OS_ANDROID)
-// Forces the update menu item to show.
-const char kForceShowUpdateMenuItem[] = "force-show-update-menu-item";
-
-// Forces a summary to be displayed below the update menu item.
-const char kForceShowUpdateMenuItemSummary[] = "show_summary";
-
-// Forces the new features summary to be displayed below the update menu item.
-const char kForceShowUpdateMenuItemNewFeaturesSummary[] =
-    "use_new_features_summary";
-
-// Forces a custom summary to be displayed below the update menu item.
-const char kForceShowUpdateMenuItemCustomSummary[] = "custom_summary";
-
-// Forces the update menu badge to show.
-const char kForceShowUpdateMenuBadge[] = "force-show-update-menu-badge";
-
-// Sets the market URL for Chrome for use in testing.
-const char kMarketUrlForTesting[] = "market-url-for-testing";
-
-// Specifies a particular tab management experiment to enable.
-const char kTabManagementExperimentTypeDisabled[] =
-    "tab-management-experiment-type-disabled";
-const char kTabManagementExperimentTypeAnise[] =
-    "tab-management-experiment-type-anise";
-const char kTabManagementExperimentTypeBasil[] =
-    "tab-management-experiment-type-basil";
-const char kTabManagementExperimentTypeChive[] =
-    "tab-management-experiment-type-chive";
-const char kTabManagementExperimentTypeDill[] =
-    "tab-management-experiment-type-dill";
-const char kTabManagementExperimentTypeElderberry[] =
-    "tab-management-experiment-type-elderberry";
-#endif  // defined(OS_ANDROID)
-
 #if defined(OS_WIN) || defined(OS_LINUX)
-extern const char kEnableInputImeAPI[] = "enable-input-ime-api";
 extern const char kDisableInputImeAPI[] = "disable-input-ime-api";
+extern const char kEnableInputImeAPI[] = "enable-input-ime-api";
 #endif
 
 bool AboutInSettingsEnabled() {
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 4c50ffe..d8302e1 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -33,13 +33,13 @@
 extern const char kAllowRunningInsecureContent[];
 extern const char kAllowSilentPush[];
 extern const char kAlwaysAuthorizePlugins[];
-extern const char kAppId[];
 extern const char kApp[];
-extern const char kAppsGalleryDownloadURL[];
-extern const char kAppsGalleryURL[];
-extern const char kAppsGalleryUpdateURL[];
+extern const char kAppId[];
 extern const char kAppModeAuthCode[];
 extern const char kAppModeOAuth2Token[];
+extern const char kAppsGalleryDownloadURL[];
+extern const char kAppsGalleryUpdateURL[];
+extern const char kAppsGalleryURL[];
 extern const char kAuthExtensionPath[];
 extern const char kAuthServerWhitelist[];
 extern const char kAutoOpenDevToolsForTabs[];
@@ -49,8 +49,8 @@
 extern const char kCheckForUpdateIntervalSec[];
 extern const char kCipherSuiteBlacklist[];
 extern const char kCloudPrintFile[];
-extern const char kCloudPrintJobTitle[];
 extern const char kCloudPrintFileType[];
+extern const char kCloudPrintJobTitle[];
 extern const char kCloudPrintPrintTicket[];
 extern const char kCloudPrintSetupProxy[];
 extern const char kCrashOnHangThreads[];
@@ -62,9 +62,6 @@
 extern const char kDiagnosticsRecovery[];
 extern const char kDisableAboutInSettings[];
 extern const char kDisableAddToShelf[];
-#if defined(OS_ANDROID)
-extern const char kDisableAppLink[];
-#endif
 extern const char kDisableAsyncDns[];
 extern const char kDisableBackgroundNetworking[];
 extern const char kDisableBundledPpapiFlash[];
@@ -78,16 +75,16 @@
 extern const char kDisableDeviceDiscoveryNotifications[];
 extern const char kDisableDomainReliability[];
 extern const char kDisableDownloadNotification[];
+extern const char kDisableExtensions[];
 extern const char kDisableExtensionsFileAccessCheck[];
 extern const char kDisableExtensionsHttpThrottling[];
-extern const char kDisableExtensions[];
 extern const char kDisableFieldTrialTestingConfig[];
 extern const char kDisableMinimizeOnSecondLauncherItemClick[];
 extern const char kDisableNewBookmarkApps[];
 extern const char kDisableOfflineAutoReload[];
 extern const char kDisableOfflineAutoReloadVisibleOnly[];
 extern const char kDisableOutOfProcessPac[];
-extern const char kDisablePasswordManagerReauthentication[];
+extern const char kDisablePanels[];
 extern const char kDisablePermissionActionReporting[];
 extern const char kDisablePermissionsBlacklist[];
 extern const char kDisablePopupBlocking[];
@@ -96,10 +93,8 @@
 extern const char kDisablePromptOnRepost[];
 extern const char kDisablePushApiBackgroundMode[];
 extern const char kDisableSessionCrashedBubble[];
+extern const char kDisableSettingsWindow[];
 extern const char kDisableSiteEngagementService[];
-#if defined(OS_ANDROID)
-extern const char kDisableVrShell[];
-#endif
 extern const char kDisableWebNotificationCustomLayouts[];
 extern const char kDisableWebUsbSecurity[];
 extern const char kDisableZeroBrowsersOpenForTests[];
@@ -111,36 +106,24 @@
 extern const char kEasyUnlockAppPath[];
 extern const char kEnableAddToShelf[];
 extern const char kEnableAllBookmarksView[];
-#if defined(OS_ANDROID)
-extern const char kEnableAppLink[];
-#endif
 extern const char kEnableAppsFileAssociations[];
-#if defined(OS_CHROMEOS)
-extern const char kEnableIntentPicker[];
-#endif  // defined(OS_CHROMEOS)
 extern const char kEnableAudioDebugRecordingsFromExtension[];
 extern const char kEnableBenchmarking[];
 extern const char kEnableBookmarkUndo[];
 extern const char kEnableChildAccountDetection[];
 extern const char kEnableClearBrowsingDataCounters[];
 extern const char kEnableCloudPrintProxy[];
-extern const char kEnableDevToolsExperiments[];
 extern const char kEnableDeviceDiscoveryNotifications[];
+extern const char kEnableDevToolsExperiments[];
 extern const char kEnableDomainReliability[];
 extern const char kEnableExperimentalHotwordHardware[];
 extern const char kEnableExtensionActivityLogging[];
 extern const char kEnableExtensionActivityLogTesting[];
 extern const char kEnableFastUnload[];
-#if defined(GOOGLE_CHROME_BUILD)
-extern const char kEnableGoogleBrandedContextMenu[];
-#endif  // defined(GOOGLE_CHROME_BUILD)
 extern const char kEnableMaterialDesignExtensions[];
 extern const char kEnableMaterialDesignFeedback[];
 extern const char kEnableMaterialDesignPolicyPage[];
 extern const char kEnableNaCl[];
-#if defined(OS_CHROMEOS)
-extern const char kEnableNativeCups[];
-#endif // defined(OS_CHROMEOS)
 extern const char kEnableNativeNotifications[];
 extern const char kEnableNavigationTracing[];
 extern const char kEnableNetBenchmarking[];
@@ -148,7 +131,6 @@
 extern const char kEnableOfflineAutoReload[];
 extern const char kEnableOfflineAutoReloadVisibleOnly[];
 extern const char kEnablePanels[];
-extern const char kDisablePanels[];
 extern const char kEnablePermissionActionReporting[];
 extern const char kEnablePermissionsBlacklist[];
 extern const char kEnablePotentiallyAnnoyingSecurityFeatures[];
@@ -156,10 +138,8 @@
 extern const char kEnablePrintPreviewRegisterPromos[];
 extern const char kEnableProfiling[];
 extern const char kEnablePushApiBackgroundMode[];
-extern const char kEnableWebRtcEventLoggingFromExtension[];
 extern const char kEnableSessionCrashedBubble[];
 extern const char kEnableSettingsWindow[];
-extern const char kDisableSettingsWindow[];
 extern const char kEnableSiteEngagementAppBanner[];
 extern const char kEnableSiteEngagementEvictionPolicy[];
 extern const char kEnableSiteEngagementService[];
@@ -167,18 +147,13 @@
 extern const char kEnableTabAudioMuting[];
 extern const char kEnableThumbnailRetargeting[];
 extern const char kEnableUserAlternateProtocolPorts[];
-#if defined(OS_ANDROID)
-extern const char kEnableVrShell[];
-#endif
 extern const char kEnableWebAppFrame[];
-#if defined(OS_ANDROID)
-extern const char kEnableWebApk[];
-#endif  // defined(OS_ANDROID)
 extern const char kEnableWebNotificationCustomLayouts[];
-extern const char kExtensionContentVerificationBootstrap[];
-extern const char kExtensionContentVerificationEnforceStrict[];
-extern const char kExtensionContentVerificationEnforce[];
+extern const char kEnableWebRtcEventLoggingFromExtension[];
 extern const char kExtensionContentVerification[];
+extern const char kExtensionContentVerificationBootstrap[];
+extern const char kExtensionContentVerificationEnforce[];
+extern const char kExtensionContentVerificationEnforceStrict[];
 extern const char kExtensionsInstallVerification[];
 extern const char kExtensionsNotWebstore[];
 extern const char kExtensionsUpdateFrequency[];
@@ -186,12 +161,12 @@
 extern const char kForceAppMode[];
 extern const char kForceFieldTrialParams[];
 extern const char kForceFirstRun[];
-extern const char kForceVariationIds[];
 extern const char kForceLocalNtp[];
+extern const char kForceVariationIds[];
 extern const char kHistoryEnableGroupByDomain[];
 extern const char kHomePage[];
-extern const char kHostRules[];
 extern const char kHostResolverRetryAttempts[];
+extern const char kHostRules[];
 extern const char kIncognito[];
 extern const char kInstallChromeApp[];
 extern const char kInstallSupervisedUserWhitelists[];
@@ -202,9 +177,6 @@
 extern const char kKioskModePrinting[];
 extern const char kLoadComponentExtension[];
 extern const char kLoadExtension[];
-#if !defined(GOOGLE_CHROME_BUILD)
-extern const char kLocalNtpReload[];
-#endif
 extern const char kMakeDefaultBrowser[];
 extern const char kMediaCacheSize[];
 extern const char kMediaRouter[];
@@ -216,8 +188,8 @@
 extern const char kNoDisplayingInsecureContent[];
 extern const char kNoExperiments[];
 extern const char kNoFirstRun[];
-extern const char kNoProxyServer[];
 extern const char kNoPings[];
+extern const char kNoProxyServer[];
 extern const char kNoServiceAutorun[];
 extern const char kNoStartupWindow[];
 extern const char kNoSupervisedUserAcknowledgmentCheck[];
@@ -258,27 +230,19 @@
 extern const char kSbDisableExtensionBlacklist[];
 extern const char kSbManualDownloadBlacklist[];
 extern const char kServiceProcess[];
+extern const char kShowAppList[];
 extern const char kSilentDebuggerExtensionAPI[];
 extern const char kSilentLaunch[];
-extern const char kShowAppList[];
-extern const char kSSLKeyLogFile[];
-extern const char kSimulateElevatedRecovery[];
-extern const char kSimulateUpgrade[];
 extern const char kSimulateCriticalUpdate[];
+extern const char kSimulateElevatedRecovery[];
 extern const char kSimulateOutdated[];
 extern const char kSimulateOutdatedNoAU[];
+extern const char kSimulateUpgrade[];
 extern const char kSpeculativeResourcePrefetching[];
 extern const char kSpeculativeResourcePrefetchingDisabled[];
 extern const char kSpeculativeResourcePrefetchingEnabled[];
 extern const char kSpeculativeResourcePrefetchingLearning[];
-#if defined(ENABLE_SPELLCHECK)
-#if defined(OS_ANDROID)
-extern const char kEnableAndroidSpellChecker[];
-#endif
-extern const char kEnableSpellingFeedbackFieldTrial[];
-extern const char kSpellingServiceFeedbackUrl[];
-extern const char kSpellingServiceFeedbackIntervalSeconds[];
-#endif
+extern const char kSSLKeyLogFile[];
 extern const char kStartMaximized[];
 extern const char kSupervisedUserId[];
 extern const char kSupervisedUserSafeSites[];
@@ -289,9 +253,9 @@
 extern const char kUnlimitedStorage[];
 extern const char kUnsafelyTreatInsecureOriginAsSecure[];
 extern const char kUnsafePacUrl[];
-extern const char kUseSimpleCacheBackend[];
 extern const char kUserAgent[];
 extern const char kUserDataDir[];
+extern const char kUseSimpleCacheBackend[];
 extern const char kV8PacMojoInProcess[];
 extern const char kV8PacMojoOutOfProcess[];
 extern const char kValidateCrx[];
@@ -302,32 +266,58 @@
 extern const char kWinHttpProxyResolver[];
 extern const char kWinJumplistAction[];
 
+#if defined(ENABLE_SPELLCHECK)
+#if defined(OS_ANDROID)
+extern const char kEnableAndroidSpellChecker[];
+#endif  // defined(OS_ANDROID)
+extern const char kEnableSpellingFeedbackFieldTrial[];
+extern const char kSpellingServiceFeedbackIntervalSeconds[];
+extern const char kSpellingServiceFeedbackUrl[];
+#endif  // defined(ENABLE_SPELLCHECK)
+
+#if defined(GOOGLE_CHROME_BUILD)
+extern const char kEnableGoogleBrandedContextMenu[];
+#endif  // defined(GOOGLE_CHROME_BUILD)
+
+#if !defined(GOOGLE_CHROME_BUILD)
+extern const char kLocalNtpReload[];
+#endif
+
 #if defined(OS_ANDROID)
 extern const char kAuthAndroidNegotiateAccountType[];
+extern const char kDisableAppLink[];
 extern const char kDisableContextualSearch[];
+extern const char kDisableVrShell[];
 extern const char kEnableAccessibilityTabSwitcher[];
+extern const char kEnableAppLink[];
 extern const char kEnableContextualSearch[];
 extern const char kEnableHostedMode[];
 extern const char kEnableHungRendererInfoBar[];
-extern const char kProgressBarAnimation[];
-extern const char kEnableThemeColorInTabbedMode[];
 extern const char kEnableTabSwitcherInDocumentMode[];
 extern const char kEnableTabSwitcherThemeColors[];
-extern const char kNtpSwitchToExistingTab[];
-extern const char kForceShowUpdateMenuItem[];
-extern const char kForceShowUpdateMenuItemSummary[];
-extern const char kForceShowUpdateMenuItemNewFeaturesSummary[];
-extern const char kForceShowUpdateMenuItemCustomSummary[];
+extern const char kEnableVrShell[];
+extern const char kEnableWebApk[];
 extern const char kForceShowUpdateMenuBadge[];
+extern const char kForceShowUpdateMenuItem[];
+extern const char kForceShowUpdateMenuItemCustomSummary[];
+extern const char kForceShowUpdateMenuItemNewFeaturesSummary[];
+extern const char kForceShowUpdateMenuItemSummary[];
 extern const char kMarketUrlForTesting[];
-extern const char kTabManagementExperimentTypeDisabled[];
+extern const char kNtpSwitchToExistingTab[];
+extern const char kProgressBarAnimation[];
 extern const char kTabManagementExperimentTypeAnise[];
 extern const char kTabManagementExperimentTypeBasil[];
 extern const char kTabManagementExperimentTypeChive[];
 extern const char kTabManagementExperimentTypeDill[];
+extern const char kTabManagementExperimentTypeDisabled[];
 extern const char kTabManagementExperimentTypeElderberry[];
 #endif  // defined(OS_ANDROID)
 
+#if defined(OS_CHROMEOS)
+extern const char kEnableIntentPicker[];
+extern const char kEnableNativeCups[];
+#endif // defined(OS_CHROMEOS)
+
 #if defined(USE_ASH)
 extern const char kOpenAsh[];
 #endif
@@ -341,7 +331,6 @@
 
 #if defined(OS_MACOSX)
 extern const char kAppsKeepChromeAliveInTests[];
-extern const char kHostedAppQuitNotification[];
 extern const char kDisableAppInfoDialogMac[];
 extern const char kDisableAppWindowCycling[];
 extern const char kDisableFullscreenLowPowerMode[];
@@ -357,6 +346,7 @@
 extern const char kEnableHostedAppsInWindows[];
 extern const char kEnableMacViewsNativeAppWindows[];
 extern const char kEnableTranslateNewUX[];
+extern const char kHostedAppQuitNotification[];
 extern const char kMetricsClientID[];
 extern const char kRelauncherProcess[];
 extern const char kRelauncherProcessDMGDevice[];
@@ -393,8 +383,8 @@
 #endif
 
 #if defined(OS_WIN) || defined(OS_LINUX)
-extern const char kEnableInputImeAPI[];
 extern const char kDisableInputImeAPI[];
+extern const char kEnableInputImeAPI[];
 #endif
 
 bool AboutInSettingsEnabled();
diff --git a/chrome/common/extensions/extension_constants.cc b/chrome/common/extensions/extension_constants.cc
index c6b2bd2..4aa72be 100644
--- a/chrome/common/extensions/extension_constants.cc
+++ b/chrome/common/extensions/extension_constants.cc
@@ -51,7 +51,6 @@
     "abjokfonkihficiokmkfboogholifghn";
 const char kHotwordNewExtensionId[] = "nbpagnldghgfoolbancepceaanlmhfmd";
 const char kHotwordSharedModuleId[] = "lccekmodgklaepjeofjdjpbminllajkg";
-const char kSettingsAppId[] = "ennkphjdgehloodpbhlhldgbnhmacadg";
 const char kYoutubeAppId[] = "blpcfgokakmgnkcojhhkbfbldkacnbeo";
 const char kInAppPaymentsSupportAppId[] = "nmmhkkegccagdldgiimedpiccmgmieda";
 #if defined(ENABLE_MEDIA_ROUTER)
diff --git a/chrome/common/extensions/extension_constants.h b/chrome/common/extensions/extension_constants.h
index a7712827..ff4aaa5 100644
--- a/chrome/common/extensions/extension_constants.h
+++ b/chrome/common/extensions/extension_constants.h
@@ -94,9 +94,6 @@
 // The extension id of the hotword shared module.
 extern const char kHotwordSharedModuleId[];
 
-// The extension id of the settings application.
-extern const char kSettingsAppId[];
-
 // The extension id of the Youtube application.
 extern const char kYoutubeAppId[];
 
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 356fc944..0bf4b35 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -888,6 +888,11 @@
 // or dismissed HaTS (happiness-tracking) survey.
 const char kHatsLastInteractionTimestamp[] = "hats_last_interaction_timestamp";
 
+// A boolean pref. Indicates if we've already shown a notification to inform the
+// current user about the quick unlock feature.
+const char kQuickUnlockFeatureNotificationShown[] =
+    "quick_unlock_feature_notification_shown";
+
 // The salt and hash for the pin quick unlock mechanism.
 const char kQuickUnlockPinSalt[] = "quick_unlock.pin.salt";
 const char kQuickUnlockPinSecret[] = "quick_unlock.pin.secret";
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 7a34ddd..fb61a5b7 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -299,6 +299,7 @@
 extern const char kQuickUnlockPinSecret[];
 extern const char kEolStatus[];
 extern const char kEolNotificationDismissed[];
+extern const char kQuickUnlockFeatureNotificationShown[];
 #endif  // defined(OS_CHROMEOS)
 extern const char kShowHomeButton[];
 extern const char kRecentlySelectedEncoding[];
diff --git a/chrome/common/search/ntp_logging_events.h b/chrome/common/search/ntp_logging_events.h
index ba84f690..06aad77 100644
--- a/chrome/common/search/ntp_logging_events.h
+++ b/chrome/common/search/ntp_logging_events.h
@@ -43,10 +43,15 @@
 
   // Deleted: NTP_MOUSEOVER = 9
 
-  // A NTP Tile has finished loading (successfully or failing).
+  // A NTP Tile has finished loading (successfully or failing). Logged only by
+  // the multi-iframe version of the NTP.
   NTP_TILE_LOADED = 10,
 
-  NTP_EVENT_TYPE_LAST = NTP_TILE_LOADED
+  // All NTP tiles have finished loading (successfully or failing). Logged only
+  // by the single-iframe version of the NTP.
+  NTP_ALL_TILES_LOADED = 11,
+
+  NTP_EVENT_TYPE_LAST = NTP_ALL_TILES_LOADED
 };
 
 // The source of an NTP tile.
diff --git a/chrome/renderer/extensions/cast_streaming_native_handler.cc b/chrome/renderer/extensions/cast_streaming_native_handler.cc
index 4b20c600c..da8f742 100644
--- a/chrome/renderer/extensions/cast_streaming_native_handler.cc
+++ b/chrome/renderer/extensions/cast_streaming_native_handler.cc
@@ -21,6 +21,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/sys_info.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/common/extensions/api/cast_streaming_receiver_session.h"
 #include "chrome/common/extensions/api/cast_streaming_rtp_stream.h"
@@ -33,6 +34,7 @@
 #include "content/public/renderer/media_stream_utils.h"
 #include "extensions/renderer/script_context.h"
 #include "media/base/audio_parameters.h"
+#include "media/base/limits.h"
 #include "net/base/host_port_pair.h"
 #include "net/base/ip_address.h"
 #include "third_party/WebKit/public/platform/WebMediaStream.h"
@@ -43,10 +45,10 @@
 #include "url/gurl.h"
 
 using content::V8ValueConverter;
+using media::cast::FrameSenderConfig;
 
 // Extension types.
 using extensions::api::cast_streaming_receiver_session::RtpReceiverParams;
-using extensions::api::cast_streaming_rtp_stream::CodecSpecificParams;
 using extensions::api::cast_streaming_rtp_stream::RtpParams;
 using extensions::api::cast_streaming_rtp_stream::RtpPayloadParams;
 using extensions::api::cast_streaming_udp_transport::IPEndPoint;
@@ -54,36 +56,28 @@
 namespace extensions {
 
 namespace {
-const char kInvalidAesIvMask[] = "Invalid value for AES IV mask";
-const char kInvalidAesKey[] = "Invalid value for AES key";
-const char kInvalidAudioParams[] = "Invalid audio params";
-const char kInvalidDestination[] = "Invalid destination";
-const char kInvalidFPS[] = "Invalid FPS";
-const char kInvalidMediaStreamURL[] = "Invalid MediaStream URL";
-const char kInvalidRtpParams[] = "Invalid value for RTP params";
-const char kInvalidLatency[] = "Invalid value for max_latency. (0-1000)";
-const char kInvalidRtpTimebase[] = "Invalid rtp_timebase. (1000-1000000)";
-const char kInvalidStreamArgs[] = "Invalid stream arguments";
-const char kRtpStreamNotFound[] = "The RTP stream cannot be found";
-const char kUdpTransportNotFound[] = "The UDP transport cannot be found";
-const char kUnableToConvertArgs[] = "Unable to convert arguments";
-const char kUnableToConvertParams[] = "Unable to convert params";
 
-// These helper methods are used to convert between Extension API
-// types and Cast types.
-void ToCastCodecSpecificParams(const CodecSpecificParams& ext_params,
-                               CastCodecSpecificParams* cast_params) {
-  cast_params->key = ext_params.key;
-  cast_params->value = ext_params.value;
-}
+constexpr char kInvalidAesIvMask[] = "Invalid value for AES IV mask";
+constexpr char kInvalidAesKey[] = "Invalid value for AES key";
+constexpr char kInvalidAudioParams[] = "Invalid audio params";
+constexpr char kInvalidDestination[] = "Invalid destination";
+constexpr char kInvalidFPS[] = "Invalid FPS";
+constexpr char kInvalidMediaStreamURL[] = "Invalid MediaStream URL";
+constexpr char kInvalidRtpParams[] = "Invalid value for RTP params";
+constexpr char kInvalidLatency[] = "Invalid value for max_latency. (0-1000)";
+constexpr char kInvalidRtpTimebase[] = "Invalid rtp_timebase. (1000-1000000)";
+constexpr char kInvalidStreamArgs[] = "Invalid stream arguments";
+constexpr char kRtpStreamNotFound[] = "The RTP stream cannot be found";
+constexpr char kUdpTransportNotFound[] = "The UDP transport cannot be found";
+constexpr char kUnableToConvertArgs[] = "Unable to convert arguments";
+constexpr char kUnableToConvertParams[] = "Unable to convert params";
+constexpr char kCodecNameOpus[] = "OPUS";
+constexpr char kCodecNameVp8[] = "VP8";
+constexpr char kCodecNameH264[] = "H264";
 
-void FromCastCodecSpecificParams(const CastCodecSpecificParams& cast_params,
-                                 CodecSpecificParams* ext_params) {
-  ext_params->key = cast_params.key;
-  ext_params->value = cast_params.value;
-}
+// To convert from kilobits per second to bits per second.
+constexpr int kBitsPerKilobit = 1000;
 
-namespace {
 bool HexDecode(const std::string& input, std::string* output) {
   std::vector<uint8_t> bytes;
   if (!base::HexStringToBytes(input, &bytes))
@@ -91,107 +85,189 @@
   output->assign(reinterpret_cast<const char*>(&bytes[0]), bytes.size());
   return true;
 }
-}  // namespace
 
-bool ToCastRtpPayloadParamsOrThrow(v8::Isolate* isolate,
-                                   const RtpPayloadParams& ext_params,
-                                   CastRtpPayloadParams* cast_params) {
-  cast_params->max_latency_ms = ext_params.max_latency;
-  cast_params->min_latency_ms =
-      ext_params.min_latency ? *ext_params.min_latency : ext_params.max_latency;
-  cast_params->animated_latency_ms = ext_params.animated_latency
-                                         ? *ext_params.animated_latency
-                                         : ext_params.max_latency;
-  cast_params->codec_name = ext_params.codec_name;
-  if (cast_params->codec_name == "OPUS") {
-    cast_params->payload_type = media::cast::RtpPayloadType::AUDIO_OPUS;
-  } else if (cast_params->codec_name == "PCM16") {
-    cast_params->payload_type = media::cast::RtpPayloadType::AUDIO_PCM16;
-  } else if (cast_params->codec_name == "AAC") {
-    cast_params->payload_type = media::cast::RtpPayloadType::AUDIO_AAC;
-  } else if (cast_params->codec_name == "VP8") {
-    cast_params->payload_type = media::cast::RtpPayloadType::VIDEO_VP8;
-  } else if (cast_params->codec_name == "H264") {
-    cast_params->payload_type = media::cast::RtpPayloadType::VIDEO_H264;
+int NumberOfEncodeThreads() {
+  // Do not saturate CPU utilization just for encoding. On a lower-end system
+  // with only 1 or 2 cores, use only one thread for encoding. On systems with
+  // more cores, allow half of the cores to be used for encoding.
+  return std::min(8, (base::SysInfo::NumberOfProcessors() + 1) / 2);
+}
+
+bool ToFrameSenderConfigOrThrow(v8::Isolate* isolate,
+                                const RtpPayloadParams& ext_params,
+                                FrameSenderConfig* config) {
+  config->sender_ssrc = ext_params.ssrc;
+  config->receiver_ssrc = ext_params.feedback_ssrc;
+  if (config->sender_ssrc == config->receiver_ssrc) {
+    DVLOG(1) << "sender_ssrc " << config->sender_ssrc
+             << " cannot be equal to receiver_ssrc";
+    isolate->ThrowException(v8::Exception::Error(
+        v8::String::NewFromUtf8(isolate, kInvalidRtpParams)));
+    return false;
   }
-  cast_params->ssrc = ext_params.ssrc;
-  cast_params->feedback_ssrc = ext_params.feedback_ssrc;
-  cast_params->clock_rate = ext_params.clock_rate ? *ext_params.clock_rate : 0;
-  cast_params->min_bitrate =
-      ext_params.min_bitrate ? *ext_params.min_bitrate : 0;
-  cast_params->max_bitrate =
-      ext_params.max_bitrate ? *ext_params.max_bitrate : 0;
-  cast_params->channels = ext_params.channels ? *ext_params.channels : 0;
-  cast_params->max_frame_rate =
-      ext_params.max_frame_rate ? *ext_params.max_frame_rate : 0.0;
-  if (ext_params.aes_key &&
-      !HexDecode(*ext_params.aes_key, &cast_params->aes_key)) {
+  config->min_playout_delay = base::TimeDelta::FromMilliseconds(
+      ext_params.min_latency ? *ext_params.min_latency
+                             : ext_params.max_latency);
+  config->max_playout_delay =
+      base::TimeDelta::FromMilliseconds(ext_params.max_latency);
+  config->animated_playout_delay = base::TimeDelta::FromMilliseconds(
+      ext_params.animated_latency ? *ext_params.animated_latency
+                                  : ext_params.max_latency);
+  if (config->min_playout_delay <= base::TimeDelta()) {
+    DVLOG(1) << "min_playout_delay " << config->min_playout_delay
+             << " must be greater than zero";
+    isolate->ThrowException(v8::Exception::Error(
+        v8::String::NewFromUtf8(isolate, kInvalidRtpParams)));
+    return false;
+  }
+  if (config->min_playout_delay > config->max_playout_delay) {
+    DVLOG(1) << "min_playout_delay " << config->min_playout_delay
+             << " must be less than or equal to max_palyout_delay";
+    isolate->ThrowException(v8::Exception::Error(
+        v8::String::NewFromUtf8(isolate, kInvalidRtpParams)));
+    return false;
+  }
+  if (config->animated_playout_delay < config->min_playout_delay ||
+      config->animated_playout_delay > config->max_playout_delay) {
+    DVLOG(1) << "animated_playout_delay " << config->animated_playout_delay
+             << " must be between (inclusive) the min and max playout delay";
+    isolate->ThrowException(v8::Exception::Error(
+        v8::String::NewFromUtf8(isolate, kInvalidRtpParams)));
+    return false;
+  }
+  if (ext_params.codec_name == kCodecNameOpus) {
+    config->rtp_payload_type = media::cast::RtpPayloadType::AUDIO_OPUS;
+    config->use_external_encoder = false;
+    config->rtp_timebase = ext_params.clock_rate
+                               ? *ext_params.clock_rate
+                               : media::cast::kDefaultAudioSamplingRate;
+    // Sampling rate must be one of the Opus-supported values.
+    switch (config->rtp_timebase) {
+      case 48000:
+      case 24000:
+      case 16000:
+      case 12000:
+      case 8000:
+        break;
+      default:
+        DVLOG(1) << "rtp_timebase " << config->rtp_timebase << " is invalid";
+        isolate->ThrowException(v8::Exception::Error(
+            v8::String::NewFromUtf8(isolate, kInvalidRtpParams)));
+        return false;
+    }
+    config->channels = ext_params.channels ? *ext_params.channels : 2;
+    if (config->channels != 1 && config->channels != 2) {
+      isolate->ThrowException(v8::Exception::Error(
+          v8::String::NewFromUtf8(isolate, kInvalidRtpParams)));
+      DVLOG(1) << "channels " << config->channels << " is invalid";
+      return false;
+    }
+    config->min_bitrate = config->start_bitrate = config->max_bitrate =
+        ext_params.max_bitrate ? (*ext_params.max_bitrate) * kBitsPerKilobit
+                               : media::cast::kDefaultAudioEncoderBitrate;
+    config->max_frame_rate = 100;  // 10ms audio frames.
+    config->codec = media::cast::CODEC_AUDIO_OPUS;
+  } else if (ext_params.codec_name == kCodecNameVp8 ||
+             ext_params.codec_name == kCodecNameH264) {
+    config->rtp_timebase = media::cast::kVideoFrequency;
+    config->channels = ext_params.channels ? *ext_params.channels : 1;
+    if (config->channels != 1) {
+      isolate->ThrowException(v8::Exception::Error(
+          v8::String::NewFromUtf8(isolate, kInvalidRtpParams)));
+      DVLOG(1) << "channels " << config->channels << " is invalid";
+      return false;
+    }
+    config->min_bitrate = ext_params.min_bitrate
+                              ? (*ext_params.min_bitrate) * kBitsPerKilobit
+                              : media::cast::kDefaultMinVideoBitrate;
+    config->max_bitrate = ext_params.max_bitrate
+                              ? (*ext_params.max_bitrate) * kBitsPerKilobit
+                              : media::cast::kDefaultMaxVideoBitrate;
+    if (config->min_bitrate > config->max_bitrate) {
+      DVLOG(1) << "min_bitrate " << config->min_bitrate << " is larger than "
+               << "max_bitrate " << config->max_bitrate;
+      isolate->ThrowException(v8::Exception::Error(
+          v8::String::NewFromUtf8(isolate, kInvalidRtpParams)));
+      return false;
+    }
+    config->start_bitrate = config->min_bitrate;
+    config->max_frame_rate = std::max(
+        1.0, ext_params.max_frame_rate ? *ext_params.max_frame_rate : 0.0);
+    if (config->max_frame_rate > media::limits::kMaxFramesPerSecond) {
+      DVLOG(1) << "max_frame_rate " << config->max_frame_rate << " is invalid";
+      isolate->ThrowException(v8::Exception::Error(
+          v8::String::NewFromUtf8(isolate, kInvalidRtpParams)));
+      return false;
+    }
+    if (ext_params.codec_name == kCodecNameVp8) {
+      config->rtp_payload_type = media::cast::RtpPayloadType::VIDEO_VP8;
+      config->codec = media::cast::CODEC_VIDEO_VP8;
+      config->use_external_encoder =
+          CastRtpStream::IsHardwareVP8EncodingSupported();
+    } else {
+      config->rtp_payload_type = media::cast::RtpPayloadType::VIDEO_H264;
+      config->codec = media::cast::CODEC_VIDEO_H264;
+      config->use_external_encoder =
+          CastRtpStream::IsHardwareH264EncodingSupported();
+    }
+    if (!config->use_external_encoder)
+      config->video_codec_params.number_of_encode_threads =
+          NumberOfEncodeThreads();
+  } else {
+    DVLOG(1) << "codec_name " << ext_params.codec_name << " is invalid";
+    isolate->ThrowException(v8::Exception::Error(
+        v8::String::NewFromUtf8(isolate, kInvalidRtpParams)));
+    return false;
+  }
+  if (ext_params.aes_key && !HexDecode(*ext_params.aes_key, &config->aes_key)) {
     isolate->ThrowException(v8::Exception::Error(
         v8::String::NewFromUtf8(isolate, kInvalidAesKey)));
     return false;
   }
   if (ext_params.aes_iv_mask &&
-      !HexDecode(*ext_params.aes_iv_mask, &cast_params->aes_iv_mask)) {
+      !HexDecode(*ext_params.aes_iv_mask, &config->aes_iv_mask)) {
     isolate->ThrowException(v8::Exception::Error(
         v8::String::NewFromUtf8(isolate, kInvalidAesIvMask)));
     return false;
   }
-  for (size_t i = 0; i < ext_params.codec_specific_params.size(); ++i) {
-    CastCodecSpecificParams cast_codec_params;
-    ToCastCodecSpecificParams(ext_params.codec_specific_params[i],
-                              &cast_codec_params);
-    cast_params->codec_specific_params.push_back(cast_codec_params);
-  }
   return true;
 }
 
-void FromCastRtpPayloadParams(const CastRtpPayloadParams& cast_params,
-                              RtpPayloadParams* ext_params) {
-  ext_params->payload_type = static_cast<int>(cast_params.payload_type);
-  ext_params->max_latency = cast_params.max_latency_ms;
-  ext_params->min_latency.reset(new int(cast_params.min_latency_ms));
-  ext_params->animated_latency.reset(new int(cast_params.animated_latency_ms));
-  ext_params->codec_name = cast_params.codec_name;
-  ext_params->ssrc = cast_params.ssrc;
-  ext_params->feedback_ssrc = cast_params.feedback_ssrc;
-  if (cast_params.clock_rate)
-    ext_params->clock_rate.reset(new int(cast_params.clock_rate));
-  if (cast_params.min_bitrate)
-    ext_params->min_bitrate.reset(new int(cast_params.min_bitrate));
-  if (cast_params.max_bitrate)
-    ext_params->max_bitrate.reset(new int(cast_params.max_bitrate));
-  if (cast_params.channels)
-    ext_params->channels.reset(new int(cast_params.channels));
-  if (cast_params.max_frame_rate > 0.0)
-    ext_params->max_frame_rate.reset(new double(cast_params.max_frame_rate));
-  for (size_t i = 0; i < cast_params.codec_specific_params.size(); ++i) {
-    CodecSpecificParams ext_codec_params;
-    FromCastCodecSpecificParams(cast_params.codec_specific_params[i],
-                                &ext_codec_params);
-    ext_params->codec_specific_params.push_back(std::move(ext_codec_params));
+void FromFrameSenderConfig(const FrameSenderConfig& config,
+                           RtpPayloadParams* ext_params) {
+  ext_params->payload_type = static_cast<int>(config.rtp_payload_type);
+  ext_params->max_latency = config.max_playout_delay.InMilliseconds();
+  ext_params->min_latency.reset(
+      new int(config.min_playout_delay.InMilliseconds()));
+  ext_params->animated_latency.reset(
+      new int(config.animated_playout_delay.InMilliseconds()));
+  switch (config.codec) {
+    case media::cast::CODEC_AUDIO_OPUS:
+      ext_params->codec_name = kCodecNameOpus;
+      break;
+    case media::cast::CODEC_VIDEO_VP8:
+      ext_params->codec_name = kCodecNameVp8;
+      break;
+    case media::cast::CODEC_VIDEO_H264:
+      ext_params->codec_name = kCodecNameH264;
+      break;
+    default:
+      NOTREACHED();
   }
-}
-
-void FromCastRtpParams(const CastRtpParams& cast_params,
-                       RtpParams* ext_params) {
-  std::copy(cast_params.rtcp_features.begin(),
-            cast_params.rtcp_features.end(),
-            std::back_inserter(ext_params->rtcp_features));
-  FromCastRtpPayloadParams(cast_params.payload, &ext_params->payload);
-}
-
-bool ToCastRtpParamsOrThrow(v8::Isolate* isolate,
-                            const RtpParams& ext_params,
-                            CastRtpParams* cast_params) {
-  std::copy(ext_params.rtcp_features.begin(),
-            ext_params.rtcp_features.end(),
-            std::back_inserter(cast_params->rtcp_features));
-  if (!ToCastRtpPayloadParamsOrThrow(isolate,
-                                     ext_params.payload,
-                                     &cast_params->payload)) {
-    return false;
-  }
-  return true;
+  ext_params->ssrc = config.sender_ssrc;
+  ext_params->feedback_ssrc = config.receiver_ssrc;
+  if (config.rtp_timebase)
+    ext_params->clock_rate.reset(new int(config.rtp_timebase));
+  if (config.min_bitrate)
+    ext_params->min_bitrate.reset(
+        new int(config.min_bitrate / kBitsPerKilobit));
+  if (config.max_bitrate)
+    ext_params->max_bitrate.reset(
+        new int(config.max_bitrate / kBitsPerKilobit));
+  if (config.channels)
+    ext_params->channels.reset(new int(config.channels));
+  if (config.max_frame_rate > 0.0)
+    ext_params->max_frame_rate.reset(new double(config.max_frame_rate));
 }
 
 }  // namespace
@@ -399,13 +475,12 @@
     return;
 
   std::unique_ptr<V8ValueConverter> converter(V8ValueConverter::create());
-  std::vector<CastRtpParams> cast_params = transport->GetSupportedParams();
+  std::vector<FrameSenderConfig> configs = transport->GetSupportedConfigs();
   v8::Local<v8::Array> result =
-      v8::Array::New(args.GetIsolate(),
-                     static_cast<int>(cast_params.size()));
-  for (size_t i = 0; i < cast_params.size(); ++i) {
+      v8::Array::New(args.GetIsolate(), static_cast<int>(configs.size()));
+  for (size_t i = 0; i < configs.size(); ++i) {
     RtpParams params;
-    FromCastRtpParams(cast_params[i], &params);
+    FromFrameSenderConfig(configs[i], &params.payload);
     std::unique_ptr<base::DictionaryValue> params_value = params.ToValue();
     result->Set(
         static_cast<int>(i),
@@ -440,9 +515,9 @@
     return;
   }
 
-  CastRtpParams cast_params;
+  FrameSenderConfig config;
   v8::Isolate* isolate = context()->v8_context()->GetIsolate();
-  if (!ToCastRtpParamsOrThrow(isolate, *params, &cast_params))
+  if (!ToFrameSenderConfigOrThrow(isolate, params->payload, &config))
     return;
 
   base::Closure start_callback =
@@ -457,7 +532,7 @@
       base::Bind(&CastStreamingNativeHandler::CallErrorCallback,
                  weak_factory_.GetWeakPtr(),
                  transport_id);
-  transport->Start(cast_params, start_callback, stop_callback, error_callback);
+  transport->Start(config, start_callback, stop_callback, error_callback);
 }
 
 void CastStreamingNativeHandler::StopCastRtpStream(
@@ -816,7 +891,8 @@
       media::AudioParameters::AUDIO_PCM_LINEAR,
       media::GuessChannelLayout(audio_config.channels),
       audio_config.rtp_timebase,  // sampling rate
-      16, audio_config.rtp_timebase / audio_config.target_frame_rate);
+      16, static_cast<int>(audio_config.rtp_timebase /
+                           audio_config.target_frame_rate));
 
   if (!params.IsValid()) {
     args.GetIsolate()->ThrowException(v8::Exception::TypeError(
diff --git a/chrome/renderer/media/cast_rtp_stream.cc b/chrome/renderer/media/cast_rtp_stream.cc
index 305cd0b..01d0fce1 100644
--- a/chrome/renderer/media/cast_rtp_stream.cc
+++ b/chrome/renderer/media/cast_rtp_stream.cc
@@ -19,7 +19,6 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/strings/stringprintf.h"
-#include "base/sys_info.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/timer/timer.h"
 #include "base/trace_event/trace_event.h"
@@ -44,18 +43,10 @@
 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
 #include "ui/gfx/geometry/size.h"
 
-using media::cast::AudioSenderConfig;
-using media::cast::VideoSenderConfig;
+using media::cast::FrameSenderConfig;
 
 namespace {
 
-const char kCodecNameOpus[] = "OPUS";
-const char kCodecNameVp8[] = "VP8";
-const char kCodecNameH264[] = "H264";
-
-// To convert from kilobits per second to bits to per second.
-const int kBitrateMultiplier = 1000;
-
 // The maximum number of milliseconds that should elapse since the last video
 // frame was received from the video source, before requesting refresh frames.
 const int kRefreshIntervalMilliseconds = 250;
@@ -64,253 +55,69 @@
 // limit (60 * 250ms = 15 seconds), refresh frame requests will stop being made.
 const int kMaxConsecutiveRefreshFrames = 60;
 
-CastRtpPayloadParams DefaultOpusPayload() {
-  CastRtpPayloadParams payload;
-  payload.payload_type = media::cast::RtpPayloadType::AUDIO_OPUS;
-  payload.max_latency_ms = media::cast::kDefaultRtpMaxDelayMs;
-  payload.ssrc = 1;
-  payload.feedback_ssrc = 2;
-  payload.clock_rate = media::cast::kDefaultAudioSamplingRate;
+FrameSenderConfig DefaultOpusConfig() {
+  FrameSenderConfig config;
+  config.rtp_payload_type = media::cast::RtpPayloadType::AUDIO_OPUS;
+  config.sender_ssrc = 1;
+  config.receiver_ssrc = 2;
+  config.rtp_timebase = media::cast::kDefaultAudioSamplingRate;
+  config.channels = 2;
   // The value is 0 which means VBR.
-  payload.min_bitrate = payload.max_bitrate =
+  config.min_bitrate = config.max_bitrate = config.start_bitrate =
       media::cast::kDefaultAudioEncoderBitrate;
-  payload.channels = 2;
-  payload.max_frame_rate = 100;  // 10 ms audio frames
-  payload.codec_name = kCodecNameOpus;
-  return payload;
+  config.max_frame_rate = 100;  // 10 ms audio frames
+  config.codec = media::cast::CODEC_AUDIO_OPUS;
+  return config;
 }
 
-CastRtpPayloadParams DefaultVp8Payload() {
-  CastRtpPayloadParams payload;
-  payload.payload_type = media::cast::RtpPayloadType::VIDEO_VP8;
-  payload.max_latency_ms = media::cast::kDefaultRtpMaxDelayMs;
-  payload.ssrc = 11;
-  payload.feedback_ssrc = 12;
-  payload.clock_rate = media::cast::kVideoFrequency;
-  payload.max_bitrate = media::cast::kDefaultMaxVideoKbps;
-  payload.min_bitrate = media::cast::kDefaultMinVideoKbps;
-  payload.channels = 1;
-  payload.max_frame_rate = media::cast::kDefaultMaxFrameRate;
-  payload.codec_name = kCodecNameVp8;
-  return payload;
+FrameSenderConfig DefaultVp8Config() {
+  FrameSenderConfig config;
+  config.rtp_payload_type = media::cast::RtpPayloadType::VIDEO_VP8;
+  config.sender_ssrc = 11;
+  config.receiver_ssrc = 12;
+  config.rtp_timebase = media::cast::kVideoFrequency;
+  config.channels = 1;
+  config.max_bitrate = media::cast::kDefaultMaxVideoBitrate;
+  config.min_bitrate = media::cast::kDefaultMinVideoBitrate;
+  config.max_frame_rate = media::cast::kDefaultMaxFrameRate;
+  config.codec = media::cast::CODEC_VIDEO_VP8;
+  return config;
 }
 
-CastRtpPayloadParams DefaultH264Payload() {
-  CastRtpPayloadParams payload;
-  payload.payload_type = media::cast::RtpPayloadType::VIDEO_H264;
-  payload.max_latency_ms = media::cast::kDefaultRtpMaxDelayMs;
-  payload.ssrc = 11;
-  payload.feedback_ssrc = 12;
-  payload.clock_rate = media::cast::kVideoFrequency;
-  payload.max_bitrate = media::cast::kDefaultMaxVideoKbps;
-  payload.min_bitrate = media::cast::kDefaultMinVideoKbps;
-  payload.channels = 1;
-  payload.max_frame_rate = media::cast::kDefaultMaxFrameRate;
-  payload.codec_name = kCodecNameH264;
-  return payload;
+FrameSenderConfig DefaultH264Config() {
+  FrameSenderConfig config;
+  config.rtp_payload_type = media::cast::RtpPayloadType::VIDEO_H264;
+  config.sender_ssrc = 11;
+  config.receiver_ssrc = 12;
+  config.rtp_timebase = media::cast::kVideoFrequency;
+  config.channels = 1;
+  config.max_bitrate = media::cast::kDefaultMaxVideoBitrate;
+  config.min_bitrate = media::cast::kDefaultMinVideoBitrate;
+  config.max_frame_rate = media::cast::kDefaultMaxFrameRate;
+  config.codec = media::cast::CODEC_VIDEO_H264;
+  return config;
 }
 
-bool IsHardwareVP8EncodingSupported() {
-  const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
-  if (cmd_line->HasSwitch(switches::kDisableCastStreamingHWEncoding)) {
-    DVLOG(1) << "Disabled hardware VP8 support for Cast Streaming.";
-    return false;
-  }
-
-  // Query for hardware VP8 encoder support.
-  const std::vector<media::VideoEncodeAccelerator::SupportedProfile>
-      vea_profiles = content::GetSupportedVideoEncodeAcceleratorProfiles();
-  for (const auto& vea_profile : vea_profiles) {
-    if (vea_profile.profile >= media::VP8PROFILE_MIN &&
-        vea_profile.profile <= media::VP8PROFILE_MAX) {
-      return true;
-    }
-  }
-  return false;
-}
-
-bool IsHardwareH264EncodingSupported() {
-  const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
-  if (cmd_line->HasSwitch(switches::kDisableCastStreamingHWEncoding)) {
-    DVLOG(1) << "Disabled hardware h264 support for Cast Streaming.";
-    return false;
-  }
-
-  // Query for hardware H.264 encoder support.
-  //
-  // TODO(miu): Look into why H.264 hardware encoder on MacOS is broken.
-  // http://crbug.com/596674
-#if !defined(OS_MACOSX)
-  const std::vector<media::VideoEncodeAccelerator::SupportedProfile>
-      vea_profiles = content::GetSupportedVideoEncodeAcceleratorProfiles();
-  for (const auto& vea_profile : vea_profiles) {
-    if (vea_profile.profile >= media::H264PROFILE_MIN &&
-        vea_profile.profile <= media::H264PROFILE_MAX) {
-      return true;
-    }
-  }
-#endif  // !defined(OS_MACOSX)
-  return false;
-}
-
-int NumberOfEncodeThreads() {
-  // Do not saturate CPU utilization just for encoding. On a lower-end system
-  // with only 1 or 2 cores, use only one thread for encoding. On systems with
-  // more cores, allow half of the cores to be used for encoding.
-  return std::min(8, (base::SysInfo::NumberOfProcessors() + 1) / 2);
-}
-
-std::vector<CastRtpParams> SupportedAudioParams() {
+std::vector<FrameSenderConfig> SupportedAudioConfigs() {
   // TODO(hclam): Fill in more codecs here.
-  return std::vector<CastRtpParams>(1, CastRtpParams(DefaultOpusPayload()));
+  return std::vector<FrameSenderConfig>(1, DefaultOpusConfig());
 }
 
-std::vector<CastRtpParams> SupportedVideoParams() {
-  std::vector<CastRtpParams> supported_params;
+std::vector<FrameSenderConfig> SupportedVideoConfigs() {
+  std::vector<FrameSenderConfig> supported_configs;
 
   // Prefer VP8 over H.264 for hardware encoder.
-  if (IsHardwareVP8EncodingSupported())
-    supported_params.push_back(CastRtpParams(DefaultVp8Payload()));
-  if (IsHardwareH264EncodingSupported())
-    supported_params.push_back(CastRtpParams(DefaultH264Payload()));
+  if (CastRtpStream::IsHardwareVP8EncodingSupported())
+    supported_configs.push_back(DefaultVp8Config());
+  if (CastRtpStream::IsHardwareH264EncodingSupported())
+    supported_configs.push_back(DefaultH264Config());
 
   // Propose the default software VP8 encoder, if no hardware encoders are
   // available.
-  if (supported_params.empty())
-    supported_params.push_back(CastRtpParams(DefaultVp8Payload()));
+  if (supported_configs.empty())
+    supported_configs.push_back(DefaultVp8Config());
 
-  return supported_params;
-}
-
-bool ToAudioSenderConfig(const CastRtpParams& params,
-                         AudioSenderConfig* config) {
-  config->ssrc = params.payload.ssrc;
-  config->receiver_ssrc = params.payload.feedback_ssrc;
-  if (config->ssrc == config->receiver_ssrc) {
-    DVLOG(1) << "ssrc " << config->ssrc << " cannot be equal to receiver_ssrc";
-    return false;
-  }
-  config->min_playout_delay = base::TimeDelta::FromMilliseconds(
-                                  params.payload.min_latency_ms ?
-                                  params.payload.min_latency_ms :
-                                  params.payload.max_latency_ms);
-  config->max_playout_delay =
-      base::TimeDelta::FromMilliseconds(params.payload.max_latency_ms);
-  config->animated_playout_delay = base::TimeDelta::FromMilliseconds(
-      params.payload.animated_latency_ms ? params.payload.animated_latency_ms
-                                         : params.payload.max_latency_ms);
-  if (config->min_playout_delay <= base::TimeDelta()) {
-    DVLOG(1) << "min_playout_delay " << config->min_playout_delay
-             << " is too small";
-    return false;
-  }
-  if (config->min_playout_delay > config->max_playout_delay) {
-    DVLOG(1) << "min_playout_delay " << config->min_playout_delay
-             << " is too big";
-    return false;
-  }
-  if (config->animated_playout_delay < config->min_playout_delay ||
-      config->animated_playout_delay > config->max_playout_delay) {
-    DVLOG(1) << "animated_playout_delay " << config->animated_playout_delay
-             << " is out of range";
-    return false;
-  }
-  config->rtp_payload_type = params.payload.payload_type;
-  config->use_external_encoder = false;
-  config->frequency = params.payload.clock_rate;
-  // Sampling rate must be one of the Opus-supported values.
-  switch (config->frequency) {
-    case 48000:
-    case 24000:
-    case 16000:
-    case 12000:
-    case 8000:
-      break;
-    default:
-      DVLOG(1) << "frequency " << config->frequency << " is invalid";
-      return false;
-  }
-  config->channels = params.payload.channels;
-  if (config->channels < 1) {
-    DVLOG(1) << "channels " << config->channels << " is invalid";
-    return false;
-  }
-  config->bitrate = params.payload.max_bitrate * kBitrateMultiplier;
-  if (params.payload.codec_name == kCodecNameOpus) {
-    config->codec = media::cast::CODEC_AUDIO_OPUS;
-  } else {
-    DVLOG(1) << "codec_name " << params.payload.codec_name << " is invalid";
-    return false;
-  }
-  config->aes_key = params.payload.aes_key;
-  config->aes_iv_mask = params.payload.aes_iv_mask;
-  return true;
-}
-
-bool ToVideoSenderConfig(const CastRtpParams& params,
-                         VideoSenderConfig* config) {
-  config->ssrc = params.payload.ssrc;
-  config->receiver_ssrc = params.payload.feedback_ssrc;
-  if (config->ssrc == config->receiver_ssrc) {
-    DVLOG(1) << "ssrc " << config->ssrc << " cannot be equal to receiver_ssrc";
-    return false;
-  }
-  config->min_playout_delay = base::TimeDelta::FromMilliseconds(
-                                  params.payload.min_latency_ms ?
-                                  params.payload.min_latency_ms :
-                                  params.payload.max_latency_ms);
-  config->max_playout_delay =
-      base::TimeDelta::FromMilliseconds(params.payload.max_latency_ms);
-  config->animated_playout_delay = base::TimeDelta::FromMilliseconds(
-      params.payload.animated_latency_ms ? params.payload.animated_latency_ms
-                                         : params.payload.max_latency_ms);
-  if (config->min_playout_delay <= base::TimeDelta()) {
-    DVLOG(1) << "min_playout_delay " << config->min_playout_delay
-             << " is too small";
-    return false;
-  }
-  if (config->min_playout_delay > config->max_playout_delay) {
-    DVLOG(1) << "min_playout_delay " << config->min_playout_delay
-             << " is too big";
-    return false;
-  }
-  if (config->animated_playout_delay < config->min_playout_delay ||
-      config->animated_playout_delay > config->max_playout_delay) {
-    DVLOG(1) << "animated_playout_delay " << config->animated_playout_delay
-             << " is out of range";
-    return false;
-  }
-  config->rtp_payload_type = params.payload.payload_type;
-  config->min_bitrate = config->start_bitrate =
-      params.payload.min_bitrate * kBitrateMultiplier;
-  config->max_bitrate = params.payload.max_bitrate * kBitrateMultiplier;
-  if (config->min_bitrate > config->max_bitrate) {
-    DVLOG(1) << "min_bitrate " << config->min_bitrate << " is larger than "
-             << "max_bitrate " << config->max_bitrate;
-    return false;
-  }
-  config->start_bitrate = config->min_bitrate;
-  config->max_frame_rate = static_cast<int>(
-      std::max(1.0, params.payload.max_frame_rate) + 0.5);
-  if (config->max_frame_rate > media::limits::kMaxFramesPerSecond) {
-    DVLOG(1) << "max_frame_rate " << config->max_frame_rate << " is invalid";
-    return false;
-  }
-  if (params.payload.codec_name == kCodecNameVp8) {
-    config->use_external_encoder = IsHardwareVP8EncodingSupported();
-    config->codec = media::cast::CODEC_VIDEO_VP8;
-  } else if (params.payload.codec_name == kCodecNameH264) {
-    config->use_external_encoder = IsHardwareH264EncodingSupported();
-    config->codec = media::cast::CODEC_VIDEO_H264;
-  } else {
-    DVLOG(1) << "codec_name " << params.payload.codec_name << " is invalid";
-    return false;
-  }
-  if (!config->use_external_encoder)
-    config->number_of_encode_threads = NumberOfEncodeThreads();
-  config->aes_key = params.payload.aes_key;
-  config->aes_iv_mask = params.payload.aes_iv_mask;
-  return true;
+  return supported_configs;
 }
 
 }  // namespace
@@ -595,35 +402,48 @@
   DISALLOW_COPY_AND_ASSIGN(CastAudioSink);
 };
 
-CastRtpParams::CastRtpParams(const CastRtpPayloadParams& payload_params)
-    : payload(payload_params) {}
+bool CastRtpStream::IsHardwareVP8EncodingSupported() {
+  const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
+  if (cmd_line->HasSwitch(switches::kDisableCastStreamingHWEncoding)) {
+    DVLOG(1) << "Disabled hardware VP8 support for Cast Streaming.";
+    return false;
+  }
 
-CastCodecSpecificParams::CastCodecSpecificParams() {}
+  // Query for hardware VP8 encoder support.
+  const std::vector<media::VideoEncodeAccelerator::SupportedProfile>
+      vea_profiles = content::GetSupportedVideoEncodeAcceleratorProfiles();
+  for (const auto& vea_profile : vea_profiles) {
+    if (vea_profile.profile >= media::VP8PROFILE_MIN &&
+        vea_profile.profile <= media::VP8PROFILE_MAX) {
+      return true;
+    }
+  }
+  return false;
+}
 
-CastCodecSpecificParams::~CastCodecSpecificParams() {}
+bool CastRtpStream::IsHardwareH264EncodingSupported() {
+  const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
+  if (cmd_line->HasSwitch(switches::kDisableCastStreamingHWEncoding)) {
+    DVLOG(1) << "Disabled hardware h264 support for Cast Streaming.";
+    return false;
+  }
 
-CastRtpPayloadParams::CastRtpPayloadParams()
-    : payload_type(media::cast::RtpPayloadType::UNKNOWN),
-      max_latency_ms(0),
-      min_latency_ms(0),
-      ssrc(0),
-      feedback_ssrc(0),
-      clock_rate(0),
-      max_bitrate(0),
-      min_bitrate(0),
-      channels(0),
-      max_frame_rate(0.0) {}
-
-CastRtpPayloadParams::CastRtpPayloadParams(const CastRtpPayloadParams& other) =
-    default;
-
-CastRtpPayloadParams::~CastRtpPayloadParams() {}
-
-CastRtpParams::CastRtpParams() {}
-
-CastRtpParams::CastRtpParams(const CastRtpParams& other) = default;
-
-CastRtpParams::~CastRtpParams() {}
+// Query for hardware H.264 encoder support.
+//
+// TODO(miu): Look into why H.264 hardware encoder on MacOS is broken.
+// http://crbug.com/596674
+#if !defined(OS_MACOSX)
+  const std::vector<media::VideoEncodeAccelerator::SupportedProfile>
+      vea_profiles = content::GetSupportedVideoEncodeAcceleratorProfiles();
+  for (const auto& vea_profile : vea_profiles) {
+    if (vea_profile.profile >= media::H264PROFILE_MIN &&
+        vea_profile.profile <= media::H264PROFILE_MAX) {
+      return true;
+    }
+  }
+#endif  // !defined(OS_MACOSX)
+  return false;
+}
 
 CastRtpStream::CastRtpStream(const blink::WebMediaStreamTrack& track,
                              const scoped_refptr<CastSession>& session)
@@ -633,16 +453,14 @@
   Stop();
 }
 
-std::vector<CastRtpParams> CastRtpStream::GetSupportedParams() {
+std::vector<FrameSenderConfig> CastRtpStream::GetSupportedConfigs() {
   if (IsAudio())
-    return SupportedAudioParams();
+    return SupportedAudioConfigs();
   else
-    return SupportedVideoParams();
+    return SupportedVideoConfigs();
 }
 
-CastRtpParams CastRtpStream::GetParams() { return params_; }
-
-void CastRtpStream::Start(const CastRtpParams& params,
+void CastRtpStream::Start(const FrameSenderConfig& config,
                           const base::Closure& start_callback,
                           const base::Closure& stop_callback,
                           const ErrorCallback& error_callback) {
@@ -655,18 +473,10 @@
   error_callback_ = error_callback;
 
   if (IsAudio()) {
-    AudioSenderConfig config;
-    if (!ToAudioSenderConfig(params, &config)) {
-      DidEncounterError("Invalid parameters for audio.");
-      return;
-    }
-
     // In case of error we have to go through DidEncounterError() to stop
     // the streaming after reporting the error.
-    audio_sink_.reset(new CastAudioSink(
-        track_,
-        params.payload.channels,
-        params.payload.clock_rate));
+    audio_sink_.reset(
+        new CastAudioSink(track_, config.channels, config.rtp_timebase));
     cast_session_->StartAudio(
         config,
         base::Bind(&CastAudioSink::AddToTrack, audio_sink_->AsWeakPtr()),
@@ -674,11 +484,6 @@
                    weak_factory_.GetWeakPtr()));
     start_callback.Run();
   } else {
-    VideoSenderConfig config;
-    if (!ToVideoSenderConfig(params, &config)) {
-      DidEncounterError("Invalid parameters for video.");
-      return;
-    }
     // See the code for audio above for explanation of callbacks.
     video_sink_.reset(new CastVideoSink(
         track_,
@@ -686,7 +491,7 @@
                                             weak_factory_.GetWeakPtr()))));
     cast_session_->StartVideo(
         config, base::Bind(&CastVideoSink::AddToTrack, video_sink_->AsWeakPtr(),
-                           !params.payload.aes_key.empty()),
+                           !config.aes_key.empty()),
         base::Bind(&CastRtpStream::DidEncounterError,
                    weak_factory_.GetWeakPtr()));
     start_callback.Run();
diff --git a/chrome/renderer/media/cast_rtp_stream.h b/chrome/renderer/media/cast_rtp_stream.h
index 456463e..01c3da8 100644
--- a/chrome/renderer/media/cast_rtp_stream.h
+++ b/chrome/renderer/media/cast_rtp_stream.h
@@ -26,86 +26,6 @@
 class CastSession;
 class CastVideoSink;
 
-// A key value pair structure for codec specific parameters.
-struct CastCodecSpecificParams {
-  std::string key;
-  std::string value;
-
-  CastCodecSpecificParams();
-  ~CastCodecSpecificParams();
-};
-
-// Defines the basic properties of a payload supported by cast transport.
-struct CastRtpPayloadParams {
-  // RTP specific field that identifies the content type.
-  media::cast::RtpPayloadType payload_type =
-      media::cast::RtpPayloadType::VIDEO_VP8;
-
-  // Maximum latency in milliseconds. Implemetation tries to keep latency
-  // under this threshold.
-  int max_latency_ms = media::cast::kDefaultRtpMaxDelayMs;
-
-  // Minimum latency.
-  // Default value (0) means use max_latency_ms.
-  int min_latency_ms = 0;
-
-  // Starting latency on animated content.
-  // Default value (0) means use max_latency_ms.
-  int animated_latency_ms = 0;
-
-  // RTP specific field to identify a stream.
-  int ssrc = 1;
-
-  // RTP specific field to idenfity the feedback stream.
-  int feedback_ssrc = 2;
-
-  // Update frequency of payload sample.
-  int clock_rate = media::cast::kVideoFrequency;
-
-  // Maximum bitrate in kilobits per second.
-  int max_bitrate = media::cast::kDefaultMaxVideoKbps;
-
-  // Minimum bitrate in kilobits per second.
-  int min_bitrate = media::cast::kDefaultMinVideoKbps;
-
-  // Number of audio channels.
-  int channels = 1;
-
-  // The maximum frame rate.
-  double max_frame_rate = media::cast::kDefaultMaxFrameRate;
-
-  // Name of the codec used.
-  std::string codec_name;
-
-  // AES encryption key.
-  std::string aes_key;
-
-  // AES encryption IV mask.
-  std::string aes_iv_mask;
-
-  // List of codec specific parameters.
-  std::vector<CastCodecSpecificParams> codec_specific_params;
-
-  CastRtpPayloadParams();
-  CastRtpPayloadParams(const CastRtpPayloadParams& other);
-  ~CastRtpPayloadParams();
-};
-
-// Defines the parameters of a RTP stream.
-struct CastRtpParams {
-  explicit CastRtpParams(const CastRtpPayloadParams& payload_params);
-
-  // Payload parameters.
-  CastRtpPayloadParams payload;
-
-  // Names of supported RTCP features.
-  std::vector<std::string> rtcp_features;
-
-  CastRtpParams();
-  CastRtpParams(const CastRtpParams& other);
-  ~CastRtpParams();
-};
-
 // This object represents a RTP stream that encodes and optionally
 // encrypt audio or video data from a WebMediaStreamTrack.
 // Note that this object does not actually output packets. It allows
@@ -115,22 +35,23 @@
  public:
   typedef base::Callback<void(const std::string&)> ErrorCallback;
 
+  static bool IsHardwareVP8EncodingSupported();
+
+  static bool IsHardwareH264EncodingSupported();
+
   CastRtpStream(const blink::WebMediaStreamTrack& track,
                 const scoped_refptr<CastSession>& session);
   ~CastRtpStream();
 
   // Return parameters currently supported by this stream.
-  std::vector<CastRtpParams> GetSupportedParams();
-
-  // Return parameters set to this stream.
-  CastRtpParams GetParams();
+  std::vector<media::cast::FrameSenderConfig> GetSupportedConfigs();
 
   // Begin encoding of media stream and then submit the encoded streams
   // to underlying transport.
   // When the stream is started |start_callback| is called.
   // When the stream is stopped |stop_callback| is called.
   // When there is an error |error_callback| is called with a message.
-  void Start(const CastRtpParams& params,
+  void Start(const media::cast::FrameSenderConfig& config,
              const base::Closure& start_callback,
              const base::Closure& stop_callback,
              const ErrorCallback& error_callback);
@@ -163,7 +84,6 @@
   const scoped_refptr<CastSession> cast_session_;
   std::unique_ptr<CastAudioSink> audio_sink_;
   std::unique_ptr<CastVideoSink> video_sink_;
-  CastRtpParams params_;
   base::Closure stop_callback_;
   ErrorCallback error_callback_;
 
diff --git a/chrome/renderer/media/cast_session.cc b/chrome/renderer/media/cast_session.cc
index 61ce4379..c9fc3a6 100644
--- a/chrome/renderer/media/cast_session.cc
+++ b/chrome/renderer/media/cast_session.cc
@@ -53,7 +53,7 @@
   CHECK(io_task_runner_->DeleteSoon(FROM_HERE, delegate_.release()));
 }
 
-void CastSession::StartAudio(const media::cast::AudioSenderConfig& config,
+void CastSession::StartAudio(const media::cast::FrameSenderConfig& config,
                              const AudioFrameInputAvailableCallback& callback,
                              const ErrorCallback& error_callback) {
   DCHECK(content::RenderThread::Get());
@@ -67,7 +67,7 @@
                  media::BindToCurrentLoop(error_callback)));
 }
 
-void CastSession::StartVideo(const media::cast::VideoSenderConfig& config,
+void CastSession::StartVideo(const media::cast::FrameSenderConfig& config,
                              const VideoFrameInputAvailableCallback& callback,
                              const ErrorCallback& error_callback) {
   DCHECK(content::RenderThread::Get());
diff --git a/chrome/renderer/media/cast_session.h b/chrome/renderer/media/cast_session.h
index 658e2e7d..2ccbc747 100644
--- a/chrome/renderer/media/cast_session.h
+++ b/chrome/renderer/media/cast_session.h
@@ -60,10 +60,10 @@
   // error message. Both |callback| and |error_callback| will be made on
   // the main thread.
   // |StartUDP()| must be called before these methods.
-  void StartAudio(const media::cast::AudioSenderConfig& config,
+  void StartAudio(const media::cast::FrameSenderConfig& config,
                   const AudioFrameInputAvailableCallback& callback,
                   const ErrorCallback& error_callback);
-  void StartVideo(const media::cast::VideoSenderConfig& config,
+  void StartVideo(const media::cast::FrameSenderConfig& config,
                   const VideoFrameInputAvailableCallback& callback,
                   const ErrorCallback& error_callback);
 
diff --git a/chrome/renderer/media/cast_session_delegate.cc b/chrome/renderer/media/cast_session_delegate.cc
index 90d98957..5596d5d 100644
--- a/chrome/renderer/media/cast_session_delegate.cc
+++ b/chrome/renderer/media/cast_session_delegate.cc
@@ -29,10 +29,9 @@
 #include "media/cast/net/cast_transport.h"
 #include "media/cast/net/cast_transport_config.h"
 
-using media::cast::AudioSenderConfig;
 using media::cast::CastEnvironment;
 using media::cast::CastSender;
-using media::cast::VideoSenderConfig;
+using media::cast::FrameSenderConfig;
 
 static base::LazyInstance<CastThreads> g_cast_threads =
     LAZY_INSTANCE_INITIALIZER;
@@ -116,7 +115,7 @@
 }
 
 void CastSessionDelegate::StartAudio(
-    const AudioSenderConfig& config,
+    const FrameSenderConfig& config,
     const AudioFrameInputAvailableCallback& callback,
     const ErrorCallback& error_callback) {
   DCHECK(io_task_runner_->BelongsToCurrentThread());
@@ -134,7 +133,7 @@
 }
 
 void CastSessionDelegate::StartVideo(
-    const VideoSenderConfig& config,
+    const FrameSenderConfig& config,
     const VideoFrameInputAvailableCallback& callback,
     const ErrorCallback& error_callback,
     const media::cast::CreateVideoEncodeAcceleratorCallback& create_vea_cb,
diff --git a/chrome/renderer/media/cast_session_delegate.h b/chrome/renderer/media/cast_session_delegate.h
index dbe7626..54cf520b 100644
--- a/chrome/renderer/media/cast_session_delegate.h
+++ b/chrome/renderer/media/cast_session_delegate.h
@@ -104,17 +104,17 @@
   // deliver any data between calling the two methods.
   // It's OK to call only one of the two methods.
   // StartUDP must be called before these methods.
-  void StartAudio(const media::cast::AudioSenderConfig& config,
+  void StartAudio(const media::cast::FrameSenderConfig& config,
                   const AudioFrameInputAvailableCallback& callback,
                   const ErrorCallback& error_callback);
 
-  void StartVideo(const media::cast::VideoSenderConfig& config,
-                  const VideoFrameInputAvailableCallback& callback,
-                  const ErrorCallback& error_callback,
-                  const media::cast::CreateVideoEncodeAcceleratorCallback&
-                      create_vea_cb,
-                  const media::cast::CreateVideoEncodeMemoryCallback&
-                      create_video_encode_mem_cb);
+  void StartVideo(
+      const media::cast::FrameSenderConfig& config,
+      const VideoFrameInputAvailableCallback& callback,
+      const ErrorCallback& error_callback,
+      const media::cast::CreateVideoEncodeAcceleratorCallback& create_vea_cb,
+      const media::cast::CreateVideoEncodeMemoryCallback&
+          create_video_encode_mem_cb);
 
   void ToggleLogging(bool is_audio, bool enable);
   void GetEventLogsAndReset(bool is_audio,
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 1e608bbd..acfe5a620 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2288,6 +2288,9 @@
             ".",
             "//chrome")
   }
+  if (enable_supervised_users && !is_android && !is_chromeos) {
+    sources += [ "../browser/ui/webui/signin/signin_supervised_user_import_handler_unittest.cc" ]
+  }
   if (safe_browsing_mode == 1 && enable_extensions) {
     sources += [ "../browser/extensions/blacklist_unittest.cc" ]
   }
diff --git a/chrome/test/base/menu_model_test.cc b/chrome/test/base/menu_model_test.cc
index 4b1b25b..63b113e 100644
--- a/chrome/test/base/menu_model_test.cc
+++ b/chrome/test/base/menu_model_test.cc
@@ -17,7 +17,7 @@
 
 bool MenuModelTest::Delegate::GetAcceleratorForCommandId(
     int command_id,
-    ui::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) const {
   return false;
 }
 
diff --git a/chrome/test/base/menu_model_test.h b/chrome/test/base/menu_model_test.h
index 8133485..f321f46 100644
--- a/chrome/test/base/menu_model_test.h
+++ b/chrome/test/base/menu_model_test.h
@@ -25,8 +25,9 @@
 
     bool IsCommandIdChecked(int command_id) const override;
     bool IsCommandIdEnabled(int command_id) const override;
-    bool GetAcceleratorForCommandId(int command_id,
-                                    ui::Accelerator* accelerator) override;
+    bool GetAcceleratorForCommandId(
+        int command_id,
+        ui::Accelerator* accelerator) const override;
     void ExecuteCommand(int command_id, int event_flags) override;
 
     int execute_count_;
diff --git a/chrome/test/data/extensions/api_test/cast_streaming/rtp_stream_error.js b/chrome/test/data/extensions/api_test/cast_streaming/rtp_stream_error.js
index 9db1949..b67ddf6a 100644
--- a/chrome/test/data/extensions/api_test/cast_streaming/rtp_stream_error.js
+++ b/chrome/test/data/extensions/api_test/cast_streaming/rtp_stream_error.js
@@ -31,19 +31,21 @@
                     pass(function(stream, audioId, videoId, udpId) {
         var audioParams = rtpStream.getSupportedParams(audioId)[0];
         var videoParams = rtpStream.getSupportedParams(videoId)[0];
-        rtpStream.onError.addListener(
-            pass(function(audioId, videoId, id, msg) {
-          chrome.test.assertEq(videoId, id);
-          rtpStream.destroy(audioId);
-          rtpStream.destroy(videoId);
-          udpTransport.destroy(udpId);
-          console.log(msg);
-        }.bind(null, audioId, videoId)));
         // Specify invalid value to trigger error.
         videoParams.payload.codecName = "Animated WebP";
         udpTransport.setDestination(udpId,
                                     {address: "127.0.0.1", port: 2344});
-        rtpStream.start(videoId, videoParams);
+        try {
+          rtpStream.start(videoId, videoParams);
+          chrome.test.fail();
+        } catch (e) {
+          rtpStream.stop(audioId);
+          rtpStream.stop(videoId);
+          rtpStream.destroy(audioId);
+          rtpStream.destroy(videoId);
+          udpTransport.destroy(udpId);
+          chrome.test.succeed();
+        }
       }.bind(null, stream)));
     }));
   },
diff --git a/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js b/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js
index 4e13fcd..eb6b320 100644
--- a/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js
+++ b/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js
@@ -96,3 +96,22 @@
   cr_slider.registerTests();
   mocha.run();
 });
+
+function CrElementsSharedMenuTest() {}
+
+CrElementsSharedMenuTest.prototype = {
+  __proto__: CrElementsBrowserTest.prototype,
+
+  /** @override */
+  browsePreload:
+      'chrome://resources/cr_elements/cr_shared_menu/cr_shared_menu.html',
+
+  /** @override */
+  extraLibraries: CrElementsBrowserTest.prototype.extraLibraries.concat([
+    'cr_shared_menu_tests.js'
+  ]),
+};
+
+TEST_F('CrElementsSharedMenuTest', 'All', function() {
+  mocha.run();
+});
diff --git a/chrome/test/data/webui/cr_elements/cr_shared_menu_tests.js b/chrome/test/data/webui/cr_elements/cr_shared_menu_tests.js
new file mode 100644
index 0000000..59747fa
--- /dev/null
+++ b/chrome/test/data/webui/cr_elements/cr_shared_menu_tests.js
@@ -0,0 +1,122 @@
+// 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.
+
+/** @fileoverview Suite of tests for cr-shared-menu. */
+suite('cr-shared-menu', function() {
+  var menu;
+
+  var button;
+
+  var item1;
+  var item2;
+  var item3;
+
+  function afterOpen(callback) {
+    menu.addEventListener('iron-overlay-opened', function f() {
+      menu.removeEventListener('iron-overlay-opened', f);
+      callback();
+    });
+  }
+
+  suiteSetup(function() {
+    return PolymerTest.importHtml(
+        'chrome://resources/polymer/v1_0/paper-item/paper-item.html');
+  });
+
+  setup(function() {
+    PolymerTest.clearBody();
+    // Basic wiring to set up a menu which opens when a button is pressed.
+    menu = document.createElement('cr-shared-menu');
+    menu.$$('#dropdown').noAnimations = true;
+
+    item1 = document.createElement('paper-item');
+    menu.appendChild(item1);
+    item2 = document.createElement('paper-item');
+    menu.appendChild(item2);
+    item3 = document.createElement('paper-item');
+    menu.appendChild(item3);
+
+    button = document.createElement('button');
+    button.addEventListener('tap', function() {
+      menu.toggleMenu(button, {});
+    });
+
+    document.body.appendChild(menu);
+    document.body.appendChild(button);
+  });
+
+  test('opening and closing menu', function(done) {
+    MockInteractions.tap(button);
+    assertTrue(menu.menuOpen);
+
+    afterOpen(function() {
+      // Using tap to close the menu requires that the iron-overlay-behavior
+      // has finished initializing, which happens asynchronously between
+      // tapping the button and firing iron-overlay-opened.
+      MockInteractions.tap(document.body);
+      assertFalse(menu.menuOpen);
+
+      MockInteractions.tap(button);
+      assertTrue(menu.menuOpen);
+
+      // Pressing escape should close the menu.
+      MockInteractions.pressAndReleaseKeyOn(menu, 27);
+      assertTrue(menu.menuOpen);
+      done();
+    });
+  });
+
+  test('refocus button on close', function(done) {
+    button.focus();
+    MockInteractions.tap(button);
+
+    afterOpen(function() {
+      assertTrue(menu.menuOpen);
+      // Focus is applied asynchronously after the menu is opened.
+      assertEquals(item1, menu.shadowRoot.activeElement);
+
+      menu.closeMenu();
+      assertFalse(menu.menuOpen);
+
+      // Button should regain focus after closing the menu.
+      assertEquals(button, document.activeElement);
+
+      done();
+    });
+  });
+
+  test('closeMenu does not refocus button when focus moves', function(done) {
+    var input = document.createElement('input');
+    document.body.appendChild(input);
+
+    button.focus();
+    MockInteractions.tap(button);
+
+    afterOpen(function() {
+      input.focus();
+      menu.closeMenu();
+      assertEquals(input, document.activeElement);
+
+      done();
+    });
+  });
+
+  test('focus is trapped inside the menu', function(done) {
+    button.focus();
+    MockInteractions.tap(button);
+
+    afterOpen(function() {
+      // Simulate shift-tab on first element.
+      assertEquals(item1, menu.shadowRoot.activeElement);
+      MockInteractions.pressAndReleaseKeyOn(item1, 9, ['shift']);
+      assertEquals(item3, menu.shadowRoot.activeElement);
+
+      // Simulate tab on last element.
+      MockInteractions.pressAndReleaseKeyOn(item3, 9);
+      assertEquals(item1, menu.shadowRoot.activeElement);
+
+      done();
+    });
+  });
+});
diff --git a/chrome/test/data/webui/md_history/history_overflow_menu_test.js b/chrome/test/data/webui/md_history/history_overflow_menu_test.js
index 01836a7f..b7ca2ee 100644
--- a/chrome/test/data/webui/md_history/history_overflow_menu_test.js
+++ b/chrome/test/data/webui/md_history/history_overflow_menu_test.js
@@ -61,15 +61,6 @@
                      element.$.sharedMenu.lastAnchor_);
       });
 
-      test('keyboard input for closing menu', function() {
-        // Test that pressing escape on the document closes the menu. In the
-        // actual page, it will take two presses to close the menu due to focus.
-        // TODO(yingran): Fix this behavior to only require one key press.
-        element.toggleMenu_(MENU_EVENT);
-        MockInteractions.pressAndReleaseKeyOn(document.body, 27);
-        assertEquals(false, element.$.sharedMenu.menuOpen);
-      });
-
       teardown(function() {
         element.$.sharedMenu.lastAnchor_ = null;
       });
diff --git a/chrome/test/data/webui/md_history/history_toolbar_test.js b/chrome/test/data/webui/md_history/history_toolbar_test.js
index 6eb61f6..5383fd1d 100644
--- a/chrome/test/data/webui/md_history/history_toolbar_test.js
+++ b/chrome/test/data/webui/md_history/history_toolbar_test.js
@@ -45,7 +45,7 @@
       test('search term gathered correctly from toolbar', function(done) {
         app.queryState_.queryingDisabled = false;
         registerMessageCallback('queryHistory', this, function (info) {
-          assertEquals(info[0], 'Test');
+          assertEquals('Test', info[0]);
           done();
         });
 
@@ -70,7 +70,19 @@
             document.body, 70, 'ctrl', 'f');
         assertTrue(field.showingSearch);
         assertEquals(field.$.searchInput, field.root.activeElement);
-     });
+      });
+
+      test('spinner is active on search' , function(done) {
+        app.queryState_.queryingDisabled = false;
+        registerMessageCallback('queryHistory', this, function (info) {
+          assertTrue(toolbar.spinnerActive);
+          app.historyResult(createHistoryInfo(), TEST_HISTORY_RESULTS);
+          assertFalse(toolbar.spinnerActive);
+          done();
+        });
+
+        toolbar.$$('cr-toolbar').fire('search-changed', 'Test2');
+      });
 
       teardown(function() {
         element.historyData_ = [];
diff --git a/chrome/test/data/webui/settings/search_engines_page_test.js b/chrome/test/data/webui/settings/search_engines_page_test.js
index a96ecee..599043e 100644
--- a/chrome/test/data/webui/settings/search_engines_page_test.js
+++ b/chrome/test/data/webui/settings/search_engines_page_test.js
@@ -16,7 +16,7 @@
       canBeEdited: canBeEdited,
       canBeRemoved: canBeRemoved,
       default: false,
-      displayName: "Google",
+      displayName: "Google displayName",
       iconURL: "http://www.google.com/favicon.ico",
       isOmniboxExtension: false,
       keyword: "google.com",
@@ -34,7 +34,7 @@
       canBeEdited: false,
       canBeRemoved: false,
       default: false,
-      displayName: "Omnibox extension",
+      displayName: "Omnibox extension displayName",
       extension: {
         icon: "chrome://extension-icon/some-extension-icon",
         id: "dummyextensionid",
@@ -143,19 +143,39 @@
       /** @type {?SettingsSearchEngineEntryElement} */
       var entry = null;
 
+      /** @type {!settings_search.TestSearchEnginesBrowserProxy} */
       var browserProxy = null;
 
+      /** @type {!SearchEngine} */
+      var searchEngine = createSampleSearchEngine(true, true, true);
+
       setup(function() {
         browserProxy = new settings_search.TestSearchEnginesBrowserProxy();
         settings.SearchEnginesBrowserProxyImpl.instance_ = browserProxy;
         PolymerTest.clearBody();
         entry = document.createElement('settings-search-engine-entry');
-        entry.set('engine', createSampleSearchEngine(true, true, true));
+        entry.set('engine', searchEngine);
         document.body.appendChild(entry);
       });
 
       teardown(function() { entry.remove(); });
 
+      // Test that the <search-engine-entry> is populated according to its
+      // underlying SearchEngine model.
+      test('Initialization', function() {
+        var nameElement = entry.$$('.name');
+        assertTrue(!!nameElement);
+        assertEquals(searchEngine.displayName, nameElement.textContent);
+
+        var keywordElement = entry.$$('.keyword-column');
+        assertTrue(!!keywordElement);
+        assertEquals(searchEngine.keyword, keywordElement.textContent);
+
+        var urlElement = entry.$$('.url-column');
+        assertTrue(!!urlElement);
+        assertEquals(searchEngine.url, urlElement.textContent);
+      });
+
       test('Remove_Enabled', function() {
         var deleteButton = entry.$.delete;
         assertTrue(!!deleteButton);
@@ -191,7 +211,7 @@
               assertTrue(!!dialog);
 
               // Check that the paper-input fields are pre-populated.
-              assertEquals(engine.displayName, dialog.$.searchEngine.value);
+              assertEquals(engine.name, dialog.$.searchEngine.value);
               assertEquals(engine.keyword, dialog.$.keyword.value);
               assertEquals(engine.url, dialog.$.queryUrl.value);
 
diff --git a/chrome/test/data/webui_test_resources.grd b/chrome/test/data/webui_test_resources.grd
index 6f8530d..3c269a9 100644
--- a/chrome/test/data/webui_test_resources.grd
+++ b/chrome/test/data/webui_test_resources.grd
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="0" current_release="1">
+<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
   <outputs>
     <output filename="chrome/test/data/grit/webui_test_resources.h" type="rc_header">
       <emit emit_type='prepend'></emit>
diff --git a/chrome/utility/importer/bookmark_html_reader.cc b/chrome/utility/importer/bookmark_html_reader.cc
index f23183c0..8e524b83 100644
--- a/chrome/utility/importer/bookmark_html_reader.cc
+++ b/chrome/utility/importer/bookmark_html_reader.cc
@@ -297,19 +297,20 @@
 namespace internal {
 
 bool ParseCharsetFromLine(const std::string& line, std::string* charset) {
-  const char kCharset[] = "charset=";
-  if (base::StartsWith(line, "<META", base::CompareCase::INSENSITIVE_ASCII) &&
-      (line.find("CONTENT=\"") != std::string::npos ||
-       line.find("content=\"") != std::string::npos)) {
-    size_t begin = line.find(kCharset);
-    if (begin == std::string::npos)
-      return false;
-    begin += std::string(kCharset).size();
-    size_t end = line.find_first_of('\"', begin);
-    *charset = line.substr(begin, end - begin);
-    return true;
+  if (!base::StartsWith(line, "<META", base::CompareCase::INSENSITIVE_ASCII) ||
+      (line.find("CONTENT=\"") == std::string::npos &&
+       line.find("content=\"") == std::string::npos)) {
+    return false;
   }
-  return false;
+
+  const char kCharset[] = "charset=";
+  size_t begin = line.find(kCharset);
+  if (begin == std::string::npos)
+    return false;
+  begin += sizeof(kCharset) - 1;
+  size_t end = line.find_first_of('\"', begin);
+  *charset = line.substr(begin, end - begin);
+  return true;
 }
 
 bool ParseFolderNameFromLine(const std::string& lineDt,
diff --git a/chrome/utility/importer/nss_decryptor.cc b/chrome/utility/importer/nss_decryptor.cc
index af7e847..be88f05 100644
--- a/chrome/utility/importer/nss_decryptor.cc
+++ b/chrome/utility/importer/nss_decryptor.cc
@@ -206,7 +206,7 @@
     if (lines[begin].find(kRealmBracketBegin) != std::string::npos) {
       size_t start = lines[begin].find(kRealmBracketBegin);
       raw_password_info.host = lines[begin].substr(0, start);
-      start += std::string(kRealmBracketBegin).size();
+      start += sizeof(kRealmBracketBegin) - 1;
       size_t end = lines[begin].rfind(kRealmBracketEnd);
       raw_password_info.realm = lines[begin].substr(start, end - start);
     } else {
diff --git a/chrome/utility/safe_browsing/mac/udif.cc b/chrome/utility/safe_browsing/mac/udif.cc
index d3cadf8..2a51bdb 100644
--- a/chrome/utility/safe_browsing/mac/udif.cc
+++ b/chrome/utility/safe_browsing/mac/udif.cc
@@ -70,16 +70,21 @@
   uint64_t plist_offset;  // Offset and length of the blkx plist.
   uint64_t plist_length;
 
-  uint8_t  reserved1[120];
+  uint8_t  reserved1[64];
+
+  uint64_t code_signature_offset;
+  uint64_t code_signature_length;
+
+  uint8_t  reserved2[40];
 
   UDIFChecksum master_checksum;
 
   uint32_t image_variant;
   uint64_t sector_count;
 
-  uint32_t reserved2;
   uint32_t reserved3;
   uint32_t reserved4;
+  uint32_t reserved5;
 };
 
 static void ConvertBigEndian(uuid_t* uuid) {
@@ -102,6 +107,8 @@
   ConvertBigEndian(&file->data_checksum);
   ConvertBigEndian(&file->plist_offset);
   ConvertBigEndian(&file->plist_length);
+  ConvertBigEndian(&file->code_signature_offset);
+  ConvertBigEndian(&file->code_signature_length);
   ConvertBigEndian(&file->master_checksum);
   ConvertBigEndian(&file->image_variant);
   ConvertBigEndian(&file->sector_count);
diff --git a/chromecast/media/audio/BUILD.gn b/chromecast/media/audio/BUILD.gn
index e959969..cfead8c 100644
--- a/chromecast/media/audio/BUILD.gn
+++ b/chromecast/media/audio/BUILD.gn
@@ -2,17 +2,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/buildflag_header.gni")
-
-declare_args() {
-  enable_mixer = false
-}
-
-buildflag_header("audio_features") {
-  header = "audio_features.h"
-  flags = [ "ENABLE_PCM_MIXING=$enable_mixer" ]
-}
-
 source_set("audio") {
   sources = [
     "cast_audio_manager.cc",
@@ -24,7 +13,6 @@
   ]
 
   deps = [
-    ":audio_features",
     "//base",
     "//chromecast/base",
     "//chromecast/media/base",
diff --git a/chromecast/media/audio/cast_audio_manager.cc b/chromecast/media/audio/cast_audio_manager.cc
index af639bf..230a1f9 100644
--- a/chromecast/media/audio/cast_audio_manager.cc
+++ b/chromecast/media/audio/cast_audio_manager.cc
@@ -8,7 +8,6 @@
 #include <string>
 
 #include "base/bind.h"
-#include "chromecast/media/audio/audio_features.h"
 #include "chromecast/media/audio/cast_audio_mixer.h"
 #include "chromecast/media/audio/cast_audio_output_stream.h"
 #include "chromecast/media/cma/backend/media_pipeline_backend_manager.h"
@@ -33,17 +32,13 @@
     scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
     ::media::AudioLogFactory* audio_log_factory,
     MediaPipelineBackendManager* backend_manager)
-    : AudioManagerBase(std::move(task_runner),
-                       std::move(worker_task_runner),
-                       audio_log_factory),
-      backend_manager_(backend_manager) {
-#if BUILDFLAG(ENABLE_PCM_MIXING)
-  // |this| is guaranteed to outlive |mixer_|, so it is safe to
-  // use base::Unretained here.
-  mixer_.reset(new CastAudioMixer(base::Bind(
-      &CastAudioManager::MakeMixerOutputStream, base::Unretained(this))));
-#endif
-}
+    : CastAudioManager(task_runner,
+                       worker_task_runner,
+                       audio_log_factory,
+                       backend_manager,
+                       new CastAudioMixer(
+                           base::Bind(&CastAudioManager::MakeMixerOutputStream,
+                                      base::Unretained(this)))) {}
 
 CastAudioManager::CastAudioManager(
     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index 4051b9b..98dac5d 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-8562.0.0
\ No newline at end of file
+8580.0.0
\ No newline at end of file
diff --git a/components/arc.gypi b/components/arc.gypi
index 3aad39d..7f4eac80 100644
--- a/components/arc.gypi
+++ b/components/arc.gypi
@@ -54,21 +54,24 @@
         'arc/ime/arc_ime_bridge_impl.h',
         'arc/ime/arc_ime_service.cc',
         'arc/ime/arc_ime_service.h',
+        'arc/instance_holder.h',
         'arc/intent_helper/activity_icon_loader.cc',
         'arc/intent_helper/activity_icon_loader.h',
         'arc/intent_helper/arc_intent_helper_bridge.cc',
         'arc/intent_helper/arc_intent_helper_bridge.h',
         'arc/intent_helper/font_size_util.cc',
         'arc/intent_helper/font_size_util.h',
+        'arc/intent_helper/intent_filter.cc',
+        'arc/intent_helper/intent_filter.h',
         'arc/intent_helper/link_handler_model_impl.cc',
         'arc/intent_helper/link_handler_model_impl.h',
         'arc/intent_helper/local_activity_resolver.cc',
         'arc/intent_helper/local_activity_resolver.h',
+        'arc/metrics/arc_metrics_service.cc',
+        'arc/metrics/arc_metrics_service.h',
         'arc/metrics/oom_kills_histogram.h',
         'arc/metrics/oom_kills_monitor.cc',
         'arc/metrics/oom_kills_monitor.h',
-        'arc/metrics/arc_metrics_service.cc',
-        'arc/metrics/arc_metrics_service.h',
         'arc/net/arc_net_host_impl.cc',
         'arc/net/arc_net_host_impl.h',
         'arc/obb_mounter/arc_obb_mounter_bridge.cc',
diff --git a/components/arc/BUILD.gn b/components/arc/BUILD.gn
index dfe4ee8d..745c0a8c 100644
--- a/components/arc/BUILD.gn
+++ b/components/arc/BUILD.gn
@@ -34,6 +34,8 @@
     "intent_helper/arc_intent_helper_bridge.h",
     "intent_helper/font_size_util.cc",
     "intent_helper/font_size_util.h",
+    "intent_helper/intent_filter.cc",
+    "intent_helper/intent_filter.h",
     "intent_helper/link_handler_model_impl.cc",
     "intent_helper/link_handler_model_impl.h",
     "intent_helper/local_activity_resolver.cc",
@@ -98,6 +100,7 @@
     "arc_bridge_service.h",
     "arc_service.cc",
     "arc_service.h",
+    "instance_holder.h",
   ]
 
   deps = [
diff --git a/components/arc/arc_bridge_service.cc b/components/arc/arc_bridge_service.cc
index bc864faf..80e70b6 100644
--- a/components/arc/arc_bridge_service.cc
+++ b/components/arc/arc_bridge_service.cc
@@ -45,46 +45,6 @@
 void ArcBridgeService::AddObserver(Observer* observer) {
   DCHECK(CalledOnValidThread());
   observer_list_.AddObserver(observer);
-
-  // If any of the instances were ready before the call to AddObserver(), the
-  // |observer| won't get any readiness events. For such cases, we have to call
-  // them explicitly now to avoid a race.
-  if (app_instance())
-    observer->OnAppInstanceReady();
-  if (audio_instance())
-    observer->OnAudioInstanceReady();
-  if (auth_instance())
-    observer->OnAuthInstanceReady();
-  if (bluetooth_instance())
-    observer->OnBluetoothInstanceReady();
-  if (clipboard_instance())
-    observer->OnClipboardInstanceReady();
-  if (crash_collector_instance())
-    observer->OnCrashCollectorInstanceReady();
-  if (file_system_instance())
-    observer->OnFileSystemInstanceReady();
-  if (ime_instance())
-    observer->OnImeInstanceReady();
-  if (metrics_instance())
-    observer->OnMetricsInstanceReady();
-  if (net_instance())
-    observer->OnNetInstanceReady();
-  if (notifications_instance())
-    observer->OnNotificationsInstanceReady();
-  if (obb_mounter_instance())
-    observer->OnObbMounterInstanceReady();
-  if (policy_instance())
-    observer->OnPolicyInstanceReady();
-  if (power_instance())
-    observer->OnPowerInstanceReady();
-  if (process_instance())
-    observer->OnProcessInstanceReady();
-  if (storage_manager_instance())
-    observer->OnStorageManagerInstanceReady();
-  if (video_instance())
-    observer->OnVideoInstanceReady();
-  if (window_manager_instance())
-    observer->OnWindowManagerInstanceReady();
 }
 
 void ArcBridgeService::RemoveObserver(Observer* observer) {
@@ -94,484 +54,109 @@
 
 void ArcBridgeService::OnAppInstanceReady(mojom::AppInstancePtr app_ptr) {
   DCHECK(CalledOnValidThread());
-  temporary_app_ptr_ = std::move(app_ptr);
-  temporary_app_ptr_.QueryVersion(base::Bind(
-      &ArcBridgeService::OnAppVersionReady, weak_factory_.GetWeakPtr()));
-}
-
-void ArcBridgeService::OnAppVersionReady(uint32_t version) {
-  DCHECK(CalledOnValidThread());
-  app_ptr_ = std::move(temporary_app_ptr_);
-  app_ptr_.set_connection_error_handler(base::Bind(
-      &ArcBridgeService::CloseAppChannel, weak_factory_.GetWeakPtr()));
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnAppInstanceReady());
-}
-
-void ArcBridgeService::CloseAppChannel() {
-  DCHECK(CalledOnValidThread());
-  if (!app_ptr_)
-    return;
-
-  app_ptr_.reset();
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnAppInstanceClosed());
+  app_.OnInstanceReady(std::move(app_ptr));
 }
 
 void ArcBridgeService::OnAudioInstanceReady(mojom::AudioInstancePtr audio_ptr) {
   DCHECK(CalledOnValidThread());
-  temporary_audio_ptr_ = std::move(audio_ptr);
-  temporary_audio_ptr_.QueryVersion(base::Bind(
-      &ArcBridgeService::OnAudioVersionReady, weak_factory_.GetWeakPtr()));
-}
-
-void ArcBridgeService::OnAudioVersionReady(uint32_t version) {
-  DCHECK(CalledOnValidThread());
-  audio_ptr_ = std::move(temporary_audio_ptr_);
-  audio_ptr_.set_connection_error_handler(base::Bind(
-      &ArcBridgeService::CloseAudioChannel, weak_factory_.GetWeakPtr()));
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnAudioInstanceReady());
-}
-
-void ArcBridgeService::CloseAudioChannel() {
-  if (!audio_ptr_)
-    return;
-
-  audio_ptr_.reset();
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnAudioInstanceClosed());
+  audio_.OnInstanceReady(std::move(audio_ptr));
 }
 
 void ArcBridgeService::OnAuthInstanceReady(mojom::AuthInstancePtr auth_ptr) {
   DCHECK(CalledOnValidThread());
-  temporary_auth_ptr_ = std::move(auth_ptr);
-  temporary_auth_ptr_.QueryVersion(base::Bind(
-      &ArcBridgeService::OnAuthVersionReady, weak_factory_.GetWeakPtr()));
-}
-
-void ArcBridgeService::OnAuthVersionReady(uint32_t version) {
-  DCHECK(CalledOnValidThread());
-  auth_ptr_ = std::move(temporary_auth_ptr_);
-  auth_ptr_.set_connection_error_handler(base::Bind(
-      &ArcBridgeService::CloseAuthChannel, weak_factory_.GetWeakPtr()));
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnAuthInstanceReady());
-}
-
-void ArcBridgeService::CloseAuthChannel() {
-  DCHECK(CalledOnValidThread());
-  if (!auth_ptr_)
-    return;
-
-  auth_ptr_.reset();
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnAuthInstanceClosed());
+  auth_.OnInstanceReady(std::move(auth_ptr));
 }
 
 void ArcBridgeService::OnBluetoothInstanceReady(
     mojom::BluetoothInstancePtr bluetooth_ptr) {
   DCHECK(CalledOnValidThread());
-  temporary_bluetooth_ptr_ = std::move(bluetooth_ptr);
-  temporary_bluetooth_ptr_.QueryVersion(base::Bind(
-      &ArcBridgeService::OnBluetoothVersionReady, weak_factory_.GetWeakPtr()));
-}
-
-void ArcBridgeService::OnBluetoothVersionReady(uint32_t version) {
-  DCHECK(CalledOnValidThread());
-  bluetooth_ptr_ = std::move(temporary_bluetooth_ptr_);
-  bluetooth_ptr_.set_connection_error_handler(base::Bind(
-      &ArcBridgeService::CloseBluetoothChannel, weak_factory_.GetWeakPtr()));
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnBluetoothInstanceReady());
-}
-
-void ArcBridgeService::CloseBluetoothChannel() {
-  DCHECK(CalledOnValidThread());
-  if (!bluetooth_ptr_)
-    return;
-
-  bluetooth_ptr_.reset();
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnBluetoothInstanceClosed());
+  bluetooth_.OnInstanceReady(std::move(bluetooth_ptr));
 }
 
 void ArcBridgeService::OnClipboardInstanceReady(
     mojom::ClipboardInstancePtr clipboard_ptr) {
   DCHECK(CalledOnValidThread());
-  temporary_clipboard_ptr_ = std::move(clipboard_ptr);
-  temporary_clipboard_ptr_.QueryVersion(base::Bind(
-      &ArcBridgeService::OnClipboardVersionReady, weak_factory_.GetWeakPtr()));
-}
-
-void ArcBridgeService::OnClipboardVersionReady(uint32_t version) {
-  DCHECK(CalledOnValidThread());
-  clipboard_ptr_ = std::move(temporary_clipboard_ptr_);
-  clipboard_ptr_.set_connection_error_handler(base::Bind(
-      &ArcBridgeService::CloseClipboardChannel, weak_factory_.GetWeakPtr()));
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnClipboardInstanceReady());
-}
-
-void ArcBridgeService::CloseClipboardChannel() {
-  DCHECK(CalledOnValidThread());
-  if (!clipboard_ptr_)
-    return;
-
-  clipboard_ptr_.reset();
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnClipboardInstanceClosed());
+  clipboard_.OnInstanceReady(std::move(clipboard_ptr));
 }
 
 void ArcBridgeService::OnCrashCollectorInstanceReady(
     mojom::CrashCollectorInstancePtr crash_collector_ptr) {
   DCHECK(CalledOnValidThread());
-  temporary_crash_collector_ptr_ = std::move(crash_collector_ptr);
-  temporary_crash_collector_ptr_.QueryVersion(
-      base::Bind(&ArcBridgeService::OnCrashCollectorVersionReady,
-                 weak_factory_.GetWeakPtr()));
-}
-
-void ArcBridgeService::OnCrashCollectorVersionReady(uint32_t version) {
-  DCHECK(CalledOnValidThread());
-  crash_collector_ptr_ = std::move(temporary_crash_collector_ptr_);
-  crash_collector_ptr_.set_connection_error_handler(
-      base::Bind(&ArcBridgeService::CloseCrashCollectorChannel,
-                 weak_factory_.GetWeakPtr()));
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnCrashCollectorInstanceReady());
-}
-
-void ArcBridgeService::CloseCrashCollectorChannel() {
-  DCHECK(CalledOnValidThread());
-  if (!crash_collector_ptr_)
-    return;
-
-  crash_collector_ptr_.reset();
-  FOR_EACH_OBSERVER(Observer, observer_list(),
-                    OnCrashCollectorInstanceClosed());
+  crash_collector_.OnInstanceReady(std::move(crash_collector_ptr));
 }
 
 void ArcBridgeService::OnFileSystemInstanceReady(
     mojom::FileSystemInstancePtr file_system_ptr) {
   DCHECK(CalledOnValidThread());
-  temporary_file_system_ptr_ = std::move(file_system_ptr);
-  temporary_file_system_ptr_.QueryVersion(
-      base::Bind(&ArcBridgeService::OnFileSystemVersionReady,
-                 weak_factory_.GetWeakPtr()));
-}
-
-void ArcBridgeService::OnFileSystemVersionReady(uint32_t version) {
-  DCHECK(CalledOnValidThread());
-  file_system_ptr_ = std::move(temporary_file_system_ptr_);
-  file_system_ptr_.set_connection_error_handler(
-      base::Bind(&ArcBridgeService::CloseFileSystemChannel,
-                 weak_factory_.GetWeakPtr()));
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnFileSystemInstanceReady());
-}
-
-void ArcBridgeService::CloseFileSystemChannel() {
-  DCHECK(CalledOnValidThread());
-  if (!file_system_ptr_)
-    return;
-
-  file_system_ptr_.reset();
-  FOR_EACH_OBSERVER(Observer, observer_list(),
-                    OnFileSystemInstanceClosed());
+  file_system_.OnInstanceReady(std::move(file_system_ptr));
 }
 
 void ArcBridgeService::OnImeInstanceReady(mojom::ImeInstancePtr ime_ptr) {
   DCHECK(CalledOnValidThread());
-  temporary_ime_ptr_ = std::move(ime_ptr);
-  temporary_ime_ptr_.QueryVersion(base::Bind(
-      &ArcBridgeService::OnImeVersionReady, weak_factory_.GetWeakPtr()));
-}
-
-void ArcBridgeService::OnImeVersionReady(uint32_t version) {
-  DCHECK(CalledOnValidThread());
-  ime_ptr_ = std::move(temporary_ime_ptr_);
-  ime_ptr_.set_connection_error_handler(base::Bind(
-      &ArcBridgeService::CloseImeChannel, weak_factory_.GetWeakPtr()));
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnImeInstanceReady());
-}
-
-void ArcBridgeService::CloseImeChannel() {
-  DCHECK(CalledOnValidThread());
-  if (!ime_ptr_)
-    return;
-
-  ime_ptr_.reset();
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnImeInstanceClosed());
+  ime_.OnInstanceReady(std::move(ime_ptr));
 }
 
 void ArcBridgeService::OnIntentHelperInstanceReady(
     mojom::IntentHelperInstancePtr intent_helper_ptr) {
   DCHECK(CalledOnValidThread());
-  temporary_intent_helper_ptr_ = std::move(intent_helper_ptr);
-  temporary_intent_helper_ptr_.QueryVersion(
-      base::Bind(&ArcBridgeService::OnIntentHelperVersionReady,
-                 weak_factory_.GetWeakPtr()));
-}
-
-void ArcBridgeService::OnIntentHelperVersionReady(uint32_t version) {
-  DCHECK(CalledOnValidThread());
-  intent_helper_ptr_ = std::move(temporary_intent_helper_ptr_);
-  intent_helper_ptr_.set_connection_error_handler(base::Bind(
-      &ArcBridgeService::CloseIntentHelperChannel, weak_factory_.GetWeakPtr()));
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnIntentHelperInstanceReady());
-}
-
-void ArcBridgeService::CloseIntentHelperChannel() {
-  DCHECK(CalledOnValidThread());
-  if (!intent_helper_ptr_)
-    return;
-
-  intent_helper_ptr_.reset();
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnIntentHelperInstanceClosed());
+  intent_helper_.OnInstanceReady(std::move(intent_helper_ptr));
 }
 
 void ArcBridgeService::OnMetricsInstanceReady(
     mojom::MetricsInstancePtr metrics_ptr) {
   DCHECK(CalledOnValidThread());
-  temporary_metrics_ptr_ = std::move(metrics_ptr);
-  temporary_metrics_ptr_.QueryVersion(base::Bind(
-      &ArcBridgeService::OnMetricsVersionReady, weak_factory_.GetWeakPtr()));
-}
-
-void ArcBridgeService::OnMetricsVersionReady(uint32_t version) {
-  DCHECK(CalledOnValidThread());
-  metrics_ptr_ = std::move(temporary_metrics_ptr_);
-  metrics_ptr_.set_connection_error_handler(base::Bind(
-      &ArcBridgeService::CloseMetricsChannel, weak_factory_.GetWeakPtr()));
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnMetricsInstanceReady());
-}
-
-void ArcBridgeService::CloseMetricsChannel() {
-  DCHECK(CalledOnValidThread());
-  if (!metrics_ptr_)
-    return;
-
-  metrics_ptr_.reset();
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnMetricsInstanceClosed());
+  metrics_.OnInstanceReady(std::move(metrics_ptr));
 }
 
 void ArcBridgeService::OnNetInstanceReady(mojom::NetInstancePtr net_ptr) {
   DCHECK(CalledOnValidThread());
-  temporary_net_ptr_ = std::move(net_ptr);
-  temporary_net_ptr_.QueryVersion(base::Bind(
-      &ArcBridgeService::OnNetVersionReady, weak_factory_.GetWeakPtr()));
-}
-
-void ArcBridgeService::OnNetVersionReady(uint32_t version) {
-  DCHECK(CalledOnValidThread());
-  net_ptr_ = std::move(temporary_net_ptr_);
-  net_ptr_.set_connection_error_handler(base::Bind(
-      &ArcBridgeService::CloseNetChannel, weak_factory_.GetWeakPtr()));
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnNetInstanceReady());
-}
-
-void ArcBridgeService::CloseNetChannel() {
-  DCHECK(CalledOnValidThread());
-  if (!net_ptr_)
-    return;
-
-  net_ptr_.reset();
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnNetInstanceClosed());
+  net_.OnInstanceReady(std::move(net_ptr));
 }
 
 void ArcBridgeService::OnNotificationsInstanceReady(
     mojom::NotificationsInstancePtr notifications_ptr) {
   DCHECK(CalledOnValidThread());
-  temporary_notifications_ptr_ = std::move(notifications_ptr);
-  temporary_notifications_ptr_.QueryVersion(
-      base::Bind(&ArcBridgeService::OnNotificationsVersionReady,
-                 weak_factory_.GetWeakPtr()));
-}
-
-void ArcBridgeService::OnNotificationsVersionReady(uint32_t version) {
-  DCHECK(CalledOnValidThread());
-  notifications_ptr_ = std::move(temporary_notifications_ptr_);
-  notifications_ptr_.set_connection_error_handler(
-      base::Bind(&ArcBridgeService::CloseNotificationsChannel,
-                 weak_factory_.GetWeakPtr()));
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnNotificationsInstanceReady());
-}
-
-void ArcBridgeService::CloseNotificationsChannel() {
-  DCHECK(CalledOnValidThread());
-  if (!notifications_ptr_)
-    return;
-
-  notifications_ptr_.reset();
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnNotificationsInstanceClosed());
+  notifications_.OnInstanceReady(std::move(notifications_ptr));
 }
 
 void ArcBridgeService::OnObbMounterInstanceReady(
     mojom::ObbMounterInstancePtr obb_mounter_ptr) {
   DCHECK(CalledOnValidThread());
-  temporary_obb_mounter_ptr_ = std::move(obb_mounter_ptr);
-  temporary_obb_mounter_ptr_.QueryVersion(base::Bind(
-      &ArcBridgeService::OnObbMounterVersionReady,
-      weak_factory_.GetWeakPtr()));
-}
-
-void ArcBridgeService::OnObbMounterVersionReady(uint32_t version) {
-  DCHECK(CalledOnValidThread());
-  obb_mounter_ptr_ = std::move(temporary_obb_mounter_ptr_);
-  obb_mounter_ptr_.set_connection_error_handler(base::Bind(
-      &ArcBridgeService::CloseObbMounterChannel,
-      weak_factory_.GetWeakPtr()));
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnObbMounterInstanceReady());
-}
-
-void ArcBridgeService::CloseObbMounterChannel() {
-  if (!obb_mounter_ptr_)
-    return;
-
-  obb_mounter_ptr_.reset();
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnObbMounterInstanceClosed());
+  obb_mounter_.OnInstanceReady(std::move(obb_mounter_ptr));
 }
 
 void ArcBridgeService::OnPolicyInstanceReady(
     mojom::PolicyInstancePtr policy_ptr) {
   DCHECK(CalledOnValidThread());
-  temporary_policy_ptr_ = std::move(policy_ptr);
-  temporary_policy_ptr_.QueryVersion(base::Bind(
-      &ArcBridgeService::OnPolicyVersionReady, weak_factory_.GetWeakPtr()));
-}
-
-void ArcBridgeService::OnPolicyVersionReady(uint32_t version) {
-  DCHECK(CalledOnValidThread());
-  policy_ptr_ = std::move(temporary_policy_ptr_);
-  policy_ptr_.set_connection_error_handler(base::Bind(
-      &ArcBridgeService::ClosePolicyChannel, weak_factory_.GetWeakPtr()));
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnPolicyInstanceReady());
-}
-
-void ArcBridgeService::ClosePolicyChannel() {
-  DCHECK(CalledOnValidThread());
-  if (!policy_ptr_)
-    return;
-
-  policy_ptr_.reset();
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnPolicyInstanceClosed());
+  policy_.OnInstanceReady(std::move(policy_ptr));
 }
 
 void ArcBridgeService::OnPowerInstanceReady(mojom::PowerInstancePtr power_ptr) {
   DCHECK(CalledOnValidThread());
-  temporary_power_ptr_ = std::move(power_ptr);
-  temporary_power_ptr_.QueryVersion(base::Bind(
-      &ArcBridgeService::OnPowerVersionReady, weak_factory_.GetWeakPtr()));
-}
-
-void ArcBridgeService::OnPowerVersionReady(uint32_t version) {
-  DCHECK(CalledOnValidThread());
-  power_ptr_ = std::move(temporary_power_ptr_);
-  power_ptr_.set_connection_error_handler(base::Bind(
-      &ArcBridgeService::ClosePowerChannel, weak_factory_.GetWeakPtr()));
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnPowerInstanceReady());
-}
-
-void ArcBridgeService::ClosePowerChannel() {
-  DCHECK(CalledOnValidThread());
-  if (!power_ptr_)
-    return;
-
-  power_ptr_.reset();
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnPowerInstanceClosed());
+  power_.OnInstanceReady(std::move(power_ptr));
 }
 
 void ArcBridgeService::OnProcessInstanceReady(
     mojom::ProcessInstancePtr process_ptr) {
   DCHECK(CalledOnValidThread());
-  temporary_process_ptr_ = std::move(process_ptr);
-  temporary_process_ptr_.QueryVersion(base::Bind(
-      &ArcBridgeService::OnProcessVersionReady, weak_factory_.GetWeakPtr()));
-}
-
-void ArcBridgeService::OnProcessVersionReady(uint32_t version) {
-  DCHECK(CalledOnValidThread());
-  process_ptr_ = std::move(temporary_process_ptr_);
-  process_ptr_.set_connection_error_handler(base::Bind(
-      &ArcBridgeService::CloseProcessChannel, weak_factory_.GetWeakPtr()));
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnProcessInstanceReady());
-}
-
-void ArcBridgeService::CloseProcessChannel() {
-  DCHECK(CalledOnValidThread());
-  if (!process_ptr_)
-    return;
-
-  process_ptr_.reset();
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnProcessInstanceClosed());
+  process_.OnInstanceReady(std::move(process_ptr));
 }
 
 void ArcBridgeService::OnStorageManagerInstanceReady(
     mojom::StorageManagerInstancePtr storage_manager_ptr) {
   DCHECK(CalledOnValidThread());
-  temporary_storage_manager_ptr_ = std::move(storage_manager_ptr);
-  temporary_storage_manager_ptr_.QueryVersion(base::Bind(
-      &ArcBridgeService::OnStorageManagerVersionReady,
-      weak_factory_.GetWeakPtr()));
-}
-
-void ArcBridgeService::OnStorageManagerVersionReady(uint32_t version) {
-  DCHECK(CalledOnValidThread());
-  storage_manager_ptr_ = std::move(temporary_storage_manager_ptr_);
-  storage_manager_ptr_.set_connection_error_handler(base::Bind(
-      &ArcBridgeService::CloseStorageManagerChannel,
-      weak_factory_.GetWeakPtr()));
-  FOR_EACH_OBSERVER(
-      Observer, observer_list(), OnStorageManagerInstanceReady());
-}
-
-void ArcBridgeService::CloseStorageManagerChannel() {
-  DCHECK(CalledOnValidThread());
-  if (!storage_manager_ptr_)
-    return;
-
-  storage_manager_ptr_.reset();
-  FOR_EACH_OBSERVER(
-      Observer, observer_list(), OnStorageManagerInstanceClosed());
+  storage_manager_.OnInstanceReady(std::move(storage_manager_ptr));
 }
 
 void ArcBridgeService::OnVideoInstanceReady(mojom::VideoInstancePtr video_ptr) {
   DCHECK(CalledOnValidThread());
-  temporary_video_ptr_ = std::move(video_ptr);
-  temporary_video_ptr_.QueryVersion(base::Bind(
-      &ArcBridgeService::OnVideoVersionReady, weak_factory_.GetWeakPtr()));
-}
-
-void ArcBridgeService::OnVideoVersionReady(uint32_t version) {
-  DCHECK(CalledOnValidThread());
-  video_ptr_ = std::move(temporary_video_ptr_);
-  video_ptr_.set_connection_error_handler(base::Bind(
-      &ArcBridgeService::CloseVideoChannel, weak_factory_.GetWeakPtr()));
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnVideoInstanceReady());
-}
-
-void ArcBridgeService::CloseVideoChannel() {
-  DCHECK(CalledOnValidThread());
-  if (!video_ptr_)
-    return;
-
-  video_ptr_.reset();
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnVideoInstanceClosed());
+  video_.OnInstanceReady(std::move(video_ptr));
 }
 
 void ArcBridgeService::OnWindowManagerInstanceReady(
     mojom::WindowManagerInstancePtr window_manager_ptr) {
   DCHECK(CalledOnValidThread());
-  temporary_window_manager_ptr_ = std::move(window_manager_ptr);
-  temporary_window_manager_ptr_.QueryVersion(base::Bind(
-      &ArcBridgeService::OnWindowManagerVersionReady,
-      weak_factory_.GetWeakPtr()));
-}
-
-void ArcBridgeService::OnWindowManagerVersionReady(uint32_t version) {
-  DCHECK(CalledOnValidThread());
-  window_manager_ptr_ = std::move(temporary_window_manager_ptr_);
-  window_manager_ptr_.set_connection_error_handler(base::Bind(
-      &ArcBridgeService::CloseWindowManagerChannel,
-      weak_factory_.GetWeakPtr()));
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnWindowManagerInstanceReady());
-}
-
-void ArcBridgeService::CloseWindowManagerChannel() {
-  if (!window_manager_ptr_)
-    return;
-
-  window_manager_ptr_.reset();
-  FOR_EACH_OBSERVER(Observer, observer_list(), OnWindowManagerInstanceClosed());
+  window_manager_.OnInstanceReady(std::move(window_manager_ptr));
 }
 
 void ArcBridgeService::SetState(State state) {
@@ -599,25 +184,25 @@
 void ArcBridgeService::CloseAllChannels() {
   // Call all the error handlers of all the channels to both close the channel
   // and notify any observers that the channel is closed.
-  CloseAppChannel();
-  CloseAudioChannel();
-  CloseAuthChannel();
-  CloseBluetoothChannel();
-  CloseClipboardChannel();
-  CloseCrashCollectorChannel();
-  CloseFileSystemChannel();
-  CloseImeChannel();
-  CloseIntentHelperChannel();
-  CloseMetricsChannel();
-  CloseNetChannel();
-  CloseNotificationsChannel();
-  CloseObbMounterChannel();
-  ClosePolicyChannel();
-  ClosePowerChannel();
-  CloseProcessChannel();
-  CloseStorageManagerChannel();
-  CloseVideoChannel();
-  CloseWindowManagerChannel();
+  app_.CloseChannel();
+  audio_.CloseChannel();
+  auth_.CloseChannel();
+  bluetooth_.CloseChannel();
+  clipboard_.CloseChannel();
+  crash_collector_.CloseChannel();
+  file_system_.CloseChannel();
+  ime_.CloseChannel();
+  intent_helper_.CloseChannel();
+  metrics_.CloseChannel();
+  net_.CloseChannel();
+  notifications_.CloseChannel();
+  obb_mounter_.CloseChannel();
+  policy_.CloseChannel();
+  power_.CloseChannel();
+  process_.CloseChannel();
+  storage_manager_.CloseChannel();
+  video_.CloseChannel();
+  window_manager_.CloseChannel();
 }
 
 }  // namespace arc
diff --git a/components/arc/arc_bridge_service.h b/components/arc/arc_bridge_service.h
index bcd5b09..86b8ec6 100644
--- a/components/arc/arc_bridge_service.h
+++ b/components/arc/arc_bridge_service.h
@@ -14,6 +14,7 @@
 #include "base/observer_list.h"
 #include "base/values.h"
 #include "components/arc/common/arc_bridge.mojom.h"
+#include "components/arc/instance_holder.h"
 
 namespace base {
 class CommandLine;
@@ -39,82 +40,6 @@
     // Called whenever ARC's availability has changed for this system.
     virtual void OnAvailableChanged(bool available) {}
 
-    // Called whenever the ARC app interface state changes.
-    virtual void OnAppInstanceReady() {}
-    virtual void OnAppInstanceClosed() {}
-
-    // Called whenever the ARC audio interface state changes.
-    virtual void OnAudioInstanceReady() {}
-    virtual void OnAudioInstanceClosed() {}
-
-    // Called whenever the ARC auth interface state changes.
-    virtual void OnAuthInstanceReady() {}
-    virtual void OnAuthInstanceClosed() {}
-
-    // Called whenever ARC Bluetooth instance is ready.
-    virtual void OnBluetoothInstanceReady() {}
-    virtual void OnBluetoothInstanceClosed() {}
-
-    // Called whenever the ARC clipboard interface state changes.
-    virtual void OnClipboardInstanceReady() {}
-    virtual void OnClipboardInstanceClosed() {}
-
-    // Called whenever the ARC crash collector interface state changes.
-    virtual void OnCrashCollectorInstanceReady() {}
-    virtual void OnCrashCollectorInstanceClosed() {}
-
-    // Called whenever the ARC file system interface state changes.
-    virtual void OnFileSystemInstanceReady() {}
-    virtual void OnFileSystemInstanceClosed() {}
-
-    // Called whenever the ARC IME interface state changes.
-    virtual void OnImeInstanceReady() {}
-    virtual void OnImeInstanceClosed() {}
-
-    // Called whenever the ARC intent helper interface state changes.
-    virtual void OnIntentHelperInstanceReady() {}
-    virtual void OnIntentHelperInstanceClosed() {}
-
-    // Called whenever the ARC metrics interface state changes.
-    virtual void OnMetricsInstanceReady() {}
-    virtual void OnMetricsInstanceClosed() {}
-
-    // Called whenever the ARC notification interface state changes.
-    virtual void OnNotificationsInstanceReady() {}
-    virtual void OnNotificationsInstanceClosed() {}
-
-    // Called whenever the ARC net interface state changes.
-    virtual void OnNetInstanceReady() {}
-    virtual void OnNetInstanceClosed() {}
-
-    // Called whenever the ARC OBB mounter interface state changes.
-    virtual void OnObbMounterInstanceReady() {}
-    virtual void OnObbMounterInstanceClosed() {}
-
-    // Called whenever the ARC policy interface state changes.
-    virtual void OnPolicyInstanceReady() {}
-    virtual void OnPolicyInstanceClosed() {}
-
-    // Called whenever the ARC power interface state changes.
-    virtual void OnPowerInstanceReady() {}
-    virtual void OnPowerInstanceClosed() {}
-
-    // Called whenever the ARC process interface state changes.
-    virtual void OnProcessInstanceReady() {}
-    virtual void OnProcessInstanceClosed() {}
-
-    // Called whenever the ARC storage manager interface state changes.
-    virtual void OnStorageManagerInstanceReady() {}
-    virtual void OnStorageManagerInstanceClosed() {}
-
-    // Called whenever the ARC video interface state changes.
-    virtual void OnVideoInstanceReady() {}
-    virtual void OnVideoInstanceClosed() {}
-
-    // Called whenever the ARC window manager interface state changes.
-    virtual void OnWindowManagerInstanceReady() {}
-    virtual void OnWindowManagerInstanceClosed() {}
-
    protected:
     virtual ~Observer() {}
   };
@@ -149,72 +74,38 @@
   void AddObserver(Observer* observer);
   void RemoveObserver(Observer* observer);
 
-  // Gets the Mojo interface for all the instance services. This will return
-  // nullptr if that particular service is not ready yet. Use an Observer if
-  // you want to be notified when this is ready. This can only be called on the
-  // thread that this class was created on.
-  mojom::AppInstance* app_instance() { return app_ptr_.get(); }
-  mojom::AudioInstance* audio_instance() { return audio_ptr_.get(); }
-  mojom::AuthInstance* auth_instance() { return auth_ptr_.get(); }
-  mojom::BluetoothInstance* bluetooth_instance() {
-    return bluetooth_ptr_.get();
+  InstanceHolder<mojom::AppInstance>* app() { return &app_; }
+  InstanceHolder<mojom::AudioInstance>* audio() { return &audio_; }
+  InstanceHolder<mojom::AuthInstance>* auth() { return &auth_; }
+  InstanceHolder<mojom::BluetoothInstance>* bluetooth() { return &bluetooth_; }
+  InstanceHolder<mojom::ClipboardInstance>* clipboard() { return &clipboard_; }
+  InstanceHolder<mojom::CrashCollectorInstance>* crash_collector() {
+    return &crash_collector_;
   }
-  mojom::ClipboardInstance* clipboard_instance() {
-    return clipboard_ptr_.get();
+  InstanceHolder<mojom::FileSystemInstance>* file_system() {
+    return &file_system_;
   }
-  mojom::CrashCollectorInstance* crash_collector_instance() {
-    return crash_collector_ptr_.get();
+  InstanceHolder<mojom::ImeInstance>* ime() { return &ime_; }
+  InstanceHolder<mojom::IntentHelperInstance>* intent_helper() {
+    return &intent_helper_;
   }
-  mojom::FileSystemInstance* file_system_instance() {
-    return file_system_ptr_.get();
+  InstanceHolder<mojom::MetricsInstance>* metrics() { return &metrics_; }
+  InstanceHolder<mojom::NetInstance>* net() { return &net_; }
+  InstanceHolder<mojom::NotificationsInstance>* notifications() {
+    return &notifications_;
   }
-  mojom::ImeInstance* ime_instance() { return ime_ptr_.get(); }
-  mojom::IntentHelperInstance* intent_helper_instance() {
-    return intent_helper_ptr_.get();
+  InstanceHolder<mojom::ObbMounterInstance>* obb_mounter() {
+    return &obb_mounter_;
   }
-  mojom::MetricsInstance* metrics_instance() { return metrics_ptr_.get(); }
-  mojom::NetInstance* net_instance() { return net_ptr_.get(); }
-  mojom::NotificationsInstance* notifications_instance() {
-    return notifications_ptr_.get();
+  InstanceHolder<mojom::PolicyInstance>* policy() { return &policy_; }
+  InstanceHolder<mojom::PowerInstance>* power() { return &power_; }
+  InstanceHolder<mojom::ProcessInstance>* process() { return &process_; }
+  InstanceHolder<mojom::StorageManagerInstance>* storage_manager() {
+    return &storage_manager_;
   }
-  mojom::ObbMounterInstance* obb_mounter_instance() {
-    return obb_mounter_ptr_.get();
-  }
-  mojom::PolicyInstance* policy_instance() { return policy_ptr_.get(); }
-  mojom::PowerInstance* power_instance() { return power_ptr_.get(); }
-  mojom::ProcessInstance* process_instance() { return process_ptr_.get(); }
-  mojom::StorageManagerInstance* storage_manager_instance() {
-    return storage_manager_ptr_.get();
-  }
-  mojom::VideoInstance* video_instance() { return video_ptr_.get(); }
-  mojom::WindowManagerInstance* window_manager_instance() {
-    return window_manager_ptr_.get();
-  }
-
-  int32_t app_version() const { return app_ptr_.version(); }
-  int32_t audio_version() const { return audio_ptr_.version(); }
-  int32_t bluetooth_version() const { return bluetooth_ptr_.version(); }
-  int32_t auth_version() const { return auth_ptr_.version(); }
-  int32_t clipboard_version() const { return clipboard_ptr_.version(); }
-  int32_t crash_collector_version() const {
-    return crash_collector_ptr_.version();
-  }
-  int32_t file_system_version() const { return file_system_ptr_.version(); }
-  int32_t ime_version() const { return ime_ptr_.version(); }
-  int32_t intent_helper_version() const { return intent_helper_ptr_.version(); }
-  int32_t metrics_version() const { return metrics_ptr_.version(); }
-  int32_t net_version() const { return net_ptr_.version(); }
-  int32_t notifications_version() const { return notifications_ptr_.version(); }
-  int32_t obb_mounter_version() const { return obb_mounter_ptr_.version(); }
-  int32_t policy_version() const { return policy_ptr_.version(); }
-  int32_t power_version() const { return power_ptr_.version(); }
-  int32_t process_version() const { return process_ptr_.version(); }
-  int32_t storage_manager_version() const {
-    return storage_manager_ptr_.version();
-  }
-  int32_t video_version() const { return video_ptr_.version(); }
-  int32_t window_manager_version() const {
-    return window_manager_ptr_.version();
+  InstanceHolder<mojom::VideoInstance>* video() { return &video_; }
+  InstanceHolder<mojom::WindowManagerInstance>* window_manager() {
+    return &window_manager_;
   }
 
   // ArcHost:
@@ -318,94 +209,26 @@
   FRIEND_TEST_ALL_PREFIXES(ArcBridgeTest, ShutdownMidStartup);
   FRIEND_TEST_ALL_PREFIXES(ArcBridgeTest, Restart);
 
-  // Called when one of the individual channels is closed.
-  void CloseAppChannel();
-  void CloseAudioChannel();
-  void CloseAuthChannel();
-  void CloseBluetoothChannel();
-  void CloseClipboardChannel();
-  void CloseCrashCollectorChannel();
-  void CloseFileSystemChannel();
-  void CloseImeChannel();
-  void CloseIntentHelperChannel();
-  void CloseMetricsChannel();
-  void CloseNetChannel();
-  void CloseNotificationsChannel();
-  void CloseObbMounterChannel();
-  void ClosePolicyChannel();
-  void ClosePowerChannel();
-  void CloseProcessChannel();
-  void CloseStorageManagerChannel();
-  void CloseVideoChannel();
-  void CloseWindowManagerChannel();
-
-  // Callbacks for QueryVersion.
-  void OnAppVersionReady(uint32_t version);
-  void OnAudioVersionReady(uint32_t version);
-  void OnAuthVersionReady(uint32_t version);
-  void OnBluetoothVersionReady(uint32_t version);
-  void OnClipboardVersionReady(uint32_t version);
-  void OnCrashCollectorVersionReady(uint32_t version);
-  void OnFileSystemVersionReady(uint32_t version);
-  void OnImeVersionReady(uint32_t version);
-  void OnIntentHelperVersionReady(uint32_t version);
-  void OnMetricsVersionReady(uint32_t version);
-  void OnNetVersionReady(uint32_t version);
-  void OnNotificationsVersionReady(uint32_t version);
-  void OnObbMounterVersionReady(uint32_t version);
-  void OnPolicyVersionReady(uint32_t version);
-  void OnPowerVersionReady(uint32_t version);
-  void OnProcessVersionReady(uint32_t version);
-  void OnStorageManagerVersionReady(uint32_t version);
-  void OnVideoVersionReady(uint32_t version);
-  void OnWindowManagerVersionReady(uint32_t version);
-
-  // Mojo interfaces.
-  mojom::AppInstancePtr app_ptr_;
-  mojom::AudioInstancePtr audio_ptr_;
-  mojom::AuthInstancePtr auth_ptr_;
-  mojom::BluetoothInstancePtr bluetooth_ptr_;
-  mojom::ClipboardInstancePtr clipboard_ptr_;
-  mojom::CrashCollectorInstancePtr crash_collector_ptr_;
-  mojom::FileSystemInstancePtr file_system_ptr_;
-  mojom::ImeInstancePtr ime_ptr_;
-  mojom::IntentHelperInstancePtr intent_helper_ptr_;
-  mojom::MetricsInstancePtr metrics_ptr_;
-  mojom::NetInstancePtr net_ptr_;
-  mojom::NotificationsInstancePtr notifications_ptr_;
-  mojom::ObbMounterInstancePtr obb_mounter_ptr_;
-  mojom::PolicyInstancePtr policy_ptr_;
-  mojom::PowerInstancePtr power_ptr_;
-  mojom::ProcessInstancePtr process_ptr_;
-  mojom::StorageManagerInstancePtr storage_manager_ptr_;
-  mojom::VideoInstancePtr video_ptr_;
-  mojom::WindowManagerInstancePtr window_manager_ptr_;
-
-  // Temporary Mojo interfaces.  After a Mojo interface pointer has been
-  // received from the other endpoint, we still need to asynchronously query
-  // its version.  While that is going on, we should still return nullptr on
-  // the xxx_instance() functions.
-  // To keep the xxx_instance() functions being trivial, store the instance
-  // pointer in a temporary variable to avoid losing its reference.
-  mojom::AppInstancePtr temporary_app_ptr_;
-  mojom::AudioInstancePtr temporary_audio_ptr_;
-  mojom::AuthInstancePtr temporary_auth_ptr_;
-  mojom::BluetoothInstancePtr temporary_bluetooth_ptr_;
-  mojom::ClipboardInstancePtr temporary_clipboard_ptr_;
-  mojom::CrashCollectorInstancePtr temporary_crash_collector_ptr_;
-  mojom::FileSystemInstancePtr temporary_file_system_ptr_;
-  mojom::ImeInstancePtr temporary_ime_ptr_;
-  mojom::IntentHelperInstancePtr temporary_intent_helper_ptr_;
-  mojom::MetricsInstancePtr temporary_metrics_ptr_;
-  mojom::NetInstancePtr temporary_net_ptr_;
-  mojom::NotificationsInstancePtr temporary_notifications_ptr_;
-  mojom::ObbMounterInstancePtr temporary_obb_mounter_ptr_;
-  mojom::PolicyInstancePtr temporary_policy_ptr_;
-  mojom::PowerInstancePtr temporary_power_ptr_;
-  mojom::ProcessInstancePtr temporary_process_ptr_;
-  mojom::StorageManagerInstancePtr temporary_storage_manager_ptr_;
-  mojom::VideoInstancePtr temporary_video_ptr_;
-  mojom::WindowManagerInstancePtr temporary_window_manager_ptr_;
+  // Instance holders.
+  InstanceHolder<mojom::AppInstance> app_;
+  InstanceHolder<mojom::AudioInstance> audio_;
+  InstanceHolder<mojom::AuthInstance> auth_;
+  InstanceHolder<mojom::BluetoothInstance> bluetooth_;
+  InstanceHolder<mojom::ClipboardInstance> clipboard_;
+  InstanceHolder<mojom::CrashCollectorInstance> crash_collector_;
+  InstanceHolder<mojom::FileSystemInstance> file_system_;
+  InstanceHolder<mojom::ImeInstance> ime_;
+  InstanceHolder<mojom::IntentHelperInstance> intent_helper_;
+  InstanceHolder<mojom::MetricsInstance> metrics_;
+  InstanceHolder<mojom::NetInstance> net_;
+  InstanceHolder<mojom::NotificationsInstance> notifications_;
+  InstanceHolder<mojom::ObbMounterInstance> obb_mounter_;
+  InstanceHolder<mojom::PolicyInstance> policy_;
+  InstanceHolder<mojom::PowerInstance> power_;
+  InstanceHolder<mojom::ProcessInstance> process_;
+  InstanceHolder<mojom::StorageManagerInstance> storage_manager_;
+  InstanceHolder<mojom::VideoInstance> video_;
+  InstanceHolder<mojom::WindowManagerInstance> window_manager_;
 
   base::ObserverList<Observer> observer_list_;
 
diff --git a/components/arc/audio/arc_audio_bridge.cc b/components/arc/audio/arc_audio_bridge.cc
index 13625d4..222b5bc4 100644
--- a/components/arc/audio/arc_audio_bridge.cc
+++ b/components/arc/audio/arc_audio_bridge.cc
@@ -13,7 +13,7 @@
 
 ArcAudioBridge::ArcAudioBridge(ArcBridgeService* bridge_service)
     : ArcService(bridge_service), binding_(this) {
-  arc_bridge_service()->AddObserver(this);
+  arc_bridge_service()->audio()->AddObserver(this);
   if (chromeos::CrasAudioHandler::IsInitialized()) {
     cras_audio_handler_ = chromeos::CrasAudioHandler::Get();
     cras_audio_handler_->AddAudioObserver(this);
@@ -21,21 +21,21 @@
 }
 
 ArcAudioBridge::~ArcAudioBridge() {
-  arc_bridge_service()->RemoveObserver(this);
   if (cras_audio_handler_ && chromeos::CrasAudioHandler::IsInitialized()) {
     cras_audio_handler_->RemoveAudioObserver(this);
   }
+  arc_bridge_service()->audio()->RemoveObserver(this);
 }
 
-void ArcAudioBridge::OnAudioInstanceReady() {
+void ArcAudioBridge::OnInstanceReady() {
   mojom::AudioInstance* audio_instance =
-      arc_bridge_service()->audio_instance();
+      arc_bridge_service()->audio()->instance();
   if (!audio_instance) {
     LOG(ERROR) << "OnAudioInstanceReady called, "
                << "but no audio instance found";
     return;
   }
-  if (arc_bridge_service()->audio_version() < 1) {
+  if (arc_bridge_service()->audio()->version() < 1) {
     LOG(WARNING) << "Audio instance is too old and does not support Init()";
     return;
   }
@@ -44,8 +44,8 @@
 
 void ArcAudioBridge::ShowVolumeControls() {
   VLOG(2) << "ArcAudioBridge::ShowVolumeControls";
-  ash::WmShell::Get()->system_tray_notifier()->
-      NotifyAudioOutputVolumeChanged(0, 0);
+  ash::WmShell::Get()->system_tray_notifier()->NotifyAudioOutputVolumeChanged(
+      0, 0);
 }
 
 void ArcAudioBridge::OnAudioNodesChanged() {
@@ -53,18 +53,18 @@
   const chromeos::AudioDevice* output_device =
       cras_audio_handler_->GetDeviceFromId(output_id);
   bool headphone_inserted =
-    (output_device &&
-     output_device->type == chromeos::AudioDeviceType::AUDIO_TYPE_HEADPHONE);
+      (output_device &&
+       output_device->type == chromeos::AudioDeviceType::AUDIO_TYPE_HEADPHONE);
 
   uint64_t input_id = cras_audio_handler_->GetPrimaryActiveInputNode();
   const chromeos::AudioDevice* input_device =
       cras_audio_handler_->GetDeviceFromId(input_id);
   bool microphone_inserted =
-    (input_device &&
-     input_device->type == chromeos::AudioDeviceType::AUDIO_TYPE_MIC);
+      (input_device &&
+       input_device->type == chromeos::AudioDeviceType::AUDIO_TYPE_MIC);
 
-  VLOG(1) << "HEADPHONE " << headphone_inserted
-          << " MICROPHONE " << microphone_inserted;
+  VLOG(1) << "HEADPHONE " << headphone_inserted << " MICROPHONE "
+          << microphone_inserted;
   SendSwitchState(headphone_inserted, microphone_inserted);
 }
 
@@ -81,7 +81,8 @@
   }
 
   VLOG(1) << "Send switch state " << switch_state;
-  mojom::AudioInstance* audio_instance = arc_bridge_service()->audio_instance();
+  mojom::AudioInstance* audio_instance =
+      arc_bridge_service()->audio()->instance();
   if (audio_instance)
     audio_instance->NotifySwitchState(switch_state);
 }
diff --git a/components/arc/audio/arc_audio_bridge.h b/components/arc/audio/arc_audio_bridge.h
index 5f88b1ab..34cf4f1 100644
--- a/components/arc/audio/arc_audio_bridge.h
+++ b/components/arc/audio/arc_audio_bridge.h
@@ -11,20 +11,21 @@
 #include "chromeos/audio/cras_audio_handler.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_service.h"
+#include "components/arc/instance_holder.h"
 #include "mojo/public/cpp/bindings/binding.h"
 
 namespace arc {
 
 class ArcAudioBridge : public ArcService,
-                       public ArcBridgeService::Observer,
+                       public InstanceHolder<mojom::AudioInstance>::Observer,
                        public mojom::AudioHost,
                        public chromeos::CrasAudioHandler::AudioObserver {
  public:
   explicit ArcAudioBridge(ArcBridgeService* bridge_service);
   ~ArcAudioBridge() override;
 
-  // ArcBridgeService::Observer overrides.
-  void OnAudioInstanceReady() override;
+  // InstanceHolder<mojom::AudioInstance>::Observer overrides.
+  void OnInstanceReady() override;
 
   // mojom::AudioHost overrides.
   void ShowVolumeControls() override;
diff --git a/components/arc/bluetooth/arc_bluetooth_bridge.cc b/components/arc/bluetooth/arc_bluetooth_bridge.cc
index 5ba17cc..3437480 100644
--- a/components/arc/bluetooth/arc_bluetooth_bridge.cc
+++ b/components/arc/bluetooth/arc_bluetooth_bridge.cc
@@ -71,11 +71,11 @@
     VLOG(1) << "no bluetooth adapter available";
   }
 
-  arc_bridge_service()->AddObserver(this);
+  arc_bridge_service()->bluetooth()->AddObserver(this);
 }
 
 ArcBluetoothBridge::~ArcBluetoothBridge() {
-  arc_bridge_service()->RemoveObserver(this);
+  arc_bridge_service()->bluetooth()->RemoveObserver(this);
 
   if (bluetooth_adapter_)
     bluetooth_adapter_->RemoveObserver(this);
@@ -90,17 +90,15 @@
   bluetooth_adapter_->AddObserver(this);
 }
 
-void ArcBluetoothBridge::OnBluetoothInstanceReady() {
+void ArcBluetoothBridge::OnInstanceReady() {
   mojom::BluetoothInstance* bluetooth_instance =
-      arc_bridge_service()->bluetooth_instance();
+      arc_bridge_service()->bluetooth()->instance();
   if (!bluetooth_instance) {
     LOG(ERROR) << "OnBluetoothInstanceReady called, "
                << "but no bluetooth instance found";
     return;
   }
-
-  arc_bridge_service()->bluetooth_instance()->Init(
-      binding_.CreateInterfacePtrAndBind());
+  bluetooth_instance->Init(binding_.CreateInterfacePtrAndBind());
 }
 
 void ArcBluetoothBridge::AdapterPresentChanged(BluetoothAdapter* adapter,
@@ -132,7 +130,7 @@
   mojo::Array<mojom::BluetoothPropertyPtr> properties =
       GetDeviceProperties(mojom::BluetoothPropertyType::ALL, device);
 
-  arc_bridge_service()->bluetooth_instance()->OnDeviceFound(
+  arc_bridge_service()->bluetooth()->instance()->OnDeviceFound(
       std::move(properties));
 
   if (!CheckBluetoothInstanceVersion(kMinBtleVersion))
@@ -143,7 +141,7 @@
   int rssi = device->GetInquiryRSSI();
   mojo::Array<mojom::BluetoothAdvertisingDataPtr> adv_data =
       GetAdvertisingData(device);
-  arc_bridge_service()->bluetooth_instance()->OnLEDeviceFound(
+  arc_bridge_service()->bluetooth()->instance()->OnLEDeviceFound(
       std::move(addr), rssi, std::move(adv_data));
 }
 
@@ -213,7 +211,7 @@
   mojom::BluetoothAddressPtr addr =
       mojom::BluetoothAddress::From(device->GetAddress());
 
-  arc_bridge_service()->bluetooth_instance()->OnSearchComplete(
+  arc_bridge_service()->bluetooth()->instance()->OnSearchComplete(
       std::move(addr), mojom::BluetoothGattStatus::GATT_SUCCESS);
 }
 
@@ -278,7 +276,7 @@
   char_id->inst_id = ConvertGattIdentifierToId(characteristic->GetIdentifier());
   char_id->uuid = mojom::BluetoothUUID::From(characteristic->GetUUID());
 
-  arc_bridge_service()->bluetooth_instance()->OnGattNotify(
+  arc_bridge_service()->bluetooth()->instance()->OnGattNotify(
       std::move(address), std::move(service_id), std::move(char_id),
       true /* is_notify */, mojo::Array<uint8_t>::From(value));
 }
@@ -322,7 +320,7 @@
   mojo::Array<mojom::BluetoothPropertyPtr> properties =
       GetAdapterProperties(type);
 
-  arc_bridge_service()->bluetooth_instance()->OnAdapterProperties(
+  arc_bridge_service()->bluetooth()->instance()->OnAdapterProperties(
       mojom::BluetoothStatus::SUCCESS, std::move(properties));
 }
 
@@ -333,7 +331,7 @@
     return;
 
   // TODO(smbarber): Implement SetAdapterProperty
-  arc_bridge_service()->bluetooth_instance()->OnAdapterProperties(
+  arc_bridge_service()->bluetooth()->instance()->OnAdapterProperties(
       mojom::BluetoothStatus::FAIL,
       mojo::Array<mojom::BluetoothPropertyPtr>::New(0));
 }
@@ -357,7 +355,7 @@
     status = mojom::BluetoothStatus::FAIL;
   }
 
-  arc_bridge_service()->bluetooth_instance()->OnRemoteDeviceProperties(
+  arc_bridge_service()->bluetooth()->instance()->OnRemoteDeviceProperties(
       status, std::move(remote_addr), std::move(properties));
 }
 
@@ -369,7 +367,7 @@
     return;
 
   // TODO(smbarber): Implement SetRemoteDeviceProperty
-  arc_bridge_service()->bluetooth_instance()->OnRemoteDeviceProperties(
+  arc_bridge_service()->bluetooth()->instance()->OnRemoteDeviceProperties(
       mojom::BluetoothStatus::FAIL, std::move(remote_addr),
       mojo::Array<mojom::BluetoothPropertyPtr>::New(0));
 }
@@ -439,7 +437,7 @@
 
   discovery_session_ = std::move(session);
 
-  arc_bridge_service()->bluetooth_instance()->OnDiscoveryStateChanged(
+  arc_bridge_service()->bluetooth()->instance()->OnDiscoveryStateChanged(
       mojom::BluetoothDiscoveryState::STARTED);
 
   SendCachedDevicesFound();
@@ -451,7 +449,7 @@
 
   discovery_session_.reset();
 
-  arc_bridge_service()->bluetooth_instance()->OnDiscoveryStateChanged(
+  arc_bridge_service()->bluetooth()->instance()->OnDiscoveryStateChanged(
       mojom::BluetoothDiscoveryState::STOPPED);
 }
 
@@ -565,7 +563,7 @@
 
   DCHECK(addr);
 
-  arc_bridge_service()->bluetooth_instance()->OnLEConnectionStateChange(
+  arc_bridge_service()->bluetooth()->instance()->OnLEConnectionStateChange(
       std::move(addr), connected);
 }
 
@@ -596,7 +594,7 @@
   DCHECK(device);
 
   if (device->IsConnected()) {
-    arc_bridge_service()->bluetooth_instance()->OnLEConnectionStateChange(
+    arc_bridge_service()->bluetooth()->instance()->OnLEConnectionStateChange(
         std::move(remote_addr), true);
     return;
   }
@@ -621,7 +619,7 @@
   DCHECK(device);
 
   if (!device->IsConnected()) {
-    arc_bridge_service()->bluetooth_instance()->OnLEConnectionStateChange(
+    arc_bridge_service()->bluetooth()->instance()->OnLEConnectionStateChange(
         std::move(remote_addr), false);
     return;
   }
@@ -644,7 +642,7 @@
 
   // Call the callback if discovery is completed
   if (device->IsGattServicesDiscoveryComplete()) {
-    arc_bridge_service()->bluetooth_instance()->OnSearchComplete(
+    arc_bridge_service()->bluetooth()->instance()->OnSearchComplete(
         std::move(remote_addr), mojom::BluetoothGattStatus::GATT_SUCCESS);
     return;
   }
@@ -770,7 +768,7 @@
     }
   }
 
-  arc_bridge_service()->bluetooth_instance()->OnGetGattDB(
+  arc_bridge_service()->bluetooth()->instance()->OnGetGattDB(
       std::move(remote_addr), std::move(db));
 }
 
@@ -1032,7 +1030,7 @@
   if (!HasBluetoothInstance())
     return;
 
-  arc_bridge_service()->bluetooth_instance()->OnBondStateChanged(
+  arc_bridge_service()->bluetooth()->instance()->OnBondStateChanged(
       mojom::BluetoothStatus::SUCCESS, std::move(addr),
       mojom::BluetoothBondState::BONDING);
 }
@@ -1041,7 +1039,7 @@
   if (!HasBluetoothInstance())
     return;
 
-  arc_bridge_service()->bluetooth_instance()->OnBondStateChanged(
+  arc_bridge_service()->bluetooth()->instance()->OnBondStateChanged(
       mojom::BluetoothStatus::SUCCESS, std::move(addr),
       mojom::BluetoothBondState::BONDED);
 }
@@ -1052,7 +1050,7 @@
   if (!HasBluetoothInstance())
     return;
 
-  arc_bridge_service()->bluetooth_instance()->OnBondStateChanged(
+  arc_bridge_service()->bluetooth()->instance()->OnBondStateChanged(
       mojom::BluetoothStatus::FAIL, std::move(addr),
       mojom::BluetoothBondState::NONE);
 }
@@ -1061,7 +1059,7 @@
   if (!HasBluetoothInstance())
     return;
 
-  arc_bridge_service()->bluetooth_instance()->OnBondStateChanged(
+  arc_bridge_service()->bluetooth()->instance()->OnBondStateChanged(
       mojom::BluetoothStatus::SUCCESS, std::move(addr),
       mojom::BluetoothBondState::NONE);
 }
@@ -1076,7 +1074,7 @@
   if (device && device->IsPaired()) {
     bond_state = mojom::BluetoothBondState::BONDED;
   }
-  arc_bridge_service()->bluetooth_instance()->OnBondStateChanged(
+  arc_bridge_service()->bluetooth()->instance()->OnBondStateChanged(
       mojom::BluetoothStatus::FAIL, std::move(addr), bond_state);
 }
 
@@ -1290,23 +1288,23 @@
     mojo::Array<mojom::BluetoothPropertyPtr> properties =
         GetDeviceProperties(mojom::BluetoothPropertyType::ALL, device);
 
-    arc_bridge_service()->bluetooth_instance()->OnDeviceFound(
+    arc_bridge_service()->bluetooth()->instance()->OnDeviceFound(
         std::move(properties));
 
-    if (arc_bridge_service()->bluetooth_version() >= kMinBtleVersion) {
+    if (arc_bridge_service()->bluetooth()->version() >= kMinBtleVersion) {
       mojom::BluetoothAddressPtr addr =
           mojom::BluetoothAddress::From(device->GetAddress());
       int rssi = device->GetInquiryRSSI();
       mojo::Array<mojom::BluetoothAdvertisingDataPtr> adv_data =
           GetAdvertisingData(device);
-      arc_bridge_service()->bluetooth_instance()->OnLEDeviceFound(
+      arc_bridge_service()->bluetooth()->instance()->OnLEDeviceFound(
           std::move(addr), rssi, std::move(adv_data));
     }
   }
 }
 
 bool ArcBluetoothBridge::HasBluetoothInstance() const {
-  if (!arc_bridge_service()->bluetooth_instance()) {
+  if (!arc_bridge_service()->bluetooth()->instance()) {
     LOG(WARNING) << "no Bluetooth instance available";
     return false;
   }
@@ -1327,17 +1325,17 @@
     mojo::Array<mojom::BluetoothPropertyPtr> properties =
         GetDeviceProperties(mojom::BluetoothPropertyType::ALL, device);
 
-    arc_bridge_service()->bluetooth_instance()->OnDeviceFound(
+    arc_bridge_service()->bluetooth()->instance()->OnDeviceFound(
         std::move(properties));
 
     mojom::BluetoothAddressPtr addr =
         mojom::BluetoothAddress::From(device->GetAddress());
 
-    if (arc_bridge_service()->bluetooth_version() >= kMinBtleVersion) {
+    if (arc_bridge_service()->bluetooth()->version() >= kMinBtleVersion) {
       int rssi = device->GetInquiryRSSI();
       mojo::Array<mojom::BluetoothAdvertisingDataPtr> adv_data =
           GetAdvertisingData(device);
-      arc_bridge_service()->bluetooth_instance()->OnLEDeviceFound(
+      arc_bridge_service()->bluetooth()->instance()->OnLEDeviceFound(
           addr->Clone(), rssi, std::move(adv_data));
     }
 
@@ -1352,8 +1350,8 @@
 }
 
 bool ArcBluetoothBridge::CheckBluetoothInstanceVersion(
-    int32_t version_need) const {
-  int32_t version = arc_bridge_service()->bluetooth_version();
+    uint32_t version_need) const {
+  uint32_t version = arc_bridge_service()->bluetooth()->version();
   if (version >= version_need)
     return true;
   LOG(WARNING) << "Bluetooth instance is too old (version " << version
diff --git a/components/arc/bluetooth/arc_bluetooth_bridge.h b/components/arc/bluetooth/arc_bluetooth_bridge.h
index cebf74f7..c305661c 100644
--- a/components/arc/bluetooth/arc_bluetooth_bridge.h
+++ b/components/arc/bluetooth/arc_bluetooth_bridge.h
@@ -16,6 +16,7 @@
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_service.h"
 #include "components/arc/common/bluetooth.mojom.h"
+#include "components/arc/instance_holder.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
 #include "device/bluetooth/bluetooth_device.h"
@@ -32,7 +33,7 @@
 
 class ArcBluetoothBridge
     : public ArcService,
-      public ArcBridgeService::Observer,
+      public InstanceHolder<mojom::BluetoothInstance>::Observer,
       public device::BluetoothAdapter::Observer,
       public device::BluetoothAdapterFactory::AdapterCallback,
       public mojom::BluetoothHost {
@@ -40,8 +41,9 @@
   explicit ArcBluetoothBridge(ArcBridgeService* bridge_service);
   ~ArcBluetoothBridge() override;
 
-  // Overridden from ArcBridgeService::Observer:
-  void OnBluetoothInstanceReady() override;
+  // Overridden from
+  // InstanceHolder<mojom::BluetoothInstance>::Observer:
+  void OnInstanceReady() override;
 
   void OnAdapterInitialized(scoped_refptr<device::BluetoothAdapter> adapter);
 
@@ -264,7 +266,7 @@
 
   void SendCachedDevicesFound() const;
   bool HasBluetoothInstance() const;
-  bool CheckBluetoothInstanceVersion(int32_t version_need) const;
+  bool CheckBluetoothInstanceVersion(uint32_t version_need) const;
 
   template <class T>
   T* FindGattObjectFromUuid(const std::vector<T*> objs,
diff --git a/components/arc/clipboard/arc_clipboard_bridge.cc b/components/arc/clipboard/arc_clipboard_bridge.cc
index aa0dbe4..2a6d735 100644
--- a/components/arc/clipboard/arc_clipboard_bridge.cc
+++ b/components/arc/clipboard/arc_clipboard_bridge.cc
@@ -29,23 +29,22 @@
 
 ArcClipboardBridge::ArcClipboardBridge(ArcBridgeService* bridge_service)
     : ArcService(bridge_service), binding_(this) {
-  arc_bridge_service()->AddObserver(this);
+  arc_bridge_service()->clipboard()->AddObserver(this);
 }
 
 ArcClipboardBridge::~ArcClipboardBridge() {
   DCHECK(CalledOnValidThread());
-  arc_bridge_service()->RemoveObserver(this);
+  arc_bridge_service()->clipboard()->RemoveObserver(this);
 }
 
-void ArcClipboardBridge::OnClipboardInstanceReady() {
+void ArcClipboardBridge::OnInstanceReady() {
   mojom::ClipboardInstance* clipboard_instance =
-      arc_bridge_service()->clipboard_instance();
+      arc_bridge_service()->clipboard()->instance();
   if (!clipboard_instance) {
     LOG(ERROR) << "OnClipboardInstanceReady called, "
                << "but no clipboard instance found";
     return;
   }
-
   clipboard_instance->Init(binding_.CreateInterfacePtrAndBind());
 }
 
@@ -63,7 +62,7 @@
   clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &text);
 
   mojom::ClipboardInstance* clipboard_instance =
-      arc_bridge_service()->clipboard_instance();
+      arc_bridge_service()->clipboard()->instance();
   clipboard_instance->OnGetTextContent(ConvertString16ToMojoString(text));
 }
 
diff --git a/components/arc/clipboard/arc_clipboard_bridge.h b/components/arc/clipboard/arc_clipboard_bridge.h
index 1980b69..97a569d 100644
--- a/components/arc/clipboard/arc_clipboard_bridge.h
+++ b/components/arc/clipboard/arc_clipboard_bridge.h
@@ -10,19 +10,21 @@
 #include "base/macros.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_service.h"
+#include "components/arc/instance_holder.h"
 #include "mojo/public/cpp/bindings/binding.h"
 
 namespace arc {
 
-class ArcClipboardBridge : public ArcService,
-                           public ArcBridgeService::Observer,
-                           public mojom::ClipboardHost {
+class ArcClipboardBridge
+    : public ArcService,
+      public InstanceHolder<mojom::ClipboardInstance>::Observer,
+      public mojom::ClipboardHost {
  public:
   explicit ArcClipboardBridge(ArcBridgeService* bridge_service);
   ~ArcClipboardBridge() override;
 
-  // ArcBridgeService::Observer overrides.
-  void OnClipboardInstanceReady() override;
+  // InstanceHolder<mojom::ClipboardInstance>::Observer overrides.
+  void OnInstanceReady() override;
 
   // mojom::ClipboardHost overrides.
   void SetTextContent(const mojo::String& text) override;
diff --git a/components/arc/common/intent_helper.mojom b/components/arc/common/intent_helper.mojom
index b8fb48ae..4d7075b 100644
--- a/components/arc/common/intent_helper.mojom
+++ b/components/arc/common/intent_helper.mojom
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
-// Next MinVersion: 10
+// Next MinVersion: 11
 
 module arc.mojom;
 
@@ -15,10 +15,30 @@
   SEND_MULTIPLE,
 };
 
+[Extensible]
+enum PatternType {
+  PATTERN_LITERAL,
+  PATTERN_PREFIX,
+  PATTERN_SIMPLE_GLOB,
+};
+
+struct PatternMatcher {
+  string pattern;
+  PatternType type;
+};
+
+struct AuthorityEntry {
+  string host;
+  int32 port;
+};
+
 struct IntentFilter {
   array<string> actions;
   array<string> categories;
   array<string> data_schemes;
+  [MinVersion=10]array<AuthorityEntry>? data_authorities;
+  [MinVersion=10]array<PatternMatcher>? data_paths;
+  [MinVersion=10]array<PatternMatcher>? data_scheme_specific_parts;
 };
 
 // Describes a package that can handle a URL.
diff --git a/components/arc/crash_collector/arc_crash_collector_bridge.cc b/components/arc/crash_collector/arc_crash_collector_bridge.cc
index 3095304..8557308a 100644
--- a/components/arc/crash_collector/arc_crash_collector_bridge.cc
+++ b/components/arc/crash_collector/arc_crash_collector_bridge.cc
@@ -14,26 +14,25 @@
 #include "mojo/edk/embedder/embedder.h"
 
 namespace {
-
 const char kCrashReporterPath[] = "/sbin/crash_reporter";
-
 }
 
 namespace arc {
 
 ArcCrashCollectorBridge::ArcCrashCollectorBridge(ArcBridgeService* bridge)
     : ArcService(bridge), binding_(this) {
-  arc_bridge_service()->AddObserver(this);
+  arc_bridge_service()->crash_collector()->AddObserver(this);
 }
 
 ArcCrashCollectorBridge::~ArcCrashCollectorBridge() {
-  arc_bridge_service()->RemoveObserver(this);
+  arc_bridge_service()->crash_collector()->RemoveObserver(this);
 }
 
-void ArcCrashCollectorBridge::OnCrashCollectorInstanceReady() {
+void ArcCrashCollectorBridge::OnInstanceReady() {
   mojom::CrashCollectorHostPtr host_ptr;
   binding_.Bind(mojo::GetProxy(&host_ptr));
-  arc_bridge_service()->crash_collector_instance()->Init(std::move(host_ptr));
+  arc_bridge_service()->crash_collector()->instance()->Init(
+      std::move(host_ptr));
 }
 
 void ArcCrashCollectorBridge::DumpCrash(const mojo::String& type,
@@ -42,19 +41,16 @@
   mojo::edk::PassWrappedPlatformHandle(pipe.get().value(), &handle);
 
   base::FileHandleMappingVector fd_map = {
-    std::make_pair(handle.get().handle, STDIN_FILENO)
-  };
+      std::make_pair(handle.get().handle, STDIN_FILENO)};
 
   base::LaunchOptions options;
   options.fds_to_remap = &fd_map;
 
-  auto process = base::LaunchProcess({
-    kCrashReporterPath,
-    "--arc_java_crash=" + type.get(),
-    "--arc_device=" + device_,
-    "--arc_board=" + board_,
-    "--arc_cpu_abi=" + cpu_abi_
-  }, options);
+  auto process =
+      base::LaunchProcess({kCrashReporterPath, "--arc_java_crash=" + type.get(),
+                           "--arc_device=" + device_, "--arc_board=" + board_,
+                           "--arc_cpu_abi=" + cpu_abi_},
+                          options);
 
   int exit_code;
   if (!process.WaitForExit(&exit_code)) {
diff --git a/components/arc/crash_collector/arc_crash_collector_bridge.h b/components/arc/crash_collector/arc_crash_collector_bridge.h
index 4446bd3..cb23475 100644
--- a/components/arc/crash_collector/arc_crash_collector_bridge.h
+++ b/components/arc/crash_collector/arc_crash_collector_bridge.h
@@ -10,20 +10,22 @@
 #include "base/macros.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_service.h"
+#include "components/arc/instance_holder.h"
 #include "mojo/public/cpp/bindings/binding.h"
 
 namespace arc {
 
 // Relays dumps for non-native ARC crashes to the crash reporter in Chrome OS.
-class ArcCrashCollectorBridge : public ArcService,
-                                public ArcBridgeService::Observer,
-                                public mojom::CrashCollectorHost {
+class ArcCrashCollectorBridge
+    : public ArcService,
+      public InstanceHolder<mojom::CrashCollectorInstance>::Observer,
+      public mojom::CrashCollectorHost {
  public:
   explicit ArcCrashCollectorBridge(ArcBridgeService* bridge);
   ~ArcCrashCollectorBridge() override;
 
-  // ArcBridgeService::Observer overrides.
-  void OnCrashCollectorInstanceReady() override;
+  // InstanceHolder<mojom::CrashCollectorInstance>::Observer overrides.
+  void OnInstanceReady() override;
 
   // mojom::CrashCollectorHost overrides.
   void DumpCrash(const mojo::String& type, mojo::ScopedHandle pipe) override;
diff --git a/components/arc/ime/arc_ime_bridge_impl.cc b/components/arc/ime/arc_ime_bridge_impl.cc
index b575a4a..001f26e 100644
--- a/components/arc/ime/arc_ime_bridge_impl.cc
+++ b/components/arc/ime/arc_ime_bridge_impl.cc
@@ -64,9 +64,10 @@
         arc::mojom::CompositionSegment::New();
     segment->start_offset = underline.start_offset;
     segment->end_offset = underline.end_offset;
-    segment->emphasized = (underline.thick ||
-        (composition.selection.start() == underline.start_offset &&
-         composition.selection.end() == underline.end_offset));
+    segment->emphasized =
+        (underline.thick ||
+         (composition.selection.start() == underline.start_offset &&
+          composition.selection.end() == underline.end_offset));
     segments.push_back(std::move(segment));
   }
   return segments;
@@ -77,20 +78,21 @@
 ArcImeBridgeImpl::ArcImeBridgeImpl(Delegate* delegate,
                                    ArcBridgeService* bridge_service)
     : binding_(this), delegate_(delegate), bridge_service_(bridge_service) {
-  bridge_service_->AddObserver(this);
+  bridge_service_->ime()->AddObserver(this);
 }
 
 ArcImeBridgeImpl::~ArcImeBridgeImpl() {
-  bridge_service_->RemoveObserver(this);
+  bridge_service_->ime()->RemoveObserver(this);
 }
 
-void ArcImeBridgeImpl::OnImeInstanceReady() {
-  bridge_service_->ime_instance()->Init(binding_.CreateInterfacePtrAndBind());
+void ArcImeBridgeImpl::OnInstanceReady() {
+  bridge_service_->ime()->instance()->Init(
+      binding_.CreateInterfacePtrAndBind());
 }
 
 void ArcImeBridgeImpl::SendSetCompositionText(
     const ui::CompositionText& composition) {
-  mojom::ImeInstance* ime_instance = bridge_service_->ime_instance();
+  mojom::ImeInstance* ime_instance = bridge_service_->ime()->instance();
   if (!ime_instance) {
     LOG(ERROR) << "ArcImeInstance method called before being ready.";
     return;
@@ -101,7 +103,7 @@
 }
 
 void ArcImeBridgeImpl::SendConfirmCompositionText() {
-  mojom::ImeInstance* ime_instance = bridge_service_->ime_instance();
+  mojom::ImeInstance* ime_instance = bridge_service_->ime()->instance();
   if (!ime_instance) {
     LOG(ERROR) << "ArcImeInstance method called before being ready.";
     return;
@@ -111,7 +113,7 @@
 }
 
 void ArcImeBridgeImpl::SendInsertText(const base::string16& text) {
-  mojom::ImeInstance* ime_instance = bridge_service_->ime_instance();
+  mojom::ImeInstance* ime_instance = bridge_service_->ime()->instance();
   if (!ime_instance) {
     LOG(ERROR) << "ArcImeInstance method called before being ready.";
     return;
@@ -122,12 +124,12 @@
 
 void ArcImeBridgeImpl::SendOnKeyboardBoundsChanging(
     const gfx::Rect& new_bounds) {
-  mojom::ImeInstance* ime_instance = bridge_service_->ime_instance();
+  mojom::ImeInstance* ime_instance = bridge_service_->ime()->instance();
   if (!ime_instance) {
     LOG(ERROR) << "ArcImeInstance method called before being ready.";
     return;
   }
-  if (bridge_service_->ime_version() <
+  if (bridge_service_->ime()->version() <
       kMinVersionForOnKeyboardsBoundsChanging) {
     LOG(ERROR) << "ArcImeInstance is too old for OnKeyboardsBoundsChanging.";
     return;
@@ -138,12 +140,12 @@
 
 void ArcImeBridgeImpl::SendExtendSelectionAndDelete(
     size_t before, size_t after) {
-  mojom::ImeInstance* ime_instance = bridge_service_->ime_instance();
+  mojom::ImeInstance* ime_instance = bridge_service_->ime()->instance();
   if (!ime_instance) {
     LOG(ERROR) << "ArcImeInstance method called before being ready.";
     return;
   }
-  if (bridge_service_->ime_version() <
+  if (bridge_service_->ime()->version() <
       kMinVersionForExtendSelectionAndDelete) {
     LOG(ERROR) << "ArcImeInstance is too old for ExtendSelectionAndDelete.";
     return;
@@ -157,11 +159,9 @@
 }
 
 void ArcImeBridgeImpl::OnCursorRectChanged(arc::mojom::CursorRectPtr rect) {
-  delegate_->OnCursorRectChanged(gfx::Rect(
-      rect->left,
-      rect->top,
-      rect->right - rect->left,
-      rect->bottom - rect->top));
+  delegate_->OnCursorRectChanged(gfx::Rect(rect->left, rect->top,
+                                           rect->right - rect->left,
+                                           rect->bottom - rect->top));
 }
 
 void ArcImeBridgeImpl::OnCancelComposition() {
diff --git a/components/arc/ime/arc_ime_bridge_impl.h b/components/arc/ime/arc_ime_bridge_impl.h
index 046cfb8..2246e52 100644
--- a/components/arc/ime/arc_ime_bridge_impl.h
+++ b/components/arc/ime/arc_ime_bridge_impl.h
@@ -10,6 +10,7 @@
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/common/ime.mojom.h"
 #include "components/arc/ime/arc_ime_bridge.h"
+#include "components/arc/instance_holder.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "ui/base/ime/text_input_type.h"
 #include "ui/gfx/geometry/rect.h"
@@ -24,13 +25,13 @@
 // Chromium and the ARC container.
 class ArcImeBridgeImpl : public ArcImeBridge,
                          public mojom::ImeHost,
-                         public ArcBridgeService::Observer {
+                         public InstanceHolder<mojom::ImeInstance>::Observer {
  public:
   ArcImeBridgeImpl(Delegate* delegate, ArcBridgeService* bridge_service);
   ~ArcImeBridgeImpl() override;
 
-  // arc::ArcBridgeService::Observer overrides:
-  void OnImeInstanceReady() override;
+  // arc::InstanceHolder<mojom::ImeInstance>::Observer overrides:
+  void OnInstanceReady() override;
 
   // ArcImeBridge overrides:
   void SendSetCompositionText(const ui::CompositionText& composition) override;
diff --git a/components/arc/instance_holder.h b/components/arc/instance_holder.h
new file mode 100644
index 0000000..6aabeee8
--- /dev/null
+++ b/components/arc/instance_holder.h
@@ -0,0 +1,137 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_ARC_INSTANCE_HOLDER_H_
+#define COMPONENTS_ARC_INSTANCE_HOLDER_H_
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
+#include "base/threading/thread_checker.h"
+#include "mojo/public/cpp/bindings/interface_ptr.h"
+
+namespace arc {
+
+// Holds a Mojo instance+version pair. This also allows for listening for state
+// changes for the particular instance. T should be a Mojo interface type
+// (arc::mojom::XxxInstance).
+template <typename T>
+class InstanceHolder {
+ public:
+  // Notifies about connection events for individual instances.
+  class Observer {
+   public:
+    // Called once the instance is ready.
+    virtual void OnInstanceReady() {}
+
+    // Called when the connection to the instance is closed.
+    virtual void OnInstanceClosed() {}
+
+   protected:
+    virtual ~Observer() = default;
+  };
+
+  InstanceHolder() : weak_factory_(this) {}
+
+  // Gets the Mojo interface for all the instance services. This will return
+  // nullptr if that particular service is not ready yet. Use an Observer if you
+  // want to be notified when this is ready. This can only be called on the
+  // thread that this class was created on.
+  T* instance() const { return raw_ptr_; }
+  uint32_t version() const { return version_; }
+
+  // Adds or removes observers. This can only be called on the thread that this
+  // class was created on. RemoveObserver does nothing if |observer| is not in
+  // the list.
+  void AddObserver(Observer* observer) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    observer_list_.AddObserver(observer);
+
+    if (instance())
+      observer->OnInstanceReady();
+  }
+
+  void RemoveObserver(Observer* observer) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    observer_list_.RemoveObserver(observer);
+  }
+
+  // Called when the channel is closed.
+  void CloseChannel() {
+    if (!ptr_)
+      return;
+
+    ptr_.reset();
+    raw_ptr_ = nullptr;
+    version_ = 0;
+    if (observer_list_.might_have_observers()) {
+      typename base::ObserverList<Observer>::Iterator it(&observer_list_);
+      Observer* obs;
+      while ((obs = it.GetNext()) != nullptr)
+        obs->OnInstanceClosed();
+    }
+  }
+
+  // Sets the interface pointer to |ptr|, once the version is determined. This
+  // will eventually invoke SetInstance(), which will notify the observers.
+  void OnInstanceReady(mojo::InterfacePtr<T> ptr) {
+    temporary_ptr_ = std::move(ptr);
+    temporary_ptr_.QueryVersion(base::Bind(&InstanceHolder<T>::OnVersionReady,
+                                           weak_factory_.GetWeakPtr()));
+  }
+
+  // This method is not intended to be called directly. Normally it is called by
+  // OnInstanceReady once the version of the instance is determined, but it is
+  // also exposed so that tests can directly inject a raw pointer+version
+  // combination.
+  void SetInstance(T* raw_ptr, uint32_t raw_version = T::Version_) {
+    raw_ptr_ = raw_ptr;
+    version_ = raw_version;
+    if (observer_list_.might_have_observers()) {
+      typename base::ObserverList<Observer>::Iterator it(&observer_list_);
+      Observer* obs;
+      while ((obs = it.GetNext()) != nullptr)
+        obs->OnInstanceReady();
+    }
+  }
+
+ private:
+  void OnVersionReady(uint32_t version) {
+    ptr_ = std::move(temporary_ptr_);
+    ptr_.set_connection_error_handler(base::Bind(
+        &InstanceHolder<T>::CloseChannel, weak_factory_.GetWeakPtr()));
+    SetInstance(ptr_.get(), version);
+  }
+
+  // These two are copies of the contents of ptr_. They are provided here just
+  // so that tests can provide non-mojo implementations.
+  T* raw_ptr_ = nullptr;
+  uint32_t version_ = 0;
+
+  mojo::InterfacePtr<T> ptr_;
+
+  // Temporary Mojo interfaces.  After a Mojo interface pointer has been
+  // received from the other endpoint, we still need to asynchronously query its
+  // version.  While that is going on, we should still return nullptr on the
+  // instance() function.
+  // To keep the instance() functions being trivial, store the instance pointer
+  // in a temporary variable to avoid losing its reference.
+  mojo::InterfacePtr<T> temporary_ptr_;
+
+  base::ThreadChecker thread_checker_;
+  base::ObserverList<Observer> observer_list_;
+
+  // This needs to be the last member in order to cancel all inflight callbacks
+  // before destroying any other members.
+  base::WeakPtrFactory<InstanceHolder<T>> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(InstanceHolder<T>);
+};
+
+}  // namespace arc
+
+#endif  // COMPONENTS_ARC_INSTANCE_HOLDER_H_
diff --git a/components/arc/intent_helper/activity_icon_loader.cc b/components/arc/intent_helper/activity_icon_loader.cc
index 8a24fe1..5248f759 100644
--- a/components/arc/intent_helper/activity_icon_loader.cc
+++ b/components/arc/intent_helper/activity_icon_loader.cc
@@ -37,13 +37,13 @@
     return nullptr;
   }
   mojom::IntentHelperInstance* intent_helper_instance =
-      bridge_service->intent_helper_instance();
+      bridge_service->intent_helper()->instance();
   if (!intent_helper_instance) {
     VLOG(2) << "ARC intent helper instance is not ready.";
     *out_error_code = ActivityIconLoader::GetResult::FAILED_ARC_NOT_READY;
     return nullptr;
   }
-  if (bridge_service->intent_helper_version() < kMinInstanceVersion) {
+  if (bridge_service->intent_helper()->version() < kMinInstanceVersion) {
     VLOG(1) << "ARC intent helper instance is too old.";
     *out_error_code = ActivityIconLoader::GetResult::FAILED_ARC_NOT_SUPPORTED;
     return nullptr;
diff --git a/components/arc/intent_helper/arc_intent_helper_bridge.cc b/components/arc/intent_helper/arc_intent_helper_bridge.cc
index e4a2660..4709817 100644
--- a/components/arc/intent_helper/arc_intent_helper_bridge.cc
+++ b/components/arc/intent_helper/arc_intent_helper_bridge.cc
@@ -39,22 +39,22 @@
       set_wallpaper_delegate_(std::move(set_wallpaper_delegate)),
       activity_resolver_(activity_resolver) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  arc_bridge_service()->AddObserver(this);
+  arc_bridge_service()->intent_helper()->AddObserver(this);
 }
 
 ArcIntentHelperBridge::~ArcIntentHelperBridge() {
   DCHECK(thread_checker_.CalledOnValidThread());
-  arc_bridge_service()->RemoveObserver(this);
+  arc_bridge_service()->intent_helper()->RemoveObserver(this);
 }
 
-void ArcIntentHelperBridge::OnIntentHelperInstanceReady() {
+void ArcIntentHelperBridge::OnInstanceReady() {
   DCHECK(thread_checker_.CalledOnValidThread());
   ash::Shell::GetInstance()->set_link_handler_model_factory(this);
-  arc_bridge_service()->intent_helper_instance()->Init(
+  arc_bridge_service()->intent_helper()->instance()->Init(
       binding_.CreateInterfacePtrAndBind());
 }
 
-void ArcIntentHelperBridge::OnIntentHelperInstanceClosed() {
+void ArcIntentHelperBridge::OnInstanceClosed() {
   DCHECK(thread_checker_.CalledOnValidThread());
   ash::Shell::GetInstance()->set_link_handler_model_factory(nullptr);
 }
diff --git a/components/arc/intent_helper/arc_intent_helper_bridge.h b/components/arc/intent_helper/arc_intent_helper_bridge.h
index 4adbe47..a48e90e 100644
--- a/components/arc/intent_helper/arc_intent_helper_bridge.h
+++ b/components/arc/intent_helper/arc_intent_helper_bridge.h
@@ -15,6 +15,7 @@
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_service.h"
 #include "components/arc/common/intent_helper.mojom.h"
+#include "components/arc/instance_holder.h"
 #include "mojo/public/cpp/bindings/binding.h"
 
 namespace ash {
@@ -30,10 +31,11 @@
 class SetWallpaperDelegate;
 
 // Receives intents from ARC.
-class ArcIntentHelperBridge : public ArcService,
-                              public ArcBridgeService::Observer,
-                              public mojom::IntentHelperHost,
-                              public ash::LinkHandlerModelFactory {
+class ArcIntentHelperBridge
+    : public ArcService,
+      public InstanceHolder<mojom::IntentHelperInstance>::Observer,
+      public mojom::IntentHelperHost,
+      public ash::LinkHandlerModelFactory {
  public:
   ArcIntentHelperBridge(
       ArcBridgeService* bridge_service,
@@ -42,9 +44,9 @@
       const scoped_refptr<LocalActivityResolver>& activity_resolver);
   ~ArcIntentHelperBridge() override;
 
-  // ArcBridgeService::Observer
-  void OnIntentHelperInstanceReady() override;
-  void OnIntentHelperInstanceClosed() override;
+  // InstanceHolder<mojom::IntentHelperInstance>::Observer
+  void OnInstanceReady() override;
+  void OnInstanceClosed() override;
 
   // arc::mojom::IntentHelperHost
   void OnIconInvalidated(const mojo::String& package_name) override;
diff --git a/components/arc/intent_helper/intent_filter.cc b/components/arc/intent_helper/intent_filter.cc
new file mode 100644
index 0000000..1a0f79c
--- /dev/null
+++ b/components/arc/intent_helper/intent_filter.cc
@@ -0,0 +1,226 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/arc/intent_helper/intent_filter.h"
+
+#include "base/compiler_specific.h"
+#include "base/strings/string_util.h"
+#include "url/gurl.h"
+
+namespace arc {
+
+IntentFilter::IntentFilter(const mojom::IntentFilterPtr& mojo_intent_filter) {
+  for (const mojom::AuthorityEntryPtr& authorityptr :
+       mojo_intent_filter->data_authorities) {
+    authorities_.emplace_back(authorityptr);
+  }
+  for (const mojom::PatternMatcherPtr& pattern :
+       mojo_intent_filter->data_paths) {
+    paths_.emplace_back(pattern);
+  }
+  for (const mojom::PatternMatcherPtr& pattern :
+       mojo_intent_filter->data_scheme_specific_parts) {
+    scheme_specific_parts_.emplace_back(pattern);
+  }
+}
+
+IntentFilter::IntentFilter(const IntentFilter& other) = default;
+
+IntentFilter::~IntentFilter() = default;
+
+// Logically, this maps to IntentFilter#match, but this code only deals with
+// view intents for http/https URLs and so it really only implements the
+// #matchData part of the match code.
+bool IntentFilter::match(const GURL& url) const {
+  // Chrome-side code only receives view intents for http/https URLs, so this
+  // match code really only implements the matchData part of the android
+  // IntentFilter class.
+  if (!url.SchemeIsHTTPOrHTTPS()) {
+    return false;
+  }
+
+  if (!scheme_specific_parts_.empty() && hasDataSchemeSpecificPart(url)) {
+    return true;
+  }
+
+  // If there isn't any matching ssp, we need to match an authority.
+  if (!authorities_.empty()) {
+    return matchDataAuthority(url) && (paths_.empty() || hasDataPath(url));
+  }
+
+  return false;
+}
+
+// Transcribed from android's IntentFilter#hasDataSchemeSpecificPart.
+bool IntentFilter::hasDataSchemeSpecificPart(const GURL& url) const {
+  // The scheme-specific-part is the content of the URL minus the ref fragment.
+  GURL::Replacements replacements;
+  replacements.ClearRef();
+  const std::string ssp = url.ReplaceComponents(replacements).GetContent();
+
+  for (const PatternMatcher& pattern : scheme_specific_parts_) {
+    if (pattern.match(ssp)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+// Transcribed from android's IntentFilter#hasDataPath.
+bool IntentFilter::hasDataPath(const GURL& url) const {
+  const std::string path = url.path();
+  for (const PatternMatcher& pattern : paths_) {
+    if (pattern.match(path)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+// Transcribed from android's IntentFilter#matchDataAuthority.
+bool IntentFilter::matchDataAuthority(const GURL& url) const {
+  for (const AuthorityEntry& authority : authorities_) {
+    if (authority.match(url)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+IntentFilter::AuthorityEntry::AuthorityEntry(
+    const mojom::AuthorityEntryPtr& entry)
+    : host_(entry->host.get()), port_(entry->port) {
+  // Wildcards are only allowed at the front of the host string.
+  wild_ = !host_.empty() && host_[0] == '*';
+  if (wild_) {
+    host_ = host_.substr(1);
+  }
+
+  // TODO: Not i18n-friendly.  Figure out how to correctly deal with IDNs.
+  host_ = base::ToLowerASCII(host_);
+}
+
+// Transcribed from android's IntentFilter.AuthorityEntry#match.
+bool IntentFilter::AuthorityEntry::match(const GURL& url) const {
+  if (!url.has_host())
+    return false;
+
+  if (port_ >= 0 && port_ != url.IntPort()) {
+    return false;
+  }
+
+  if (wild_) {
+    return base::EndsWith(url.host_piece(), host_,
+                          base::CompareCase::INSENSITIVE_ASCII);
+  } else {
+    // TODO: Not i18n-friendly.  Figure out how to correctly deal with IDNs.
+    return host_ == base::ToLowerASCII(url.host_piece());
+  }
+}
+
+IntentFilter::PatternMatcher::PatternMatcher(
+    const mojom::PatternMatcherPtr& pattern)
+    : pattern_(pattern->pattern.get()), match_type_(pattern->type) {}
+
+// Transcribed from android's PatternMatcher#matchPattern.
+bool IntentFilter::PatternMatcher::match(const std::string& str) const {
+  if (str.empty()) {
+    return false;
+  }
+  switch (match_type_) {
+    case mojom::PatternType::PATTERN_LITERAL:
+      return str == pattern_;
+    case mojom::PatternType::PATTERN_PREFIX:
+      return base::StartsWith(str, pattern_,
+                              base::CompareCase::INSENSITIVE_ASCII);
+    case mojom::PatternType::PATTERN_SIMPLE_GLOB:
+      return matchGlob(str);
+  }
+
+  return false;
+}
+
+// Transcribed from android's PatternMatcher#matchPattern.
+bool IntentFilter::PatternMatcher::matchGlob(const std::string& str) const {
+#define GET_CHAR(s, i) (UNLIKELY(i >= s.length())) ? '\0' : s[i]
+
+  const size_t NP = pattern_.length();
+  const size_t NS = str.length();
+  if (NP == 0) {
+    return NS == 0;
+  }
+  size_t ip = 0, is = 0;
+  char nextChar = GET_CHAR(pattern_, 0);
+  while (ip < NP && is < NS) {
+    char c = nextChar;
+    ++ip;
+    nextChar = GET_CHAR(pattern_, ip);
+    const bool escaped = (c == '\\');
+    if (escaped) {
+      c = nextChar;
+      ++ip;
+      nextChar = GET_CHAR(pattern_, ip);
+    }
+    if (nextChar == '*') {
+      if (!escaped && c == '.') {
+        if (ip >= (NP - 1)) {
+          // At the end with a pattern match
+          return true;
+        }
+        ++ip;
+        nextChar = GET_CHAR(pattern_, ip);
+        // Consume everything until the next char in the pattern is found.
+        if (nextChar == '\\') {
+          ++ip;
+          nextChar = GET_CHAR(pattern_, ip);
+        }
+        do {
+          if (GET_CHAR(str, is) == nextChar) {
+            break;
+          }
+          ++is;
+        } while (is < NS);
+        if (is == NS) {
+          // Next char in the pattern didn't exist in the match.
+          return false;
+        }
+        ++ip;
+        nextChar = GET_CHAR(pattern_, ip);
+        ++is;
+      } else {
+        // Consume only characters matching the one before '*'.
+        do {
+          if (GET_CHAR(str, is) != c) {
+            break;
+          }
+          ++is;
+        } while (is < NS);
+        ++ip;
+        nextChar = GET_CHAR(pattern_, ip);
+      }
+    } else {
+      if (c != '.' && GET_CHAR(str, is) != c)
+        return false;
+      ++is;
+    }
+  }
+
+  if (ip >= NP && is >= NS) {
+    // Reached the end of both strings
+    return true;
+  }
+
+  // One last check: we may have finished the match string, but still have a
+  // '.*' at the end of the pattern, which is still a match.
+  if (ip == NP - 2 && GET_CHAR(pattern_, ip) == '.' &&
+      GET_CHAR(pattern_, ip + 1) == '*') {
+    return true;
+  }
+
+  return false;
+
+#undef GET_CHAR
+}
+
+}  // namespace arc
diff --git a/components/arc/intent_helper/intent_filter.h b/components/arc/intent_helper/intent_filter.h
new file mode 100644
index 0000000..7136657
--- /dev/null
+++ b/components/arc/intent_helper/intent_filter.h
@@ -0,0 +1,66 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_ARC_INTENT_HELPER_INTENT_FILTER_H_
+#define COMPONENTS_ARC_INTENT_HELPER_INTENT_FILTER_H_
+
+#include <string>
+#include <vector>
+
+#include "components/arc/common/intent_helper.mojom.h"
+
+class GURL;
+
+namespace arc {
+
+// A chrome-side implementation of Android's IntentFilter class.  This is used
+// to approximate the intent filtering and determine whether a given URL is
+// likely to be handled by any android-side apps, prior to making expensive IPC
+// calls.
+class IntentFilter {
+ public:
+  explicit IntentFilter(const mojom::IntentFilterPtr& mojo_intent_filter);
+  IntentFilter(const IntentFilter& other);
+  ~IntentFilter();
+
+  bool match(const GURL& url) const;
+
+ private:
+  // A helper class for handling matching of the host part of the URL.
+  class AuthorityEntry {
+   public:
+    explicit AuthorityEntry(const mojom::AuthorityEntryPtr& entry);
+    bool match(const GURL& url) const;
+
+   private:
+    std::string host_;
+    bool wild_;
+    int port_;
+  };
+
+  // A helper class for handling matching of various patterns in the URL.
+  class PatternMatcher {
+   public:
+    explicit PatternMatcher(const mojom::PatternMatcherPtr& pattern);
+    bool match(const std::string& match) const;
+
+   private:
+    bool matchGlob(const std::string& match) const;
+
+    std::string pattern_;
+    mojom::PatternType match_type_;
+  };
+
+  bool matchDataAuthority(const GURL& url) const;
+  bool hasDataPath(const GURL& url) const;
+  bool hasDataSchemeSpecificPart(const GURL& url) const;
+
+  std::vector<AuthorityEntry> authorities_;
+  std::vector<PatternMatcher> paths_;
+  std::vector<PatternMatcher> scheme_specific_parts_;
+};
+
+}  // namespace arc
+
+#endif  // COMPONENTS_ARC_INTENT_HELPER_INTENT_FILTER_H_
diff --git a/components/arc/intent_helper/link_handler_model_impl.cc b/components/arc/intent_helper/link_handler_model_impl.cc
index 70806f6..9577901 100644
--- a/components/arc/intent_helper/link_handler_model_impl.cc
+++ b/components/arc/intent_helper/link_handler_model_impl.cc
@@ -93,12 +93,12 @@
     return nullptr;
   }
   mojom::IntentHelperInstance* intent_helper_instance =
-      bridge_service->intent_helper_instance();
+      bridge_service->intent_helper()->instance();
   if (!intent_helper_instance) {
     DLOG(WARNING) << "ARC intent helper instance is not ready.";
     return nullptr;
   }
-  if (bridge_service->intent_helper_version() < kMinInstanceVersion) {
+  if (bridge_service->intent_helper()->version() < kMinInstanceVersion) {
     DLOG(WARNING) << "ARC intent helper instance is too old.";
     return nullptr;
   }
diff --git a/components/arc/intent_helper/local_activity_resolver.cc b/components/arc/intent_helper/local_activity_resolver.cc
index c47301b..b590543 100644
--- a/components/arc/intent_helper/local_activity_resolver.cc
+++ b/components/arc/intent_helper/local_activity_resolver.cc
@@ -6,15 +6,6 @@
 
 #include "url/gurl.h"
 
-namespace {
-
-constexpr char kIntentActionView[] = "android.intent.action.VIEW";
-constexpr char kIntentCategoryBrowsable[] = "android.intent.category.BROWSABLE";
-constexpr char kSchemeHttp[] = "http";
-constexpr char kSchemeHttps[] = "https";
-
-}  // namespace
-
 namespace arc {
 
 LocalActivityResolver::LocalActivityResolver() = default;
@@ -27,11 +18,8 @@
     return true;
   }
 
-  for (const mojom::IntentFilterPtr& filter : intent_filters_) {
-    if (IsRelevantIntentFilter(filter)) {
-      // For now err on the side of caution and let Android
-      // handle cases where there are possible matching intent
-      // filters.
+  for (const IntentFilter& filter : intent_filters_) {
+    if (filter.match(url)) {
       return false;
     }
   }
@@ -41,48 +29,11 @@
 }
 
 void LocalActivityResolver::UpdateIntentFilters(
-    mojo::Array<mojom::IntentFilterPtr> intent_filters) {
-  intent_filters_ = std::move(intent_filters);
-}
-
-bool LocalActivityResolver::IsRelevantIntentFilter(
-    const mojom::IntentFilterPtr& intent_filter) {
-  return FilterHasViewAction(intent_filter) &&
-         FilterCategoryIsBrowsable(intent_filter) &&
-         FilterHandlesWebSchemes(intent_filter);
-}
-
-bool LocalActivityResolver::FilterHasViewAction(
-    const mojom::IntentFilterPtr& intent_filter) {
-  for (const mojo::String& action : intent_filter->actions) {
-    if (action == kIntentActionView) {
-      return true;
-    }
+    mojo::Array<mojom::IntentFilterPtr> mojo_intent_filters) {
+  intent_filters_.clear();
+  for (mojom::IntentFilterPtr& mojo_filter : mojo_intent_filters) {
+    intent_filters_.emplace_back(mojo_filter);
   }
-
-  return false;
-}
-
-bool LocalActivityResolver::FilterCategoryIsBrowsable(
-    const mojom::IntentFilterPtr& intent_filter) {
-  for (const mojo::String& category : intent_filter->categories) {
-    if (category == kIntentCategoryBrowsable) {
-      return true;
-    }
-  }
-
-  return false;
-}
-
-bool LocalActivityResolver::FilterHandlesWebSchemes(
-    const mojom::IntentFilterPtr& intent_filter) {
-  for (const mojo::String& scheme : intent_filter->data_schemes) {
-    if (scheme == kSchemeHttp || scheme == kSchemeHttps) {
-      return true;
-    }
-  }
-
-  return false;
 }
 
 }  // namespace arc
diff --git a/components/arc/intent_helper/local_activity_resolver.h b/components/arc/intent_helper/local_activity_resolver.h
index ec076253..2033b7744 100644
--- a/components/arc/intent_helper/local_activity_resolver.h
+++ b/components/arc/intent_helper/local_activity_resolver.h
@@ -2,12 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_ARC_INTENT_HELPER_LOCAL_ACTIVITY_HELPER_H_
-#define COMPONENTS_ARC_INTENT_HELPER_LOCAL_ACTIVITY_HELPER_H_
+#ifndef COMPONENTS_ARC_INTENT_HELPER_LOCAL_ACTIVITY_RESOLVER_H_
+#define COMPONENTS_ARC_INTENT_HELPER_LOCAL_ACTIVITY_RESOLVER_H_
+
+#include <vector>
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "components/arc/common/intent_helper.mojom.h"
+#include "components/arc/intent_helper/intent_filter.h"
 #include "mojo/public/cpp/bindings/binding.h"
 
 class GURL;
@@ -25,15 +28,9 @@
   friend class base::RefCounted<LocalActivityResolver>;
   ~LocalActivityResolver();
 
-  bool IsRelevantIntentFilter(const mojom::IntentFilterPtr& intent_filter);
-  bool FilterHasViewAction(const mojom::IntentFilterPtr& intent_filter);
-  bool FilterCategoryIsBrowsable(const mojom::IntentFilterPtr& intent_filter);
-  bool FilterHandlesWebSchemes(const mojom::IntentFilterPtr& intent_filter);
-
   // List of intent filters from Android. Used to determine if Chrome should
   // handle a URL without handing off to Android.
-  mojo::Array<mojom::IntentFilterPtr> intent_filters_;
-
+  std::vector<IntentFilter> intent_filters_;
   DISALLOW_COPY_AND_ASSIGN(LocalActivityResolver);
 };
 
diff --git a/components/arc/metrics/arc_metrics_service.cc b/components/arc/metrics/arc_metrics_service.cc
index 5ce5aa1..9aca98bd 100644
--- a/components/arc/metrics/arc_metrics_service.cc
+++ b/components/arc/metrics/arc_metrics_service.cc
@@ -4,6 +4,8 @@
 
 #include "components/arc/metrics/arc_metrics_service.h"
 
+#include <string>
+
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_util.h"
@@ -17,19 +19,24 @@
 const char kGmsProcessNamePrefix[] = "com.google.android.gms";
 const char kBootProgressEnableScreen[] = "boot_progress_enable_screen";
 
-} // namespace
+}  // namespace
 
 namespace arc {
 
 ArcMetricsService::ArcMetricsService(ArcBridgeService* bridge_service)
-    : ArcService(bridge_service), binding_(this), weak_ptr_factory_(this) {
-  arc_bridge_service()->AddObserver(this);
+    : ArcService(bridge_service),
+      binding_(this),
+      process_observer_(this),
+      weak_ptr_factory_(this) {
+  arc_bridge_service()->metrics()->AddObserver(this);
+  arc_bridge_service()->process()->AddObserver(&process_observer_);
   oom_kills_monitor_.Start();
 }
 
 ArcMetricsService::~ArcMetricsService() {
   DCHECK(CalledOnValidThread());
-  arc_bridge_service()->RemoveObserver(this);
+  arc_bridge_service()->process()->RemoveObserver(&process_observer_);
+  arc_bridge_service()->metrics()->RemoveObserver(this);
 }
 
 bool ArcMetricsService::CalledOnValidThread() {
@@ -37,7 +44,7 @@
   return thread_checker_.CalledOnValidThread();
 }
 
-void ArcMetricsService::OnMetricsInstanceReady() {
+void ArcMetricsService::OnInstanceReady() {
   VLOG(2) << "Start metrics service.";
   // Retrieve ARC start time from session manager.
   chromeos::SessionManagerClient* session_manager_client =
@@ -47,7 +54,7 @@
                  weak_ptr_factory_.GetWeakPtr()));
 }
 
-void ArcMetricsService::OnMetricsInstanceClosed() {
+void ArcMetricsService::OnInstanceClosed() {
   VLOG(2) << "Close metrics service.";
   DCHECK(CalledOnValidThread());
   if (binding_.is_bound())
@@ -56,11 +63,9 @@
 
 void ArcMetricsService::OnProcessInstanceReady() {
   VLOG(2) << "Start updating process list.";
-  timer_.Start(
-      FROM_HERE,
-      base::TimeDelta::FromMinutes(kRequestProcessListPeriodInMinutes),
-      this,
-      &ArcMetricsService::RequestProcessList);
+  timer_.Start(FROM_HERE,
+               base::TimeDelta::FromMinutes(kRequestProcessListPeriodInMinutes),
+               this, &ArcMetricsService::RequestProcessList);
 }
 
 void ArcMetricsService::OnProcessInstanceClosed() {
@@ -70,16 +75,15 @@
 
 void ArcMetricsService::RequestProcessList() {
   mojom::ProcessInstance* process_instance =
-      arc_bridge_service()->process_instance();
+      arc_bridge_service()->process()->instance();
   if (!process_instance) {
     LOG(ERROR) << "No process instance found before RequestProcessList";
     return;
   }
 
   VLOG(2) << "RequestProcessList";
-  process_instance->RequestProcessList(
-      base::Bind(&ArcMetricsService::ParseProcessList,
-                 weak_ptr_factory_.GetWeakPtr()));
+  process_instance->RequestProcessList(base::Bind(
+      &ArcMetricsService::ParseProcessList, weak_ptr_factory_.GetWeakPtr()));
 }
 
 void ArcMetricsService::ParseProcessList(
@@ -109,12 +113,17 @@
 }
 
 void ArcMetricsService::OnArcStartTimeRetrieved(
-    bool success, base::TimeTicks arc_start_time) {
+    bool success,
+    base::TimeTicks arc_start_time) {
   DCHECK(CalledOnValidThread());
   if (!success) {
     LOG(ERROR) << "Failed to retrieve ARC start timeticks.";
     return;
   }
+  if (!arc_bridge_service()->metrics()->instance()) {
+    LOG(ERROR) << "ARC metrics instance went away while retrieving start time.";
+    return;
+  }
 
   // The binding of host interface is deferred until the ARC start time is
   // retrieved here because it prevents race condition of the ARC start
@@ -122,7 +131,7 @@
   if (!binding_.is_bound()) {
     mojom::MetricsHostPtr host_ptr;
     binding_.Bind(mojo::GetProxy(&host_ptr));
-    arc_bridge_service()->metrics_instance()->Init(std::move(host_ptr));
+    arc_bridge_service()->metrics()->instance()->Init(std::move(host_ptr));
   }
   arc_start_time_ = arc_start_time;
   VLOG(2) << "ARC start @" << arc_start_time_;
@@ -134,27 +143,36 @@
   int64_t arc_start_time_in_ms =
       (arc_start_time_ - base::TimeTicks()).InMilliseconds();
   for (const auto& event : events) {
-    VLOG(2) << "Report boot progress event:"
-        << event->event << "@" << event->uptimeMillis;
+    VLOG(2) << "Report boot progress event:" << event->event << "@"
+            << event->uptimeMillis;
     std::string title = "Arc." + event->event.get();
     base::TimeDelta elapsed_time = base::TimeDelta::FromMilliseconds(
         event->uptimeMillis - arc_start_time_in_ms);
     // Note: This leaks memory, which is expected behavior.
-    base::HistogramBase* histogram =
-        base::Histogram::FactoryTimeGet(
-            title,
-            base::TimeDelta::FromMilliseconds(1),
-            base::TimeDelta::FromSeconds(30),
-            50,
-            base::HistogramBase::kUmaTargetedHistogramFlag);
+    base::HistogramBase* histogram = base::Histogram::FactoryTimeGet(
+        title, base::TimeDelta::FromMilliseconds(1),
+        base::TimeDelta::FromSeconds(30), 50,
+        base::HistogramBase::kUmaTargetedHistogramFlag);
     histogram->AddTime(elapsed_time);
     if (event->event.get().compare(kBootProgressEnableScreen) == 0)
-      UMA_HISTOGRAM_CUSTOM_TIMES("Arc.AndroidBootTime",
-                                 elapsed_time,
+      UMA_HISTOGRAM_CUSTOM_TIMES("Arc.AndroidBootTime", elapsed_time,
                                  base::TimeDelta::FromMilliseconds(1),
-                                 base::TimeDelta::FromSeconds(30),
-                                 50);
+                                 base::TimeDelta::FromSeconds(30), 50);
   }
 }
 
+ArcMetricsService::ProcessObserver::ProcessObserver(
+    ArcMetricsService* arc_metrics_service)
+    : arc_metrics_service_(arc_metrics_service) {}
+
+ArcMetricsService::ProcessObserver::~ProcessObserver() = default;
+
+void ArcMetricsService::ProcessObserver::OnInstanceReady() {
+  arc_metrics_service_->OnProcessInstanceReady();
+}
+
+void ArcMetricsService::ProcessObserver::OnInstanceClosed() {
+  arc_metrics_service_->OnProcessInstanceClosed();
+}
+
 }  // namespace arc
diff --git a/components/arc/metrics/arc_metrics_service.h b/components/arc/metrics/arc_metrics_service.h
index 4f61178..7b7958b 100644
--- a/components/arc/metrics/arc_metrics_service.h
+++ b/components/arc/metrics/arc_metrics_service.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_ARC_METRICS_ARC_METRICS_SERVICE_H
-#define COMPONENTS_ARC_METRICS_ARC_METRICS_SERVICE_H
+#ifndef COMPONENTS_ARC_METRICS_ARC_METRICS_SERVICE_H_
+#define COMPONENTS_ARC_METRICS_ARC_METRICS_SERVICE_H_
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
@@ -12,24 +12,28 @@
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_service.h"
 #include "components/arc/common/arc_bridge.mojom.h"
+#include "components/arc/instance_holder.h"
 #include "components/arc/metrics/oom_kills_monitor.h"
 #include "mojo/public/cpp/bindings/binding.h"
 
 namespace arc {
 
 // Collects information from other ArcServices and send UMA metrics.
-class ArcMetricsService : public ArcService,
-                          public ArcBridgeService::Observer,
-                          public mojom::MetricsHost {
+class ArcMetricsService
+    : public ArcService,
+      public InstanceHolder<mojom::MetricsInstance>::Observer,
+      public mojom::MetricsHost {
  public:
   explicit ArcMetricsService(ArcBridgeService* bridge_service);
   ~ArcMetricsService() override;
 
-  // ArcBridgeService::Observer overrides.
-  void OnMetricsInstanceReady() override;
-  void OnMetricsInstanceClosed() override;
-  void OnProcessInstanceReady() override;
-  void OnProcessInstanceClosed() override;
+  // InstanceHolder<mojom::MetricsInstance>::Observer overrides.
+  void OnInstanceReady() override;
+  void OnInstanceClosed() override;
+
+  // Implementations for InstanceHolder<mojom::ProcessInstance>::Observer.
+  void OnProcessInstanceReady();
+  void OnProcessInstanceClosed();
 
   // MetricsHost overrides.
   void ReportBootProgress(
@@ -45,8 +49,24 @@
   void OnArcStartTimeRetrieved(bool success, base::TimeTicks arc_start_time);
 
  private:
+  // Adapter to be able to also observe ProcessInstance events.
+  class ProcessObserver
+      : public InstanceHolder<mojom::ProcessInstance>::Observer {
+   public:
+    explicit ProcessObserver(ArcMetricsService* arc_metrics_service);
+    ~ProcessObserver() override;
+
+   private:
+    // InstanceHolder<mojom::ProcessInstance>::Observer overrides.
+    void OnInstanceReady() override;
+    void OnInstanceClosed() override;
+
+    ArcMetricsService* arc_metrics_service_;
+  };
+
   mojo::Binding<mojom::MetricsHost> binding_;
 
+  ProcessObserver process_observer_;
   base::ThreadChecker thread_checker_;
   base::RepeatingTimer timer_;
 
@@ -63,4 +83,4 @@
 
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_METRICS_ARC_METRICS_SERVICE_H
+#endif  // COMPONENTS_ARC_METRICS_ARC_METRICS_SERVICE_H_
diff --git a/components/arc/net/arc_net_host_impl.cc b/components/arc/net/arc_net_host_impl.cc
index 63fe3295..2d03706 100644
--- a/components/arc/net/arc_net_host_impl.cc
+++ b/components/arc/net/arc_net_host_impl.cc
@@ -305,24 +305,24 @@
 
 ArcNetHostImpl::ArcNetHostImpl(ArcBridgeService* bridge_service)
     : ArcService(bridge_service), binding_(this), weak_factory_(this) {
-  arc_bridge_service()->AddObserver(this);
+  arc_bridge_service()->net()->AddObserver(this);
   GetStateHandler()->AddObserver(this, FROM_HERE);
 }
 
 ArcNetHostImpl::~ArcNetHostImpl() {
   DCHECK(thread_checker_.CalledOnValidThread());
-  arc_bridge_service()->RemoveObserver(this);
+  arc_bridge_service()->net()->RemoveObserver(this);
   if (chromeos::NetworkHandler::IsInitialized()) {
     GetStateHandler()->RemoveObserver(this, FROM_HERE);
   }
 }
 
-void ArcNetHostImpl::OnNetInstanceReady() {
+void ArcNetHostImpl::OnInstanceReady() {
   DCHECK(thread_checker_.CalledOnValidThread());
 
   mojom::NetHostPtr host;
   binding_.Bind(GetProxy(&host));
-  arc_bridge_service()->net_instance()->Init(std::move(host));
+  arc_bridge_service()->net()->instance()->Init(std::move(host));
 }
 
 void ArcNetHostImpl::GetNetworksDeprecated(
@@ -553,16 +553,16 @@
 }
 
 void ArcNetHostImpl::ScanCompleted(const chromeos::DeviceState* /*unused*/) {
-  if (!arc_bridge_service()->net_instance()) {
+  if (!arc_bridge_service()->net()->instance()) {
     VLOG(2) << "NetInstance not ready yet";
     return;
   }
-  if (arc_bridge_service()->net_version() < 1) {
+  if (arc_bridge_service()->net()->version() < 1) {
     VLOG(1) << "NetInstance does not support ScanCompleted.";
     return;
   }
 
-  arc_bridge_service()->net_instance()->ScanCompleted();
+  arc_bridge_service()->net()->instance()->ScanCompleted();
 }
 
 void ArcNetHostImpl::GetDefaultNetwork(
@@ -586,22 +586,22 @@
 void ArcNetHostImpl::DefaultNetworkSuccessCallback(
     const std::string& service_path,
     const base::DictionaryValue& dictionary) {
-  arc_bridge_service()->net_instance()->DefaultNetworkChanged(
+  arc_bridge_service()->net()->instance()->DefaultNetworkChanged(
       TranslateONCConfiguration(&dictionary),
       TranslateONCConfiguration(&dictionary));
 }
 
 void ArcNetHostImpl::DefaultNetworkChanged(
     const chromeos::NetworkState* network) {
-  if (arc_bridge_service()->net_version() < 2) {
+  if (arc_bridge_service()->net()->version() < 2) {
     VLOG(1) << "ArcBridgeService does not support DefaultNetworkChanged.";
     return;
   }
 
   if (!network) {
     VLOG(1) << "No default network";
-    arc_bridge_service()->net_instance()->DefaultNetworkChanged(nullptr,
-                                                                nullptr);
+    arc_bridge_service()->net()->instance()->DefaultNetworkChanged(nullptr,
+                                                                   nullptr);
     return;
   }
 
@@ -615,14 +615,14 @@
 }
 
 void ArcNetHostImpl::DeviceListChanged() {
-  if (arc_bridge_service()->net_version() < 3) {
+  if (arc_bridge_service()->net()->version() < 3) {
     VLOG(1) << "ArcBridgeService does not support DeviceListChanged.";
     return;
   }
 
   bool is_enabled = GetStateHandler()->IsTechnologyEnabled(
       chromeos::NetworkTypePattern::WiFi());
-  arc_bridge_service()->net_instance()->WifiEnabledStateChanged(is_enabled);
+  arc_bridge_service()->net()->instance()->WifiEnabledStateChanged(is_enabled);
 }
 
 void ArcNetHostImpl::OnShuttingDown() {
diff --git a/components/arc/net/arc_net_host_impl.h b/components/arc/net/arc_net_host_impl.h
index 8aa52b7..a21a0b0 100644
--- a/components/arc/net/arc_net_host_impl.h
+++ b/components/arc/net/arc_net_host_impl.h
@@ -17,6 +17,7 @@
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_service.h"
 #include "components/arc/common/net.mojom.h"
+#include "components/arc/instance_holder.h"
 #include "mojo/public/cpp/bindings/binding.h"
 
 namespace base {
@@ -31,7 +32,7 @@
 
 // Private implementation of ArcNetHost.
 class ArcNetHostImpl : public ArcService,
-                       public ArcBridgeService::Observer,
+                       public InstanceHolder<mojom::NetInstance>::Observer,
                        public chromeos::NetworkStateHandlerObserver,
                        public mojom::NetHost {
  public:
@@ -77,8 +78,8 @@
   void DeviceListChanged() override;
   void GetDefaultNetwork(const GetDefaultNetworkCallback& callback) override;
 
-  // Overridden from ArcBridgeService::Observer:
-  void OnNetInstanceReady() override;
+  // Overridden from ArcBridgeService::InterfaceObserver<mojom::NetInstance>:
+  void OnInstanceReady() override;
 
  private:
   void DefaultNetworkSuccessCallback(const std::string& service_path,
diff --git a/components/arc/obb_mounter/arc_obb_mounter_bridge.cc b/components/arc/obb_mounter/arc_obb_mounter_bridge.cc
index b9f3356..04362b7c 100644
--- a/components/arc/obb_mounter/arc_obb_mounter_bridge.cc
+++ b/components/arc/obb_mounter/arc_obb_mounter_bridge.cc
@@ -22,18 +22,17 @@
 }  // namespace
 
 ArcObbMounterBridge::ArcObbMounterBridge(ArcBridgeService* bridge_service)
-    : ArcService(bridge_service),
-      binding_(this) {
-  arc_bridge_service()->AddObserver(this);
+    : ArcService(bridge_service), binding_(this) {
+  arc_bridge_service()->obb_mounter()->AddObserver(this);
 }
 
 ArcObbMounterBridge::~ArcObbMounterBridge() {
-  arc_bridge_service()->RemoveObserver(this);
+  arc_bridge_service()->obb_mounter()->RemoveObserver(this);
 }
 
-void ArcObbMounterBridge::OnObbMounterInstanceReady() {
+void ArcObbMounterBridge::OnInstanceReady() {
   mojom::ObbMounterInstance* obb_mounter_instance =
-      arc_bridge_service()->obb_mounter_instance();
+      arc_bridge_service()->obb_mounter()->instance();
   obb_mounter_instance->Init(binding_.CreateInterfacePtrAndBind());
 }
 
diff --git a/components/arc/obb_mounter/arc_obb_mounter_bridge.h b/components/arc/obb_mounter/arc_obb_mounter_bridge.h
index d2371521..6b5e3fcc 100644
--- a/components/arc/obb_mounter/arc_obb_mounter_bridge.h
+++ b/components/arc/obb_mounter/arc_obb_mounter_bridge.h
@@ -8,20 +8,22 @@
 #include "base/macros.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_service.h"
+#include "components/arc/instance_holder.h"
 #include "mojo/public/cpp/bindings/binding.h"
 
 namespace arc {
 
 // This class handles OBB mount/unmount requests from Android.
-class ArcObbMounterBridge : public ArcService,
-                            public ArcBridgeService::Observer,
-                            public mojom::ObbMounterHost {
+class ArcObbMounterBridge
+    : public ArcService,
+      public InstanceHolder<mojom::ObbMounterInstance>::Observer,
+      public mojom::ObbMounterHost {
  public:
   explicit ArcObbMounterBridge(ArcBridgeService* bridge_service);
   ~ArcObbMounterBridge() override;
 
-  // ArcBridgeService::Observer overrides:
-  void OnObbMounterInstanceReady() override;
+  // InstanceHolder<mojom::ObbMounterInstance>::Observer overrides:
+  void OnInstanceReady() override;
 
   // mojom::ObbMounterHost overrides:
   void MountObb(const mojo::String& obb_file,
diff --git a/components/arc/power/arc_power_bridge.cc b/components/arc/power/arc_power_bridge.cc
index 7943943..fb8b1fdc 100644
--- a/components/arc/power/arc_power_bridge.cc
+++ b/components/arc/power/arc_power_bridge.cc
@@ -16,16 +16,17 @@
 
 ArcPowerBridge::ArcPowerBridge(ArcBridgeService* bridge_service)
     : ArcService(bridge_service), binding_(this) {
-  arc_bridge_service()->AddObserver(this);
+  arc_bridge_service()->power()->AddObserver(this);
 }
 
 ArcPowerBridge::~ArcPowerBridge() {
-  arc_bridge_service()->RemoveObserver(this);
+  arc_bridge_service()->power()->RemoveObserver(this);
   ReleaseAllDisplayWakeLocks();
 }
 
-void ArcPowerBridge::OnPowerInstanceReady() {
-  mojom::PowerInstance* power_instance = arc_bridge_service()->power_instance();
+void ArcPowerBridge::OnInstanceReady() {
+  mojom::PowerInstance* power_instance =
+      arc_bridge_service()->power()->instance();
   if (!power_instance) {
     LOG(ERROR) << "OnPowerInstanceReady called, but no power instance found";
     return;
@@ -35,14 +36,15 @@
   ash::Shell::GetInstance()->display_configurator()->AddObserver(this);
 }
 
-void ArcPowerBridge::OnPowerInstanceClosed() {
+void ArcPowerBridge::OnInstanceClosed() {
   ash::Shell::GetInstance()->display_configurator()->RemoveObserver(this);
   ReleaseAllDisplayWakeLocks();
 }
 
 void ArcPowerBridge::OnPowerStateChanged(
     chromeos::DisplayPowerState power_state) {
-  mojom::PowerInstance* power_instance = arc_bridge_service()->power_instance();
+  mojom::PowerInstance* power_instance =
+      arc_bridge_service()->power()->instance();
   if (!power_instance) {
     LOG(ERROR) << "PowerInstance is not available";
     return;
diff --git a/components/arc/power/arc_power_bridge.h b/components/arc/power/arc_power_bridge.h
index d82aad6..c82c380 100644
--- a/components/arc/power/arc_power_bridge.h
+++ b/components/arc/power/arc_power_bridge.h
@@ -10,6 +10,7 @@
 #include "base/macros.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_service.h"
+#include "components/arc/instance_holder.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "ui/display/chromeos/display_configurator.h"
 
@@ -18,16 +19,16 @@
 // ARC Power Client sets power management policy based on requests from
 // ARC instances.
 class ArcPowerBridge : public ArcService,
-                       public ArcBridgeService::Observer,
+                       public InstanceHolder<mojom::PowerInstance>::Observer,
                        public ui::DisplayConfigurator::Observer,
                        public mojom::PowerHost {
  public:
   explicit ArcPowerBridge(ArcBridgeService* bridge_service);
   ~ArcPowerBridge() override;
 
-  // ArcBridgeService::Observer overrides.
-  void OnPowerInstanceReady() override;
-  void OnPowerInstanceClosed() override;
+  // InstanceHolder<mojom::PowerInstance>::Observer overrides.
+  void OnInstanceReady() override;
+  void OnInstanceClosed() override;
 
   // DisplayConfigurator::Observer overrides.
   void OnPowerStateChanged(chromeos::DisplayPowerState power_state) override;
diff --git a/components/arc/storage_manager/arc_storage_manager.cc b/components/arc/storage_manager/arc_storage_manager.cc
index 926ac50..6bc2cf5 100644
--- a/components/arc/storage_manager/arc_storage_manager.cc
+++ b/components/arc/storage_manager/arc_storage_manager.cc
@@ -22,7 +22,7 @@
 
 }  // namespace
 
-ArcStorageManager::ArcStorageManager(ArcBridgeService *bridge_service)
+ArcStorageManager::ArcStorageManager(ArcBridgeService* bridge_service)
     : ArcService(bridge_service) {
   DCHECK(!g_arc_storage_manager);
   g_arc_storage_manager = this;
@@ -39,10 +39,6 @@
   return g_arc_storage_manager;
 }
 
-void ArcStorageManager::OnStorageManagerInstanceReady() {
-  VLOG(1) << "ArcStorageManagerInstance is ready";
-}
-
 bool ArcStorageManager::OpenPrivateVolumeSettings() {
   auto storage_manager_instance = GetStorageManagerInstance();
   if (!storage_manager_instance) {
@@ -74,12 +70,12 @@
 
 mojom::StorageManagerInstance* ArcStorageManager::GetStorageManagerInstance() {
   auto bridge_service = arc_bridge_service();
-  auto storage_manager_instance = bridge_service->storage_manager_instance();
+  auto storage_manager_instance = bridge_service->storage_manager()->instance();
   if (!storage_manager_instance) {
     DLOG(WARNING) << "ARC storage manager instance is not ready.";
     return nullptr;
   }
-  auto storage_manager_version = bridge_service->storage_manager_version();
+  auto storage_manager_version = bridge_service->storage_manager()->version();
   if (storage_manager_version < kMinInstanceVersion) {
     DLOG(ERROR) << "ARC storage manager instance (version "
                 << storage_manager_version << ") is too old.";
diff --git a/components/arc/storage_manager/arc_storage_manager.h b/components/arc/storage_manager/arc_storage_manager.h
index f4111bf..1ca766e7 100644
--- a/components/arc/storage_manager/arc_storage_manager.h
+++ b/components/arc/storage_manager/arc_storage_manager.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_ARC_STORAGE_MANAGER_ARC_STORAGE_MANAGER_H
-#define COMPONENTS_ARC_STORAGE_MANAGER_ARC_STORAGE_MANAGER_H
+#ifndef COMPONENTS_ARC_STORAGE_MANAGER_ARC_STORAGE_MANAGER_H_
+#define COMPONENTS_ARC_STORAGE_MANAGER_ARC_STORAGE_MANAGER_H_
 
 #include <memory>
 
@@ -16,8 +16,7 @@
 namespace arc {
 
 // This class represents as a simple proxy of StorageManager to Chrome OS.
-class ArcStorageManager : public ArcService,
-                          public ArcBridgeService::Observer {
+class ArcStorageManager : public ArcService {
  public:
   explicit ArcStorageManager(ArcBridgeService* bridge_service);
   ~ArcStorageManager() override;
@@ -27,16 +26,13 @@
   // nullptr (or aborts on Debug build).
   static ArcStorageManager* Get();
 
-  // ArcBridgeService::Observer
-  void OnStorageManagerInstanceReady() override;
-
   // Opens detailed preference screen of private volume on ARC.
   // Returns false when an instance of ARC-side isn't ready yet.
   bool OpenPrivateVolumeSettings();
 
   // Gets storage usage of all application's APK, data, and cache size.
-  using GetApplicationsSizeCallback = base::Callback<
-      void(bool succeeded, arc::mojom::ApplicationsSizePtr)>;
+  using GetApplicationsSizeCallback =
+      base::Callback<void(bool succeeded, arc::mojom::ApplicationsSizePtr)>;
   bool GetApplicationsSize(const GetApplicationsSizeCallback& callback);
 
   // Deletes all applications' cache files.
@@ -50,4 +46,4 @@
 
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_STORAGE_MANAGER_ARC_STORAGE_MANAGER_H
+#endif  // COMPONENTS_ARC_STORAGE_MANAGER_ARC_STORAGE_MANAGER_H_
diff --git a/components/arc/test/fake_policy_instance.cc b/components/arc/test/fake_policy_instance.cc
index 8111244c..42fd121c 100644
--- a/components/arc/test/fake_policy_instance.cc
+++ b/components/arc/test/fake_policy_instance.cc
@@ -11,11 +11,11 @@
     mojo::InterfaceRequest<mojom::PolicyInstance> request,
     ArcBridgeService* bridge_service)
     : binding_(this, std::move(request)), bridge_service_(bridge_service) {
-  bridge_service_->AddObserver(this);
+  bridge_service_->policy()->AddObserver(this);
 }
 
 FakePolicyInstance::~FakePolicyInstance() {
-  bridge_service_->RemoveObserver(this);
+  bridge_service_->policy()->RemoveObserver(this);
 }
 
 void FakePolicyInstance::OnPolicyUpdated() {}
@@ -24,7 +24,7 @@
   host_ptr_ = std::move(host_ptr);
 }
 
-void FakePolicyInstance::OnPolicyInstanceReady() {
+void FakePolicyInstance::OnInstanceReady() {
   ready_ = true;
 }
 
diff --git a/components/arc/test/fake_policy_instance.h b/components/arc/test/fake_policy_instance.h
index 213f3d39..8bd5af9 100644
--- a/components/arc/test/fake_policy_instance.h
+++ b/components/arc/test/fake_policy_instance.h
@@ -7,12 +7,14 @@
 
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/common/policy.mojom.h"
+#include "components/arc/instance_holder.h"
 #include "components/arc/test/fake_arc_bridge_instance.h"
 
 namespace arc {
 
-class FakePolicyInstance : public mojom::PolicyInstance,
-                           public arc::ArcBridgeService::Observer {
+class FakePolicyInstance
+    : public mojom::PolicyInstance,
+      public arc::InstanceHolder<mojom::PolicyInstance>::Observer {
  public:
   // bridge_service should not be destroyed before the destructor is called.
   FakePolicyInstance(mojo::InterfaceRequest<mojom::PolicyInstance> request,
@@ -23,8 +25,8 @@
   void Init(mojom::PolicyHostPtr host_ptr) override;
   void OnPolicyUpdated() override;
 
-  // arc::ArcBridgeService::Observer
-  void OnPolicyInstanceReady() override;
+  // arc::InstanceHolder<mojom::PolicyInstance>::Observer
+  void OnInstanceReady() override;
 
   void WaitForOnPolicyInstanceReady();
   void CallGetPolicies(const mojom::PolicyHost::GetPoliciesCallback& callback);
diff --git a/components/arc/window_manager/arc_window_manager_bridge.cc b/components/arc/window_manager/arc_window_manager_bridge.cc
index 45b9686..ee2e28b5 100644
--- a/components/arc/window_manager/arc_window_manager_bridge.cc
+++ b/components/arc/window_manager/arc_window_manager_bridge.cc
@@ -14,7 +14,7 @@
 ArcWindowManagerBridge::ArcWindowManagerBridge(ArcBridgeService* bridge_service)
     : ArcService(bridge_service),
       current_mode_(mojom::WindowManagerMode::MODE_NORMAL) {
-  arc_bridge_service()->AddObserver(this);
+  arc_bridge_service()->window_manager()->AddObserver(this);
   if (!ash::WmShell::HasInstance()) {
     // The shell gets always loaded before ARC. If there is no shell it can only
     // mean that a unit test is running.
@@ -24,7 +24,7 @@
   ash::WmShell::Get()->AddShellObserver(this);
 }
 
-void ArcWindowManagerBridge::OnWindowManagerInstanceReady() {
+void ArcWindowManagerBridge::OnInstanceReady() {
   if (!ash::WmShell::HasInstance()) {
     // The shell gets always loaded before ARC. If there is no shell it can only
     // mean that a unit test is running.
@@ -42,7 +42,7 @@
 ArcWindowManagerBridge::~ArcWindowManagerBridge() {
   if (ash::WmShell::HasInstance())
     ash::WmShell::Get()->RemoveShellObserver(this);
-  arc_bridge_service()->RemoveObserver(this);
+  arc_bridge_service()->window_manager()->RemoveObserver(this);
 }
 
 void ArcWindowManagerBridge::OnMaximizeModeStarted() {
@@ -57,12 +57,12 @@
     bool touch_view_enabled) {
   // We let the ArcBridgeService check that we are calling on the right thread.
   DCHECK(ArcBridgeService::Get() != nullptr);
-  mojom::WindowManagerMode wm_mode = touch_view_enabled ?
-      mojom::WindowManagerMode::MODE_TOUCH_VIEW :
-      mojom::WindowManagerMode::MODE_NORMAL;
+  mojom::WindowManagerMode wm_mode =
+      touch_view_enabled ? mojom::WindowManagerMode::MODE_TOUCH_VIEW
+                         : mojom::WindowManagerMode::MODE_NORMAL;
 
   mojom::WindowManagerInstance* wm_instance =
-      arc_bridge_service()->window_manager_instance();
+      arc_bridge_service()->window_manager()->instance();
   if (!wm_instance || wm_mode == current_mode_) {
     return;
   }
diff --git a/components/arc/window_manager/arc_window_manager_bridge.h b/components/arc/window_manager/arc_window_manager_bridge.h
index f206e5de..27a346d 100644
--- a/components/arc/window_manager/arc_window_manager_bridge.h
+++ b/components/arc/window_manager/arc_window_manager_bridge.h
@@ -11,18 +11,20 @@
 #include "base/macros.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_service.h"
+#include "components/arc/instance_holder.h"
 
 namespace arc {
 
-class ArcWindowManagerBridge : public ArcService,
-                               public ArcBridgeService::Observer,
-                               public ash::ShellObserver {
+class ArcWindowManagerBridge
+    : public ArcService,
+      public InstanceHolder<mojom::WindowManagerInstance>::Observer,
+      public ash::ShellObserver {
  public:
   explicit ArcWindowManagerBridge(ArcBridgeService* bridge_service);
   ~ArcWindowManagerBridge() override;
 
-  // ArcBridgeService::Observer
-  void OnWindowManagerInstanceReady() override;
+  // InstanceHolder<mojom::WindowManagerInstance>::Observer
+  void OnInstanceReady() override;
 
   // Ash::Shell::ShellObserver
   void OnMaximizeModeStarted() override;
diff --git a/components/autofill/core/browser/autofill_external_delegate.cc b/components/autofill/core/browser/autofill_external_delegate.cc
index a81613d0..cf22acfc 100644
--- a/components/autofill/core/browser/autofill_external_delegate.cc
+++ b/components/autofill/core/browser/autofill_external_delegate.cc
@@ -12,6 +12,7 @@
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/sparse_histogram.h"
+#include "base/metrics/user_metrics.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -117,6 +118,8 @@
     signin_promo_suggestion.frontend_id =
         POPUP_ITEM_ID_CREDIT_CARD_SIGNIN_PROMO;
     suggestions.push_back(signin_promo_suggestion);
+    base::RecordAction(
+        base::UserMetricsAction("Signin_Impression_FromAutofillDropdown"));
   }
 
 #if !defined(OS_ANDROID)
diff --git a/components/autofill/core/browser/autofill_external_delegate_unittest.cc b/components/autofill/core/browser/autofill_external_delegate_unittest.cc
index fb67541..62e964d6 100644
--- a/components/autofill/core/browser/autofill_external_delegate_unittest.cc
+++ b/components/autofill/core/browser/autofill_external_delegate_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/histogram_tester.h"
+#include "base/test/user_action_tester.h"
 #include "build/build_config.h"
 #include "components/autofill/core/browser/autofill_manager.h"
 #include "components/autofill/core/browser/autofill_metrics.h"
@@ -216,11 +217,15 @@
   EXPECT_CALL(autofill_client_,
               ShowAutofillPopup(_, _, SuggestionVectorIdsAre(element_ids), _));
 
+  base::UserActionTester user_action_tester;
+
   // This should call ShowAutofillPopup.
   std::vector<Suggestion> autofill_item;
   autofill_item.push_back(Suggestion());
   autofill_item[0].frontend_id = kAutofillProfileId;
   external_delegate_->OnSuggestionsReturned(kQueryId, autofill_item);
+  EXPECT_EQ(1, user_action_tester.GetActionCount(
+                   "Signin_Impression_FromAutofillDropdown"));
 
   EXPECT_CALL(
       *autofill_manager_,
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc
index e43e85b2..04650708 100644
--- a/components/autofill/core/browser/autofill_manager.cc
+++ b/components/autofill/core/browser/autofill_manager.cc
@@ -515,11 +515,15 @@
           GetProfileSuggestions(*form_structure, field, *autofill_field);
     }
     if (!suggestions.empty()) {
+      bool is_context_secure =
+          client_->IsContextSecure(form_structure->source_url());
+      if (is_filling_credit_card)
+        AutofillMetrics::LogIsQueriedCreditCardFormSecure(is_context_secure);
+
       // Don't provide credit card suggestions for non-secure pages, but do
       // provide them for secure pages with passive mixed content (see impl. of
       // IsContextSecure).
-      if (is_filling_credit_card &&
-          !client_->IsContextSecure(form_structure->source_url())) {
+      if (is_filling_credit_card && !is_context_secure) {
         Suggestion warning_suggestion(l10n_util::GetStringUTF16(
             IDS_AUTOFILL_WARNING_INSECURE_CONNECTION));
         warning_suggestion.frontend_id = POPUP_ITEM_ID_WARNING_MESSAGE;
diff --git a/components/autofill/core/browser/autofill_metrics.cc b/components/autofill/core/browser/autofill_metrics.cc
index ff13a65..aed621c 100644
--- a/components/autofill/core/browser/autofill_metrics.cc
+++ b/components/autofill/core/browser/autofill_metrics.cc
@@ -641,6 +641,11 @@
                             std::min(int(num_removed), 50));
 }
 
+// static
+void AutofillMetrics::LogIsQueriedCreditCardFormSecure(bool is_secure) {
+  UMA_HISTOGRAM_BOOLEAN("Autofill.QueriedCreditCardFormIsSecure", is_secure);
+}
+
 AutofillMetrics::FormEventLogger::FormEventLogger(bool is_for_credit_card)
     : is_for_credit_card_(is_for_credit_card),
       is_server_data_available_(false),
diff --git a/components/autofill/core/browser/autofill_metrics.h b/components/autofill/core/browser/autofill_metrics.h
index de9b8ff54..d0fcb7c 100644
--- a/components/autofill/core/browser/autofill_metrics.h
+++ b/components/autofill/core/browser/autofill_metrics.h
@@ -646,6 +646,10 @@
   // Log how many profiles were removed as part of the deduplication process.
   static void LogNumberOfProfilesRemovedDuringDedupe(size_t num_removed);
 
+  // Log whether the Autofill query on a credit card form is made in a secure
+  // context.
+  static void LogIsQueriedCreditCardFormSecure(bool is_secure);
+
   // Utility to autofill form events in the relevant histograms depending on
   // the presence of server and/or local data.
   class FormEventLogger {
diff --git a/components/autofill/core/browser/autofill_metrics_unittest.cc b/components/autofill/core/browser/autofill_metrics_unittest.cc
index 1d5c5168..c19f5c2 100644
--- a/components/autofill/core/browser/autofill_metrics_unittest.cc
+++ b/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -155,7 +155,8 @@
     local_credit_cards_.clear();
     server_credit_cards_.clear();
     if (include_local_credit_card) {
-      CreditCard* credit_card = new CreditCard;
+      CreditCard* credit_card =
+          new CreditCard(base::ASCIIToUTF16("4111111111111111"), 12, 24);
       credit_card->set_guid("10000000-0000-0000-0000-000000000001");
       local_credit_cards_.push_back(credit_card);
     }
@@ -1812,6 +1813,56 @@
                    "Autofill_PolledCreditCardSuggestions"));
 }
 
+// Tests that the Autofill.QueriedCreditCardFormIsSecure histogram is logged
+// properly.
+TEST_F(AutofillMetricsTest, QueriedCreditCardFormIsSecure) {
+  personal_data_->RecreateCreditCards(
+      true /* include_local_credit_card */,
+      false /* include_masked_server_credit_card */,
+      false /* include_full_server_credit_card */);
+
+  // Set up the form data.
+  FormData form;
+  form.name = ASCIIToUTF16("TestForm");
+  form.origin = GURL("http://example.com/form.html");
+  form.action = GURL("http://example.com/submit.html");
+
+  FormFieldData field;
+  std::vector<ServerFieldType> field_types;
+  test::CreateTestFormField("Month", "card_month", "", "text", &field);
+  form.fields.push_back(field);
+  field_types.push_back(CREDIT_CARD_EXP_MONTH);
+  test::CreateTestFormField("Year", "card_year", "", "text", &field);
+  form.fields.push_back(field);
+  field_types.push_back(CREDIT_CARD_EXP_2_DIGIT_YEAR);
+  test::CreateTestFormField("Credit card", "card", "", "text", &field);
+  form.fields.push_back(field);
+  field_types.push_back(CREDIT_CARD_NUMBER);
+
+  // Simulate having seen this form on page load.
+  autofill_manager_->AddSeenForm(form, field_types, field_types);
+
+  {
+    // Simulate an Autofill query on a credit card field.
+    autofill_client_.set_is_context_secure(true);
+    base::HistogramTester histogram_tester;
+    autofill_manager_->OnQueryFormFieldAutofill(0, form, form.fields[1],
+                                                gfx::RectF());
+    histogram_tester.ExpectUniqueSample(
+        "Autofill.QueriedCreditCardFormIsSecure", true, 1);
+  }
+
+  {
+    // Simulate an Autofill query on a credit card field.
+    autofill_client_.set_is_context_secure(false);
+    base::HistogramTester histogram_tester;
+    autofill_manager_->OnQueryFormFieldAutofill(0, form, form.fields[1],
+                                                gfx::RectF());
+    histogram_tester.ExpectUniqueSample(
+        "Autofill.QueriedCreditCardFormIsSecure", false, 1);
+  }
+}
+
 // Tests that the Autofill_PolledProfileSuggestions user action is only logged
 // once if the field is queried repeatedly.
 TEST_F(AutofillMetricsTest, PolledProfileSuggestions_DebounceLogs) {
diff --git a/components/browser_sync/browser/profile_sync_service.h b/components/browser_sync/browser/profile_sync_service.h
index 201e3030..0e37bcf 100644
--- a/components/browser_sync/browser/profile_sync_service.h
+++ b/components/browser_sync/browser/profile_sync_service.h
@@ -669,6 +669,7 @@
     SYNC_INITIAL_STATE_LIMIT
   };
 
+  friend class PermissionUmaUtilTest;
   friend class ProfileSyncServicePasswordTest;
   friend class SyncTest;
   friend class TestProfileSyncService;
diff --git a/components/components_tests.gyp b/components/components_tests.gyp
index 6700418..1db06f0 100644
--- a/components/components_tests.gyp
+++ b/components/components_tests.gyp
@@ -807,6 +807,7 @@
       'subresource_filter/core/common/knuth_morris_pratt_unittest.cc',
       'subresource_filter/core/common/ngram_extractor_unittest.cc',
       'subresource_filter/core/common/string_splitter_unittest.cc',
+      'subresource_filter/core/common/url_pattern_matching_unittest.cc',
     ],
     'suggestions_unittest_sources': [
       'suggestions/blacklist_store_unittest.cc',
diff --git a/components/content_settings/core/common/content_settings_pattern.cc b/components/content_settings/core/common/content_settings_pattern.cc
index d6dd272..aa89594 100644
--- a/components/content_settings/core/common/content_settings_pattern.cc
+++ b/components/content_settings/core/common/content_settings_pattern.cc
@@ -29,7 +29,7 @@
   return std::string();
 }
 
-// Returns true if |sub_domain| is a sub domain or equls |domain|.  E.g.
+// Returns true if |sub_domain| is a sub domain or equals |domain|.  E.g.
 // "mail.google.com" is a sub domain of "google.com" but "evilhost.com" is not a
 // subdomain of "host.com".
 bool IsSubDomainOrEqual(const std::string& sub_domain,
diff --git a/components/cronet/android/api/src/org/chromium/net/NetworkQualityRttListener.java b/components/cronet/android/api/src/org/chromium/net/NetworkQualityRttListener.java
index 29dd1c10..c6705a9 100644
--- a/components/cronet/android/api/src/org/chromium/net/NetworkQualityRttListener.java
+++ b/components/cronet/android/api/src/org/chromium/net/NetworkQualityRttListener.java
@@ -20,11 +20,6 @@
      */
     private final Executor mExecutor;
 
-    // TODO(tbansal):  http://crbug.com/618034 Remove this constructor.
-    public NetworkQualityRttListener() {
-        mExecutor = null;
-    }
-
     /**
      * @param executor The executor on which the observations are reported.
      */
diff --git a/components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java b/components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java
index 60ca98c..bbd522a 100644
--- a/components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java
+++ b/components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java
@@ -308,9 +308,6 @@
         if (!mNetworkQualityEstimatorEnabled) {
             throw new IllegalStateException("Network quality estimator must be enabled");
         }
-        if (mNetworkQualityExecutor == null && listener.getExecutor() == null) {
-            throw new IllegalStateException("Executor must not be null");
-        }
         synchronized (mNetworkQualityLock) {
             if (mRttListenerList.isEmpty()) {
                 synchronized (mLock) {
@@ -496,14 +493,7 @@
                         listener.onRttObservation(rttMs, whenMs, source);
                     }
                 };
-                // Use the executor provided by the listener. If not available,
-                // use the network quality executor.
-                // TODO(tbansal): Change this to always use the executor
-                // provided by the listener, once all embedders start providing
-                // a non-null executor.
-                Executor executor = listener.getExecutor() != null ? listener.getExecutor()
-                                                                   : mNetworkQualityExecutor;
-                postObservationTaskToExecutor(executor, task);
+                postObservationTaskToExecutor(listener.getExecutor(), task);
             }
         }
     }
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java
index ee00041..60244fa 100644
--- a/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java
+++ b/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java
@@ -255,25 +255,6 @@
 
     @SmallTest
     @Feature({"Cronet"})
-    public void testRealTimeNetworkQualityObservationsNotEnabled_LegacyAPI() throws Exception {
-        mTestFramework = startCronetTestFramework();
-        TestNetworkQualityRttListener rttListener = new TestNetworkQualityRttListener();
-        try {
-            mTestFramework.mCronetEngine.addRttListener(rttListener);
-            fail("Should throw an exception.");
-        } catch (IllegalStateException e) {
-        }
-        TestUrlRequestCallback callback = new TestUrlRequestCallback();
-        UrlRequest urlRequest =
-                mTestFramework.mCronetEngine.createRequest(mUrl, callback, callback.getExecutor());
-        urlRequest.start();
-        callback.blockForDone();
-        assertEquals(0, rttListener.rttObservationCount());
-        mTestFramework.mCronetEngine.shutdown();
-    }
-
-    @SmallTest
-    @Feature({"Cronet"})
     public void testRealTimeNetworkQualityObservationsListenerRemoved() throws Exception {
         CronetEngine.Builder mCronetEngineBuilder = new CronetEngine.Builder(getContext());
         TestExecutor networkQualityExecutor = new TestExecutor();
@@ -298,26 +279,6 @@
 
     @SmallTest
     @Feature({"Cronet"})
-    public void testRealTimeNetworkQualityObservationsListenerRemoved_LegacyAPI() throws Exception {
-        mTestFramework = startCronetTestFramework();
-        TestExecutor testExecutor = new TestExecutor();
-        TestNetworkQualityRttListener rttListener = new TestNetworkQualityRttListener();
-        mTestFramework.mCronetEngine.enableNetworkQualityEstimator(testExecutor);
-        mTestFramework.mCronetEngine.configureNetworkQualityEstimatorForTesting(true, true);
-        mTestFramework.mCronetEngine.addRttListener(rttListener);
-        mTestFramework.mCronetEngine.removeRttListener(rttListener);
-        TestUrlRequestCallback callback = new TestUrlRequestCallback();
-        UrlRequest urlRequest =
-                mTestFramework.mCronetEngine.createRequest(mUrl, callback, callback.getExecutor());
-        urlRequest.start();
-        callback.blockForDone();
-        testExecutor.runAllTasks();
-        assertEquals(0, rttListener.rttObservationCount());
-        mTestFramework.mCronetEngine.shutdown();
-    }
-
-    @SmallTest
-    @Feature({"Cronet"})
     public void testRealTimeNetworkQualityObservationsQuicDisabled() throws Exception {
         CronetEngine.Builder mCronetEngineBuilder = new CronetEngine.Builder(getContext());
         Executor requestFinishedListenerExecutor =
@@ -373,38 +334,6 @@
         mTestFramework.mCronetEngine.shutdown();
     }
 
-    @SmallTest
-    @Feature({"Cronet"})
-    public void testRealTimeNetworkQualityObservations_LegacyAPI() throws Exception {
-        mTestFramework = startCronetTestFramework();
-        Executor executor = Executors.newSingleThreadExecutor();
-        ConditionVariable waitForThroughput = new ConditionVariable();
-        TestNetworkQualityRttListener rttListener = new TestNetworkQualityRttListener();
-        TestNetworkQualityThroughputListener throughputListener =
-                new TestNetworkQualityThroughputListener(executor, waitForThroughput);
-        mTestFramework.mCronetEngine.enableNetworkQualityEstimator(executor);
-        mTestFramework.mCronetEngine.configureNetworkQualityEstimatorForTesting(true, true);
-        mTestFramework.mCronetEngine.addRttListener(rttListener);
-        mTestFramework.mCronetEngine.addThroughputListener(throughputListener);
-        TestUrlRequestCallback callback = new TestUrlRequestCallback();
-        UrlRequest urlRequest =
-                mTestFramework.mCronetEngine.createRequest(mUrl, callback, callback.getExecutor());
-        urlRequest.start();
-        callback.blockForDone();
-
-        // Throughput observation is posted to the network quality estimator on the network thread
-        // after the UrlRequest is completed. The observations are then eventually posted to
-        // throughput listeners on the executor provided to network quality.
-        waitForThroughput.block();
-        assertTrue(throughputListener.throughputObservationCount() > 0);
-
-        // Check RTT observation count after throughput observation has been received. This ensures
-        // that executor has finished posting the RTT observation to the RTT listeners.
-        assertTrue(rttListener.rttObservationCount() > 0);
-
-        mTestFramework.mCronetEngine.shutdown();
-    }
-
     // TODO(tbansal):  http://crbug.com/618034 Remove this.
     private static class TestRequestFinishedListener
             implements CronetEngine.RequestFinishedListener {
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/TestNetworkQualityRttListener.java b/components/cronet/android/test/javatests/src/org/chromium/net/TestNetworkQualityRttListener.java
index e43e4ad..afeec1f 100644
--- a/components/cronet/android/test/javatests/src/org/chromium/net/TestNetworkQualityRttListener.java
+++ b/components/cronet/android/test/javatests/src/org/chromium/net/TestNetworkQualityRttListener.java
@@ -20,13 +20,6 @@
 
     private Thread mExecutorThread;
 
-    // TODO(tbansal):  http://crbug.com/618034 Reomve this constructor once all
-    // embedders start providing a non-null executor, and the tests for legacy
-    // API are removed.
-    TestNetworkQualityRttListener() {
-        super();
-    }
-
     TestNetworkQualityRttListener(Executor executor) {
         super(executor);
     }
diff --git a/components/cronet/android/test/quic_test_server.cc b/components/cronet/android/test/quic_test_server.cc
index 86a7a7c..60aa74b7 100644
--- a/components/cronet/android/test/quic_test_server.cc
+++ b/components/cronet/android/test/quic_test_server.cc
@@ -44,13 +44,13 @@
 
   // Set up server certs.
   base::FilePath directory = test_data_dir.Append("net/data/ssl/certificates");
-  // TODO(xunjieli): Use scoped_ptr when crbug.com/545474 is fixed.
-  net::ProofSourceChromium* proof_source = new net::ProofSourceChromium();
+  std::unique_ptr<net::ProofSourceChromium> proof_source(
+      new net::ProofSourceChromium());
   CHECK(proof_source->Initialize(
       directory.Append("quic_test.example.com.crt"),
       directory.Append("quic_test.example.com.key.pkcs8"),
       directory.Append("quic_test.example.com.key.sct")));
-  g_quic_server = new net::QuicSimpleServer(proof_source, config,
+  g_quic_server = new net::QuicSimpleServer(std::move(proof_source), config,
                                             net::QuicSupportedVersions());
 
   // Start listening.
diff --git a/components/cronet/ios/test/quic_test_server.cc b/components/cronet/ios/test/quic_test_server.cc
index 59a7c13..6353f4c2 100644
--- a/components/cronet/ios/test/quic_test_server.cc
+++ b/components/cronet/ios/test/quic_test_server.cc
@@ -70,13 +70,13 @@
   // Set up server certs.
   base::FilePath directory;
   directory = test_files_root;
-  // TODO(xunjieli): Use scoped_ptr when crbug.com/545474 is fixed.
-  net::ProofSourceChromium* proof_source = new net::ProofSourceChromium();
+  std::unique_ptr<net::ProofSourceChromium> proof_source(
+      new net::ProofSourceChromium());
   CHECK(proof_source->Initialize(
       directory.Append("quic_test.example.com.crt"),
       directory.Append("quic_test.example.com.key.pkcs8"),
       directory.Append("quic_test.example.com.key.sct")));
-  g_quic_server = new net::QuicSimpleServer(proof_source, config,
+  g_quic_server = new net::QuicSimpleServer(std::move(proof_source), config,
                                             net::QuicSupportedVersions());
 
   // Start listening.
diff --git a/components/data_reduction_proxy/content/browser/content_lofi_decider.cc b/components/data_reduction_proxy/content/browser/content_lofi_decider.cc
index 5fe9d03..0523f7ea 100644
--- a/components/data_reduction_proxy/content/browser/content_lofi_decider.cc
+++ b/components/data_reduction_proxy/content/browser/content_lofi_decider.cc
@@ -88,4 +88,17 @@
   return true;
 }
 
+bool ContentLoFiDecider::ShouldRecordLoFiUMA(
+    const net::URLRequest& request) const {
+  const content::ResourceRequestInfo* request_info =
+      content::ResourceRequestInfo::ForRequest(&request);
+
+  // User is not using Lo-Fi.
+  if (!request_info || !request_info->IsUsingLoFi())
+    return false;
+
+  return params::IsIncludedInLoFiEnabledFieldTrial() ||
+         params::IsIncludedInLoFiControlFieldTrial();
+}
+
 }  // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/content/browser/content_lofi_decider.h b/components/data_reduction_proxy/content/browser/content_lofi_decider.h
index 01e0377..cc3face 100644
--- a/components/data_reduction_proxy/content/browser/content_lofi_decider.h
+++ b/components/data_reduction_proxy/content/browser/content_lofi_decider.h
@@ -31,6 +31,7 @@
   bool MaybeAddLoFiDirectiveToHeaders(
       const net::URLRequest& request,
       net::HttpRequestHeaders* headers) const override;
+  bool ShouldRecordLoFiUMA(const net::URLRequest& request) const override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ContentLoFiDecider);
diff --git a/components/data_reduction_proxy/content/browser/content_lofi_decider_unittest.cc b/components/data_reduction_proxy/content/browser/content_lofi_decider_unittest.cc
index cf1ffc4..a2c4341 100644
--- a/components/data_reduction_proxy/content/browser/content_lofi_decider_unittest.cc
+++ b/components/data_reduction_proxy/content/browser/content_lofi_decider_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/strings/string_util.h"
 #include "build/build_config.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h"
@@ -220,6 +221,10 @@
                                                tests[i].is_using_previews &&
                                                tests[i].is_main_frame,
                                            headers);
+    DataReductionProxyData* data = DataReductionProxyData::GetData(*request);
+    // |lofi_requested| should be set to false when Lo-Fi is enabled using
+    // flags.
+    EXPECT_FALSE(data->lofi_requested());
 
     // The Lo-Fi flag is "always-on" and Lo-Fi is being used. Lo-Fi header
     // should be added.
@@ -242,6 +247,10 @@
                      headers);
     VerifyLoFiPreviewHeader(false, headers);
     VerifyLoFiIgnorePreviewBlacklistHeader(false, headers);
+    data = DataReductionProxyData::GetData(*request);
+    // |lofi_requested| should be set to false when Lo-Fi is enabled using
+    // flags.
+    EXPECT_FALSE(data->lofi_requested());
 
     // The Lo-Fi flag is "slow-connections-only" and Lo-Fi is being used. Lo-Fi
     // header should be added.
@@ -254,6 +263,10 @@
                      headers);
     VerifyLoFiPreviewHeader(false, headers);
     VerifyLoFiIgnorePreviewBlacklistHeader(false, headers);
+    data = DataReductionProxyData::GetData(*request);
+    // |lofi_requested| should be set to false when Lo-Fi is enabled using
+    // flags.
+    EXPECT_FALSE(data->lofi_requested());
   }
 }
 
@@ -278,6 +291,8 @@
                      headers);
     VerifyLoFiPreviewHeader(false, headers);
     VerifyLoFiIgnorePreviewBlacklistHeader(false, headers);
+    DataReductionProxyData* data = DataReductionProxyData::GetData(*request);
+    EXPECT_EQ(tests[i].is_using_lofi, data->lofi_requested()) << i;
   }
 }
 
@@ -301,6 +316,8 @@
     VerifyLoFiHeader(false, headers);
     VerifyLoFiPreviewHeader(false, headers);
     VerifyLoFiIgnorePreviewBlacklistHeader(false, headers);
+    DataReductionProxyData* data = DataReductionProxyData::GetData(*request);
+    EXPECT_EQ(tests[i].is_using_lofi, data->lofi_requested()) << i;
   }
 }
 
@@ -327,6 +344,8 @@
     VerifyLoFiPreviewHeader(tests[i].is_using_lofi && tests[i].is_main_frame,
                             headers);
     VerifyLoFiIgnorePreviewBlacklistHeader(false, headers);
+    DataReductionProxyData* data = DataReductionProxyData::GetData(*request);
+    EXPECT_EQ(tests[i].is_using_lofi, data->lofi_requested()) << i;
   }
 }
 
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h
index cb7c9107..4e44d72 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h
@@ -30,7 +30,9 @@
     used_data_reduction_proxy_ = used_data_reduction_proxy;
   }
 
-  // Whether Lo-Fi was requested for this request or navigation.
+  // Whether Lo-Fi was requested for this request or navigation. True if the
+  // session is in Lo-Fi control or enabled group, and the network quality is
+  // slow.
   bool lofi_requested() const { return lofi_requested_; }
   void set_lofi_requested(bool lofi_requested) {
     lofi_requested_ = lofi_requested;
@@ -65,7 +67,9 @@
   // Whether the DataReductionProxy was used for this request or navigation.
   bool used_data_reduction_proxy_;
 
-  // Whether Lo-Fi was requested for this request or navigation.
+  // Whether Lo-Fi was requested for this request or navigation. True if the
+  // session is in Lo-Fi control or enabled group, and the network quality is
+  // slow.
   bool lofi_requested_;
 
   // The session key used for this request or navigation.
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc
index 2b89856..4e11f1b 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc
@@ -210,15 +210,16 @@
   if (data_reduction_proxy_io_data_ &&
       data_reduction_proxy_io_data_->lofi_decider()) {
     LoFiDecider* lofi_decider = data_reduction_proxy_io_data_->lofi_decider();
-    bool is_using_lofi_mode =
+    const bool is_using_lofi_mode =
         lofi_decider->MaybeAddLoFiDirectiveToHeaders(*request, headers);
 
     if ((request->load_flags() & net::LOAD_MAIN_FRAME)) {
       data_reduction_proxy_io_data_->SetLoFiModeActiveOnMainFrame(
           is_using_lofi_mode);
     }
+
     if (data)
-      data->set_lofi_requested(is_using_lofi_mode);
+      data->set_lofi_requested(lofi_decider->ShouldRecordLoFiUMA(*request));
   }
 
   if (data_reduction_proxy_request_options_) {
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
index 0c42547..8d7bd69 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
@@ -115,6 +115,10 @@
     return false;
   }
 
+  bool ShouldRecordLoFiUMA(const net::URLRequest& request) const override {
+    return should_request_lofi_resource_;
+  }
+
  private:
   bool should_request_lofi_resource_;
 };
@@ -189,6 +193,17 @@
     EXPECT_EQ(is_preview, lofi_ui_service_->is_preview());
   }
 
+  void VerifyDataReductionProxyData(const net::URLRequest& request,
+                                    bool data_reduction_proxy_used,
+                                    bool lofi_used) {
+    DataReductionProxyData* data = DataReductionProxyData::GetData(request);
+    if (!data_reduction_proxy_used) {
+      EXPECT_EQ(nullptr, data);
+    } else {
+      EXPECT_EQ(lofi_used, data->lofi_requested());
+    }
+  }
+
   // Each line in |response_headers| should end with "\r\n" and not '\0', and
   // the last line should have a second "\r\n".
   // An empty |response_headers| is allowed. It works by making this look like
@@ -362,6 +377,9 @@
                                                   proxy_retry_info, &headers);
       VerifyHeaders(tests[i].is_data_reduction_proxy, true, headers);
       VerifyWasLoFiModeActiveOnMainFrame(tests[i].is_data_reduction_proxy);
+      VerifyDataReductionProxyData(
+          *fake_request, tests[i].is_data_reduction_proxy,
+          config()->ShouldEnableLoFiMode(*fake_request.get()));
     }
 
     {
@@ -378,6 +396,8 @@
       // Not a mainframe request, WasLoFiModeActiveOnMainFrame should still be
       // true if the proxy is a Data Reduction Proxy.
       VerifyWasLoFiModeActiveOnMainFrame(tests[i].is_data_reduction_proxy);
+      VerifyDataReductionProxyData(*fake_request,
+                                   tests[i].is_data_reduction_proxy, false);
     }
 
     {
@@ -395,6 +415,8 @@
       // Not a mainframe request, WasLoFiModeActiveOnMainFrame should still be
       // true if the proxy is a Data Reduction Proxy.
       VerifyWasLoFiModeActiveOnMainFrame(tests[i].is_data_reduction_proxy);
+      VerifyDataReductionProxyData(*fake_request,
+                                   tests[i].is_data_reduction_proxy, true);
     }
 
     {
@@ -411,6 +433,8 @@
                                                   proxy_retry_info, &headers);
       VerifyHeaders(tests[i].is_data_reduction_proxy, false, headers);
       VerifyWasLoFiModeActiveOnMainFrame(false);
+      VerifyDataReductionProxyData(*fake_request,
+                                   tests[i].is_data_reduction_proxy, false);
     }
 
     {
@@ -427,6 +451,8 @@
       // Not a mainframe request, WasLoFiModeActiveOnMainFrame should still be
       // false.
       VerifyWasLoFiModeActiveOnMainFrame(false);
+      VerifyDataReductionProxyData(*fake_request,
+                                   tests[i].is_data_reduction_proxy, false);
     }
 
     {
@@ -443,6 +469,9 @@
                                                   proxy_retry_info, &headers);
       VerifyHeaders(tests[i].is_data_reduction_proxy, true, headers);
       VerifyWasLoFiModeActiveOnMainFrame(tests[i].is_data_reduction_proxy);
+      VerifyDataReductionProxyData(
+          *fake_request, tests[i].is_data_reduction_proxy,
+          config()->ShouldEnableLoFiMode(*fake_request.get()));
     }
   }
 }
diff --git a/components/data_reduction_proxy/core/common/lofi_decider.h b/components/data_reduction_proxy/core/common/lofi_decider.h
index 3f0db843..1a66aad4 100644
--- a/components/data_reduction_proxy/core/common/lofi_decider.h
+++ b/components/data_reduction_proxy/core/common/lofi_decider.h
@@ -32,6 +32,11 @@
   virtual bool MaybeAddLoFiDirectiveToHeaders(
       const net::URLRequest& request,
       net::HttpRequestHeaders* headers) const = 0;
+
+  // Returns true if the Lo-Fi specific UMA should be recorded. It is set to
+  // true if Lo-Fi is enabled for |request|, Chrome session is in Lo-Fi
+  // Enabled or Control field trial, and the network quality was slow.
+  virtual bool ShouldRecordLoFiUMA(const net::URLRequest& request) const = 0;
 };
 
 }  // namespace data_reduction_proxy
diff --git a/components/drive/job_scheduler_unittest.cc b/components/drive/job_scheduler_unittest.cc
index b5624fc..005e0bec 100644
--- a/components/drive/job_scheduler_unittest.cc
+++ b/components/drive/job_scheduler_unittest.cc
@@ -128,6 +128,9 @@
   bool upload_new_file_cancelable_;
 };
 
+const char kHello[] = "Hello";
+const size_t kHelloLen = sizeof(kHello) - 1;
+
 }  // namespace
 
 class JobSchedulerTest : public testing::Test {
@@ -928,13 +931,13 @@
 
   // Upload job.
   path = temp_dir.path().AppendASCII("new_file.txt");
-  ASSERT_TRUE(google_apis::test_util::WriteStringToFile(path, "Hello"));
+  ASSERT_TRUE(google_apis::test_util::WriteStringToFile(path, kHello));
   google_apis::DriveApiErrorCode upload_error =
       google_apis::DRIVE_OTHER_ERROR;
   std::unique_ptr<google_apis::FileResource> entry;
 
   scheduler_->UploadNewFile(
-      fake_drive_service_->GetRootResourceId(), std::string("Hello").size(),
+      fake_drive_service_->GetRootResourceId(), kHelloLen,
       base::FilePath::FromUTF8Unsafe("drive/new_file.txt"), path, "dummy title",
       "plain/plain", UploadNewFileOptions(), ClientContext(BACKGROUND),
       google_apis::test_util::CreateCopyResultCallback(&upload_error, &entry));
@@ -952,7 +955,7 @@
   base::ScopedTempDir temp_dir;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   base::FilePath upload_path = temp_dir.path().AppendASCII("new_file.txt");
-  ASSERT_TRUE(google_apis::test_util::WriteStringToFile(upload_path, "Hello"));
+  ASSERT_TRUE(google_apis::test_util::WriteStringToFile(upload_path, kHello));
 
   // To create a pending job for testing, set the mode to cellular connection
   // and issue BACKGROUND jobs.
@@ -963,7 +966,7 @@
   google_apis::DriveApiErrorCode error1 = google_apis::DRIVE_OTHER_ERROR;
   std::unique_ptr<google_apis::FileResource> entry;
   scheduler_->UploadNewFile(
-      fake_drive_service_->GetRootResourceId(), std::string("Hello").size(),
+      fake_drive_service_->GetRootResourceId(), kHelloLen,
       base::FilePath::FromUTF8Unsafe("dummy/path"), upload_path,
       "dummy title 1", "text/plain", UploadNewFileOptions(),
       ClientContext(BACKGROUND),
@@ -977,7 +980,7 @@
   // Start the second job.
   google_apis::DriveApiErrorCode error2 = google_apis::DRIVE_OTHER_ERROR;
   scheduler_->UploadNewFile(
-      fake_drive_service_->GetRootResourceId(), std::string("Hello").size(),
+      fake_drive_service_->GetRootResourceId(), kHelloLen,
       base::FilePath::FromUTF8Unsafe("dummy/path"), upload_path,
       "dummy title 2", "text/plain", UploadNewFileOptions(),
       ClientContext(BACKGROUND),
@@ -1000,14 +1003,14 @@
   base::ScopedTempDir temp_dir;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   base::FilePath upload_path = temp_dir.path().AppendASCII("new_file.txt");
-  ASSERT_TRUE(google_apis::test_util::WriteStringToFile(upload_path, "Hello"));
+  ASSERT_TRUE(google_apis::test_util::WriteStringToFile(upload_path, kHello));
 
   // Run as a cancelable task.
   fake_drive_service_->set_upload_new_file_cancelable(true);
   google_apis::DriveApiErrorCode error1 = google_apis::DRIVE_OTHER_ERROR;
   std::unique_ptr<google_apis::FileResource> entry;
   scheduler_->UploadNewFile(
-      fake_drive_service_->GetRootResourceId(), std::string("Hello").size(),
+      fake_drive_service_->GetRootResourceId(), kHelloLen,
       base::FilePath::FromUTF8Unsafe("dummy/path"), upload_path,
       "dummy title 1", "text/plain", UploadNewFileOptions(),
       ClientContext(USER_INITIATED),
@@ -1022,7 +1025,7 @@
   fake_drive_service_->set_upload_new_file_cancelable(false);
   google_apis::DriveApiErrorCode error2 = google_apis::DRIVE_OTHER_ERROR;
   scheduler_->UploadNewFile(
-      fake_drive_service_->GetRootResourceId(), std::string("Hello").size(),
+      fake_drive_service_->GetRootResourceId(), kHelloLen,
       base::FilePath::FromUTF8Unsafe("dummy/path"), upload_path,
       "dummy title 2", "text/plain", UploadNewFileOptions(),
       ClientContext(USER_INITIATED),
diff --git a/components/exo/surface.cc b/components/exo/surface.cc
index 0822a3d..bd1167f3 100644
--- a/components/exo/surface.cc
+++ b/components/exo/surface.cc
@@ -145,7 +145,7 @@
                      const cc::SurfaceSequence& sequence) {
   std::vector<uint32_t> sequences;
   sequences.push_back(sequence.sequence);
-  manager->DidSatisfySequences(sequence.id_namespace, &sequences);
+  manager->DidSatisfySequences(sequence.client_id, &sequences);
 }
 
 void RequireCallback(cc::SurfaceManager* manager,
@@ -610,7 +610,7 @@
   SetSurfaceLayerContents(new_layer);
 }
 
-void Surface::WillDraw(cc::SurfaceId id) {
+void Surface::WillDraw(const cc::SurfaceId& id) {
   while (!active_frame_callbacks_.empty()) {
     active_frame_callbacks_.front().Run(base::TimeTicks::Now());
     active_frame_callbacks_.pop_front();
diff --git a/components/exo/surface.h b/components/exo/surface.h
index 2db6298..9a36ab7 100644
--- a/components/exo/surface.h
+++ b/components/exo/surface.h
@@ -102,7 +102,7 @@
 
   aura::Window* window() { return window_.get(); }
 
-  cc::SurfaceId surface_id() const { return surface_id_; }
+  const cc::SurfaceId& surface_id() const { return surface_id_; }
 
   // Set a buffer as the content of this surface. A buffer can only be attached
   // to one surface at a time.
@@ -215,7 +215,7 @@
   // Overridden from ui::ContextFactoryObserver.
   void OnLostResources() override;
 
-  void WillDraw(cc::SurfaceId surface_id);
+  void WillDraw(const cc::SurfaceId& surface_id);
 
   // Check whether this Surface and its children need to create new cc::Surface
   // IDs for their contents next time they get new buffer contents.
diff --git a/components/memory_pressure/direct_memory_pressure_calculator_linux.cc b/components/memory_pressure/direct_memory_pressure_calculator_linux.cc
index f1dbc01f..cb548ad 100644
--- a/components/memory_pressure/direct_memory_pressure_calculator_linux.cc
+++ b/components/memory_pressure/direct_memory_pressure_calculator_linux.cc
@@ -13,6 +13,14 @@
 
 static const int kKiBperMiB = 1024;
 
+int GetAvailableSystemMemoryMiB(const base::SystemMemoryInfoKB* mem_info) {
+  // How much system memory is actively available for use right now, in MBs.
+  return (mem_info->available
+              ? mem_info->available
+              : (mem_info->free + mem_info->buffers + mem_info->cached)) /
+         kKiBperMiB;
+}
+
 }  // namespace
 
 // Thresholds at which we consider the system being under moderate/critical
@@ -39,9 +47,7 @@
   base::SystemMemoryInfoKB mem_info = {};
   if (!GetSystemMemoryInfo(&mem_info))
     return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE;
-
-  // How much system memory is actively available for use right now, in MBs.
-  int phys_free = mem_info.free / kKiBperMiB;
+  int phys_free = GetAvailableSystemMemoryMiB(&mem_info);
 
   // Determine if the physical memory is under critical memory pressure.
   if (phys_free <= critical_threshold_mb_)
diff --git a/components/metrics/file_metrics_provider.cc b/components/metrics/file_metrics_provider.cc
index 2d331d6..14d853a 100644
--- a/components/metrics/file_metrics_provider.cc
+++ b/components/metrics/file_metrics_provider.cc
@@ -372,7 +372,7 @@
     std::unique_ptr<base::HistogramBase> histogram = histogram_iter.GetNext();
     if (!histogram)
       break;
-    snapshot_manager->PrepareFinalDeltaTakingOwnership(std::move(histogram));
+    snapshot_manager->PrepareFinalDelta(histogram.get());
     ++histogram_count;
   }
 
diff --git a/components/metrics/file_metrics_provider_unittest.cc b/components/metrics/file_metrics_provider_unittest.cc
index d1d340b..19e33a4 100644
--- a/components/metrics/file_metrics_provider_unittest.cc
+++ b/components/metrics/file_metrics_provider_unittest.cc
@@ -411,9 +411,7 @@
   {
     HistogramFlattenerDeltaRecorder flattener;
     base::HistogramSnapshotManager snapshot_manager(&flattener);
-    snapshot_manager.StartDeltas();
     RecordInitialHistogramSnapshots(&snapshot_manager);
-    snapshot_manager.FinishDeltas();
     EXPECT_EQ(2U, flattener.GetRecordedDeltaHistogramNames().size());
   }
   EXPECT_TRUE(base::PathExists(metrics_file()));
diff --git a/components/metrics/metrics_service.cc b/components/metrics/metrics_service.cc
index a14b047..cad1598 100644
--- a/components/metrics/metrics_service.cc
+++ b/components/metrics/metrics_service.cc
@@ -1125,28 +1125,24 @@
   for (MetricsProvider* provider : metrics_providers_)
     provider->MergeHistogramDeltas();
 
-  histogram_snapshot_manager_.StartDeltas();
   // "true" to the begin() call indicates that StatisticsRecorder should include
   // histograms held in persistent storage.
-  histogram_snapshot_manager_.PrepareDeltasWithoutStartFinish(
+  histogram_snapshot_manager_.PrepareDeltas(
       base::StatisticsRecorder::begin(true), base::StatisticsRecorder::end(),
       base::Histogram::kNoFlags, base::Histogram::kUmaTargetedHistogramFlag);
   for (MetricsProvider* provider : metrics_providers_)
     provider->RecordHistogramSnapshots(&histogram_snapshot_manager_);
-  histogram_snapshot_manager_.FinishDeltas();
 }
 
 void MetricsService::RecordCurrentStabilityHistograms() {
   DCHECK(log_manager_.current_log());
-  histogram_snapshot_manager_.StartDeltas();
   // "true" indicates that StatisticsRecorder should include histograms in
   // persistent storage.
-  histogram_snapshot_manager_.PrepareDeltasWithoutStartFinish(
+  histogram_snapshot_manager_.PrepareDeltas(
       base::StatisticsRecorder::begin(true), base::StatisticsRecorder::end(),
       base::Histogram::kNoFlags, base::Histogram::kUmaStabilityHistogramFlag);
   for (MetricsProvider* provider : metrics_providers_)
     provider->RecordInitialHistogramSnapshots(&histogram_snapshot_manager_);
-  histogram_snapshot_manager_.FinishDeltas();
 }
 
 void MetricsService::LogCleanShutdown() {
diff --git a/components/nacl/renderer/ppb_nacl_private_impl.cc b/components/nacl/renderer/ppb_nacl_private_impl.cc
index 4daa4c7..db128c40 100644
--- a/components/nacl/renderer/ppb_nacl_private_impl.cc
+++ b/components/nacl/renderer/ppb_nacl_private_impl.cc
@@ -348,7 +348,6 @@
 blink::WebURLRequest CreateWebURLRequest(const blink::WebDocument& document,
                                          const GURL& gurl) {
   blink::WebURLRequest request;
-  request.initialize();
   request.setURL(gurl);
   request.setFirstPartyForCookies(document.firstPartyForCookies());
   return request;
diff --git a/components/ntp_snippets/content_suggestions_category_status.h b/components/ntp_snippets/content_suggestions_category_status.h
index d3b5ba4..16b65af0 100644
--- a/components/ntp_snippets/content_suggestions_category_status.h
+++ b/components/ntp_snippets/content_suggestions_category_status.h
@@ -11,6 +11,10 @@
 // On Android builds, a Java counterpart will be generated for this enum.
 // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.ntp.snippets
 enum class ContentSuggestionsCategoryStatus {
+  // The provider is still initializing and it is not yet determined whether
+  // content suggestions will be available or not.
+  INITIALIZING,
+
   // Content suggestions are available (though the list of available suggestions
   // may be empty simply because there are no reasonable suggestions to be made
   // at the moment).
@@ -36,9 +40,10 @@
   PASSPHRASE_ENCRYPTION_ENABLED,
   // Content suggestions are not available because history sync is disabled.
   HISTORY_SYNC_DISABLED,
-  // Content suggestions are not available because the history sync service is
-  // not yet completely initialized and its status is unknown.
-  HISTORY_SYNC_STATE_UNKNOWN
+
+  // Content suggestions are not available because an error occured when loading
+  // or updating them.
+  LOADING_ERROR
 };
 
 // Determines whether the given status is one of the AVAILABLE statuses.
diff --git a/components/ntp_snippets/content_suggestions_provider.cc b/components/ntp_snippets/content_suggestions_provider.cc
index 696a3813..e4565e5 100644
--- a/components/ntp_snippets/content_suggestions_provider.cc
+++ b/components/ntp_snippets/content_suggestions_provider.cc
@@ -23,7 +23,8 @@
 std::string ContentSuggestionsProvider::MakeUniqueID(
     ContentSuggestionsCategory category,
     const std::string& within_category_id) {
-  return base::StringPrintf(kCombinedIDFormat, int(category),
+  return base::StringPrintf(kCombinedIDFormat,
+                            static_cast<int>(category),
                             within_category_id.c_str());
 }
 
diff --git a/components/ntp_snippets/content_suggestions_provider.h b/components/ntp_snippets/content_suggestions_provider.h
index 93872f58..8d0b5dd 100644
--- a/components/ntp_snippets/content_suggestions_provider.h
+++ b/components/ntp_snippets/content_suggestions_provider.h
@@ -62,7 +62,8 @@
   };
 
   // Sets an observer which is notified about changes to the available
-  // suggestions, or removes it by passing a nullptr.
+  // suggestions, or removes it by passing a nullptr. The provider does not take
+  // ownership of the observer and the observer must outlive this provider.
   virtual void SetObserver(Observer* observer) = 0;
 
   // Determines the status of the given |category|, see
@@ -78,6 +79,8 @@
 
   // Fetches the image for the suggestion with the given ID and returns it
   // through the callback. This fetch may occur locally or from the internet.
+  // If that suggestion doesn't exist, doesn't have an image or if the fetch
+  // fails, the callback gets a null image.
   virtual void FetchSuggestionImage(const std::string& suggestion_id,
                                     const ImageFetchedCallback& callback) = 0;
 
diff --git a/components/ntp_snippets/content_suggestions_service.cc b/components/ntp_snippets/content_suggestions_service.cc
index 5b86d95..3ce179f4 100644
--- a/components/ntp_snippets/content_suggestions_service.cc
+++ b/components/ntp_snippets/content_suggestions_service.cc
@@ -61,7 +61,7 @@
   ContentSuggestionsCategory category = id_category_map_[suggestion_id];
   if (!providers_.count(category)) {
     LOG(WARNING) << "Requested image for suggestion " << suggestion_id
-                 << " for unavailable category " << int(category);
+                 << " for unavailable category " << static_cast<int>(category);
     callback.Run(suggestion_id, gfx::Image());
     return;
   }
@@ -92,7 +92,7 @@
   ContentSuggestionsCategory category = id_category_map_[suggestion_id];
   if (!providers_.count(category)) {
     LOG(WARNING) << "Discarded suggestion " << suggestion_id
-                 << " for unavailable category " << int(category);
+                 << " for unavailable category " << static_cast<int>(category);
     return;
   }
   providers_[category]->DiscardSuggestion(suggestion_id);
diff --git a/components/ntp_snippets/ntp_snippets_service.cc b/components/ntp_snippets/ntp_snippets_service.cc
index 51efc2a..3ca1876 100644
--- a/components/ntp_snippets/ntp_snippets_service.cc
+++ b/components/ntp_snippets/ntp_snippets_service.cc
@@ -193,10 +193,13 @@
     std::unique_ptr<ImageDecoder> image_decoder,
     std::unique_ptr<NTPSnippetsDatabase> database,
     std::unique_ptr<NTPSnippetsStatusService> status_service)
-    : state_(State::NOT_INITED),
+    : ContentSuggestionsProvider({ContentSuggestionsCategory::ARTICLES}),
+      state_(State::NOT_INITED),
+      category_status_(ContentSuggestionsCategoryStatus::INITIALIZING),
       pref_service_(pref_service),
       suggestions_service_(suggestions_service),
       application_language_code_(application_language_code),
+      observer_(nullptr),
       scheduler_(scheduler),
       snippets_fetcher_(std::move(snippets_fetcher)),
       image_fetcher_(std::move(image_fetcher)),
@@ -204,9 +207,15 @@
       database_(std::move(database)),
       snippets_status_service_(std::move(status_service)),
       fetch_after_load_(false) {
-  if (!enabled || database_->IsErrorState()) {
-    // Don't even bother loading the database.
-    EnterState(State::SHUT_DOWN);
+  // In some cases, don't even bother loading the database.
+  if (!enabled) {
+    EnterState(State::SHUT_DOWN,
+               ContentSuggestionsCategoryStatus::CATEGORY_EXPLICITLY_DISABLED);
+    return;
+  }
+  if (database_->IsErrorState()) {
+    EnterState(State::SHUT_DOWN,
+               ContentSuggestionsCategoryStatus::LOADING_ERROR);
     return;
   }
 
@@ -230,7 +239,7 @@
 
 // Inherited from KeyedService.
 void NTPSnippetsService::Shutdown() {
-  EnterState(State::SHUT_DOWN);
+  EnterState(State::SHUT_DOWN, ContentSuggestionsCategoryStatus::NOT_PROVIDED);
 }
 
 void NTPSnippetsService::FetchSnippets() {
@@ -263,16 +272,16 @@
   }
 }
 
-void NTPSnippetsService::FetchSnippetImage(
-    const std::string& snippet_id,
+void NTPSnippetsService::FetchSuggestionImage(
+    const std::string& suggestion_id,
     const ImageFetchedCallback& callback) {
   database_->LoadImage(
-      snippet_id,
+      suggestion_id,
       base::Bind(&NTPSnippetsService::OnSnippetImageFetchedFromDatabase,
-                 base::Unretained(this), snippet_id, callback));
+                 base::Unretained(this), suggestion_id, callback));
 }
 
-void NTPSnippetsService::ClearSnippets() {
+void NTPSnippetsService::ClearCachedSuggestionsForDebugging() {
   if (!initialized())
     return;
 
@@ -282,8 +291,7 @@
   database_->DeleteSnippets(snippets_);
   snippets_.clear();
 
-  FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_,
-                    NTPSnippetsServiceLoaded());
+  NotifyNewSuggestions();
 }
 
 std::set<std::string> NTPSnippetsService::GetSuggestionsHosts() const {
@@ -296,17 +304,17 @@
       suggestions_service_->GetSuggestionsDataFromCache());
 }
 
-bool NTPSnippetsService::DiscardSnippet(const std::string& snippet_id) {
+void NTPSnippetsService::DiscardSuggestion(const std::string& suggestion_id) {
   if (!ready())
-    return false;
+    return;
 
-  auto it =
-      std::find_if(snippets_.begin(), snippets_.end(),
-                   [&snippet_id](const std::unique_ptr<NTPSnippet>& snippet) {
-                     return snippet->id() == snippet_id;
-                   });
+  auto it = std::find_if(
+      snippets_.begin(), snippets_.end(),
+      [&suggestion_id](const std::unique_ptr<NTPSnippet>& snippet) {
+        return snippet->id() == suggestion_id;
+      });
   if (it == snippets_.end())
-    return false;
+    return;
 
   (*it)->set_discarded(true);
 
@@ -316,12 +324,10 @@
   discarded_snippets_.push_back(std::move(*it));
   snippets_.erase(it);
 
-  FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_,
-                    NTPSnippetsServiceLoaded());
-  return true;
+  NotifyNewSuggestions();
 }
 
-void NTPSnippetsService::ClearDiscardedSnippets() {
+void NTPSnippetsService::ClearDiscardedSuggestionsForDebugging() {
   if (!initialized())
     return;
 
@@ -332,6 +338,16 @@
   discarded_snippets_.clear();
 }
 
+void NTPSnippetsService::SetObserver(Observer* observer) {
+  observer_ = observer;
+}
+
+ContentSuggestionsCategoryStatus NTPSnippetsService::GetCategoryStatus(
+    ContentSuggestionsCategory category) {
+  DCHECK_EQ(ContentSuggestionsCategory::ARTICLES, category);
+  return category_status_;
+}
+
 void NTPSnippetsService::AddObserver(NTPSnippetsServiceObserver* observer) {
   observers_.AddObserver(observer);
 }
@@ -390,7 +406,7 @@
 }
 
 void NTPSnippetsService::OnDatabaseError() {
-  EnterState(State::SHUT_DOWN);
+  EnterState(State::SHUT_DOWN, ContentSuggestionsCategoryStatus::LOADING_ERROR);
 }
 
 void NTPSnippetsService::OnSuggestionsChanged(
@@ -416,8 +432,7 @@
 
   StoreSnippetHostsToPrefs(hosts);
 
-  FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_,
-                    NTPSnippetsServiceLoaded());
+  NotifyNewSuggestions();
 
   FetchSnippetsFromHosts(hosts);
 }
@@ -454,8 +469,7 @@
                          discarded_snippets_.size());
   }
 
-  FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_,
-                    NTPSnippetsServiceLoaded());
+  NotifyNewSuggestions();
 }
 
 void NTPSnippetsService::MergeSnippets(NTPSnippet::PtrVector new_snippets) {
@@ -647,8 +661,8 @@
 }
 
 void NTPSnippetsService::EnterStateDisabled() {
-  ClearSnippets();
-  ClearDiscardedSnippets();
+  ClearCachedSuggestionsForDebugging();
+  ClearDiscardedSuggestionsForDebugging();
 
   expiry_timer_.Stop();
   suggestions_service_subscription_.reset();
@@ -679,8 +693,7 @@
   snippets_status_service_->Init(base::Bind(
       &NTPSnippetsService::UpdateStateForStatus, base::Unretained(this)));
 
-  FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_,
-                    NTPSnippetsServiceLoaded());
+  NotifyNewSuggestions();
 }
 
 void NTPSnippetsService::UpdateStateForStatus(DisabledReason disabled_reason) {
@@ -688,9 +701,11 @@
                     NTPSnippetsServiceDisabledReasonChanged(disabled_reason));
 
   State new_state;
+  ContentSuggestionsCategoryStatus new_status;
   switch (disabled_reason) {
     case DisabledReason::NONE:
       new_state = State::READY;
+      new_status = ContentSuggestionsCategoryStatus::AVAILABLE;
       break;
 
     case DisabledReason::HISTORY_SYNC_STATE_UNKNOWN:
@@ -700,27 +715,54 @@
       DVLOG(1) << "Sync configuration incomplete, continuing based on the "
                   "current state.";
       new_state = state_;
+      new_status = ContentSuggestionsCategoryStatus::INITIALIZING;
       break;
 
     case DisabledReason::EXPLICITLY_DISABLED:
+      new_state = State::DISABLED;
+      new_status =
+          ContentSuggestionsCategoryStatus::CATEGORY_EXPLICITLY_DISABLED;
+      break;
+
     case DisabledReason::SIGNED_OUT:
+      new_state = State::DISABLED;
+      new_status = ContentSuggestionsCategoryStatus::SIGNED_OUT;
+      break;
+
     case DisabledReason::SYNC_DISABLED:
+      new_state = State::DISABLED;
+      new_status = ContentSuggestionsCategoryStatus::SYNC_DISABLED;
+      break;
+
     case DisabledReason::PASSPHRASE_ENCRYPTION_ENABLED:
+      new_state = State::DISABLED;
+      new_status =
+          ContentSuggestionsCategoryStatus::PASSPHRASE_ENCRYPTION_ENABLED;
+      break;
+
     case DisabledReason::HISTORY_SYNC_DISABLED:
       new_state = State::DISABLED;
+      new_status = ContentSuggestionsCategoryStatus::HISTORY_SYNC_DISABLED;
       break;
 
     default:
       // All cases should be handled by the above switch
       NOTREACHED();
       new_state = State::DISABLED;
+      new_status = ContentSuggestionsCategoryStatus::LOADING_ERROR;
       break;
   }
 
-  EnterState(new_state);
+  EnterState(new_state, new_status);
 }
 
-void NTPSnippetsService::EnterState(State state) {
+void NTPSnippetsService::EnterState(State state,
+                                    ContentSuggestionsCategoryStatus status) {
+  if (status != category_status_) {
+    category_status_ = status;
+    NotifyCategoryStatusChanged();
+  }
+
   if (state == state_)
     return;
 
@@ -757,4 +799,38 @@
   }
 }
 
+void NTPSnippetsService::NotifyNewSuggestions() {
+  // TODO(pke): Remove this as soon as this becomes a pure provider.
+  FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_,
+                    NTPSnippetsServiceLoaded());
+
+  if (!observer_)
+    return;
+
+  std::vector<ContentSuggestion> result;
+  for (const std::unique_ptr<NTPSnippet>& snippet : snippets_) {
+    if (!snippet->is_complete())
+      continue;
+    ContentSuggestion suggestion(
+        MakeUniqueID(ContentSuggestionsCategory::ARTICLES, snippet->id()),
+        snippet->best_source().url);
+    suggestion.set_amp_url(snippet->best_source().amp_url);
+    suggestion.set_title(snippet->title());
+    suggestion.set_snippet_text(snippet->snippet());
+    suggestion.set_publish_date(snippet->publish_date());
+    suggestion.set_publisher_name(snippet->best_source().publisher_name);
+    suggestion.set_score(snippet->score());
+    result.emplace_back(std::move(suggestion));
+  }
+  observer_->OnNewSuggestions(ContentSuggestionsCategory::ARTICLES,
+                              std::move(result));
+}
+
+void NTPSnippetsService::NotifyCategoryStatusChanged() {
+  if (observer_) {
+    observer_->OnCategoryStatusChanged(ContentSuggestionsCategory::ARTICLES,
+                                       category_status_);
+  }
+}
+
 }  // namespace ntp_snippets
diff --git a/components/ntp_snippets/ntp_snippets_service.h b/components/ntp_snippets/ntp_snippets_service.h
index 1482fb9..6e13c3c 100644
--- a/components/ntp_snippets/ntp_snippets_service.h
+++ b/components/ntp_snippets/ntp_snippets_service.h
@@ -19,6 +19,10 @@
 #include "base/timer/timer.h"
 #include "components/image_fetcher/image_fetcher_delegate.h"
 #include "components/keyed_service/core/keyed_service.h"
+#include "components/ntp_snippets/content_suggestion.h"
+#include "components/ntp_snippets/content_suggestions_category.h"
+#include "components/ntp_snippets/content_suggestions_category_status.h"
+#include "components/ntp_snippets/content_suggestions_provider.h"
 #include "components/ntp_snippets/ntp_snippet.h"
 #include "components/ntp_snippets/ntp_snippets_fetcher.h"
 #include "components/ntp_snippets/ntp_snippets_scheduler.h"
@@ -58,11 +62,14 @@
 class NTPSnippetsServiceObserver;
 
 // Stores and vends fresh content data for the NTP.
+// TODO(pke): Rename this service to ArticleSuggestionsService and move to
+// a subdirectory.
 class NTPSnippetsService : public KeyedService,
-                           public image_fetcher::ImageFetcherDelegate {
+                           public image_fetcher::ImageFetcherDelegate,
+                           public ContentSuggestionsProvider {
  public:
   using ImageFetchedCallback =
-      base::Callback<void(const std::string& snippet_id, const gfx::Image&)>;
+      base::Callback<void(const std::string& suggestion_id, const gfx::Image&)>;
 
   // |application_language_code| should be a ISO 639-1 compliant string, e.g.
   // 'en' or 'en-US'. Note that this code should only specify the language, not
@@ -126,21 +133,17 @@
   // the schedule depends on the time of day.
   void RescheduleFetching();
 
-  // Fetches the image for the snippet with the given |snippet_id| and runs the
-  // |callback|. If that snippet doesn't exist or the fetch fails, the callback
-  // gets a null image.
-  void FetchSnippetImage(const std::string& snippet_id,
-                         const ImageFetchedCallback& callback);
-
-  // Deletes all currently stored snippets.
-  void ClearSnippets();
-
-  // Discards the snippet with the given |snippet_id|, if it exists. Returns
-  // true iff a snippet was discarded.
-  bool DiscardSnippet(const std::string& snippet_id);
-
-  // Clears the lists of snippets previously discarded by the user.
-  void ClearDiscardedSnippets();
+  // ContentSuggestionsProvider implementation
+  // TODO(pke): At some point reorder the implementations in the .cc file
+  // accordingly.
+  void SetObserver(Observer* observer) override;
+  ContentSuggestionsCategoryStatus GetCategoryStatus(
+      ContentSuggestionsCategory category) override;
+  void DiscardSuggestion(const std::string& suggestion_id) override;
+  void FetchSuggestionImage(const std::string& suggestion_id,
+                            const ImageFetchedCallback& callback) override;
+  void ClearCachedSuggestionsForDebugging() override;
+  void ClearDiscardedSuggestionsForDebugging() override;
 
   // Returns the lists of suggestion hosts the snippets are restricted to.
   std::set<std::string> GetSuggestionsHosts() const;
@@ -155,6 +158,9 @@
  private:
   FRIEND_TEST_ALL_PREFIXES(NTPSnippetsServiceTest, HistorySyncStateChanges);
 
+  // TODO(pke): As soon as the DisabledReason is replaced with the new status,
+  // also remove the old State enum and replace it with
+  // ContentSuggestionsCategoryStatus and a similar status diagram.
   // Possible state transitions:
   //  +------- NOT_INITED ------+
   //  |        /       \        |
@@ -238,8 +244,9 @@
   void UpdateStateForStatus(DisabledReason disabled_reason);
 
   // Verifies state transitions (see |State|'s documentation) and applies them.
-  // Does nothing if called with the current state.
-  void EnterState(State state);
+  // Also updates the provider status. Does nothing except updating the provider
+  // status if called with the current state.
+  void EnterState(State state, ContentSuggestionsCategoryStatus status);
 
   // Enables the service and triggers a fetch if required. Do not call directly,
   // use |EnterState| instead.
@@ -252,8 +259,18 @@
   // directly, use |EnterState| instead.
   void EnterStateShutdown();
 
+  // Converts the cached snippets to article content suggestions and notifies
+  // the observers.
+  void NotifyNewSuggestions();
+
+  // Notifies the content suggestions observer about a change in the
+  // |category_status_|.
+  void NotifyCategoryStatusChanged();
+
   State state_;
 
+  ContentSuggestionsCategoryStatus category_status_;
+
   PrefService* pref_service_;
 
   suggestions::SuggestionsService* suggestions_service_;
@@ -269,8 +286,12 @@
   const std::string application_language_code_;
 
   // The observers.
+  // TODO(pke): This is an old kind of observers that will be removed.
   base::ObserverList<NTPSnippetsServiceObserver> observers_;
 
+  // The observer to deliver data to.
+  Observer* observer_;
+
   // Scheduler for fetching snippets. Not owned.
   NTPSnippetsScheduler* scheduler_;
 
@@ -303,6 +324,8 @@
   DISALLOW_COPY_AND_ASSIGN(NTPSnippetsService);
 };
 
+// TODO(pke): Remove this when snippets internals don't access this service
+// directly anymore.
 class NTPSnippetsServiceObserver {
  public:
   // Sent every time the service loads a new set of data.
diff --git a/components/ntp_snippets/ntp_snippets_service_unittest.cc b/components/ntp_snippets/ntp_snippets_service_unittest.cc
index 9ba767d..9a7dad0 100644
--- a/components/ntp_snippets/ntp_snippets_service_unittest.cc
+++ b/components/ntp_snippets/ntp_snippets_service_unittest.cc
@@ -414,7 +414,7 @@
   LoadFromJSONString(json_str);
   EXPECT_THAT(service()->snippets(), SizeIs(1));
 
-  service()->ClearSnippets();
+  service()->ClearCachedSuggestionsForDebugging();
   EXPECT_THAT(service()->snippets(), IsEmpty());
 }
 
@@ -499,11 +499,11 @@
   ASSERT_THAT(service()->snippets(), SizeIs(1));
 
   // Discarding a non-existent snippet shouldn't do anything.
-  EXPECT_FALSE(service()->DiscardSnippet("http://othersite.com"));
+  service()->DiscardSuggestion("http://othersite.com");
   EXPECT_THAT(service()->snippets(), SizeIs(1));
 
   // Discard the snippet.
-  EXPECT_TRUE(service()->DiscardSnippet(kSnippetUrl));
+  service()->DiscardSuggestion(kSnippetUrl);
   EXPECT_THAT(service()->snippets(), IsEmpty());
 
   // Make sure that fetching the same snippet again does not re-add it.
@@ -517,7 +517,7 @@
   EXPECT_THAT(service()->snippets(), IsEmpty());
 
   // The snippet can be added again after clearing discarded snippets.
-  service()->ClearDiscardedSnippets();
+  service()->ClearDiscardedSuggestionsForDebugging();
   EXPECT_THAT(service()->snippets(), IsEmpty());
   LoadFromJSONString(json_str);
   EXPECT_THAT(service()->snippets(), SizeIs(1));
@@ -526,8 +526,7 @@
 TEST_F(NTPSnippetsServiceTest, GetDiscarded) {
   LoadFromJSONString(GetTestJson({GetSnippet()}));
 
-  // For the test, we need the snippet to get discarded.
-  ASSERT_TRUE(service()->DiscardSnippet(kSnippetUrl));
+  service()->DiscardSuggestion(kSnippetUrl);
   const NTPSnippet::PtrVector& snippets = service()->discarded_snippets();
   EXPECT_EQ(1u, snippets.size());
   for (auto& snippet : snippets) {
@@ -535,7 +534,7 @@
   }
 
   // There should be no discarded snippet after clearing the list.
-  service()->ClearDiscardedSnippets();
+  service()->ClearDiscardedSuggestionsForDebugging();
   EXPECT_EQ(0u, service()->discarded_snippets().size());
 }
 
@@ -648,7 +647,7 @@
     EXPECT_EQ(snippet.best_source().amp_url, GURL());
   }
 
-  service()->ClearSnippets();
+  service()->ClearCachedSuggestionsForDebugging();
   // Set Source 1 to have no AMP url, and Source 2 to have no publisher name
   // Source 1 should win in this case since we prefer publisher name to AMP url
   source_urls.clear();
@@ -674,7 +673,7 @@
     EXPECT_EQ(snippet.best_source().amp_url, GURL());
   }
 
-  service()->ClearSnippets();
+  service()->ClearCachedSuggestionsForDebugging();
   // Set source 1 to have no AMP url and no source, and source 2 to only have
   // amp url. There should be no snippets since we only add sources we consider
   // complete
@@ -721,7 +720,7 @@
   }
 
   // Test 2 complete sources, we should choose the first complete source
-  service()->ClearSnippets();
+  service()->ClearCachedSuggestionsForDebugging();
   source_urls.clear();
   source_urls.push_back(std::string("http://source1.com"));
   source_urls.push_back(std::string("http://source2.com"));
@@ -749,7 +748,7 @@
   }
 
   // Test 3 complete sources, we should choose the first complete source
-  service()->ClearSnippets();
+  service()->ClearCachedSuggestionsForDebugging();
   source_urls.clear();
   source_urls.push_back(std::string("http://source1.com"));
   source_urls.push_back(std::string("http://source2.com"));
@@ -813,7 +812,7 @@
       IsEmpty());
   // Discarding a snippet should decrease the list size. This will only be
   // logged after the next fetch.
-  EXPECT_TRUE(service()->DiscardSnippet(kSnippetUrl));
+  service()->DiscardSuggestion(kSnippetUrl);
   LoadFromJSONString(GetTestJson({GetSnippet()}));
   EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticles"),
               ElementsAre(base::Bucket(/*min=*/0, /*count=*/3),
@@ -852,7 +851,7 @@
       source_urls[0], creation, expiry, source_urls, publishers, amp_urls)}));
   ASSERT_THAT(service()->snippets(), SizeIs(1));
   // Discard the snippet via the mashable source corpus ID.
-  EXPECT_TRUE(service()->DiscardSnippet(source_urls[0]));
+  service()->DiscardSuggestion(source_urls[0]);
   EXPECT_THAT(service()->snippets(), IsEmpty());
 
   // The same article from the AOL domain should now be detected as discarded.
diff --git a/components/ntp_tiles.gypi b/components/ntp_tiles.gypi
index 1e6de87..232a4ad 100644
--- a/components/ntp_tiles.gypi
+++ b/components/ntp_tiles.gypi
@@ -49,7 +49,7 @@
           'target_name': 'ntp_tiles_enums_java',
           'type': 'none',
           'variables': {
-            'source_file': 'ntp_tiles/most_visited_sites.cc',
+            'source_file': 'ntp_tiles/most_visited_sites.h',
           },
           'includes': [
             '../build/android/java_cpp_enum.gypi'
diff --git a/components/ntp_tiles/BUILD.gn b/components/ntp_tiles/BUILD.gn
index 7422d6d..a948cd1 100644
--- a/components/ntp_tiles/BUILD.gn
+++ b/components/ntp_tiles/BUILD.gn
@@ -54,7 +54,7 @@
 if (is_android) {
   java_cpp_enum("ntp_tiles_enums_java") {
     sources = [
-      "most_visited_sites.cc",
+      "most_visited_sites.h",
     ]
   }
 }
diff --git a/components/ntp_tiles/most_visited_sites.cc b/components/ntp_tiles/most_visited_sites.cc
index 3da5f03a..3a4cba7 100644
--- a/components/ntp_tiles/most_visited_sites.cc
+++ b/components/ntp_tiles/most_visited_sites.cc
@@ -47,25 +47,6 @@
 const base::Feature kDisplaySuggestionsServiceTiles{
     "DisplaySuggestionsServiceTiles", base::FEATURE_ENABLED_BY_DEFAULT};
 
-// The visual type of a most visited tile.
-//
-// These values must stay in sync with the MostVisitedTileType enum
-// in histograms.xml.
-//
-// A Java counterpart will be generated for this enum.
-// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.ntp
-enum MostVisitedTileType {
-    // The icon or thumbnail hasn't loaded yet.
-    NONE,
-    // The item displays a site's actual favicon or touch icon.
-    ICON_REAL,
-    // The item displays a color derived from the site's favicon or touch icon.
-    ICON_COLOR,
-    // The item displays a default gray box in place of an icon.
-    ICON_DEFAULT,
-    NUM_TILE_TYPES,
-};
-
 // Log an event for a given |histogram| at a given element |position|. This
 // routine exists because regular histogram macros are cached thus can't be used
 // if the name of the histogram will change at a given call site.
@@ -121,9 +102,8 @@
   return url1.host() == url2.host() && url1.path() == url2.path();
 }
 
-std::string GetSourceHistogramName(
-        const MostVisitedSites::Suggestion& suggestion) {
-  switch (suggestion.source) {
+std::string GetSourceHistogramName(int source, int provider_index) {
+  switch (source) {
     case MostVisitedSites::TOP_SITES:
       return kHistogramClientName;
     case MostVisitedSites::POPULAR:
@@ -131,15 +111,19 @@
     case MostVisitedSites::WHITELIST:
       return kHistogramWhitelistName;
     case MostVisitedSites::SUGGESTIONS_SERVICE:
-      return suggestion.provider_index >= 0
-                 ? base::StringPrintf(kHistogramServerFormat,
-                                      suggestion.provider_index)
+      return provider_index >= 0
+                 ? base::StringPrintf(kHistogramServerFormat, provider_index)
                  : kHistogramServerName;
   }
   NOTREACHED();
   return std::string();
 }
 
+std::string GetSourceHistogramNameFromSuggestion(
+    const MostVisitedSites::Suggestion& suggestion) {
+  return GetSourceHistogramName(suggestion.source, suggestion.provider_index);
+}
+
 void AppendSuggestions(MostVisitedSites::SuggestionsVector src,
                        MostVisitedSites::SuggestionsVector* dst) {
   dst->insert(dst->end(),
@@ -252,15 +236,16 @@
 }
 
 void MostVisitedSites::RecordTileTypeMetrics(
-    const std::vector<int>& tile_types) {
-  DCHECK_EQ(current_suggestions_.size(), tile_types.size());
+    const std::vector<int>& tile_types,
+    const std::vector<int>& sources,
+    const std::vector<int>& provider_indices) {
   int counts_per_type[NUM_TILE_TYPES] = {0};
   for (size_t i = 0; i < tile_types.size(); ++i) {
     int tile_type = tile_types[i];
     ++counts_per_type[tile_type];
     std::string histogram = base::StringPrintf(
         "NewTabPage.TileType.%s",
-        GetSourceHistogramName(current_suggestions_[i]).c_str());
+        GetSourceHistogramName(sources[i], provider_indices[i]).c_str());
     LogHistogramEvent(histogram, tile_type, NUM_TILE_TYPES);
   }
 
@@ -273,16 +258,21 @@
 }
 
 void MostVisitedSites::RecordOpenedMostVisitedItem(int index, int tile_type) {
+  // TODO(treib): |current_suggestions_| could be updated before this function
+  // is called, leading to DCHECKs and/or memory corruption.  Adjust this
+  // function to work with asynchronous UI.
   DCHECK_GE(index, 0);
   DCHECK_LT(index, static_cast<int>(current_suggestions_.size()));
   std::string histogram = base::StringPrintf(
       "NewTabPage.MostVisited.%s",
-      GetSourceHistogramName(current_suggestions_[index]).c_str());
+      GetSourceHistogramNameFromSuggestion(current_suggestions_[index])
+          .c_str());
   LogHistogramEvent(histogram, index, num_sites_);
 
   histogram = base::StringPrintf(
       "NewTabPage.TileTypeClicked.%s",
-      GetSourceHistogramName(current_suggestions_[index]).c_str());
+      GetSourceHistogramNameFromSuggestion(current_suggestions_[index])
+          .c_str());
   LogHistogramEvent(histogram, tile_type, NUM_TILE_TYPES);
 }
 
@@ -557,7 +547,7 @@
   for (size_t i = 0; i < current_suggestions_.size(); i++) {
     std::string histogram = base::StringPrintf(
         "NewTabPage.SuggestionsImpression.%s",
-        GetSourceHistogramName(current_suggestions_[i]).c_str());
+        GetSourceHistogramNameFromSuggestion(current_suggestions_[i]).c_str());
     LogHistogramEvent(histogram, static_cast<int>(i), num_sites_);
   }
 }
diff --git a/components/ntp_tiles/most_visited_sites.h b/components/ntp_tiles/most_visited_sites.h
index 2765d97f..12c2ffb4 100644
--- a/components/ntp_tiles/most_visited_sites.h
+++ b/components/ntp_tiles/most_visited_sites.h
@@ -91,8 +91,38 @@
   using SuggestionsVector = std::vector<Suggestion>;
   using PopularSitesVector = std::vector<PopularSites::Site>;
 
+  // The visual type of a most visited tile.
+  //
+  // These values must stay in sync with the MostVisitedTileType enum
+  // in histograms.xml.
+  //
+  // A Java counterpart will be generated for this enum.
+  // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.ntp
+  enum MostVisitedTileType {
+    // The icon or thumbnail hasn't loaded yet.
+    NONE,
+    // The item displays a site's actual favicon or touch icon.
+    ICON_REAL,
+    // The item displays a color derived from the site's favicon or touch icon.
+    ICON_COLOR,
+    // The item displays a default gray box in place of an icon.
+    ICON_DEFAULT,
+    NUM_TILE_TYPES,
+  };
+
   // The source of the Most Visited sites.
-  enum MostVisitedSource { TOP_SITES, SUGGESTIONS_SERVICE, POPULAR, WHITELIST };
+  // A Java counterpart will be generated for this enum.
+  // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.ntp
+  enum MostVisitedSource {
+    // Item comes from the personal top sites list.
+    TOP_SITES,
+    // Item comes from the suggestions service.
+    SUGGESTIONS_SERVICE,
+    // Item is regionally popular.
+    POPULAR,
+    // Item is on an custodian-managed whitelist.
+    WHITELIST
+  };
 
   // The observer to be notified when the list of most visited sites changes.
   class Observer {
@@ -143,7 +173,9 @@
   void SetMostVisitedURLsObserver(Observer* observer, int num_sites);
 
   void AddOrRemoveBlacklistedUrl(const GURL& url, bool add_url);
-  void RecordTileTypeMetrics(const std::vector<int>& tile_types);
+  void RecordTileTypeMetrics(const std::vector<int>& tile_types,
+                             const std::vector<int>& sources,
+                             const std::vector<int>& provider_indices);
   void RecordOpenedMostVisitedItem(int index, int tile_type);
 
   // MostVisitedSitesSupervisor::Observer implementation.
diff --git a/components/password_manager/core/browser/login_database.cc b/components/password_manager/core/browser/login_database.cc
index d4e913c..0fd6d4d 100644
--- a/components/password_manager/core/browser/login_database.cc
+++ b/components/password_manager/core/browser/login_database.cc
@@ -8,6 +8,7 @@
 #include <stdint.h>
 #include <algorithm>
 #include <limits>
+#include <map>
 #include <utility>
 
 #include "base/bind.h"
@@ -1047,9 +1048,11 @@
   return StatementToForms(&s, nullptr, forms);
 }
 
-bool LoginDatabase::DisableAutoSignInForAllLogins() {
+bool LoginDatabase::DisableAutoSignInForOrigin(const GURL& origin) {
   sql::Statement s(db_.GetCachedStatement(
-      SQL_FROM_HERE, "UPDATE logins SET skip_zero_click = 1;"));
+      SQL_FROM_HERE,
+      "UPDATE logins SET skip_zero_click = 1 WHERE origin_url = ?;"));
+  s.BindString(0, origin.spec());
 
   return s.Run();
 }
@@ -1057,7 +1060,7 @@
 // static
 LoginDatabase::EncryptionResult LoginDatabase::InitPasswordFormFromStatement(
     PasswordForm* form,
-    sql::Statement& s) {
+    const sql::Statement& s) {
   std::string encrypted_password;
   s.ColumnBlobAsString(COLUMN_PASSWORD_VALUE, &encrypted_password);
   base::string16 decrypted_password;
diff --git a/components/password_manager/core/browser/login_database.h b/components/password_manager/core/browser/login_database.h
index c992f3e..13a7eaa 100644
--- a/components/password_manager/core/browser/login_database.h
+++ b/components/password_manager/core/browser/login_database.h
@@ -36,7 +36,7 @@
 // the login information.
 class LoginDatabase {
  public:
-  LoginDatabase(const base::FilePath& db_path);
+  explicit LoginDatabase(const base::FilePath& db_path);
   virtual ~LoginDatabase();
 
   // Actually creates/opens the database. If false is returned, no other method
@@ -77,8 +77,8 @@
   bool RemoveLoginsSyncedBetween(base::Time delete_begin,
                                  base::Time delete_end);
 
-  // Sets the 'skip_zero_click' flag to 'true' for all logins.
-  bool DisableAutoSignInForAllLogins();
+  // Sets the 'skip_zero_click' flag on all forms on |origin| to 'true'.
+  bool DisableAutoSignInForOrigin(const GURL& origin);
 
   // All Get* methods below overwrite |forms| with the returned credentials. On
   // success, those methods return true.
@@ -179,7 +179,7 @@
   // ENCRYPTION_RESULT_SUCCESS, |form| is not filled.
   static EncryptionResult InitPasswordFormFromStatement(
       autofill::PasswordForm* form,
-      sql::Statement& s);
+      const sql::Statement& s);
 
   // Gets all blacklisted or all non-blacklisted (depending on |blacklisted|)
   // credentials. On success returns true and overwrites |forms| with the
diff --git a/components/password_manager/core/browser/login_database_unittest.cc b/components/password_manager/core/browser/login_database_unittest.cc
index abf7ab0..73226b516 100644
--- a/components/password_manager/core/browser/login_database_unittest.cc
+++ b/components/password_manager/core/browser/login_database_unittest.cc
@@ -88,18 +88,19 @@
 }
 
 bool AddZeroClickableLogin(LoginDatabase* db,
-                           const std::string& unique_string) {
+                           const std::string& unique_string,
+                           const GURL& origin) {
   // Example password form.
   PasswordForm form;
-  form.origin = GURL("https://example.com/");
+  form.origin = origin;
   form.username_element = ASCIIToUTF16(unique_string);
   form.username_value = ASCIIToUTF16(unique_string);
   form.password_element = ASCIIToUTF16(unique_string);
   form.submit_element = ASCIIToUTF16("signIn");
   form.signon_realm = form.origin.spec();
   form.display_name = ASCIIToUTF16(unique_string);
-  form.icon_url = GURL("https://example.com/");
-  form.federation_origin = url::Origin(GURL("https://example.com/"));
+  form.icon_url = origin;
+  form.federation_origin = url::Origin(origin);
   form.date_created = base::Time::Now();
 
   form.skip_zero_click = false;
@@ -854,37 +855,47 @@
 TEST_F(LoginDatabaseTest, GetAutoSignInLogins) {
   ScopedVector<autofill::PasswordForm> result;
 
-  EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo1"));
-  EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo2"));
-  EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo3"));
-  EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo4"));
+  GURL origin("https://example.com");
+  EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo1", origin));
+  EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo2", origin));
+  EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo3", origin));
+  EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo4", origin));
 
   EXPECT_TRUE(db().GetAutoSignInLogins(&result));
   EXPECT_EQ(4U, result.size());
   for (const auto& form : result)
     EXPECT_FALSE(form->skip_zero_click);
 
-  EXPECT_TRUE(db().DisableAutoSignInForAllLogins());
+  EXPECT_TRUE(db().DisableAutoSignInForOrigin(origin));
   EXPECT_TRUE(db().GetAutoSignInLogins(&result));
   EXPECT_EQ(0U, result.size());
 }
 
-TEST_F(LoginDatabaseTest, DisableAutoSignInForAllLogins) {
+TEST_F(LoginDatabaseTest, DisableAutoSignInForOrigin) {
   ScopedVector<autofill::PasswordForm> result;
 
-  EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo1"));
-  EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo2"));
-  EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo3"));
-  EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo4"));
+  GURL origin1("https://google.com");
+  GURL origin2("https://chrome.com");
+  GURL origin3("http://example.com");
+  GURL origin4("http://localhost");
+  EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo1", origin1));
+  EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo2", origin2));
+  EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo3", origin3));
+  EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo4", origin4));
 
   EXPECT_TRUE(db().GetAutofillableLogins(&result));
   for (const auto& form : result)
     EXPECT_FALSE(form->skip_zero_click);
 
-  EXPECT_TRUE(db().DisableAutoSignInForAllLogins());
+  EXPECT_TRUE(db().DisableAutoSignInForOrigin(origin1));
+  EXPECT_TRUE(db().DisableAutoSignInForOrigin(origin3));
   EXPECT_TRUE(db().GetAutofillableLogins(&result));
-  for (const auto& form : result)
-    EXPECT_TRUE(form->skip_zero_click);
+  for (const auto* form : result) {
+    if (form->origin == origin1 || form->origin == origin3)
+      EXPECT_TRUE(form->skip_zero_click);
+    else
+      EXPECT_FALSE(form->skip_zero_click);
+  }
 }
 
 TEST_F(LoginDatabaseTest, BlacklistedLogins) {
diff --git a/components/password_manager/core/browser/mock_password_store.h b/components/password_manager/core/browser/mock_password_store.h
index 0c127f7..1806d66 100644
--- a/components/password_manager/core/browser/mock_password_store.h
+++ b/components/password_manager/core/browser/mock_password_store.h
@@ -45,7 +45,9 @@
                PasswordStoreChangeList(base::Time, base::Time));
   MOCK_METHOD2(RemoveStatisticsCreatedBetweenImpl,
                bool(base::Time, base::Time));
-  MOCK_METHOD0(DisableAutoSignInForAllLoginsImpl, PasswordStoreChangeList());
+  MOCK_METHOD1(
+      DisableAutoSignInForOriginsImpl,
+      PasswordStoreChangeList(const base::Callback<bool(const GURL&)>&));
   ScopedVector<autofill::PasswordForm> FillMatchingLogins(
       const autofill::PasswordForm& form) override {
     return ScopedVector<autofill::PasswordForm>();
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc
index 28085c07..37835477 100644
--- a/components/password_manager/core/browser/password_manager.cc
+++ b/components/password_manager/core/browser/password_manager.cc
@@ -635,19 +635,15 @@
                 provisional_save_manager_->pending_credentials().action,
                 all_visible_forms_[i].action)) {
           provisional_save_manager_->LogSubmitFailed();
-          // Generated passwords should always be saved, but we do want to
-          // record that the submission normally would have failed for UMA.
-          if (!provisional_save_manager_->has_generated_password()) {
-            if (logger) {
-              logger->LogPasswordForm(Logger::STRING_PASSWORD_FORM_REAPPEARED,
-                                      all_visible_forms_[i]);
-              logger->LogMessage(Logger::STRING_DECISION_DROP);
-            }
-            provisional_save_manager_.reset();
-            // Clear all_visible_forms_ once we found the match.
-            all_visible_forms_.clear();
-            return;
+          if (logger) {
+            logger->LogPasswordForm(Logger::STRING_PASSWORD_FORM_REAPPEARED,
+                                    all_visible_forms_[i]);
+            logger->LogMessage(Logger::STRING_DECISION_DROP);
           }
+          provisional_save_manager_.reset();
+          // Clear all_visible_forms_ once we found the match.
+          all_visible_forms_.clear();
+          return;
         }
       }
     } else {
diff --git a/components/password_manager/core/browser/password_manager_unittest.cc b/components/password_manager/core/browser/password_manager_unittest.cc
index 3fe98f205..ae4886df 100644
--- a/components/password_manager/core/browser/password_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_manager_unittest.cc
@@ -1108,11 +1108,7 @@
   form_manager_to_save->Save();
 }
 
-TEST_F(PasswordManagerTest, PasswordGenerationForceSaving) {
-  // Test the safety net against password loss during generation
-  // (http://crbug.com/506307) -- out of the two rules (1) "always save
-  // generated passwords" and (2) "do not save passwords when the password form
-  // reappears", rule (1) takes precedence.
+TEST_F(PasswordManagerTest, PasswordGeneration_FailedSubmission) {
   std::vector<PasswordForm> observed;
   PasswordForm form(MakeFormWithOnlyNewPasswordField());
   observed.push_back(form);
@@ -1125,29 +1121,21 @@
       .WillRepeatedly(Return(true));
   manager()->SetHasGeneratedPasswordForForm(&driver_, form, true);
 
-  // The user should not need to confirm saving as they have already given
-  // consent by using the generated password. The form should be saved once
-  // navigation occurs. The client will be informed that automatic saving has
-  // occured.
+  // Do not save generated password when the password form reappears.
   EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_, _)).Times(0);
-  PasswordForm form_to_save;
-  EXPECT_CALL(*store_, AddLogin(_)).WillOnce(SaveArg<0>(&form_to_save));
-  EXPECT_CALL(client_, AutomaticPasswordSaveIndicator());
+  EXPECT_CALL(*store_, AddLogin(_)).Times(0);
+  EXPECT_CALL(client_, AutomaticPasswordSaveIndicator()).Times(0);
 
   // Simulate submission failing, with the same form being visible after
   // navigation.
   OnPasswordFormSubmitted(form);
   manager()->OnPasswordFormsParsed(&driver_, observed);
   manager()->OnPasswordFormsRendered(&driver_, observed, true);
-  EXPECT_EQ(form.username_value, form_to_save.username_value);
-  // What was "new password" field in the submitted form, becomes the current
-  // password field in the form to save.
-  EXPECT_EQ(form.new_password_value, form_to_save.password_value);
 }
 
 // If the user edits the generated password, but does not remove it completely,
 // it should stay treated as a generated password.
-TEST_F(PasswordManagerTest, PasswordGenerationPasswordEdited) {
+TEST_F(PasswordManagerTest, PasswordGenerationPasswordEdited_FailedSubmission) {
   std::vector<PasswordForm> observed;
   PasswordForm form(MakeFormWithOnlyNewPasswordField());
   observed.push_back(form);
@@ -1165,23 +1153,15 @@
   form.new_password_value = ASCIIToUTF16("different_password");
   OnPasswordFormSubmitted(form);
 
-  // The user should not be presented with an infobar as they have already given
-  // consent by using the generated password. The form should be saved once
-  // navigation occurs. The client will be informed that automatic saving has
-  // occurred.
+  // Do not save generated password when the password form reappears.
   EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_, _)).Times(0);
-  PasswordForm form_to_save;
-  EXPECT_CALL(*store_, AddLogin(_)).WillOnce(SaveArg<0>(&form_to_save));
-  EXPECT_CALL(client_, AutomaticPasswordSaveIndicator());
+  EXPECT_CALL(*store_, AddLogin(_)).Times(0);
+  EXPECT_CALL(client_, AutomaticPasswordSaveIndicator()).Times(0);
 
   // Simulate submission failing, with the same form being visible after
   // navigation.
   manager()->OnPasswordFormsParsed(&driver_, observed);
   manager()->OnPasswordFormsRendered(&driver_, observed, true);
-  EXPECT_EQ(form.username_value, form_to_save.username_value);
-  // What was "new password" field in the submitted form, becomes the current
-  // password field in the form to save.
-  EXPECT_EQ(form.new_password_value, form_to_save.password_value);
 }
 
 // Generated password are saved even if it looks like the submit failed (the
diff --git a/components/password_manager/core/browser/password_store.cc b/components/password_manager/core/browser/password_store.cc
index 1ffb69d..111c861 100644
--- a/components/password_manager/core/browser/password_store.cc
+++ b/components/password_manager/core/browser/password_store.cc
@@ -149,10 +149,12 @@
                  delete_begin, delete_end, completion));
 }
 
-void PasswordStore::DisableAutoSignInForAllLogins(
+void PasswordStore::DisableAutoSignInForOrigins(
+    const base::Callback<bool(const GURL&)>& origin_filter,
     const base::Closure& completion) {
-  ScheduleTask(base::Bind(&PasswordStore::DisableAutoSignInForAllLoginsInternal,
-                          this, completion));
+  ScheduleTask(
+      base::Bind(&PasswordStore::DisableAutoSignInForOriginsInternal, this,
+                 base::Callback<bool(const GURL&)>(origin_filter), completion));
 }
 
 void PasswordStore::TrimAffiliationCache() {
@@ -417,9 +419,10 @@
     main_thread_runner_->PostTask(FROM_HERE, completion);
 }
 
-void PasswordStore::DisableAutoSignInForAllLoginsInternal(
+void PasswordStore::DisableAutoSignInForOriginsInternal(
+    const base::Callback<bool(const GURL&)>& origin_filter,
     const base::Closure& completion) {
-  DisableAutoSignInForAllLoginsImpl();
+  DisableAutoSignInForOriginsImpl(origin_filter);
   if (!completion.is_null())
     main_thread_runner_->PostTask(FROM_HERE, completion);
 }
diff --git a/components/password_manager/core/browser/password_store.h b/components/password_manager/core/browser/password_store.h
index 7a36fdf..5f03a99 100644
--- a/components/password_manager/core/browser/password_store.h
+++ b/components/password_manager/core/browser/password_store.h
@@ -136,10 +136,13 @@
                                       base::Time delete_end,
                                       const base::Closure& completion);
 
-  // Sets the 'skip_zero_click' flag for all logins in the database to 'true'.
-  // |completion| will be posted to the |main_thread_runner_| after these
-  // modifications are completed and notifications are sent out.
-  void DisableAutoSignInForAllLogins(const base::Closure& completion);
+  // Sets the 'skip_zero_click' flag for all logins in the database that match
+  // |origin_filter| to 'true'. |completion| will be posted to
+  // the |main_thread_runner_| after these modifications are completed
+  // and notifications are sent out.
+  void DisableAutoSignInForOrigins(
+      const base::Callback<bool(const GURL&)>& origin_filter,
+      const base::Closure& completion);
 
   // Removes cached affiliation data that is no longer needed; provided that
   // affiliation-based matching is enabled.
@@ -269,7 +272,8 @@
                                                   base::Time delete_end) = 0;
 
   // Synchronous implementation to disable auto sign-in.
-  virtual PasswordStoreChangeList DisableAutoSignInForAllLoginsImpl() = 0;
+  virtual PasswordStoreChangeList DisableAutoSignInForOriginsImpl(
+      const base::Callback<bool(const GURL&)>& origin_filter) = 0;
 
   // Finds all PasswordForms with a signon_realm that is equal to, or is a
   // PSL-match to that of |form|, and takes care of notifying the consumer with
@@ -371,7 +375,9 @@
   void RemoveStatisticsCreatedBetweenInternal(base::Time delete_begin,
                                               base::Time delete_end,
                                               const base::Closure& completion);
-  void DisableAutoSignInForAllLoginsInternal(const base::Closure& completion);
+  void DisableAutoSignInForOriginsInternal(
+      const base::Callback<bool(const GURL&)>& origin_filter,
+      const base::Closure& completion);
 
   // Finds all non-blacklist PasswordForms, and notifies the consumer.
   void GetAutofillableLoginsImpl(std::unique_ptr<GetLoginsRequest> request);
diff --git a/components/password_manager/core/browser/password_store_default.cc b/components/password_manager/core/browser/password_store_default.cc
index 79cae2a..1a7b647 100644
--- a/components/password_manager/core/browser/password_store_default.cc
+++ b/components/password_manager/core/browser/password_store_default.cc
@@ -135,18 +135,32 @@
   return changes;
 }
 
-PasswordStoreChangeList
-PasswordStoreDefault::DisableAutoSignInForAllLoginsImpl() {
+PasswordStoreChangeList PasswordStoreDefault::DisableAutoSignInForOriginsImpl(
+    const base::Callback<bool(const GURL&)>& origin_filter) {
   ScopedVector<autofill::PasswordForm> forms;
   PasswordStoreChangeList changes;
-  if (login_db_ && login_db_->GetAutoSignInLogins(&forms)) {
-    if (login_db_->DisableAutoSignInForAllLogins()) {
-      for (const auto* form : forms) {
-        changes.push_back(
-            PasswordStoreChange(PasswordStoreChange::UPDATE, *form));
-      }
+  if (!login_db_ || !login_db_->GetAutoSignInLogins(&forms))
+    return changes;
+
+  std::set<GURL> origins_to_update;
+  for (const auto* form : forms) {
+    if (origin_filter.Run(form->origin))
+      origins_to_update.insert(form->origin);
+  }
+
+  std::set<GURL> origins_updated;
+  for (const GURL& origin : origins_to_update) {
+    if (login_db_->DisableAutoSignInForOrigin(origin))
+      origins_updated.insert(origin);
+  }
+
+  for (const auto* form : forms) {
+    if (origins_updated.count(form->origin)) {
+      changes.push_back(
+          PasswordStoreChange(PasswordStoreChange::UPDATE, *form));
     }
   }
+
   return changes;
 }
 
diff --git a/components/password_manager/core/browser/password_store_default.h b/components/password_manager/core/browser/password_store_default.h
index 9ebcea09..55428a9 100644
--- a/components/password_manager/core/browser/password_store_default.h
+++ b/components/password_manager/core/browser/password_store_default.h
@@ -58,7 +58,8 @@
   PasswordStoreChangeList RemoveLoginsSyncedBetweenImpl(
       base::Time delete_begin,
       base::Time delete_end) override;
-  PasswordStoreChangeList DisableAutoSignInForAllLoginsImpl() override;
+  PasswordStoreChangeList DisableAutoSignInForOriginsImpl(
+      const base::Callback<bool(const GURL&)>& origin_filter) override;
   bool RemoveStatisticsCreatedBetweenImpl(base::Time delete_begin,
                                           base::Time delete_end) override;
   ScopedVector<autofill::PasswordForm> FillMatchingLogins(
diff --git a/components/password_manager/core/browser/test_password_store.cc b/components/password_manager/core/browser/test_password_store.cc
index f4a0f6f5..6e79357 100644
--- a/components/password_manager/core/browser/test_password_store.cc
+++ b/components/password_manager/core/browser/test_password_store.cc
@@ -118,7 +118,8 @@
   return PasswordStoreChangeList();
 }
 
-PasswordStoreChangeList TestPasswordStore::DisableAutoSignInForAllLoginsImpl() {
+PasswordStoreChangeList TestPasswordStore::DisableAutoSignInForOriginsImpl(
+    const base::Callback<bool(const GURL&)>& origin_filter) {
   return PasswordStoreChangeList();
 }
 
diff --git a/components/password_manager/core/browser/test_password_store.h b/components/password_manager/core/browser/test_password_store.h
index 1e76e305..f8a2f5b8 100644
--- a/components/password_manager/core/browser/test_password_store.h
+++ b/components/password_manager/core/browser/test_password_store.h
@@ -60,7 +60,8 @@
   PasswordStoreChangeList RemoveLoginsSyncedBetweenImpl(
       base::Time delete_begin,
       base::Time delete_end) override;
-  PasswordStoreChangeList DisableAutoSignInForAllLoginsImpl() override;
+  PasswordStoreChangeList DisableAutoSignInForOriginsImpl(
+      const base::Callback<bool(const GURL&)>& origin_filter) override;
   bool RemoveStatisticsCreatedBetweenImpl(base::Time delete_begin,
                                           base::Time delete_end) override;
   bool FillAutofillableLogins(
diff --git a/components/plugins/renderer/mobile_youtube_plugin.cc b/components/plugins/renderer/mobile_youtube_plugin.cc
index 4b77abd5..455640b 100644
--- a/components/plugins/renderer/mobile_youtube_plugin.cc
+++ b/components/plugins/renderer/mobile_youtube_plugin.cc
@@ -106,7 +106,6 @@
   std::string youtube("vnd.youtube:");
   GURL url(youtube.append(GetYoutubeVideoId(GetPluginParams())));
   WebURLRequest request;
-  request.initialize();
   request.setURL(url);
   render_frame()->LoadURLExternally(request,
                                     blink::WebNavigationPolicyNewForegroundTab);
diff --git a/components/printing/test/print_web_view_helper_browsertest.cc b/components/printing/test/print_web_view_helper_browsertest.cc
index c6e58cb..5fbfacc 100644
--- a/components/printing/test/print_web_view_helper_browsertest.cc
+++ b/components/printing/test/print_web_view_helper_browsertest.cc
@@ -41,11 +41,10 @@
 
 namespace {
 
-#if !defined(OS_CHROMEOS)
-
 // A simple web page.
 const char kHelloWorldHTML[] = "<body><p>Hello World!</p></body>";
 
+#if !defined(OS_CHROMEOS)
 // A simple webpage with a button to print itself with.
 const char kPrintOnUserAction[] =
     "<body>"
diff --git a/components/proximity_auth/fake_secure_context.cc b/components/proximity_auth/fake_secure_context.cc
index 92e54b0..f8f8802 100644
--- a/components/proximity_auth/fake_secure_context.cc
+++ b/components/proximity_auth/fake_secure_context.cc
@@ -2,15 +2,20 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "components/proximity_auth/fake_secure_context.h"
+
 #include <stddef.h>
 
-#include "components/proximity_auth/fake_secure_context.h"
+#include "base/strings/string_util.h"
 
 namespace proximity_auth {
 
 namespace {
+
 const char kFakeEncodingSuffix[] = ", but encoded";
+const size_t kFakeEncodingSuffixLen = sizeof(kFakeEncodingSuffix) - 1;
 const char kChannelBindingData[] = "channel binding data";
+
 }  // namespace
 
 FakeSecureContext::FakeSecureContext()
@@ -33,15 +38,13 @@
 
 void FakeSecureContext::Decode(const std::string& encoded_message,
                                const MessageCallback& callback) {
-  size_t suffix_size = std::string(kFakeEncodingSuffix).size();
-  if (encoded_message.size() < suffix_size &&
-      encoded_message.substr(encoded_message.size() - suffix_size) !=
-          kFakeEncodingSuffix) {
+  if (!EndsWith(encoded_message, kFakeEncodingSuffix,
+                base::CompareCase::SENSITIVE)) {
     callback.Run(std::string());
   }
 
   std::string decoded_message = encoded_message;
-  decoded_message.erase(decoded_message.rfind(kFakeEncodingSuffix));
+  decoded_message.erase(decoded_message.size() - kFakeEncodingSuffixLen);
   callback.Run(decoded_message);
 }
 
diff --git a/components/renderer_context_menu/render_view_context_menu_base.h b/components/renderer_context_menu/render_view_context_menu_base.h
index 82792dd..d57b9dc1 100644
--- a/components/renderer_context_menu/render_view_context_menu_base.h
+++ b/components/renderer_context_menu/render_view_context_menu_base.h
@@ -149,8 +149,8 @@
 #endif
 
   // Returns the accelerator for given |command_id|.
-  bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override = 0;
+  bool GetAcceleratorForCommandId(int command_id, ui::Accelerator* accelerator)
+      const override = 0;
 
   // Subclasses should send notification.
   virtual void NotifyMenuShown() = 0;
diff --git a/components/subresource_filter.gypi b/components/subresource_filter.gypi
index b864159..2e347cd 100644
--- a/components/subresource_filter.gypi
+++ b/components/subresource_filter.gypi
@@ -72,6 +72,10 @@
         'subresource_filter/core/common/ngram_extractor.h',
         'subresource_filter/core/common/string_splitter.h',
         'subresource_filter/core/common/uint64_hasher.h',
+        'subresource_filter/core/common/url_pattern.cc',
+        'subresource_filter/core/common/url_pattern.h',
+        'subresource_filter/core/common/url_pattern_matching.cc',
+        'subresource_filter/core/common/url_pattern_matching.h',
       ],
       'export_dependent_settings': [
         'subresource_filter_core_common_ruleset_flatbuffer',
diff --git a/components/subresource_filter/core/common/BUILD.gn b/components/subresource_filter/core/common/BUILD.gn
index d8c3659..f8e2e787 100644
--- a/components/subresource_filter/core/common/BUILD.gn
+++ b/components/subresource_filter/core/common/BUILD.gn
@@ -15,6 +15,10 @@
     "ngram_extractor.h",
     "string_splitter.h",
     "uint64_hasher.h",
+    "url_pattern.cc",
+    "url_pattern.h",
+    "url_pattern_matching.cc",
+    "url_pattern_matching.h",
   ]
 
   public_deps = [
@@ -24,6 +28,7 @@
 
   deps = [
     "//base",
+    "//url:url",
   ]
 }
 
@@ -35,10 +40,12 @@
     "knuth_morris_pratt_unittest.cc",
     "ngram_extractor_unittest.cc",
     "string_splitter_unittest.cc",
+    "url_pattern_matching_unittest.cc",
   ]
   deps = [
     ":common",
     "//base",
     "//testing/gtest",
+    "//url:url",
   ]
 }
diff --git a/components/subresource_filter/core/common/url_pattern.cc b/components/subresource_filter/core/common/url_pattern.cc
new file mode 100644
index 0000000..1cfa663
--- /dev/null
+++ b/components/subresource_filter/core/common/url_pattern.cc
@@ -0,0 +1,76 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/subresource_filter/core/common/url_pattern.h"
+
+#include "components/subresource_filter/core/common/flat/rules_generated.h"
+
+namespace subresource_filter {
+
+namespace {
+
+proto::UrlPatternType ConvertUrlPatternType(flat::UrlPatternType type) {
+  switch (type) {
+    case flat::UrlPatternType_SUBSTRING:
+      return proto::URL_PATTERN_TYPE_SUBSTRING;
+    case flat::UrlPatternType_WILDCARDED:
+      return proto::URL_PATTERN_TYPE_WILDCARDED;
+    case flat::UrlPatternType_REGEXP:
+      return proto::URL_PATTERN_TYPE_REGEXP;
+    default:
+      return proto::URL_PATTERN_TYPE_UNSPECIFIED;
+  }
+}
+
+proto::AnchorType ConvertAnchorType(flat::AnchorType type) {
+  switch (type) {
+    case flat::AnchorType_NONE:
+      return proto::ANCHOR_TYPE_NONE;
+    case flat::AnchorType_BOUNDARY:
+      return proto::ANCHOR_TYPE_BOUNDARY;
+    case flat::AnchorType_SUBDOMAIN:
+      return proto::ANCHOR_TYPE_SUBDOMAIN;
+    default:
+      return proto::ANCHOR_TYPE_UNSPECIFIED;
+  }
+}
+
+base::StringPiece ConvertString(const flatbuffers::String* string) {
+  return string ? base::StringPiece(string->data(), string->size())
+                : base::StringPiece();
+}
+
+}  // namespace
+
+UrlPattern::UrlPattern() = default;
+
+UrlPattern::UrlPattern(base::StringPiece url_pattern,
+                       proto::UrlPatternType type)
+    : type(type), url_pattern(url_pattern) {}
+
+UrlPattern::UrlPattern(base::StringPiece url_pattern,
+                       proto::AnchorType anchor_left,
+                       proto::AnchorType anchor_right)
+    : type(proto::URL_PATTERN_TYPE_WILDCARDED),
+      url_pattern(url_pattern),
+      anchor_left(anchor_left),
+      anchor_right(anchor_right) {}
+
+UrlPattern::UrlPattern(const flat::UrlRule& rule)
+    : type(ConvertUrlPatternType(rule.url_pattern_type())),
+      url_pattern(ConvertString(rule.url_pattern())),
+      anchor_left(ConvertAnchorType(rule.anchor_left())),
+      anchor_right(ConvertAnchorType(rule.anchor_right())),
+      match_case(!!(rule.options() & flat::OptionFlag_IS_MATCH_CASE)) {}
+
+UrlPattern::UrlPattern(const proto::UrlRule& rule)
+    : type(rule.url_pattern_type()),
+      url_pattern(rule.url_pattern()),
+      anchor_left(rule.anchor_left()),
+      anchor_right(rule.anchor_right()),
+      match_case(rule.match_case()) {}
+
+UrlPattern::~UrlPattern() = default;
+
+}  // namespace subresource_filter
diff --git a/components/subresource_filter/core/common/url_pattern.h b/components/subresource_filter/core/common/url_pattern.h
new file mode 100644
index 0000000..f49b5ea
--- /dev/null
+++ b/components/subresource_filter/core/common/url_pattern.h
@@ -0,0 +1,53 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_URL_PATTERN_H_
+#define COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_URL_PATTERN_H_
+
+#include "base/macros.h"
+#include "base/strings/string_piece.h"
+#include "components/subresource_filter/core/common/proto/rules.pb.h"
+
+namespace subresource_filter {
+
+namespace flat {
+struct UrlRule;  // The FlatBuffers version of UrlRule.
+}
+
+// The structure used to mirror a URL pattern regardless of the representation
+// of the UrlRule that owns it.
+struct UrlPattern {
+  UrlPattern();
+
+  // Creates a |url_pattern| of a certain |type|.
+  UrlPattern(base::StringPiece url_pattern,
+             proto::UrlPatternType type = proto::URL_PATTERN_TYPE_WILDCARDED);
+
+  // Creates a WILDCARDED |url_pattern| with the specified anchors.
+  UrlPattern(base::StringPiece url_pattern,
+             proto::AnchorType anchor_left,
+             proto::AnchorType anchor_right);
+
+  // The following constructors create UrlPattern from one of the UrlRule
+  // representations. The passed in |rule| must outlive the created instance.
+  explicit UrlPattern(const flat::UrlRule& rule);
+  explicit UrlPattern(const proto::UrlRule& rule);
+
+  ~UrlPattern();
+
+  proto::UrlPatternType type = proto::URL_PATTERN_TYPE_UNSPECIFIED;
+  base::StringPiece url_pattern;
+
+  proto::AnchorType anchor_left = proto::ANCHOR_TYPE_NONE;
+  proto::AnchorType anchor_right = proto::ANCHOR_TYPE_NONE;
+
+  bool match_case = false;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(UrlPattern);
+};
+
+}  // namespace subresource_filter
+
+#endif  // COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_URL_PATTERN_H_
diff --git a/components/subresource_filter/core/common/url_pattern_matching.cc b/components/subresource_filter/core/common/url_pattern_matching.cc
new file mode 100644
index 0000000..91541c0
--- /dev/null
+++ b/components/subresource_filter/core/common/url_pattern_matching.cc
@@ -0,0 +1,125 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/subresource_filter/core/common/url_pattern_matching.h"
+
+#include "base/logging.h"
+#include "components/subresource_filter/core/common/fuzzy_pattern_matching.h"
+#include "components/subresource_filter/core/common/knuth_morris_pratt.h"
+#include "components/subresource_filter/core/common/string_splitter.h"
+#include "components/subresource_filter/core/common/url_pattern.h"
+
+namespace subresource_filter {
+
+namespace {
+
+bool IsWildcard(char c) {
+  return c == '*';
+}
+
+size_t FindFirstOccurrenceFuzzy(base::StringPiece text,
+                                base::StringPiece subpattern,
+                                const size_t* failure) {
+  return *AllOccurrencesFuzzy(text, subpattern, failure).begin();
+}
+
+}  // namespace
+
+void BuildFailureFunction(const UrlPattern& pattern,
+                          std::vector<size_t>* failure) {
+  auto subpatterns = CreateStringSplitter(pattern.url_pattern, IsWildcard);
+  auto subpattern_it = subpatterns.begin();
+  auto subpattern_end = subpatterns.end();
+
+  if (subpattern_it == subpattern_end)
+    return;
+  if (pattern.anchor_left == proto::ANCHOR_TYPE_BOUNDARY)
+    ++subpattern_it;
+
+  while (subpattern_it != subpattern_end) {
+    const base::StringPiece part = *subpattern_it++;
+    DCHECK(!part.empty());
+    if (pattern.anchor_right == proto::ANCHOR_TYPE_BOUNDARY &&
+        subpattern_it == subpattern_end) {
+      break;
+    }
+
+    if (part.find(kSeparatorPlaceholder) == base::StringPiece::npos) {
+      BuildFailureFunction(part, failure);
+    } else {
+      // Prepend the value '1' to the failure function to let matchers
+      // distinguish between the subpatterns with separator placeholders and
+      // those without.
+      failure->push_back(1);
+      BuildFailureFunctionFuzzy(part, failure);
+    }
+  }
+}
+
+// TODO(pkalinnikov): Support SUBDOMAIN anchors.
+bool IsMatch(const GURL& url,
+             const UrlPattern& pattern,
+             const std::vector<size_t>& failure) {
+  auto subpatterns = CreateStringSplitter(pattern.url_pattern, IsWildcard);
+  auto subpattern_it = subpatterns.begin();
+  auto subpattern_end = subpatterns.end();
+
+  if (subpattern_it == subpattern_end) {
+    return pattern.anchor_left != proto::ANCHOR_TYPE_BOUNDARY ||
+           pattern.anchor_right != proto::ANCHOR_TYPE_BOUNDARY ||
+           url.is_empty();
+  }
+
+  base::StringPiece spec = url.spec();
+
+  if (pattern.anchor_left == proto::ANCHOR_TYPE_BOUNDARY) {
+    const base::StringPiece subpattern = *subpattern_it++;
+    if (!StartsWithFuzzy(spec, subpattern))
+      return false;
+    if (subpattern_it == subpattern_end) {
+      return pattern.anchor_right != proto::ANCHOR_TYPE_BOUNDARY ||
+             spec.size() == subpattern.size();
+    }
+    spec.remove_prefix(subpattern.size());
+  }
+
+  base::StringPiece subpattern;
+  auto failure_it = failure.begin();
+  while (subpattern_it != subpattern_end) {
+    subpattern = *subpattern_it++;
+    DCHECK(!subpattern.empty());
+
+    if (subpattern_it == subpattern_end &&
+        pattern.anchor_right == proto::ANCHOR_TYPE_BOUNDARY) {
+      break;
+    }
+
+    // The subpatterns with separator placeholders were indexed differently and
+    // should be matched accordingly. Their failure functions were prepended by
+    // a non-zero value, and we need to skip it. If the value turned to be zero,
+    // it is the initial value of a failure function of a regular substring.
+    CHECK(failure_it < failure.end());
+    const bool has_separator_placeholders = (*failure_it != 0);
+    if (has_separator_placeholders)
+      ++failure_it;
+    CHECK(failure_it + subpattern.size() <= failure.end());
+
+    // If the subpattern has separator placeholders, it should be matched with
+    // FindFirstOccurrenceOfSubpattern, otherwise it can be found as a regular
+    // substring.
+    const size_t match_end =
+        (has_separator_placeholders
+             ? FindFirstOccurrenceFuzzy(spec, subpattern, &*failure_it)
+             : FindFirstOccurrence(spec, subpattern, &*failure_it));
+    if (match_end == base::StringPiece::npos)
+      return false;
+    spec.remove_prefix(match_end);
+    failure_it += subpattern.size();
+  }
+
+  return pattern.anchor_right != proto::ANCHOR_TYPE_BOUNDARY ||
+         EndsWithFuzzy(spec, subpattern);
+}
+
+}  // namespace subresource_filter
diff --git a/components/subresource_filter/core/common/url_pattern_matching.h b/components/subresource_filter/core/common/url_pattern_matching.h
new file mode 100644
index 0000000..74c6a3a
--- /dev/null
+++ b/components/subresource_filter/core/common/url_pattern_matching.h
@@ -0,0 +1,61 @@
+// 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.
+
+// The matching logic distinguishes between the terms URL pattern and
+// subpattern. A URL pattern usually stands for the full thing, e.g.
+// "example.com^*path*par=val^", whereas subpattern denotes a maximal substring
+// of a pattern not containing the wildcard '*' character. For the example above
+// the subpatterns are: "example.com^", "path" and "par=val^".
+//
+// The separator placeholder '^' symbol is used in subpatterns to match any
+// separator character, which is any ASCII symbol except letters, digits, and
+// the following: '_', '-', '.', '%'. Note that the separator placeholder
+// character '^' is itself a separator, as well as '\0'.
+
+#ifndef COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_URL_PATTERN_MATCHING_H_
+#define COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_URL_PATTERN_MATCHING_H_
+
+#include <stddef.h>
+
+#include <vector>
+
+#include "base/strings/string_piece.h"
+#include "url/gurl.h"
+
+namespace subresource_filter {
+
+struct UrlPattern;
+
+// Builds a compound Knuth-Morris-Pratt failure function used to match URLs
+// against the |pattern|.
+//
+// The |pattern| is split on the '*' wildcard symbol and then a failure function
+// is built for each subpattern by BuildFailureFunctionFuzzy or
+// BuildFailureFunction (depending on whether the subpattern contains separator
+// placeholders), and appended to the returned vector. Some of the subpatterns
+// can be exempted from being indexed. E.g., if the |pattern| has a BOUNDARY
+// left anchor, the first subpattern can be matched by checking if it's a prefix
+// of a URL.
+//
+// Each subpattern indexed with BuildFailureFunctionFuzzy is prepended with a
+// value 1 (to distinguish them from the subpatterns indexed with
+// BuildFailureFunction, their failure functions always start with 0).
+//
+// The URL |pattern| must be normalized. Namely, it must not have the following
+// substrings: **, *<END>, <BEGIN>*. If the the |pattern| has a BOUNDARY anchor,
+// the corresponding side of its string must not end with a '*' wildcard.
+void BuildFailureFunction(const UrlPattern& pattern,
+                          std::vector<size_t>* failure);
+
+// Returns whether the |url| matches the URL |pattern|. The |failure| function
+// must be the output of BuildFailureFunction() called with the same |pattern|.
+//
+// TODO(pkalinnikov): Outline algorithms implemented in this function.
+bool IsMatch(const GURL& url,
+             const UrlPattern& pattern,
+             const std::vector<size_t>& failure);
+
+}  // namespace subresource_filter
+
+#endif  // COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_URL_PATTERN_MATCHING_H_
diff --git a/components/subresource_filter/core/common/url_pattern_matching_unittest.cc b/components/subresource_filter/core/common/url_pattern_matching_unittest.cc
new file mode 100644
index 0000000..e87aa08
--- /dev/null
+++ b/components/subresource_filter/core/common/url_pattern_matching_unittest.cc
@@ -0,0 +1,133 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/subresource_filter/core/common/url_pattern_matching.h"
+
+#include <vector>
+
+#include "components/subresource_filter/core/common/url_pattern.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace subresource_filter {
+
+namespace {
+
+constexpr proto::AnchorType kAnchorNone = proto::ANCHOR_TYPE_NONE;
+constexpr proto::AnchorType kBoundary = proto::ANCHOR_TYPE_BOUNDARY;
+constexpr proto::AnchorType kSubdomain = proto::ANCHOR_TYPE_SUBDOMAIN;
+
+}  // namespace
+
+TEST(UrlPatternMatchingTest, BuildFailureFunctionForUrlPattern) {
+  const struct {
+    UrlPattern url_pattern;
+    std::vector<size_t> expected_failure_function;
+  } kTestCases[] = {
+      {{"abcd", proto::URL_PATTERN_TYPE_SUBSTRING}, {0, 0, 0, 0}},
+      {{"&a?a/"}, {0, 0, 0, 0, 0}},
+      {{"^a?a/"}, {1, 0, 0, 1, 2, 3}},
+
+      {{"abc*abc", kBoundary, kAnchorNone}, {0, 0, 0}},
+      {{"abc*aaa", kBoundary, kAnchorNone}, {0, 1, 2}},
+      {{"aaa*abc", kBoundary, kAnchorNone}, {0, 0, 0}},
+
+      {{"abc*abc", kAnchorNone, kBoundary}, {0, 0, 0}},
+      {{"abc*aaa", kAnchorNone, kBoundary}, {0, 0, 0}},
+      {{"aaa*abc", kAnchorNone, kBoundary}, {0, 1, 2}},
+
+      {{"abc*cca", kSubdomain, kAnchorNone}, {0, 0, 0, 0, 1, 0}},
+      {{"abc*cca", kBoundary, kAnchorNone}, {0, 1, 0}},
+      {{"abc*cca"}, {0, 0, 0, 0, 1, 0}},
+
+      {{"abc*abacaba*cab"}, {0, 0, 0, 0, 0, 1, 0, 1, 2, 3, 0, 0, 0}},
+      {{"aaa*a^d*^^b"}, {0, 1, 2, 1, 0, 0, 0, 1, 0, 1, 0}},
+      {{"aaa*a^d*^^b", kAnchorNone, kBoundary}, {0, 1, 2, 1, 0, 0, 0}},
+      {{"^^a*a^d*^^b", kBoundary, kAnchorNone}, {1, 0, 0, 0, 1, 0, 1, 0}},
+  };
+
+  for (const auto& test_case : kTestCases) {
+    SCOPED_TRACE(testing::Message()
+                 << "Pattern: " << test_case.url_pattern.url_pattern
+                 << "; Anchors: "
+                 << static_cast<int>(test_case.url_pattern.anchor_left) << ", "
+                 << static_cast<int>(test_case.url_pattern.anchor_right));
+
+    std::vector<size_t> failure;
+    BuildFailureFunction(test_case.url_pattern, &failure);
+    EXPECT_EQ(test_case.expected_failure_function, failure);
+  }
+}
+
+TEST(UrlPatternMatchingTest, IsMatch) {
+  const struct {
+    UrlPattern url_pattern;
+    const char* url;
+    bool expect_match;
+  } kTestCases[] = {
+      {{"xampl", proto::URL_PATTERN_TYPE_SUBSTRING},
+       "http://example.com",
+       true},
+      {{"example", proto::URL_PATTERN_TYPE_SUBSTRING},
+       "http://example.com",
+       true},
+      {{"/a?a"}, "http://ex.com/a?a", true},
+      {{"^abc"}, "http://ex.com/abc?a", true},
+      {{"^abc"}, "http://ex.com/a?abc", true},
+      {{"^abc"}, "http://ex.com/abc?abc", true},
+
+      {{"http://ex", kBoundary, kAnchorNone}, "http://example.com", true},
+      {{"mple.com/", kAnchorNone, kBoundary}, "http://example.com", true},
+
+      // Note: "example.com" will be normalized into "example.com/".
+      {{"http://*mpl", kBoundary, kAnchorNone}, "http://example.com", true},
+      {{"mpl*com/", kAnchorNone, kBoundary}, "http://example.com", true},
+      {{"example^com"}, "http://example.com", false},
+      {{"example^com"}, "http://example/com", true},
+      {{"example.com^"}, "http://example.com:8080", true},
+      {{"http*.com/", kBoundary, kBoundary}, "http://example.com", true},
+      {{"http*.org/", kBoundary, kBoundary}, "http://example.com", false},
+
+      {{"/path?*&p1=*&p2="}, "http://ex.com/aaa/path/bbb?k=v&p1=0&p2=1", false},
+      {{"/path?*&p1=*&p2="}, "http://ex.com/aaa/path?k=v&p1=0&p2=1", true},
+      {{"/path?*&p1=*&p2="}, "http://ex.com/aaa/path?k=v&k=v&p1=0&p2=1", true},
+      {{"/path?*&p1=*&p2="},
+       "http://ex.com/aaa/path?k=v&p1=0&p3=10&p2=1",
+       true},
+      {{"/path?*&p1=*&p2="}, "http://ex.com/aaa/path&p1=0&p2=1", false},
+      {{"/path?*&p1=*&p2="}, "http://ex.com/aaa/path?k=v&p2=0&p1=1", false},
+
+      {{"abc*def*ghijk*xyz"},
+       "http://example.com/abcdeffffghijkmmmxyzzz",
+       true},
+      {{"abc*cdef"}, "http://example.com/abcdef", false},
+
+      {{"^^a^^"}, "http://ex.com/?a=/", true},
+      {{"^^a^^"}, "http://ex.com/?a=/&b=0", true},
+      {{"^^a^^"}, "http://ex.com/?a=", false},
+
+      {{"ex.com^path^*k=v^"}, "http://ex.com/path/?k1=v1&ak=v&kk=vv", true},
+      {{"ex.com^path^*k=v^"}, "http://ex.com/p/path/?k1=v1&ak=v&kk=vv", false},
+      {{"a^a&a^a&"}, "http://ex.com/a/a/a/a/?a&a&a&a&a", true},
+
+      {{"abc*def^"}, "http://ex.com/abc/a/ddef/", true},
+  };
+
+  for (const auto& test_case : kTestCases) {
+    SCOPED_TRACE(testing::Message()
+                 << "Rule: " << test_case.url_pattern.url_pattern
+                 << "; Anchors: "
+                 << static_cast<int>(test_case.url_pattern.anchor_left) << ", "
+                 << static_cast<int>(test_case.url_pattern.anchor_right)
+                 << "; URL: " << GURL(test_case.url));
+
+    std::vector<size_t> failure;
+    BuildFailureFunction(test_case.url_pattern, &failure);
+    const bool is_match =
+        IsMatch(GURL(test_case.url), test_case.url_pattern, failure);
+    EXPECT_EQ(test_case.expect_match, is_match);
+  }
+}
+
+}  // namespace subresource_filter
diff --git a/components/test_runner/test_runner_for_specific_view.h b/components/test_runner/test_runner_for_specific_view.h
index 06c245c..e0c6d5e 100644
--- a/components/test_runner/test_runner_for_specific_view.h
+++ b/components/test_runner/test_runner_for_specific_view.h
@@ -171,8 +171,7 @@
   // Dump current PageImportanceSignals for the page.
   void DumpPageImportanceSignals();
 
-  // WebPageOverlay related functions. Permits the adding and removing of only
-  // one opaque overlay.
+  // Permits the adding and removing of only one opaque overlay.
   void AddWebPageOverlay();
   void RemoveWebPageOverlay();
 
diff --git a/components/tools/metrics/browser_components_metrics.py b/components/tools/metrics/browser_components_metrics.py
deleted file mode 100755
index c1f5b4b0..0000000
--- a/components/tools/metrics/browser_components_metrics.py
+++ /dev/null
@@ -1,65 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 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.
-
-"""Generates the metrics collected weekly for the Browser Components project.
-
-See
-http://www.chromium.org/developers/design-documents/browser-components
-for details.
-"""
-
-import os
-import sys
-
-
-# This is done so that we can import checkdeps.  If not invoked as
-# main, our user must ensure it is in PYTHONPATH.
-if __name__ == '__main__':
-  sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..',
-                               'buildtools', 'checkdeps'))
-
-
-import count_ifdefs
-import checkdeps
-import results
-
-
-# Preprocessor pattern to find OS_XYZ defines.
-PREPROCESSOR_PATTERN = 'OS_[A-Z]+'
-
-
-class BrowserComponentsMetricsGenerator(object):
-  def __init__(self, checkout_root):
-    self.checkout_root = checkout_root
-    self.chrome_browser = os.path.join(checkout_root, 'chrome', 'browser')
-
-  def CountIfdefs(self, skip_tests):
-    return count_ifdefs.CountIfdefs(
-        PREPROCESSOR_PATTERN, self.chrome_browser, skip_tests)
-
-  def CountViolations(self, skip_tests):
-    deps_checker = checkdeps.DepsChecker(self.checkout_root,
-                                         ignore_temp_rules=True,
-                                         skip_tests=skip_tests)
-    deps_checker.results_formatter = results.CountViolationsFormatter()
-    deps_checker.CheckDirectory(os.path.join('chrome', 'browser'))
-    return int(deps_checker.results_formatter.GetResults())
-
-
-def main():
-  generator = BrowserComponentsMetricsGenerator(
-      os.path.join(os.path.dirname(__file__), '..', '..', '..'))
-
-  print "All metrics are for chrome/browser.\n"
-  print "OS ifdefs, all:                   %d" % generator.CountIfdefs(False)
-  print "OS ifdefs, -tests:                %d" % generator.CountIfdefs(True)
-  print ("Intended DEPS violations, all:    %d" %
-         generator.CountViolations(False))
-  print "Intended DEPS violations, -tests: %d" % generator.CountViolations(True)
-  return 0
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/components/tools/metrics/count_ifdefs.py b/components/tools/metrics/count_ifdefs.py
deleted file mode 100755
index 2e3c2ad..0000000
--- a/components/tools/metrics/count_ifdefs.py
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 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.
-
-"""Counts the number of #if or #ifdef lines containing at least one
-preprocessor token that is a full match for the given pattern, in the
-given directory.
-"""
-
-
-import optparse
-import os
-import re
-import sys
-
-
-# Filename extensions we know will be handled by the C preprocessor.
-# We ignore files not matching these.
-CPP_EXTENSIONS = [
-  '.h',
-  '.cc',
-  '.m',
-  '.mm',
-]
-
-
-def _IsTestFile(filename):
-  """Does a rudimentary check to try to skip test files; this could be
-  improved but is good enough for basic metrics generation.
-  """
-  return re.match('(test|mock|dummy)_.*|.*_[a-z]*test\.(h|cc|mm)', filename)
-
-
-def CountIfdefs(token_pattern, directory, skip_tests=False):
-  """Returns the number of lines in files in |directory| and its
-  subdirectories that have an extension from |CPP_EXTENSIONS| and are
-  an #if or #ifdef line with a preprocessor token fully matching
-  the string |token_pattern|.
-
-  If |skip_tests| is true, a best effort is made to ignore test files.
-  """
-  token_line_re = re.compile(r'^#if(def)?.*\b(%s)\b.*$' % token_pattern)
-  count = 0
-  for root, dirs, files in os.walk(directory):
-    for filename in files:
-      if os.path.splitext(filename)[1] in CPP_EXTENSIONS:
-        if not skip_tests or not _IsTestFile(filename):
-          with open(os.path.join(root, filename)) as f:
-            for line in f:
-              line = line.strip()
-              if token_line_re.match(line):
-                count += 1
-  return count
-
-
-def PrintUsage():
-  print "Usage: %s [--skip-tests] TOKEN_PATTERN DIRECTORY" % sys.argv[0]
-
-
-def main():
-  option_parser = optparse.OptionParser()
-  option_parser.add_option('', '--skip-tests', action='store_true',
-                           dest='skip_tests', default=False,
-                           help='Skip test files.')
-  options, args = option_parser.parse_args()
-
-  if len(args) < 2:
-    PrintUsage()
-    return 1
-  else:
-    print CountIfdefs(args[0], args[1], options.skip_tests)
-    return 0
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/components/tools/metrics/count_ifdefs_unittest.py b/components/tools/metrics/count_ifdefs_unittest.py
deleted file mode 100755
index 9b8c322..0000000
--- a/components/tools/metrics/count_ifdefs_unittest.py
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 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.
-
-"""Tests for count_ifdefs.
-"""
-
-import os
-import unittest
-
-import count_ifdefs
-
-
-class CountIfdefsTest(unittest.TestCase):
-
-  def setUp(self):
-    self.root = os.path.join(os.path.dirname(__file__), 'testdata')
-
-  def testNormal(self):
-    count = count_ifdefs.CountIfdefs('OS_[A-Z]+', self.root)
-    self.failUnless(count == 6)
-
-  def testSkipTests(self):
-    count = count_ifdefs.CountIfdefs('OS_[A-Z]+', self.root, True)
-    self.failUnless(count == 4)
-
-
-if __name__ == '__main__':
-  unittest.main()
diff --git a/components/tools/metrics/testdata/foo.cc b/components/tools/metrics/testdata/foo.cc
deleted file mode 100644
index bd3d3c71..0000000
--- a/components/tools/metrics/testdata/foo.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2012 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.
-
-// Should not match
-#ifndef FOO_OS_ANDROID_BLAT
-#define FOO_OS_ANDROID_BLAT
-
-#if defined(OS_ANDROID)
-
-#if defined(OS_ANDROID) || defined(OS_IOS) || defined(OS_CHROMEOS)
-
-#if !defined(OS_CAT)
-
-#if defined(OS_WIN)
-
-#endif  // !OS_ANDROID && !OS_IOS
-#endif  // OS_CAT
-
-#endif  // FOO_OS_ANDROID_BLAT
diff --git a/components/tools/metrics/testdata/foo_ignored.txt b/components/tools/metrics/testdata/foo_ignored.txt
deleted file mode 100644
index 2b186f93..0000000
--- a/components/tools/metrics/testdata/foo_ignored.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-#if defined(OS_ANDROID)
-
-#if defined(OS_WIN)
-
diff --git a/components/tools/metrics/testdata/subdir/foo_test.mm b/components/tools/metrics/testdata/subdir/foo_test.mm
deleted file mode 100644
index adf1f89..0000000
--- a/components/tools/metrics/testdata/subdir/foo_test.mm
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#if defined(OS_ANDROID)
-
-#if defined(OS_WIN)
-
diff --git a/components/translate/core/browser/options_menu_model.cc b/components/translate/core/browser/options_menu_model.cc
index d369f63..f56ddb0 100644
--- a/components/translate/core/browser/options_menu_model.cc
+++ b/components/translate/core/browser/options_menu_model.cc
@@ -102,7 +102,7 @@
 
 bool OptionsMenuModel::GetAcceleratorForCommandId(
     int command_id,
-    ui::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) const {
   return false;
 }
 
diff --git a/components/translate/core/browser/options_menu_model.h b/components/translate/core/browser/options_menu_model.h
index 44fc5b2..165fdff 100644
--- a/components/translate/core/browser/options_menu_model.h
+++ b/components/translate/core/browser/options_menu_model.h
@@ -33,7 +33,7 @@
   bool IsCommandIdChecked(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
 
  private:
diff --git a/components/webcrypto/webcrypto_impl.cc b/components/webcrypto/webcrypto_impl.cc
index 7986b77..9f47270 100644
--- a/components/webcrypto/webcrypto_impl.cc
+++ b/components/webcrypto/webcrypto_impl.cc
@@ -763,9 +763,9 @@
   }
 }
 
-blink::WebCryptoDigestor* WebCryptoImpl::createDigestor(
+std::unique_ptr<blink::WebCryptoDigestor> WebCryptoImpl::createDigestor(
     blink::WebCryptoAlgorithmId algorithm_id) {
-  return webcrypto::CreateDigestor(algorithm_id).release();
+  return webcrypto::CreateDigestor(algorithm_id);
 }
 
 bool WebCryptoImpl::deserializeKeyForClone(
diff --git a/components/webcrypto/webcrypto_impl.h b/components/webcrypto/webcrypto_impl.h
index af5f6fc..b551213 100644
--- a/components/webcrypto/webcrypto_impl.h
+++ b/components/webcrypto/webcrypto_impl.h
@@ -96,10 +96,8 @@
   // This method returns a digestor object that can be used to synchronously
   // compute a digest one chunk at a time. Thus, the consume does not need to
   // hold onto a large buffer with all the data to digest. Chunks can be given
-  // one at a time and the digest will be computed piecemeal. The allocated
-  // WebCrytpoDigestor that is returned by createDigestor must be freed by the
-  // caller.
-  blink::WebCryptoDigestor* createDigestor(
+  // one at a time and the digest will be computed piecemeal.
+  std::unique_ptr<blink::WebCryptoDigestor> createDigestor(
       blink::WebCryptoAlgorithmId algorithm_id) override;
 
   bool deserializeKeyForClone(const blink::WebCryptoKeyAlgorithm& algorithm,
diff --git a/content/browser/browser_plugin/browser_plugin_guest.cc b/content/browser/browser_plugin/browser_plugin_guest.cc
index 2f6fd0e3..ceeaaa3 100644
--- a/content/browser/browser_plugin/browser_plugin_guest.cc
+++ b/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -409,7 +409,7 @@
   std::vector<uint32_t> sequences;
   sequences.push_back(sequence.sequence);
   cc::SurfaceManager* manager = GetSurfaceManager();
-  manager->DidSatisfySequences(sequence.id_namespace, &sequences);
+  manager->DidSatisfySequences(sequence.client_id, &sequences);
 }
 
 void BrowserPluginGuest::OnRequireSequence(
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc
index eb8a142..f40a64bc 100644
--- a/content/browser/compositor/gpu_process_transport_factory.cc
+++ b/content/browser/compositor/gpu_process_transport_factory.cc
@@ -180,7 +180,7 @@
 };
 
 GpuProcessTransportFactory::GpuProcessTransportFactory()
-    : next_surface_id_namespace_(1u),
+    : next_surface_client_id_(1u),
       task_graph_runner_(new cc::SingleThreadTaskGraphRunner),
       callback_factory_(this) {
   cc::SetClientNameForMetrics("Browser");
@@ -581,7 +581,7 @@
       surface_manager_.get(), HostSharedBitmapManager::current(),
       BrowserGpuMemoryBufferManager::current(),
       compositor->GetRendererSettings(),
-      compositor->surface_id_allocator()->id_namespace(),
+      compositor->surface_id_allocator()->client_id(),
       std::move(begin_frame_source), std::move(display_output_surface),
       std::move(scheduler), base::MakeUnique<cc::TextureMailboxDeleter>(
                                 compositor->task_runner().get()));
@@ -692,10 +692,10 @@
 
 std::unique_ptr<cc::SurfaceIdAllocator>
 GpuProcessTransportFactory::CreateSurfaceIdAllocator() {
-  std::unique_ptr<cc::SurfaceIdAllocator> allocator = base::WrapUnique(
-      new cc::SurfaceIdAllocator(next_surface_id_namespace_++));
+  std::unique_ptr<cc::SurfaceIdAllocator> allocator =
+      base::WrapUnique(new cc::SurfaceIdAllocator(next_surface_client_id_++));
   if (GetSurfaceManager())
-    allocator->RegisterSurfaceIdNamespace(GetSurfaceManager());
+    allocator->RegisterSurfaceClientId(GetSurfaceManager());
   return allocator;
 }
 
diff --git a/content/browser/compositor/gpu_process_transport_factory.h b/content/browser/compositor/gpu_process_transport_factory.h
index 0cad211..0db60467 100644
--- a/content/browser/compositor/gpu_process_transport_factory.h
+++ b/content/browser/compositor/gpu_process_transport_factory.h
@@ -103,7 +103,7 @@
   std::unique_ptr<display_compositor::GLHelper> gl_helper_;
   base::ObserverList<ui::ContextFactoryObserver> observer_list_;
   std::unique_ptr<cc::SurfaceManager> surface_manager_;
-  uint32_t next_surface_id_namespace_;
+  uint32_t next_surface_client_id_;
   std::unique_ptr<cc::SingleThreadTaskGraphRunner> task_graph_runner_;
   scoped_refptr<ContextProviderCommandBuffer> shared_worker_context_provider_;
 
diff --git a/content/browser/devtools/protocol/input_handler.cc b/content/browser/devtools/protocol/input_handler.cc
index 120314bf..e77697f 100644
--- a/content/browser/devtools/protocol/input_handler.cc
+++ b/content/browser/devtools/protocol/input_handler.cc
@@ -166,6 +166,7 @@
     const bool* is_keypad,
     const bool* is_system_key) {
   NativeWebKeyboardEvent event;
+  event.skip_in_browser = true;
 
   if (type == dispatch_key_event::kTypeKeyDown) {
     event.type = blink::WebInputEvent::KeyDown;
diff --git a/content/browser/download/download_item_impl.cc b/content/browser/download/download_item_impl.cc
index be68b07..674cc90dd 100644
--- a/content/browser/download/download_item_impl.cc
+++ b/content/browser/download/download_item_impl.cc
@@ -766,10 +766,6 @@
   open_when_complete_ = open;
 }
 
-void DownloadItemImpl::SetIsTemporary(bool temporary) {
-  is_temporary_ = temporary;
-}
-
 void DownloadItemImpl::SetOpened(bool opened) {
   opened_ = opened;
 }
diff --git a/content/browser/download/download_item_impl.h b/content/browser/download/download_item_impl.h
index 802c5af..abf382e 100644
--- a/content/browser/download/download_item_impl.h
+++ b/content/browser/download/download_item_impl.h
@@ -161,7 +161,6 @@
   WebContents* GetWebContents() const override;
   void OnContentCheckCompleted(DownloadDangerType danger_type) override;
   void SetOpenWhenComplete(bool open) override;
-  void SetIsTemporary(bool temporary) override;
   void SetOpened(bool opened) override;
   void SetDisplayName(const base::FilePath& name) override;
   std::string DebugString(bool verbose) const override;
diff --git a/content/browser/download/download_item_impl_unittest.cc b/content/browser/download/download_item_impl_unittest.cc
index c9389638..a68eca8 100644
--- a/content/browser/download/download_item_impl_unittest.cc
+++ b/content/browser/download/download_item_impl_unittest.cc
@@ -1309,10 +1309,12 @@
 }
 
 TEST_F(DownloadItemTest, EnabledActionsForTemporaryDownload) {
+  // A download created with a non-empty FilePath is considered a temporary
+  // download.
+  create_info()->save_info->file_path = base::FilePath(kDummyTargetPath);
   DownloadItemImpl* item = CreateDownloadItem();
   MockDownloadFile* download_file =
       DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
-  item->SetIsTemporary(true);
 
   // InProgress Temporary
   ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
diff --git a/content/browser/download/download_manager_impl_unittest.cc b/content/browser/download/download_manager_impl_unittest.cc
index e17656e..52933ca 100644
--- a/content/browser/download/download_manager_impl_unittest.cc
+++ b/content/browser/download/download_manager_impl_unittest.cc
@@ -177,7 +177,6 @@
   MOCK_CONST_METHOD0(HasUserGesture, bool());
   MOCK_CONST_METHOD0(GetTransitionType, ui::PageTransition());
   MOCK_CONST_METHOD0(IsTemporary, bool());
-  MOCK_METHOD1(SetIsTemporary, void(bool));
   MOCK_METHOD1(SetOpened, void(bool));
   MOCK_CONST_METHOD0(GetOpened, bool());
   MOCK_CONST_METHOD0(GetLastModifiedTime, const std::string&());
diff --git a/content/browser/frame_host/cross_process_frame_connector.cc b/content/browser/frame_host/cross_process_frame_connector.cc
index 8fd9e87..dc21186 100644
--- a/content/browser/frame_host/cross_process_frame_connector.cc
+++ b/content/browser/frame_host/cross_process_frame_connector.cc
@@ -97,7 +97,7 @@
   std::vector<uint32_t> sequences;
   sequences.push_back(sequence.sequence);
   cc::SurfaceManager* manager = GetSurfaceManager();
-  manager->DidSatisfySequences(sequence.id_namespace, &sequences);
+  manager->DidSatisfySequences(sequence.client_id, &sequences);
 }
 
 void CrossProcessFrameConnector::OnRequireSequence(
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame.cc b/content/browser/frame_host/render_widget_host_view_child_frame.cc
index 67dfe7d..7da5da6 100644
--- a/content/browser/frame_host/render_widget_host_view_child_frame.cc
+++ b/content/browser/frame_host/render_widget_host_view_child_frame.cc
@@ -48,7 +48,7 @@
       frame_connector_(nullptr),
       begin_frame_source_(nullptr),
       observing_begin_frame_source_(false),
-      parent_surface_id_namespace_(0),
+      parent_surface_client_id_(0),
       weak_factory_(this) {
   id_allocator_ = CreateSurfaceIdAllocator();
   RegisterSurfaceNamespaceId();
@@ -67,28 +67,28 @@
     return;
 
   if (frame_connector_) {
-    if (parent_surface_id_namespace_) {
+    if (parent_surface_client_id_) {
       GetSurfaceManager()->UnregisterSurfaceNamespaceHierarchy(
-          parent_surface_id_namespace_, GetSurfaceIdNamespace());
+          parent_surface_client_id_, GetSurfaceClientId());
     }
     // Unregister the client here, as it is not guaranteed in tests that the
     // destructor will be called.
     GetSurfaceManager()->UnregisterSurfaceFactoryClient(
-        id_allocator_->id_namespace());
+        id_allocator_->client_id());
 
-    parent_surface_id_namespace_ = 0;
+    parent_surface_client_id_ = 0;
   }
   frame_connector_ = frame_connector;
   if (frame_connector_) {
     GetSurfaceManager()->RegisterSurfaceFactoryClient(
-        id_allocator_->id_namespace(), this);
+        id_allocator_->client_id(), this);
     RenderWidgetHostViewBase* parent_view =
         frame_connector_->GetParentRenderWidgetHostView();
     if (parent_view) {
-      parent_surface_id_namespace_ = parent_view->GetSurfaceIdNamespace();
-      DCHECK_NE(parent_surface_id_namespace_, 0u);
+      parent_surface_client_id_ = parent_view->GetSurfaceClientId();
+      DCHECK_NE(parent_surface_client_id_, 0u);
       GetSurfaceManager()->RegisterSurfaceNamespaceHierarchy(
-          parent_surface_id_namespace_, GetSurfaceIdNamespace());
+          parent_surface_client_id_, GetSurfaceClientId());
     }
   }
 }
@@ -262,7 +262,7 @@
 }
 
 void RenderWidgetHostViewChildFrame::Destroy() {
-  // SurfaceIdNamespaces registered with RenderWidgetHostInputEventRouter
+  // SurfaceClientIds registered with RenderWidgetHostInputEventRouter
   // have already been cleared when RenderWidgetHostViewBase notified its
   // observers of our impending destruction.
   if (frame_connector_) {
@@ -304,16 +304,16 @@
   if (host_ && host_->delegate() && host_->delegate()->GetInputEventRouter()) {
     RenderWidgetHostInputEventRouter* router =
         host_->delegate()->GetInputEventRouter();
-    if (!router->is_registered(GetSurfaceIdNamespace()))
-      router->AddSurfaceIdNamespaceOwner(GetSurfaceIdNamespace(), this);
+    if (!router->is_registered(GetSurfaceClientId()))
+      router->AddSurfaceClientIdOwner(GetSurfaceClientId(), this);
   }
 }
 
 void RenderWidgetHostViewChildFrame::UnregisterSurfaceNamespaceId() {
   DCHECK(host_);
   if (host_->delegate() && host_->delegate()->GetInputEventRouter()) {
-    host_->delegate()->GetInputEventRouter()->RemoveSurfaceIdNamespaceOwner(
-        GetSurfaceIdNamespace());
+    host_->delegate()->GetInputEventRouter()->RemoveSurfaceClientIdOwner(
+        GetSurfaceClientId());
   }
 }
 
@@ -392,7 +392,7 @@
     surface_factory_->Create(surface_id_);
 
     cc::SurfaceSequence sequence = cc::SurfaceSequence(
-        id_allocator_->id_namespace(), next_surface_sequence_++);
+        id_allocator_->client_id(), next_surface_sequence_++);
     // The renderer process will satisfy this dependency when it creates a
     // SurfaceLayer.
     cc::SurfaceManager* manager = GetSurfaceManager();
@@ -473,8 +473,8 @@
   return false;
 }
 
-uint32_t RenderWidgetHostViewChildFrame::GetSurfaceIdNamespace() {
-  return id_allocator_->id_namespace();
+uint32_t RenderWidgetHostViewChildFrame::GetSurfaceClientId() {
+  return id_allocator_->client_id();
 }
 
 void RenderWidgetHostViewChildFrame::ProcessKeyboardEvent(
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame.h b/content/browser/frame_host/render_widget_host_view_child_frame.h
index dc9bd12..74d535b 100644
--- a/content/browser/frame_host/render_widget_host_view_child_frame.h
+++ b/content/browser/frame_host/render_widget_host_view_child_frame.h
@@ -127,7 +127,7 @@
                               InputEventAckState ack_result) override;
   bool LockMouse() override;
   void UnlockMouse() override;
-  uint32_t GetSurfaceIdNamespace() override;
+  uint32_t GetSurfaceClientId() override;
   void ProcessKeyboardEvent(const NativeWebKeyboardEvent& event) override;
   void ProcessMouseEvent(const blink::WebMouseEvent& event,
                          const ui::LatencyInfo& latency) override;
@@ -234,8 +234,8 @@
   cc::BeginFrameSource* begin_frame_source_;
   cc::BeginFrameArgs last_begin_frame_args_;
   bool observing_begin_frame_source_;
-  // The surface id namespace of the parent RenderWidgetHostView.  0 if none.
-  uint32_t parent_surface_id_namespace_;
+  // The surface client ID of the parent RenderWidgetHostView.  0 if none.
+  uint32_t parent_surface_client_id_;
 
   base::WeakPtrFactory<RenderWidgetHostViewChildFrame> weak_factory_;
   DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewChildFrame);
diff --git a/content/browser/frame_host/render_widget_host_view_guest.cc b/content/browser/frame_host/render_widget_host_view_guest.cc
index b4557c2..82c0da9 100644
--- a/content/browser/frame_host/render_widget_host_view_guest.cc
+++ b/content/browser/frame_host/render_widget_host_view_guest.cc
@@ -115,7 +115,7 @@
     // the renderer.
     if (!surface_id_.is_null()) {
       cc::SurfaceSequence sequence = cc::SurfaceSequence(
-          id_allocator_->id_namespace(), next_surface_sequence_++);
+          id_allocator_->client_id(), next_surface_sequence_++);
       GetSurfaceManager()
           ->GetSurfaceForId(surface_id_)
           ->AddDestructionDependency(sequence);
@@ -295,7 +295,7 @@
     surface_factory_->Create(surface_id_);
 
     cc::SurfaceSequence sequence = cc::SurfaceSequence(
-        id_allocator_->id_namespace(), next_surface_sequence_++);
+        id_allocator_->client_id(), next_surface_sequence_++);
     // The renderer process will satisfy this dependency when it creates a
     // SurfaceLayer.
     cc::SurfaceManager* manager = GetSurfaceManager();
diff --git a/content/browser/indexed_db/indexed_db_backing_store.cc b/content/browser/indexed_db/indexed_db_backing_store.cc
index 020126e..a2dccf46 100644
--- a/content/browser/indexed_db/indexed_db_backing_store.cc
+++ b/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -819,18 +819,15 @@
     const Origin& origin,
     const base::FilePath& path_base,
     net::URLRequestContext* request_context,
-    blink::WebIDBDataLoss* data_loss,
-    std::string* data_loss_message,
+    IndexedDBDataLossInfo* data_loss_info,
     bool* disk_full,
     base::SequencedTaskRunner* task_runner,
     bool clean_journal,
     leveldb::Status* status) {
-  *data_loss = blink::WebIDBDataLossNone;
   DefaultLevelDBFactory leveldb_factory;
   return IndexedDBBackingStore::Open(
-      indexed_db_factory, origin, path_base, request_context, data_loss,
-      data_loss_message, disk_full, &leveldb_factory, task_runner,
-      clean_journal, status);
+      indexed_db_factory, origin, path_base, request_context, data_loss_info,
+      disk_full, &leveldb_factory, task_runner, clean_journal, status);
 }
 
 static std::string OriginToCustomHistogramSuffix(const Origin& origin) {
@@ -962,8 +959,7 @@
     const Origin& origin,
     const base::FilePath& path_base,
     net::URLRequestContext* request_context,
-    blink::WebIDBDataLoss* data_loss,
-    std::string* data_loss_message,
+    IndexedDBDataLossInfo* data_loss_info,
     bool* is_disk_full,
     LevelDBFactory* leveldb_factory,
     base::SequencedTaskRunner* task_runner,
@@ -971,10 +967,9 @@
     leveldb::Status* status) {
   IDB_TRACE("IndexedDBBackingStore::Open");
   DCHECK(!path_base.empty());
-  *data_loss = blink::WebIDBDataLossNone;
-  *data_loss_message = "";
   *is_disk_full = false;
 
+  data_loss_info->status = blink::WebIDBDataLossNone;
   *status = leveldb::Status::OK();
 
   std::unique_ptr<LevelDBComparator> comparator(new Comparator());
@@ -1012,8 +1007,8 @@
     if (leveldb_env::IndicatesDiskFull(*status)) {
       *is_disk_full = true;
     } else if (status->IsCorruption()) {
-      *data_loss = blink::WebIDBDataLossTotal;
-      *data_loss_message = leveldb_env::GetCorruptionMessage(*status);
+      data_loss_info->status = blink::WebIDBDataLossTotal;
+      data_loss_info->message = leveldb_env::GetCorruptionMessage(*status);
     }
   }
 
@@ -1026,8 +1021,8 @@
       HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_PRIOR_CORRUPTION,
                           origin);
       db.reset();
-      *data_loss = blink::WebIDBDataLossTotal;
-      *data_loss_message =
+      data_loss_info->status = blink::WebIDBDataLossTotal;
+      data_loss_info->message =
           "IndexedDB (database was corrupt): " + corruption_message;
     } else if (!IsSchemaKnown(db.get(), &is_schema_known)) {
       LOG(ERROR) << "IndexedDB had IO error checking schema, treating it as "
@@ -1036,16 +1031,16 @@
           INDEXED_DB_BACKING_STORE_OPEN_FAILED_IO_ERROR_CHECKING_SCHEMA,
           origin);
       db.reset();
-      *data_loss = blink::WebIDBDataLossTotal;
-      *data_loss_message = "I/O error checking schema";
+      data_loss_info->status = blink::WebIDBDataLossTotal;
+      data_loss_info->message = "I/O error checking schema";
     } else if (!is_schema_known) {
       LOG(ERROR) << "IndexedDB backing store had unknown schema, treating it "
                     "as failure to open";
       HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_SCHEMA,
                           origin);
       db.reset();
-      *data_loss = blink::WebIDBDataLossTotal;
-      *data_loss_message = "Unknown schema";
+      data_loss_info->status = blink::WebIDBDataLossTotal;
+      data_loss_info->message = "Unknown schema";
     }
   }
 
diff --git a/content/browser/indexed_db/indexed_db_backing_store.h b/content/browser/indexed_db/indexed_db_backing_store.h
index 7368eec..722a1d4 100644
--- a/content/browser/indexed_db/indexed_db_backing_store.h
+++ b/content/browser/indexed_db/indexed_db_backing_store.h
@@ -56,6 +56,7 @@
 class LevelDBComparator;
 class LevelDBDatabase;
 class LevelDBFactory;
+struct IndexedDBDataLossInfo;
 struct IndexedDBValue;
 
 class CONTENT_EXPORT IndexedDBBackingStore
@@ -372,8 +373,7 @@
       const url::Origin& origin,
       const base::FilePath& path_base,
       net::URLRequestContext* request_context,
-      blink::WebIDBDataLoss* data_loss,
-      std::string* data_loss_message,
+      IndexedDBDataLossInfo* data_loss_info,
       bool* disk_full,
       base::SequencedTaskRunner* task_runner,
       bool clean_journal,
@@ -383,8 +383,7 @@
       const url::Origin& origin,
       const base::FilePath& path_base,
       net::URLRequestContext* request_context,
-      blink::WebIDBDataLoss* data_loss,
-      std::string* data_loss_message,
+      IndexedDBDataLossInfo* data_loss_info,
       bool* disk_full,
       LevelDBFactory* leveldb_factory,
       base::SequencedTaskRunner* task_runner,
diff --git a/content/browser/indexed_db/indexed_db_backing_store_unittest.cc b/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
index c049019d..644e608b 100644
--- a/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
@@ -187,18 +187,12 @@
   scoped_refptr<TestableIndexedDBBackingStore> OpenBackingStoreForTest(
       const Origin& origin,
       net::URLRequestContext* url_request_context) {
-    blink::WebIDBDataLoss data_loss;
-    std::string data_loss_reason;
+    IndexedDBDataLossInfo data_loss_info;
     bool disk_full;
     leveldb::Status status;
     scoped_refptr<IndexedDBBackingStore> backing_store =
-        OpenBackingStore(origin,
-                         context()->data_path(),
-                         url_request_context,
-                         &data_loss,
-                         &data_loss_reason,
-                         &disk_full,
-                         &status);
+        OpenBackingStore(origin, context()->data_path(), url_request_context,
+                         &data_loss_info, &disk_full, &status);
     scoped_refptr<TestableIndexedDBBackingStore> testable_store =
         static_cast<TestableIndexedDBBackingStore*>(backing_store.get());
     return testable_store;
@@ -211,8 +205,7 @@
       const Origin& origin,
       const base::FilePath& data_directory,
       net::URLRequestContext* request_context,
-      blink::WebIDBDataLoss* data_loss,
-      std::string* data_loss_message,
+      IndexedDBDataLossInfo* data_loss_info,
       bool* disk_full,
       bool first_time,
       leveldb::Status* status) override {
diff --git a/content/browser/indexed_db/indexed_db_callbacks.cc b/content/browser/indexed_db/indexed_db_callbacks.cc
index 6c541b7..353fa45 100644
--- a/content/browser/indexed_db/indexed_db_callbacks.cc
+++ b/content/browser/indexed_db/indexed_db_callbacks.cc
@@ -7,6 +7,7 @@
 #include <stddef.h>
 
 #include <algorithm>
+#include <utility>
 
 #include "base/metrics/histogram.h"
 #include "base/strings/utf_string_conversions.h"
@@ -49,7 +50,6 @@
       host_transaction_id_(kNoTransaction),
       ipc_database_id_(kNoDatabase),
       ipc_database_callbacks_id_(kNoDatabaseCallbacks),
-      data_loss_(blink::WebIDBDataLossNone),
       sent_blocked_(false) {}
 
 IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
@@ -63,7 +63,6 @@
       host_transaction_id_(kNoTransaction),
       ipc_database_id_(kNoDatabase),
       ipc_database_callbacks_id_(kNoDatabaseCallbacks),
-      data_loss_(blink::WebIDBDataLossNone),
       sent_blocked_(false) {}
 
 IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
@@ -80,7 +79,6 @@
       origin_(origin),
       ipc_database_id_(kNoDatabase),
       ipc_database_callbacks_id_(ipc_database_callbacks_id),
-      data_loss_(blink::WebIDBDataLossNone),
       sent_blocked_(false) {}
 
 IndexedDBCallbacks::~IndexedDBCallbacks() {}
@@ -107,7 +105,7 @@
   DCHECK_EQ(kNoTransaction, host_transaction_id_);
   DCHECK_EQ(kNoDatabase, ipc_database_id_);
   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
-  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
+  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_info_.status);
 
   std::vector<base::string16> list;
   for (unsigned i = 0; i < value.size(); ++i)
@@ -142,11 +140,8 @@
   }
 }
 
-void IndexedDBCallbacks::OnDataLoss(blink::WebIDBDataLoss data_loss,
-                                    std::string data_loss_message) {
-  DCHECK_NE(blink::WebIDBDataLossNone, data_loss);
-  data_loss_ = data_loss;
-  data_loss_message_ = data_loss_message;
+void IndexedDBCallbacks::OnDataLoss(const IndexedDBDataLossInfo& info) {
+  data_loss_info_ = info;
 }
 
 void IndexedDBCallbacks::OnUpgradeNeeded(
@@ -173,8 +168,8 @@
   params.ipc_database_callbacks_id = ipc_database_callbacks_id_;
   params.old_version = old_version;
   params.idb_metadata = IndexedDBDispatcherHost::ConvertMetadata(metadata);
-  params.data_loss = data_loss_;
-  params.data_loss_message = data_loss_message_;
+  params.data_loss = data_loss_info_.status;
+  params.data_loss_message = data_loss_info_.message;
   dispatcher_host_->Send(new IndexedDBMsg_CallbacksUpgradeNeeded(params));
 
   if (!connection_open_start_time_.is_null()) {
@@ -345,7 +340,7 @@
   DCHECK_EQ(kNoTransaction, host_transaction_id_);
   DCHECK_EQ(kNoDatabase, ipc_database_id_);
   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
-  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
+  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_info_.status);
 
   int32_t ipc_object_id = dispatcher_host_->Add(cursor.get());
   std::unique_ptr<IndexedDBMsg_CallbacksSuccessIDBCursor_Params> params(
@@ -384,7 +379,7 @@
   DCHECK_EQ(kNoTransaction, host_transaction_id_);
   DCHECK_EQ(kNoDatabase, ipc_database_id_);
   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
-  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
+  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_info_.status);
 
   IndexedDBCursor* idb_cursor =
       dispatcher_host_->GetCursorFromId(ipc_cursor_id_);
@@ -435,7 +430,7 @@
   DCHECK_EQ(kNoTransaction, host_transaction_id_);
   DCHECK_EQ(kNoDatabase, ipc_database_id_);
   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
-  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
+  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_info_.status);
 
   std::vector<IndexedDBKey> msg_keys;
   std::vector<IndexedDBKey> msg_primary_keys;
@@ -493,7 +488,7 @@
   DCHECK_EQ(kNoTransaction, host_transaction_id_);
   DCHECK_EQ(kNoDatabase, ipc_database_id_);
   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
-  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
+  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_info_.status);
 
   std::unique_ptr<IndexedDBMsg_CallbacksSuccessValue_Params> params(
       new IndexedDBMsg_CallbacksSuccessValue_Params());
@@ -529,7 +524,7 @@
   DCHECK_EQ(kNoTransaction, host_transaction_id_);
   DCHECK_EQ(kNoDatabase, ipc_database_id_);
   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
-  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
+  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_info_.status);
 
   std::unique_ptr<IndexedDBMsg_CallbacksSuccessArray_Params> params(
       new IndexedDBMsg_CallbacksSuccessArray_Params());
@@ -573,7 +568,7 @@
   DCHECK_EQ(kNoTransaction, host_transaction_id_);
   DCHECK_EQ(kNoDatabase, ipc_database_id_);
   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
-  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
+  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_info_.status);
 
   dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIndexedDBKey(
       ipc_thread_id_, ipc_callbacks_id_, value));
@@ -587,7 +582,7 @@
   DCHECK_EQ(kNoTransaction, host_transaction_id_);
   DCHECK_EQ(kNoDatabase, ipc_database_id_);
   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
-  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
+  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_info_.status);
 
   dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessInteger(
       ipc_thread_id_, ipc_callbacks_id_, value));
@@ -601,7 +596,7 @@
   DCHECK_EQ(kNoTransaction, host_transaction_id_);
   DCHECK_EQ(kNoDatabase, ipc_database_id_);
   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
-  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
+  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_info_.status);
 
   dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessUndefined(
       ipc_thread_id_, ipc_callbacks_id_));
diff --git a/content/browser/indexed_db/indexed_db_callbacks.h b/content/browser/indexed_db/indexed_db_callbacks.h
index 4895c3b..683a15e7 100644
--- a/content/browser/indexed_db/indexed_db_callbacks.h
+++ b/content/browser/indexed_db/indexed_db_callbacks.h
@@ -31,6 +31,11 @@
 struct IndexedDBReturnValue;
 struct IndexedDBValue;
 
+struct IndexedDBDataLossInfo {
+  blink::WebIDBDataLoss status = blink::WebIDBDataLossNone;
+  std::string message;
+};
+
 class CONTENT_EXPORT IndexedDBCallbacks
     : public base::RefCounted<IndexedDBCallbacks> {
  public:
@@ -62,8 +67,7 @@
   virtual void OnBlocked(int64_t existing_version);
 
   // IndexedDBFactory::Open
-  virtual void OnDataLoss(blink::WebIDBDataLoss data_loss,
-                          std::string data_loss_message);
+  virtual void OnDataLoss(const IndexedDBDataLossInfo& data_loss_info);
   virtual void OnUpgradeNeeded(
       int64_t old_version,
       std::unique_ptr<IndexedDBConnection> connection,
@@ -107,7 +111,9 @@
   // IndexedDBCursor::Continue / Advance (when complete)
   virtual void OnSuccess();
 
-  blink::WebIDBDataLoss data_loss() const { return data_loss_; }
+  const IndexedDBDataLossInfo& data_loss_info() const {
+    return data_loss_info_;
+  }
 
   void SetConnectionOpenStartTime(const base::TimeTicks& start_time);
 
@@ -134,9 +140,8 @@
   int32_t ipc_database_id_;
   int32_t ipc_database_callbacks_id_;
 
-  // Stored in OnDataLoss, merged with OnUpgradeNeeded response.
-  blink::WebIDBDataLoss data_loss_;
-  std::string data_loss_message_;
+  // Used to assert that OnSuccess is only called if there was no data loss.
+  IndexedDBDataLossInfo data_loss_info_;
 
   // The "blocked" event should be sent at most once per request.
   bool sent_blocked_;
diff --git a/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc b/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc
index a922cffa..d6660df 100644
--- a/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "content/browser/indexed_db/indexed_db_backing_store.h"
+#include "content/browser/indexed_db/indexed_db_callbacks.h"
 #include "content/browser/indexed_db/leveldb/leveldb_database.h"
 #include "content/browser/indexed_db/leveldb/mock_leveldb_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -98,24 +99,15 @@
 
   EXPECT_CALL(mock_leveldb_factory, OpenLevelDB(_, _, _, _)).Times(Exactly(1));
   EXPECT_CALL(mock_leveldb_factory, DestroyLevelDB(_)).Times(Exactly(1));
-  blink::WebIDBDataLoss data_loss = blink::WebIDBDataLossNone;
-  std::string data_loss_message;
+  content::IndexedDBDataLossInfo data_loss_info;
   bool disk_full = false;
   base::SequencedTaskRunner* task_runner = NULL;
   bool clean_journal = false;
   leveldb::Status s;
   scoped_refptr<IndexedDBBackingStore> backing_store =
-      IndexedDBBackingStore::Open(factory,
-                                  origin,
-                                  path,
-                                  request_context,
-                                  &data_loss,
-                                  &data_loss_message,
-                                  &disk_full,
-                                  &mock_leveldb_factory,
-                                  task_runner,
-                                  clean_journal,
-                                  &s);
+      IndexedDBBackingStore::Open(
+          factory, origin, path, request_context, &data_loss_info, &disk_full,
+          &mock_leveldb_factory, task_runner, clean_journal, &s);
 }
 
 TEST(IndexedDBNonRecoverableIOErrorTest, NuancedCleanupTest) {
@@ -125,9 +117,7 @@
   base::ScopedTempDir temp_directory;
   ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
   const base::FilePath path = temp_directory.path();
-  blink::WebIDBDataLoss data_loss =
-      blink::WebIDBDataLossNone;
-  std::string data_loss_reason;
+  content::IndexedDBDataLossInfo data_loss_info;
   bool disk_full = false;
   base::SequencedTaskRunner* task_runner = NULL;
   bool clean_journal = false;
@@ -147,17 +137,9 @@
                                           leveldb_env::kNewLogger,
                                           base::File::FILE_ERROR_NO_SPACE));
   scoped_refptr<IndexedDBBackingStore> backing_store =
-      IndexedDBBackingStore::Open(factory,
-                                  origin,
-                                  path,
-                                  request_context,
-                                  &data_loss,
-                                  &data_loss_reason,
-                                  &disk_full,
-                                  &mock_leveldb_factory,
-                                  task_runner,
-                                  clean_journal,
-                                  &s);
+      IndexedDBBackingStore::Open(
+          factory, origin, path, request_context, &data_loss_info, &disk_full,
+          &mock_leveldb_factory, task_runner, clean_journal, &s);
   ASSERT_TRUE(s.IsIOError());
 
   busted_factory.SetOpenError(MakeIOError("some filename",
@@ -165,34 +147,18 @@
                                           leveldb_env::kNewLogger,
                                           base::File::FILE_ERROR_NO_MEMORY));
   scoped_refptr<IndexedDBBackingStore> backing_store2 =
-      IndexedDBBackingStore::Open(factory,
-                                  origin,
-                                  path,
-                                  request_context,
-                                  &data_loss,
-                                  &data_loss_reason,
-                                  &disk_full,
-                                  &mock_leveldb_factory,
-                                  task_runner,
-                                  clean_journal,
-                                  &s);
+      IndexedDBBackingStore::Open(
+          factory, origin, path, request_context, &data_loss_info, &disk_full,
+          &mock_leveldb_factory, task_runner, clean_journal, &s);
   ASSERT_TRUE(s.IsIOError());
 
   busted_factory.SetOpenError(MakeIOError("some filename", "some message",
                                           leveldb_env::kNewLogger,
                                           base::File::FILE_ERROR_IO));
   scoped_refptr<IndexedDBBackingStore> backing_store3 =
-      IndexedDBBackingStore::Open(factory,
-                                  origin,
-                                  path,
-                                  request_context,
-                                  &data_loss,
-                                  &data_loss_reason,
-                                  &disk_full,
-                                  &mock_leveldb_factory,
-                                  task_runner,
-                                  clean_journal,
-                                  &s);
+      IndexedDBBackingStore::Open(
+          factory, origin, path, request_context, &data_loss_info, &disk_full,
+          &mock_leveldb_factory, task_runner, clean_journal, &s);
   ASSERT_TRUE(s.IsIOError());
 
   busted_factory.SetOpenError(MakeIOError("some filename",
@@ -200,17 +166,9 @@
                                           leveldb_env::kNewLogger,
                                           base::File::FILE_ERROR_FAILED));
   scoped_refptr<IndexedDBBackingStore> backing_store4 =
-      IndexedDBBackingStore::Open(factory,
-                                  origin,
-                                  path,
-                                  request_context,
-                                  &data_loss,
-                                  &data_loss_reason,
-                                  &disk_full,
-                                  &mock_leveldb_factory,
-                                  task_runner,
-                                  clean_journal,
-                                  &s);
+      IndexedDBBackingStore::Open(
+          factory, origin, path, request_context, &data_loss_info, &disk_full,
+          &mock_leveldb_factory, task_runner, clean_journal, &s);
   ASSERT_TRUE(s.IsIOError());
 }
 
diff --git a/content/browser/indexed_db/indexed_db_database.cc b/content/browser/indexed_db/indexed_db_database.cc
index 3b4b7173..82f3609c0 100644
--- a/content/browser/indexed_db/indexed_db_database.cc
+++ b/content/browser/indexed_db/indexed_db_database.cc
@@ -1740,7 +1740,8 @@
     // The backing store only detects data loss when it is first opened. The
     // presence of existing connections means we didn't even check for data loss
     // so there'd better not be any.
-    DCHECK_NE(blink::WebIDBDataLossTotal, connection.callbacks->data_loss());
+    DCHECK_NE(blink::WebIDBDataLossTotal,
+              connection.callbacks->data_loss_info().status);
     pending_open_calls_.push(connection);
     return;
   }
@@ -1830,7 +1831,7 @@
   DCHECK(callbacks.get());
   DCHECK(connections_.count(connection.get()));
   if (ConnectionCount() > 1) {
-    DCHECK_NE(blink::WebIDBDataLossTotal, callbacks->data_loss());
+    DCHECK_NE(blink::WebIDBDataLossTotal, callbacks->data_loss_info().status);
     // Front end ensures the event is not fired at connections that have
     // close_pending set.
     for (const auto* iter : connections_) {
diff --git a/content/browser/indexed_db/indexed_db_factory.h b/content/browser/indexed_db/indexed_db_factory.h
index 1ac6625..3b64fb2 100644
--- a/content/browser/indexed_db/indexed_db_factory.h
+++ b/content/browser/indexed_db/indexed_db_factory.h
@@ -31,6 +31,7 @@
 
 class IndexedDBBackingStore;
 struct IndexedDBPendingConnection;
+struct IndexedDBDataLossInfo;
 
 class CONTENT_EXPORT IndexedDBFactory
     : NON_EXPORTED_BASE(public base::RefCountedThreadSafe<IndexedDBFactory>) {
@@ -91,8 +92,7 @@
       const url::Origin& origin,
       const base::FilePath& data_directory,
       net::URLRequestContext* request_context,
-      blink::WebIDBDataLoss* data_loss,
-      std::string* data_loss_reason,
+      IndexedDBDataLossInfo* data_loss_info,
       bool* disk_full,
       leveldb::Status* status) = 0;
 
@@ -100,8 +100,7 @@
       const url::Origin& origin,
       const base::FilePath& data_directory,
       net::URLRequestContext* request_context,
-      blink::WebIDBDataLoss* data_loss,
-      std::string* data_loss_message,
+      IndexedDBDataLossInfo* data_loss_info,
       bool* disk_full,
       bool first_time,
       leveldb::Status* status) = 0;
diff --git a/content/browser/indexed_db/indexed_db_factory_impl.cc b/content/browser/indexed_db/indexed_db_factory_impl.cc
index 38836c1..1ddb6d4 100644
--- a/content/browser/indexed_db/indexed_db_factory_impl.cc
+++ b/content/browser/indexed_db/indexed_db_factory_impl.cc
@@ -175,14 +175,12 @@
     net::URLRequestContext* request_context) {
   IDB_TRACE("IndexedDBFactoryImpl::GetDatabaseNames");
   // TODO(dgrogan): Plumb data_loss back to script eventually?
-  blink::WebIDBDataLoss data_loss;
-  std::string data_loss_message;
+  IndexedDBDataLossInfo data_loss_info;
   bool disk_full;
   leveldb::Status s;
   // TODO(cmumford): Handle this error
-  scoped_refptr<IndexedDBBackingStore> backing_store =
-      OpenBackingStore(origin, data_directory, request_context, &data_loss,
-                       &data_loss_message, &disk_full, &s);
+  scoped_refptr<IndexedDBBackingStore> backing_store = OpenBackingStore(
+      origin, data_directory, request_context, &data_loss_info, &disk_full, &s);
   if (!backing_store.get()) {
     callbacks->OnError(
         IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
@@ -225,13 +223,11 @@
   }
 
   // TODO(dgrogan): Plumb data_loss back to script eventually?
-  blink::WebIDBDataLoss data_loss;
-  std::string data_loss_message;
+  IndexedDBDataLossInfo data_loss_info;
   bool disk_full = false;
   leveldb::Status s;
-  scoped_refptr<IndexedDBBackingStore> backing_store =
-      OpenBackingStore(origin, data_directory, request_context, &data_loss,
-                       &data_loss_message, &disk_full, &s);
+  scoped_refptr<IndexedDBBackingStore> backing_store = OpenBackingStore(
+      origin, data_directory, request_context, &data_loss_info, &disk_full, &s);
   if (!backing_store.get()) {
     IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
                                  ASCIIToUTF16(
@@ -346,22 +342,20 @@
     const Origin& origin,
     const base::FilePath& data_directory,
     net::URLRequestContext* request_context,
-    blink::WebIDBDataLoss* data_loss,
-    std::string* data_loss_message,
+    IndexedDBDataLossInfo* data_loss_info,
     bool* disk_full,
     bool first_time,
     leveldb::Status* status) {
   return IndexedDBBackingStore::Open(
-      this, origin, data_directory, request_context, data_loss,
-      data_loss_message, disk_full, context_->TaskRunner(), first_time, status);
+      this, origin, data_directory, request_context, data_loss_info, disk_full,
+      context_->TaskRunner(), first_time, status);
 }
 
 scoped_refptr<IndexedDBBackingStore> IndexedDBFactoryImpl::OpenBackingStore(
     const Origin& origin,
     const base::FilePath& data_directory,
     net::URLRequestContext* request_context,
-    blink::WebIDBDataLoss* data_loss,
-    std::string* data_loss_message,
+    IndexedDBDataLossInfo* data_loss_info,
     bool* disk_full,
     leveldb::Status* status) {
   const bool open_in_memory = data_directory.empty();
@@ -380,9 +374,9 @@
   } else {
     first_time = !backends_opened_since_boot_.count(origin);
 
-    backing_store = OpenBackingStoreHelper(
-        origin, data_directory, request_context, data_loss, data_loss_message,
-        disk_full, first_time, status);
+    backing_store =
+        OpenBackingStoreHelper(origin, data_directory, request_context,
+                               data_loss_info, disk_full, first_time, status);
   }
 
   if (backing_store.get()) {
@@ -412,15 +406,14 @@
   scoped_refptr<IndexedDBDatabase> database;
   IndexedDBDatabase::Identifier unique_identifier(origin, name);
   const auto& it = database_map_.find(unique_identifier);
-  blink::WebIDBDataLoss data_loss = blink::WebIDBDataLossNone;
-  std::string data_loss_message;
+  IndexedDBDataLossInfo data_loss_info;
   bool disk_full = false;
   bool was_open = (it != database_map_.end());
   if (!was_open) {
     leveldb::Status s;
     scoped_refptr<IndexedDBBackingStore> backing_store =
-        OpenBackingStore(origin, data_directory, request_context, &data_loss,
-                         &data_loss_message, &disk_full, &s);
+        OpenBackingStore(origin, data_directory, request_context,
+                         &data_loss_info, &disk_full, &s);
     if (!backing_store.get()) {
       if (disk_full) {
         connection.callbacks->OnError(
@@ -461,8 +454,8 @@
     database = it->second;
   }
 
-  if (data_loss != blink::WebIDBDataLossNone)
-    connection.callbacks->OnDataLoss(data_loss, data_loss_message);
+  if (data_loss_info.status != blink::WebIDBDataLossNone)
+    connection.callbacks->OnDataLoss(data_loss_info);
 
   database->OpenConnection(connection);
 
diff --git a/content/browser/indexed_db/indexed_db_factory_impl.h b/content/browser/indexed_db/indexed_db_factory_impl.h
index ce224d3..345f9282 100644
--- a/content/browser/indexed_db/indexed_db_factory_impl.h
+++ b/content/browser/indexed_db/indexed_db_factory_impl.h
@@ -76,8 +76,7 @@
       const url::Origin& origin,
       const base::FilePath& data_directory,
       net::URLRequestContext* request_context,
-      blink::WebIDBDataLoss* data_loss,
-      std::string* data_loss_reason,
+      IndexedDBDataLossInfo* data_loss_info,
       bool* disk_full,
       leveldb::Status* s) override;
 
@@ -85,8 +84,7 @@
       const url::Origin& origin,
       const base::FilePath& data_directory,
       net::URLRequestContext* request_context,
-      blink::WebIDBDataLoss* data_loss,
-      std::string* data_loss_message,
+      IndexedDBDataLossInfo* data_loss_info,
       bool* disk_full,
       bool first_time,
       leveldb::Status* s) override;
diff --git a/content/browser/indexed_db/indexed_db_factory_unittest.cc b/content/browser/indexed_db/indexed_db_factory_unittest.cc
index cc4cb3c..3baab1d 100644
--- a/content/browser/indexed_db/indexed_db_factory_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_factory_unittest.cc
@@ -39,20 +39,13 @@
   scoped_refptr<IndexedDBBackingStore> TestOpenBackingStore(
       const Origin& origin,
       const base::FilePath& data_directory) {
-    blink::WebIDBDataLoss data_loss =
-        blink::WebIDBDataLossNone;
-    std::string data_loss_message;
+    IndexedDBDataLossInfo data_loss_info;
     bool disk_full;
     leveldb::Status s;
     scoped_refptr<IndexedDBBackingStore> backing_store =
-        OpenBackingStore(origin,
-                         data_directory,
-                         NULL /* request_context */,
-                         &data_loss,
-                         &data_loss_message,
-                         &disk_full,
-                         &s);
-    EXPECT_EQ(blink::WebIDBDataLossNone, data_loss);
+        OpenBackingStore(origin, data_directory, NULL /* request_context */,
+                         &data_loss_info, &disk_full, &s);
+    EXPECT_EQ(blink::WebIDBDataLossNone, data_loss_info.status);
     return backing_store;
   }
 
@@ -221,8 +214,7 @@
       const Origin& origin,
       const base::FilePath& data_directory,
       net::URLRequestContext* request_context,
-      blink::WebIDBDataLoss* data_loss,
-      std::string* data_loss_message,
+      IndexedDBDataLossInfo* data_loss_info,
       bool* disk_full,
       leveldb::Status* s) override {
     *disk_full = true;
@@ -447,7 +439,7 @@
   ErrorCallbacks() : MockIndexedDBCallbacks(false), saw_error_(false) {}
 
   void OnError(const IndexedDBDatabaseError& error) override {
-    saw_error_= true;
+    saw_error_ = true;
   }
   bool saw_error() const { return saw_error_; }
 
diff --git a/content/browser/indexed_db/mock_indexed_db_factory.h b/content/browser/indexed_db/mock_indexed_db_factory.h
index 120c96a..ca073516 100644
--- a/content/browser/indexed_db/mock_indexed_db_factory.h
+++ b/content/browser/indexed_db/mock_indexed_db_factory.h
@@ -57,23 +57,21 @@
  protected:
   virtual ~MockIndexedDBFactory();
 
-  MOCK_METHOD7(OpenBackingStore,
+  MOCK_METHOD6(OpenBackingStore,
                scoped_refptr<IndexedDBBackingStore>(
                    const url::Origin& origin,
                    const base::FilePath& data_directory,
                    net::URLRequestContext* request_context,
-                   blink::WebIDBDataLoss* data_loss,
-                   std::string* data_loss_reason,
+                   IndexedDBDataLossInfo* data_loss_info,
                    bool* disk_full,
                    leveldb::Status* s));
 
-  MOCK_METHOD8(OpenBackingStoreHelper,
+  MOCK_METHOD7(OpenBackingStoreHelper,
                scoped_refptr<IndexedDBBackingStore>(
                    const url::Origin& origin,
                    const base::FilePath& data_directory,
                    net::URLRequestContext* request_context,
-                   blink::WebIDBDataLoss* data_loss,
-                   std::string* data_loss_message,
+                   IndexedDBDataLossInfo* data_loss_info,
                    bool* disk_full,
                    bool first_time,
                    leveldb::Status* s));
diff --git a/content/browser/loader/async_resource_handler.cc b/content/browser/loader/async_resource_handler.cc
index d038898..91d0350b 100644
--- a/content/browser/loader/async_resource_handler.cc
+++ b/content/browser/loader/async_resource_handler.cc
@@ -29,6 +29,7 @@
 #include "content/public/browser/resource_dispatcher_host_delegate.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/resource_response.h"
+#include "ipc/ipc_message_macros.h"
 #include "net/base/io_buffer.h"
 #include "net/base/load_flags.h"
 #include "net/log/net_log.h"
@@ -72,6 +73,14 @@
   GetNumericArg("resource-buffer-max-allocation-size", &kMaxAllocationSize);
 }
 
+// Updates |*cached| to |updated| and returns the difference from the old
+// value.
+int TrackDifference(int64_t updated, int64_t* cached) {
+  int difference = updated - *cached;
+  *cached = updated;
+  return difference;
+}
+
 }  // namespace
 
 // Used when kOptimizeLoadingIPCForSmallResources is enabled.
@@ -117,6 +126,7 @@
   // Returns true if the received data is sent to the consumer.
   bool SendInlinedDataIfApplicable(int bytes_read,
                                    int encoded_data_length,
+                                   int encoded_body_length,
                                    IPC::Sender* sender,
                                    int request_id) {
     DCHECK(sender);
@@ -129,7 +139,7 @@
     leading_chunk_buffer_ = nullptr;
 
     sender->Send(new ResourceMsg_InlinedDataChunkReceived(
-        request_id, data, encoded_data_length));
+        request_id, data, encoded_data_length, encoded_body_length));
     return true;
   }
 
@@ -206,7 +216,8 @@
       inlining_helper_(new InliningHelper),
       last_upload_position_(0),
       waiting_for_upload_progress_ack_(false),
-      reported_transfer_size_(0) {
+      reported_transfer_size_(0),
+      reported_encoded_body_length_(0) {
   InitializeResourceBufferConstants();
 }
 
@@ -338,8 +349,8 @@
   }
 
   if (rdh_->delegate()) {
-    rdh_->delegate()->OnResponseStarted(
-        request(), info->GetContext(), response, info->filter());
+    rdh_->delegate()->OnResponseStarted(request(), info->GetContext(),
+                                        response);
   }
 
   NetLogObserver::PopulateResponseInfo(request(), response);
@@ -439,10 +450,12 @@
     return false;
 
   int encoded_data_length = CalculateEncodedDataLengthToReport();
+  int encoded_body_length = CalculateEncodedBodyLengthToReport();
 
   // Return early if InliningHelper handled the received data.
   if (inlining_helper_->SendInlinedDataIfApplicable(
-          bytes_read, encoded_data_length, filter, GetRequestID()))
+          bytes_read, encoded_data_length, encoded_body_length, filter,
+          GetRequestID()))
     return true;
 
   buffer_->ShrinkLastAllocation(bytes_read);
@@ -460,8 +473,9 @@
 
   int data_offset = buffer_->GetLastAllocationOffset();
 
-  filter->Send(new ResourceMsg_DataReceived(
-      GetRequestID(), data_offset, bytes_read, encoded_data_length));
+  filter->Send(new ResourceMsg_DataReceived(GetRequestID(), data_offset,
+                                            bytes_read, encoded_data_length,
+                                            encoded_body_length));
   ++pending_data_count_;
 
   if (!buffer_->CanAllocate()) {
@@ -565,10 +579,13 @@
 }
 
 int AsyncResourceHandler::CalculateEncodedDataLengthToReport() {
-  int64_t current_transfer_size = request()->GetTotalReceivedBytes();
-  int encoded_data_length = current_transfer_size - reported_transfer_size_;
-  reported_transfer_size_ = current_transfer_size;
-  return encoded_data_length;
+  return TrackDifference(request()->GetTotalReceivedBytes(),
+                         &reported_transfer_size_);
+}
+
+int AsyncResourceHandler::CalculateEncodedBodyLengthToReport() {
+  return TrackDifference(request()->GetRawBodyBytes(),
+                         &reported_encoded_body_length_);
 }
 
 void AsyncResourceHandler::RecordHistogram() {
diff --git a/content/browser/loader/async_resource_handler.h b/content/browser/loader/async_resource_handler.h
index 0991021..c087f16 100644
--- a/content/browser/loader/async_resource_handler.h
+++ b/content/browser/loader/async_resource_handler.h
@@ -14,6 +14,7 @@
 #include "base/timer/timer.h"
 #include "content/browser/loader/resource_handler.h"
 #include "content/browser/loader/resource_message_delegate.h"
+#include "content/common/content_export.h"
 #include "net/base/io_buffer.h"
 #include "url/gurl.h"
 
@@ -30,8 +31,8 @@
 
 // Used to complete an asynchronous resource request in response to resource
 // load events from the resource dispatcher host.
-class AsyncResourceHandler : public ResourceHandler,
-                             public ResourceMessageDelegate {
+class CONTENT_EXPORT AsyncResourceHandler : public ResourceHandler,
+                                            public ResourceMessageDelegate {
  public:
   AsyncResourceHandler(net::URLRequest* request,
                        ResourceDispatcherHostImpl* rdh);
@@ -70,6 +71,7 @@
   void OnDefer();
   bool CheckForSufficientResource();
   int CalculateEncodedDataLengthToReport();
+  int CalculateEncodedBodyLengthToReport();
   void RecordHistogram();
 
   scoped_refptr<ResourceBuffer> buffer_;
@@ -96,6 +98,7 @@
   base::RepeatingTimer progress_timer_;
 
   int64_t reported_transfer_size_;
+  int64_t reported_encoded_body_length_;
 
   DISALLOW_COPY_AND_ASSIGN(AsyncResourceHandler);
 };
diff --git a/content/browser/loader/async_resource_handler_unittest.cc b/content/browser/loader/async_resource_handler_unittest.cc
new file mode 100644
index 0000000..69f2f59
--- /dev/null
+++ b/content/browser/loader/async_resource_handler_unittest.cc
@@ -0,0 +1,339 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/loader/async_resource_handler.h"
+
+#include <stddef.h>
+#include <stdint.h>
+#include <memory>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/feature_list.h"
+#include "base/format_macros.h"
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/process/process.h"
+#include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
+#include "content/browser/loader/resource_dispatcher_host_impl.h"
+#include "content/browser/loader/resource_loader.h"
+#include "content/browser/loader/resource_loader_delegate.h"
+#include "content/browser/loader/resource_message_filter.h"
+#include "content/browser/loader/resource_request_info_impl.h"
+#include "content/common/resource_messages.h"
+#include "content/common/resource_request.h"
+#include "content/public/browser/resource_context.h"
+#include "content/public/browser/resource_request_info.h"
+#include "content/public/common/content_features.h"
+#include "content/public/common/process_type.h"
+#include "content/public/common/resource_type.h"
+#include "content/public/test/mock_resource_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_message_macros.h"
+#include "net/http/http_response_headers.h"
+#include "net/http/http_util.h"
+#include "net/ssl/client_cert_store.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_job_factory_impl.h"
+#include "net/url_request/url_request_test_job.h"
+#include "net/url_request/url_request_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/page_transition_types.h"
+#include "url/gurl.h"
+
+namespace content {
+
+namespace {
+
+std::string GenerateHeader(size_t response_data_size) {
+  return base::StringPrintf(
+      "HTTP/1.1 200 OK\n"
+      "Content-type: text/html\n"
+      "Content-Length: %" PRIuS "\n",
+      response_data_size);
+}
+
+std::string GenerateData(size_t response_data_size) {
+  return std::string(response_data_size, 'a');
+}
+
+// This test job adds a Content-Length header and implements
+// GetTotalReceivedBytes().
+class TestJob : public net::URLRequestTestJob {
+ public:
+  TestJob(net::URLRequest* request,
+          net::NetworkDelegate* network_delegate,
+          size_t response_data_size)
+      : net::URLRequestTestJob(request,
+                               network_delegate,
+                               GenerateHeader(response_data_size),
+                               GenerateData(response_data_size),
+                               true) {}
+
+  static TestJob* CreateJob(net::URLRequest* request,
+                            net::NetworkDelegate* network_delegate,
+                            size_t response_data_size) {
+    return new TestJob(request, network_delegate, response_data_size);
+  }
+
+  // URLRequestJob implementation:
+  // TODO(ricea): Move this to URLRequestTestJob.
+  int64_t GetTotalReceivedBytes() const override {
+    std::string http_headers = net::HttpUtil::ConvertHeadersBackToHTTPResponse(
+        response_headers_->raw_headers());
+    return http_headers.size() + offset_;
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TestJob);
+};
+
+class TestJobProtocolHandler
+    : public net::URLRequestJobFactory::ProtocolHandler {
+ public:
+  TestJobProtocolHandler(size_t response_data_size)
+      : response_data_size_(response_data_size) {}
+
+  net::URLRequestJob* MaybeCreateJob(
+      net::URLRequest* request,
+      net::NetworkDelegate* network_delegate) const override {
+    return TestJob::CreateJob(request, network_delegate, response_data_size_);
+  }
+
+ private:
+  size_t response_data_size_;
+};
+
+// A subclass of ResourceMessageFilter that records IPC messages that are sent.
+class RecordingResourceMessageFilter : public ResourceMessageFilter {
+ public:
+  RecordingResourceMessageFilter(ResourceContext* resource_context,
+                                 net::URLRequestContext* request_context)
+      : ResourceMessageFilter(
+            0,
+            PROCESS_TYPE_RENDERER,
+            nullptr,
+            nullptr,
+            nullptr,
+            nullptr,
+            nullptr,
+            base::Bind(&RecordingResourceMessageFilter::GetContexts,
+                       base::Unretained(this))),
+        resource_context_(resource_context),
+        request_context_(request_context) {
+    set_peer_process_for_testing(base::Process::Current());
+  }
+
+  const std::vector<std::unique_ptr<IPC::Message>>& messages() const {
+    return messages_;
+  }
+
+  // IPC::Sender implementation:
+  bool Send(IPC::Message* message) override {
+    // Unpickle the base::SharedMemoryHandle to avoid warnings about
+    // "MessageAttachmentSet destroyed with unconsumed descriptors".
+    if (message->type() == ResourceMsg_SetDataBuffer::ID) {
+      ResourceMsg_SetDataBuffer::Param params;
+      ResourceMsg_SetDataBuffer::Read(message, &params);
+    }
+    messages_.push_back(base::WrapUnique(message));
+    return true;
+  }
+
+ private:
+  ~RecordingResourceMessageFilter() override {}
+
+  void GetContexts(ResourceType resource_type,
+                   int origin_pid,
+                   ResourceContext** resource_context,
+                   net::URLRequestContext** request_context) {
+    *resource_context = resource_context_;
+    *request_context = request_context_;
+  }
+
+  ResourceContext* const resource_context_;
+  net::URLRequestContext* const request_context_;
+  std::vector<std::unique_ptr<IPC::Message>> messages_;
+};
+
+class AsyncResourceHandlerTest : public ::testing::Test,
+                                 public ResourceLoaderDelegate {
+ protected:
+  AsyncResourceHandlerTest()
+      : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP), context_(true) {}
+
+  void TearDown() override {
+    // Prevent memory leaks.
+    rdh_.Shutdown();
+    base::RunLoop().RunUntilIdle();
+  }
+
+  void CreateRequestWithResponseDataSize(size_t response_data_size) {
+    test_job_factory_.SetProtocolHandler(
+        "test", base::MakeUnique<TestJobProtocolHandler>(response_data_size));
+    context_.set_job_factory(&test_job_factory_);
+    context_.Init();
+    std::unique_ptr<net::URLRequest> request = context_.CreateRequest(
+        GURL("test:test"), net::DEFAULT_PRIORITY, nullptr);
+    resource_context_ = base::MakeUnique<MockResourceContext>(&context_);
+    filter_ =
+        new RecordingResourceMessageFilter(resource_context_.get(), &context_);
+    ResourceRequestInfoImpl* info = new ResourceRequestInfoImpl(
+        PROCESS_TYPE_RENDERER,                 // process_type
+        0,                                     // child_id
+        0,                                     // route_id
+        -1,                                    // frame_tree_node_id
+        0,                                     // origin_pid
+        0,                                     // request_id
+        0,                                     // render_frame_id
+        false,                                 // is_main_frame
+        false,                                 // parent_is_main_frame
+        RESOURCE_TYPE_IMAGE,                   // resource_type
+        ui::PAGE_TRANSITION_LINK,              // transition_type
+        false,                                 // should_replace_current_entry
+        false,                                 // is_download
+        false,                                 // is_stream
+        false,                                 // allow_download
+        false,                                 // has_user_gesture
+        false,                                 // enable load timing
+        false,                                 // enable upload progress
+        false,                                 // do_not_prompt_for_login
+        blink::WebReferrerPolicyDefault,       // referrer_policy
+        blink::WebPageVisibilityStateVisible,  // visibility_state
+        resource_context_.get(),               // context
+        filter_->GetWeakPtr(),                 // filter
+        false,                                 // report_raw_headers
+        true,                                  // is_async
+        false,                                 // is_using_lofi
+        std::string(),                         // original_headers
+        nullptr,                               // body
+        false);                                // initiated_in_secure_context
+    info->AssociateWithRequest(request.get());
+    std::unique_ptr<AsyncResourceHandler> handler =
+        base::MakeUnique<AsyncResourceHandler>(request.get(), &rdh_);
+    loader_ = base::MakeUnique<ResourceLoader>(
+        std::move(request), std::move(handler), nullptr, this);
+  }
+
+  void StartRequestAndWaitWithResponseDataSize(size_t response_data_size) {
+    CreateRequestWithResponseDataSize(response_data_size);
+    loader_->StartRequest();
+    finish_waiter_.reset(new base::RunLoop);
+    finish_waiter_->Run();
+  }
+
+  scoped_refptr<RecordingResourceMessageFilter> filter_;
+
+ private:
+  // ResourceLoaderDelegate implementation:
+  ResourceDispatcherHostLoginDelegate* CreateLoginDelegate(
+      ResourceLoader* loader,
+      net::AuthChallengeInfo* auth_info) override {
+    return nullptr;
+  }
+
+  bool HandleExternalProtocol(ResourceLoader* loader,
+                              const GURL& url) override {
+    return false;
+  }
+  void DidStartRequest(ResourceLoader* loader) override {}
+  void DidReceiveRedirect(ResourceLoader* loader,
+                          const GURL& new_url) override {}
+  void DidReceiveResponse(ResourceLoader* loader) override {}
+  void DidFinishLoading(ResourceLoader* loader) override {
+    loader_.reset();
+    finish_waiter_->Quit();
+  }
+  std::unique_ptr<net::ClientCertStore> CreateClientCertStore(
+      ResourceLoader* loader) override {
+    return nullptr;
+  }
+
+  TestBrowserThreadBundle thread_bundle_;
+  ResourceDispatcherHostImpl rdh_;
+  net::TestURLRequestContext context_;
+  net::URLRequestJobFactoryImpl test_job_factory_;
+  std::unique_ptr<MockResourceContext> resource_context_;
+  std::unique_ptr<ResourceLoader> loader_;
+  std::unique_ptr<base::RunLoop> finish_waiter_;
+};
+
+TEST_F(AsyncResourceHandlerTest, Construct) {
+  CreateRequestWithResponseDataSize(1);
+}
+
+TEST_F(AsyncResourceHandlerTest, OneChunkLengths) {
+  // Larger than kInlinedLeadingChunkSize and smaller than
+  // kMaxAllocationSize.
+  StartRequestAndWaitWithResponseDataSize(4096);
+  const auto& messages = filter_->messages();
+  ASSERT_EQ(4u, messages.size());
+  ASSERT_EQ(ResourceMsg_DataReceived::ID, messages[2]->type());
+  ResourceMsg_DataReceived::Param params;
+  ResourceMsg_DataReceived::Read(messages[2].get(), &params);
+
+  int encoded_data_length = std::get<3>(params);
+  EXPECT_EQ(4162, encoded_data_length);
+  int encoded_body_length = std::get<4>(params);
+  EXPECT_EQ(4096, encoded_body_length);
+}
+
+TEST_F(AsyncResourceHandlerTest, InlinedChunkLengths) {
+  // TODO(ricea): Remove this Feature-enabling code once the feature is on by
+  // default.
+  auto feature_list = base::MakeUnique<base::FeatureList>();
+  feature_list->InitializeFromCommandLine(
+      features::kOptimizeLoadingIPCForSmallResources.name, "");
+  base::FeatureList::ClearInstanceForTesting();
+  base::FeatureList::SetInstance(std::move(feature_list));
+
+  // Smaller than kInlinedLeadingChunkSize.
+  StartRequestAndWaitWithResponseDataSize(8);
+  const auto& messages = filter_->messages();
+  ASSERT_EQ(3u, messages.size());
+  ASSERT_EQ(ResourceMsg_InlinedDataChunkReceived::ID, messages[1]->type());
+  ResourceMsg_InlinedDataChunkReceived::Param params;
+  ResourceMsg_InlinedDataChunkReceived::Read(messages[1].get(), &params);
+
+  int encoded_data_length = std::get<2>(params);
+  EXPECT_EQ(71, encoded_data_length);
+  int encoded_body_length = std::get<3>(params);
+  EXPECT_EQ(8, encoded_body_length);
+}
+
+TEST_F(AsyncResourceHandlerTest, TwoChunksLengths) {
+  // Larger than kMaxAllocationSize.
+  StartRequestAndWaitWithResponseDataSize(64*1024);
+  const auto& messages = filter_->messages();
+  ASSERT_EQ(5u, messages.size());
+  ASSERT_EQ(ResourceMsg_DataReceived::ID, messages[2]->type());
+  ResourceMsg_DataReceived::Param params;
+  ResourceMsg_DataReceived::Read(messages[2].get(), &params);
+
+  int encoded_data_length = std::get<3>(params);
+  EXPECT_EQ(32835, encoded_data_length);
+  int encoded_body_length = std::get<4>(params);
+  EXPECT_EQ(32768, encoded_body_length);
+
+  ASSERT_EQ(ResourceMsg_DataReceived::ID, messages[3]->type());
+  ResourceMsg_DataReceived::Read(messages[3].get(), &params);
+
+  encoded_data_length = std::get<3>(params);
+  EXPECT_EQ(32768, encoded_data_length);
+  encoded_body_length = std::get<4>(params);
+  EXPECT_EQ(32768, encoded_body_length);
+}
+
+}  // namespace
+
+}  // namespace content
diff --git a/content/browser/loader/resource_dispatcher_host_unittest.cc b/content/browser/loader/resource_dispatcher_host_unittest.cc
index 175ac72..8b3637ca 100644
--- a/content/browser/loader/resource_dispatcher_host_unittest.cc
+++ b/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -740,7 +740,7 @@
 // Waits for a ShareableFileReference to be released.
 class ShareableFileReleaseWaiter {
  public:
-  ShareableFileReleaseWaiter(const base::FilePath& path) {
+  explicit ShareableFileReleaseWaiter(const base::FilePath& path) {
     scoped_refptr<ShareableFileReference> file =
         ShareableFileReference::Get(path);
     file->AddFinalReleaseCallback(
@@ -766,7 +766,7 @@
 // ResourceDispatcherHostImpl.
 class TestWebContentsObserver : public WebContentsObserver {
  public:
-  TestWebContentsObserver(WebContents* web_contents)
+  explicit TestWebContentsObserver(WebContents* web_contents)
       : WebContentsObserver(web_contents),
         resource_request_redirect_count_(0),
         resource_response_start_count_(0) {}
@@ -1836,7 +1836,7 @@
   // Now that the async IO path is in place, the IO always completes on the
   // initial call; so the requests have already completed.  This basically
   // breaks the whole test.
-  //EXPECT_EQ(3, host_.pending_requests());
+  // EXPECT_EQ(3, host_.pending_requests());
 
   // Process test_url_2 and test_url_3 for one level so one callback is called.
   // We'll cancel test_url_4 (detachable) before processing it to verify that it
@@ -2212,8 +2212,7 @@
   // ResourceDispatcherHost::CalculateApproximateMemoryCost().
   int kMemoryCostOfTest2Req =
       ResourceDispatcherHostImpl::kAvgBytesPerOutstandingRequest +
-      std::string("GET").size() +
-      net::URLRequestTestJob::test_url_2().spec().size();
+      net::URLRequestTestJob::test_url_2().spec().size() + sizeof("GET") - 1;
 
   // Tighten the bound on the ResourceDispatcherHost, to speed things up.
   int kMaxCostPerProcess = 440000;
diff --git a/content/browser/loader/sync_resource_handler.cc b/content/browser/loader/sync_resource_handler.cc
index 36eec61..c4217b29 100644
--- a/content/browser/loader/sync_resource_handler.cc
+++ b/content/browser/loader/sync_resource_handler.cc
@@ -73,8 +73,8 @@
     return false;
 
   if (rdh_->delegate()) {
-    rdh_->delegate()->OnResponseStarted(
-        request(), info->GetContext(), response, info->filter());
+    rdh_->delegate()->OnResponseStarted(request(), info->GetContext(),
+                                        response);
   }
 
   NetLogObserver::PopulateResponseInfo(request(), response);
@@ -127,6 +127,7 @@
 
   int total_transfer_size = request()->GetTotalReceivedBytes();
   result_.encoded_data_length = total_transfer_size_ + total_transfer_size;
+  result_.encoded_body_length = request()->GetRawBodyBytes();
 
   ResourceHostMsg_SyncLoad::WriteReplyParams(result_message_, result_);
   filter->Send(result_message_);
diff --git a/content/browser/manifest/manifest_browsertest.cc b/content/browser/manifest/manifest_browsertest.cc
index 0666eb4..7a9d1079 100644
--- a/content/browser/manifest/manifest_browsertest.cc
+++ b/content/browser/manifest/manifest_browsertest.cc
@@ -50,7 +50,7 @@
  protected:
   friend MockWebContentsDelegate;
 
-  ManifestBrowserTest() : console_error_count_(0), has_manifest_(false) {
+  ManifestBrowserTest() : console_error_count_(0) {
     cors_embedded_test_server_.reset(new net::EmbeddedTestServer);
     cors_embedded_test_server_->ServeFilesFromSourceDirectory(
         "content/test/data");
@@ -76,31 +76,18 @@
     message_loop_runner_->Run();
   }
 
-  void HasManifestAndWait() {
-    shell()->web_contents()->HasManifest(
-        base::Bind(&ManifestBrowserTest::OnHasManifest,
-                   base::Unretained(this)));
-
-    message_loop_runner_ = new MessageLoopRunner();
-    message_loop_runner_->Run();
-  }
-
   void OnGetManifest(const GURL& manifest_url, const Manifest& manifest) {
+    manifest_url_ = manifest_url;
     manifest_ = manifest;
     message_loop_runner_->Quit();
   }
 
-  void OnHasManifest(bool has_manifest) {
-    has_manifest_ = has_manifest;
-    message_loop_runner_->Quit();
-  }
-
   const Manifest& manifest() const {
     return manifest_;
   }
 
-  bool has_manifest() const {
-    return has_manifest_;
+  const GURL& manifest_url() const {
+    return manifest_url_;
   }
 
   unsigned int console_error_count() const {
@@ -119,9 +106,9 @@
   scoped_refptr<MessageLoopRunner> message_loop_runner_;
   std::unique_ptr<MockWebContentsDelegate> mock_web_contents_delegate_;
   std::unique_ptr<net::EmbeddedTestServer> cors_embedded_test_server_;
+  GURL manifest_url_;
   Manifest manifest_;
   int console_error_count_;
-  bool has_manifest_;
 
   DISALLOW_COPY_AND_ASSIGN(ManifestBrowserTest);
 };
@@ -142,7 +129,7 @@
 }
 
 // If a page has no manifest, requesting a manifest should return the empty
-// manifest.
+// manifest. The URL should be empty.
 IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, NoManifest) {
   GURL test_url = GetTestUrl("manifest", "no-manifest.html");
 
@@ -152,14 +139,12 @@
 
   GetManifestAndWait();
   EXPECT_TRUE(manifest().IsEmpty());
-
-  HasManifestAndWait();
-  EXPECT_FALSE(has_manifest());
+  EXPECT_TRUE(manifest_url().is_empty());
   EXPECT_EQ(0u, console_error_count());
 }
 
 // If a page manifest points to a 404 URL, requesting the manifest should return
-// the empty manifest. However, HasManifest will return true.
+// the empty manifest. However, the manifest URL will be non-empty.
 IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, 404Manifest) {
   GURL test_url = GetTestUrl("manifest", "404-manifest.html");
 
@@ -169,14 +154,12 @@
 
   GetManifestAndWait();
   EXPECT_TRUE(manifest().IsEmpty());
-
-  HasManifestAndWait();
-  EXPECT_TRUE(has_manifest());
+  EXPECT_FALSE(manifest_url().is_empty());
   EXPECT_EQ(0u, console_error_count());
 }
 
 // If a page has an empty manifest, requesting the manifest should return the
-// empty manifest.
+// empty manifest. The manifest URL should be non-empty.
 IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, EmptyManifest) {
   GURL test_url = GetTestUrl("manifest", "empty-manifest.html");
 
@@ -186,14 +169,12 @@
 
   GetManifestAndWait();
   EXPECT_TRUE(manifest().IsEmpty());
-
-  HasManifestAndWait();
-  EXPECT_TRUE(has_manifest());
+  EXPECT_FALSE(manifest_url().is_empty());
   EXPECT_EQ(0u, console_error_count());
 }
 
 // If a page's manifest can't be parsed correctly, requesting the manifest
-// should return an empty manifest.
+// should return an empty manifest. The manifest URL should be non-empty.
 IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, ParseErrorManifest) {
   GURL test_url = GetTestUrl("manifest", "parse-error-manifest.html");
 
@@ -203,14 +184,13 @@
 
   GetManifestAndWait();
   EXPECT_TRUE(manifest().IsEmpty());
-
-  HasManifestAndWait();
-  EXPECT_TRUE(has_manifest());
+  EXPECT_FALSE(manifest_url().is_empty());
   EXPECT_EQ(1u, console_error_count());
 }
 
 // If a page has a manifest that can be fetched and parsed, requesting the
-// manifest should return a properly filled manifest.
+// manifest should return a properly filled manifest. The manifest URL should be
+// non-empty.
 IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, DummyManifest) {
   GURL test_url = GetTestUrl("manifest", "dummy-manifest.html");
 
@@ -220,9 +200,8 @@
 
   GetManifestAndWait();
   EXPECT_FALSE(manifest().IsEmpty());
+  EXPECT_FALSE(manifest_url().is_empty());
 
-  HasManifestAndWait();
-  EXPECT_TRUE(has_manifest());
   EXPECT_EQ(0u, console_error_count());
 }
 
@@ -238,35 +217,29 @@
   {
     GetManifestAndWait();
     EXPECT_TRUE(manifest().IsEmpty());
-
-    HasManifestAndWait();
-    EXPECT_FALSE(has_manifest());
+    EXPECT_TRUE(manifest_url().is_empty());
   }
 
   {
-    std::string manifest_url =
+    std::string manifest_link =
         GetTestUrl("manifest", "dummy-manifest.json").spec();
     ASSERT_TRUE(content::ExecuteScript(
-        shell(), "setManifestTo('" + manifest_url + "')"));
+        shell(), "setManifestTo('" + manifest_link + "')"));
 
     GetManifestAndWait();
     EXPECT_FALSE(manifest().IsEmpty());
-
-    HasManifestAndWait();
-    EXPECT_TRUE(has_manifest());
+    EXPECT_FALSE(manifest_url().is_empty());
   }
 
   {
-    std::string manifest_url =
+    std::string manifest_link =
         GetTestUrl("manifest", "empty-manifest.json").spec();
     ASSERT_TRUE(content::ExecuteScript(
-        shell(), "setManifestTo('" + manifest_url + "')"));
+        shell(), "setManifestTo('" + manifest_link + "')"));
 
     GetManifestAndWait();
     EXPECT_TRUE(manifest().IsEmpty());
-
-    HasManifestAndWait();
-    EXPECT_TRUE(has_manifest());
+    EXPECT_FALSE(manifest_url().is_empty());
   }
 
   EXPECT_EQ(0u, console_error_count());
@@ -288,16 +261,14 @@
   shell()->LoadURL(test_url);
   navigation_observer.Wait();
 
-  std::string manifest_url = cors_embedded_test_server()->GetURL(
+  std::string manifest_link = cors_embedded_test_server()->GetURL(
       "/manifest/dummy-manifest.json").spec();
-  ASSERT_TRUE(
-      content::ExecuteScript(shell(), "setManifestTo('" + manifest_url + "')"));
+  ASSERT_TRUE(content::ExecuteScript(shell(),
+                                     "setManifestTo('" + manifest_link + "')"));
 
   GetManifestAndWait();
   EXPECT_TRUE(manifest().IsEmpty());
-
-  HasManifestAndWait();
-  EXPECT_TRUE(has_manifest());
+  EXPECT_FALSE(manifest_url().is_empty());
   EXPECT_EQ(0u, console_error_count());
 
   // The purpose of this second load is to make sure the first load is fully
@@ -306,10 +277,10 @@
   // reliable way to know when the fetch is finished from the browser test
   // except by fetching the same file from same origin, making it succeed when
   // it is actually fully loaded.
-  manifest_url =
+  manifest_link =
       embedded_test_server()->GetURL("/manifest/dummy-manifest.json").spec();
-  ASSERT_TRUE(
-      content::ExecuteScript(shell(), "setManifestTo('" + manifest_url + "')"));
+  ASSERT_TRUE(content::ExecuteScript(shell(),
+                                     "setManifestTo('" + manifest_link + "')"));
   GetManifestAndWait();
 }
 
@@ -328,16 +299,14 @@
   shell()->LoadURL(test_url);
   navigation_observer.Wait();
 
-  std::string manifest_url = cors_embedded_test_server()->GetURL(
+  std::string manifest_link = cors_embedded_test_server()->GetURL(
       "/manifest/manifest-cors.json").spec();
-  ASSERT_TRUE(
-      content::ExecuteScript(shell(), "setManifestTo('" + manifest_url + "')"));
+  ASSERT_TRUE(content::ExecuteScript(shell(),
+                                     "setManifestTo('" + manifest_link + "')"));
 
   GetManifestAndWait();
   EXPECT_FALSE(manifest().IsEmpty());
-
-  HasManifestAndWait();
-  EXPECT_TRUE(has_manifest());
+  EXPECT_FALSE(manifest_url().is_empty());
   EXPECT_EQ(0u, console_error_count());
 }
 
@@ -358,16 +327,14 @@
   shell()->LoadURL(test_url);
   navigation_observer.Wait();
 
-  std::string manifest_url =
+  std::string manifest_link =
       https_server->GetURL("/manifest/dummy-manifest.json").spec();
-  ASSERT_TRUE(
-      content::ExecuteScript(shell(), "setManifestTo('" + manifest_url + "')"));
+  ASSERT_TRUE(content::ExecuteScript(shell(),
+                                     "setManifestTo('" + manifest_link + "')"));
 
   GetManifestAndWait();
   EXPECT_TRUE(manifest().IsEmpty());
-
-  HasManifestAndWait();
-  EXPECT_TRUE(has_manifest());
+  EXPECT_FALSE(manifest_url().is_empty());
   EXPECT_EQ(0u, console_error_count());
 }
 
@@ -382,10 +349,8 @@
 
   GetManifestAndWait();
   EXPECT_TRUE(manifest().IsEmpty());
+  EXPECT_FALSE(manifest_url().is_empty());
   EXPECT_EQ(6u, console_error_count());
-
-  HasManifestAndWait();
-  EXPECT_TRUE(has_manifest());
 }
 
 // If a page has a manifest and the page is navigated to a page without a
@@ -402,9 +367,7 @@
 
     GetManifestAndWait();
     EXPECT_FALSE(manifest().IsEmpty());
-
-    HasManifestAndWait();
-    EXPECT_TRUE(has_manifest());
+    EXPECT_FALSE(manifest_url().is_empty());
     EXPECT_EQ(0u, console_error_count());
   }
 
@@ -419,9 +382,7 @@
     GetManifestAndWait();
     EXPECT_TRUE(manifest().IsEmpty());
     EXPECT_EQ(0u, console_error_count());
-
-    HasManifestAndWait();
-    EXPECT_FALSE(has_manifest());
+    EXPECT_TRUE(manifest_url().is_empty());
   }
 }
 
@@ -447,9 +408,7 @@
 
   GetManifestAndWait();
   EXPECT_FALSE(manifest().IsEmpty());
-
-  HasManifestAndWait();
-  EXPECT_TRUE(has_manifest());
+  EXPECT_FALSE(manifest_url().is_empty());
   EXPECT_EQ(0u, console_error_count());
 }
 
@@ -477,10 +436,7 @@
 
   GetManifestAndWait();
   EXPECT_FALSE(manifest().IsEmpty());
-  EXPECT_EQ(0u, console_error_count());
-
-  HasManifestAndWait();
-  EXPECT_TRUE(has_manifest());
+  EXPECT_FALSE(manifest_url().is_empty());
   EXPECT_EQ(0u, console_error_count());
 }
 
@@ -536,9 +492,7 @@
 
   GetManifestAndWait();
   EXPECT_FALSE(manifest().IsEmpty());
-
-  HasManifestAndWait();
-  EXPECT_TRUE(has_manifest());
+  EXPECT_FALSE(manifest_url().is_empty());
   EXPECT_EQ(0u, console_error_count());
 
   // The custom embedded test server will fill the name field with the cookie
@@ -595,9 +549,7 @@
 
   GetManifestAndWait();
   EXPECT_FALSE(manifest().IsEmpty());
-
-  HasManifestAndWait();
-  EXPECT_TRUE(has_manifest());
+  EXPECT_FALSE(manifest_url().is_empty());
   EXPECT_EQ(0u, console_error_count());
 
   // The custom embedded test server will fill set the name to 'no cookies' if
diff --git a/content/browser/manifest/manifest_manager_host.cc b/content/browser/manifest/manifest_manager_host.cc
index 112c3344..ea6557f 100644
--- a/content/browser/manifest/manifest_manager_host.cc
+++ b/content/browser/manifest/manifest_manager_host.cc
@@ -34,7 +34,6 @@
 
 ManifestManagerHost::~ManifestManagerHost() {
   STLDeleteValues(&pending_get_callbacks_);
-  STLDeleteValues(&pending_has_callbacks_);
 }
 
 ManifestManagerHost::GetCallbackMap*
@@ -45,49 +44,22 @@
   return it != pending_get_callbacks_.end() ? it->second : nullptr;
 }
 
-ManifestManagerHost::HasCallbackMap*
-ManifestManagerHost::HasCallbackMapForFrame(
-    RenderFrameHost* render_frame_host) {
-  FrameHasCallbackMap::iterator it =
-      pending_has_callbacks_.find(render_frame_host);
-  return it != pending_has_callbacks_.end() ? it->second : nullptr;
-}
-
 void ManifestManagerHost::RenderFrameDeleted(
     RenderFrameHost* render_frame_host) {
+  GetCallbackMap* callbacks = GetCallbackMapForFrame(render_frame_host);
+  if (!callbacks)
+    return;
+
+  // Call the callbacks with a failure state before deleting them. Do this in
+  // a block so the iterator is destroyed before |callbacks|.
   {
-    GetCallbackMap* callbacks = GetCallbackMapForFrame(render_frame_host);
-    if (!callbacks)
-      return;
-
-    // Call the callbacks with a failure state before deleting them. Do this in
-    // a block so the iterator is destroyed before |callbacks|.
-    {
-      GetCallbackMap::const_iterator it(callbacks);
-      for (; !it.IsAtEnd(); it.Advance())
-        it.GetCurrentValue()->Run(GURL(), Manifest());
-    }
-
-    delete callbacks;
-    pending_get_callbacks_.erase(render_frame_host);
+    GetCallbackMap::const_iterator it(callbacks);
+    for (; !it.IsAtEnd(); it.Advance())
+      it.GetCurrentValue()->Run(GURL(), Manifest());
   }
 
-  {
-    HasCallbackMap* callbacks = HasCallbackMapForFrame(render_frame_host);
-    if (!callbacks)
-      return;
-
-    // Call the callbacks with a failure state before deleting them. Do this in
-    // a block so the iterator is destroyed before |callbacks|.
-    {
-      HasCallbackMap::const_iterator it(callbacks);
-      for (; !it.IsAtEnd(); it.Advance())
-        it.GetCurrentValue()->Run(false);
-    }
-
-    delete callbacks;
-    pending_has_callbacks_.erase(render_frame_host);
-  }
+  delete callbacks;
+  pending_get_callbacks_.erase(render_frame_host);
 }
 
 void ManifestManagerHost::GetManifest(RenderFrameHost* render_frame_host,
@@ -104,20 +76,6 @@
       render_frame_host->GetRoutingID(), request_id));
 }
 
-void ManifestManagerHost::HasManifest(RenderFrameHost* render_frame_host,
-                                      const HasManifestCallback& callback) {
-  HasCallbackMap* callbacks = HasCallbackMapForFrame(render_frame_host);
-  if (!callbacks) {
-    callbacks = new HasCallbackMap();
-    pending_has_callbacks_[render_frame_host] = callbacks;
-  }
-
-  int request_id = callbacks->Add(new HasManifestCallback(callback));
-
-  render_frame_host->Send(new ManifestManagerMsg_HasManifest(
-      render_frame_host->GetRoutingID(), request_id));
-}
-
 bool ManifestManagerHost::OnMessageReceived(
     const IPC::Message& message, RenderFrameHost* render_frame_host) {
   bool handled = true;
@@ -126,8 +84,6 @@
                                    render_frame_host)
     IPC_MESSAGE_HANDLER(ManifestManagerHostMsg_RequestManifestResponse,
                         OnRequestManifestResponse)
-    IPC_MESSAGE_HANDLER(ManifestManagerHostMsg_HasManifestResponse,
-                        OnHasManifestResponse)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
 
@@ -203,32 +159,4 @@
   }
 }
 
-void ManifestManagerHost::OnHasManifestResponse(
-    RenderFrameHost* render_frame_host,
-    int request_id,
-    bool has_manifest) {
-  HasCallbackMap* callbacks = HasCallbackMapForFrame(render_frame_host);
-  if (!callbacks) {
-    DVLOG(1) << "Unexpected HasManifestResponse from renderer. "
-                "Killing renderer.";
-    KillRenderer(render_frame_host);
-    return;
-  }
-
-  HasManifestCallback* callback = callbacks->Lookup(request_id);
-  if (!callback) {
-    DVLOG(1) << "Received a request_id (" << request_id << ") from renderer "
-                "with no associated callback. Killing renderer.";
-    KillRenderer(render_frame_host);
-    return;
-  }
-
-  callback->Run(has_manifest);
-  callbacks->Remove(request_id);
-  if (callbacks->IsEmpty()) {
-    delete callbacks;
-    pending_has_callbacks_.erase(render_frame_host);
-  }
-}
-
 } // namespace content
diff --git a/content/browser/manifest/manifest_manager_host.h b/content/browser/manifest/manifest_manager_host.h
index 810f525a..ce593ecc 100644
--- a/content/browser/manifest/manifest_manager_host.h
+++ b/content/browser/manifest/manifest_manager_host.h
@@ -26,38 +26,27 @@
 
   using GetManifestCallback =
       base::Callback<void(const GURL&, const Manifest&)>;
-  using HasManifestCallback = base::Callback<void(bool)>;
 
   // Calls the given callback with the manifest associated with the
   // given RenderFrameHost. If the frame has no manifest or if getting it failed
   // the callback will have an empty manifest.
   void GetManifest(RenderFrameHost*, const GetManifestCallback&);
 
-  // Calls the given callback with a bool indicating whether or not the document
-  // associated with the given RenderFrameHost has a manifest.
-  void HasManifest(RenderFrameHost*, const HasManifestCallback&);
-
   // WebContentsObserver
   bool OnMessageReceived(const IPC::Message&, RenderFrameHost*) override;
   void RenderFrameDeleted(RenderFrameHost*) override;
 
  private:
   using GetCallbackMap = IDMap<GetManifestCallback, IDMapOwnPointer>;
-  using HasCallbackMap = IDMap<HasManifestCallback, IDMapOwnPointer>;
   using FrameGetCallbackMap = base::hash_map<RenderFrameHost*, GetCallbackMap*>;
-  using FrameHasCallbackMap = base::hash_map<RenderFrameHost*, HasCallbackMap*>;
 
   void OnRequestManifestResponse(
       RenderFrameHost*, int request_id, const GURL&, const Manifest&);
-  void OnHasManifestResponse(
-      RenderFrameHost*, int request_id, bool);
 
   // Returns the CallbackMap associated with the given RenderFrameHost, or null.
   GetCallbackMap* GetCallbackMapForFrame(RenderFrameHost*);
-  HasCallbackMap* HasCallbackMapForFrame(RenderFrameHost*);
 
   FrameGetCallbackMap pending_get_callbacks_;
-  FrameHasCallbackMap pending_has_callbacks_;
 
   DISALLOW_COPY_AND_ASSIGN(ManifestManagerHost);
 };
diff --git a/content/browser/media/webrtc/webrtc_eventlog_host.cc b/content/browser/media/webrtc/webrtc_eventlog_host.cc
index 279ed48..80aec9a 100644
--- a/content/browser/media/webrtc/webrtc_eventlog_host.cc
+++ b/content/browser/media/webrtc/webrtc_eventlog_host.cc
@@ -78,14 +78,15 @@
 
 void WebRTCEventLogHost::PeerConnectionAdded(int peer_connection_local_id) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  DCHECK(std::find(active_peer_connection_local_ids_.begin(),
-                   active_peer_connection_local_ids_.end(),
-                   peer_connection_local_id) ==
-         active_peer_connection_local_ids_.end());
-  active_peer_connection_local_ids_.push_back(peer_connection_local_id);
-  if (rtc_event_logging_enabled_ &&
-      number_active_log_files_ < kMaxNumberLogFiles) {
-    StartEventLogForPeerConnection(peer_connection_local_id);
+  if (std::find(active_peer_connection_local_ids_.begin(),
+                active_peer_connection_local_ids_.end(),
+                peer_connection_local_id) ==
+      active_peer_connection_local_ids_.end()) {
+    active_peer_connection_local_ids_.push_back(peer_connection_local_id);
+    if (rtc_event_logging_enabled_ &&
+        number_active_log_files_ < kMaxNumberLogFiles) {
+      StartEventLogForPeerConnection(peer_connection_local_id);
+    }
   }
 }
 
@@ -94,8 +95,9 @@
   const auto found = std::find(active_peer_connection_local_ids_.begin(),
                                active_peer_connection_local_ids_.end(),
                                peer_connection_local_id);
-  DCHECK(found != active_peer_connection_local_ids_.end());
-  active_peer_connection_local_ids_.erase(found);
+  if (found != active_peer_connection_local_ids_.end()) {
+    active_peer_connection_local_ids_.erase(found);
+  }
 }
 
 bool WebRTCEventLogHost::StartWebRTCEventLog(const base::FilePath& file_path) {
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.h b/content/browser/renderer_host/browser_compositor_view_mac.h
index e2bb10e..119a3b3 100644
--- a/content/browser/renderer_host/browser_compositor_view_mac.h
+++ b/content/browser/renderer_host/browser_compositor_view_mac.h
@@ -122,6 +122,7 @@
       const base::TimeTicks& timebase,
       const base::TimeDelta& interval) override;
   void SetBeginFrameSource(cc::BeginFrameSource* source) override;
+  bool IsAutoResizeEnabled() const override;
 
   // cc::BeginFrameObserver implementation.
   void OnBeginFrame(const cc::BeginFrameArgs& args) override;
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.mm b/content/browser/renderer_host/browser_compositor_view_mac.mm
index a8e2fa9..a83fc5a 100644
--- a/content/browser/renderer_host/browser_compositor_view_mac.mm
+++ b/content/browser/renderer_host/browser_compositor_view_mac.mm
@@ -451,6 +451,11 @@
     begin_frame_source_->AddObserver(this);
 }
 
+bool BrowserCompositorMac::IsAutoResizeEnabled() const {
+  NOTREACHED();
+  return false;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // cc::BeginFrameSourceBase, public:
 
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index 838ec05..bf9411d 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -298,7 +298,7 @@
 base::LazyInstance<cc::SurfaceManager> g_surface_manager =
     LAZY_INSTANCE_INITIALIZER;
 
-int g_surface_id_namespace = 0;
+int g_surface_client_id = 0;
 
 class SingleThreadTaskGraphRunner : public cc::SingleThreadTaskGraphRunner {
  public:
@@ -342,10 +342,10 @@
 std::unique_ptr<cc::SurfaceIdAllocator>
 CompositorImpl::CreateSurfaceIdAllocator() {
   std::unique_ptr<cc::SurfaceIdAllocator> allocator(
-      new cc::SurfaceIdAllocator(++g_surface_id_namespace));
+      new cc::SurfaceIdAllocator(++g_surface_client_id));
   cc::SurfaceManager* manager = GetSurfaceManager();
   DCHECK(manager);
-  allocator->RegisterSurfaceIdNamespace(manager);
+  allocator->RegisterSurfaceClientId(manager);
   return allocator;
 }
 
@@ -475,7 +475,7 @@
   host_ = cc::LayerTreeHost::CreateSingleThreaded(this, &params);
   DCHECK(!host_->visible());
   host_->SetRootLayer(root_layer_);
-  host_->set_surface_id_namespace(surface_id_allocator_->id_namespace());
+  host_->set_surface_client_id(surface_id_allocator_->client_id());
   host_->SetViewportSize(size_);
   host_->set_has_transparent_background(has_transparent_background_);
   host_->SetDeviceScaleFactor(device_scale_factor_);
@@ -705,9 +705,9 @@
   display_.reset(new cc::Display(
       manager, HostSharedBitmapManager::current(),
       BrowserGpuMemoryBufferManager::current(),
-      host_->settings().renderer_settings,
-      surface_id_allocator_->id_namespace(), std::move(begin_frame_source),
-      std::move(display_output_surface), std::move(scheduler),
+      host_->settings().renderer_settings, surface_id_allocator_->client_id(),
+      std::move(begin_frame_source), std::move(display_output_surface),
+      std::move(scheduler),
       base::MakeUnique<cc::TextureMailboxDeleter>(task_runner)));
 
   std::unique_ptr<cc::SurfaceDisplayOutputSurface> delegated_output_surface(
diff --git a/content/browser/renderer_host/delegated_frame_host.cc b/content/browser/renderer_host/delegated_frame_host.cc
index 78e5ca7..def08103 100644
--- a/content/browser/renderer_host/delegated_frame_host.cc
+++ b/content/browser/renderer_host/delegated_frame_host.cc
@@ -44,7 +44,7 @@
                      const cc::SurfaceSequence& sequence) {
   std::vector<uint32_t> sequences;
   sequences.push_back(sequence.sequence);
-  manager->DidSatisfySequences(sequence.id_namespace, &sequences);
+  manager->DidSatisfySequences(sequence.client_id, &sequences);
 }
 
 void RequireCallback(cc::SurfaceManager* manager,
@@ -78,7 +78,7 @@
   factory->GetContextFactory()->AddObserver(this);
   id_allocator_ = factory->GetContextFactory()->CreateSurfaceIdAllocator();
   factory->GetSurfaceManager()->RegisterSurfaceFactoryClient(
-      id_allocator_->id_namespace(), this);
+      id_allocator_->client_id(), this);
 }
 
 void DelegatedFrameHost::WasShown(const ui::LatencyInfo& latency_info) {
@@ -204,8 +204,8 @@
   frame_subscriber_.reset();
 }
 
-uint32_t DelegatedFrameHost::GetSurfaceIdNamespace() {
-  return id_allocator_->id_namespace();
+uint32_t DelegatedFrameHost::GetSurfaceClientId() {
+  return id_allocator_->client_id();
 }
 
 cc::SurfaceId DelegatedFrameHost::SurfaceIdAtPoint(
@@ -390,6 +390,9 @@
 void DelegatedFrameHost::SwapDelegatedFrame(uint32_t output_surface_id,
                                             cc::CompositorFrame frame) {
   DCHECK(frame.delegated_frame_data.get());
+#if defined(OS_CHROMEOS)
+  DCHECK(!resize_lock_ || !client_->IsAutoResizeEnabled());
+#endif
   cc::DelegatedFrameData* frame_data = frame.delegated_frame_data.get();
   float frame_device_scale_factor = frame.metadata.device_scale_factor;
 
@@ -817,7 +820,7 @@
   if (!surface_id_.is_null())
     surface_factory_->Destroy(surface_id_);
   factory->GetSurfaceManager()->UnregisterSurfaceFactoryClient(
-      id_allocator_->id_namespace());
+      id_allocator_->client_id());
 
   DCHECK(!vsync_manager_.get());
 }
@@ -833,9 +836,9 @@
   vsync_manager_->AddObserver(this);
 
   ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
-  uint32_t parent = compositor->surface_id_allocator()->id_namespace();
+  uint32_t parent = compositor->surface_id_allocator()->client_id();
   factory->GetSurfaceManager()->RegisterSurfaceNamespaceHierarchy(
-      parent, id_allocator_->id_namespace());
+      parent, id_allocator_->client_id());
 }
 
 void DelegatedFrameHost::ResetCompositor() {
@@ -853,9 +856,9 @@
   }
 
   ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
-  uint32_t parent = compositor_->surface_id_allocator()->id_namespace();
+  uint32_t parent = compositor_->surface_id_allocator()->client_id();
   factory->GetSurfaceManager()->UnregisterSurfaceNamespaceHierarchy(
-      parent, id_allocator_->id_namespace());
+      parent, id_allocator_->client_id());
 
   compositor_ = nullptr;
 }
diff --git a/content/browser/renderer_host/delegated_frame_host.h b/content/browser/renderer_host/delegated_frame_host.h
index d539e9e..288060d 100644
--- a/content/browser/renderer_host/delegated_frame_host.h
+++ b/content/browser/renderer_host/delegated_frame_host.h
@@ -81,6 +81,7 @@
       const base::TimeTicks& timebase,
       const base::TimeDelta& interval) = 0;
   virtual void SetBeginFrameSource(cc::BeginFrameSource* source) = 0;
+  virtual bool IsAutoResizeEnabled() const = 0;
 };
 
 // The DelegatedFrameHost is used to host all of the RenderWidgetHostView state
@@ -158,7 +159,7 @@
       std::unique_ptr<RenderWidgetHostViewFrameSubscriber> subscriber);
   void EndFrameSubscription();
   bool HasFrameSubscriber() const { return !!frame_subscriber_; }
-  uint32_t GetSurfaceIdNamespace();
+  uint32_t GetSurfaceClientId();
   // Returns a null SurfaceId if this DelegatedFrameHost has not yet created
   // a compositor Surface.
   cc::SurfaceId SurfaceIdAtPoint(cc::SurfaceHittestDelegate* delegate,
diff --git a/content/browser/renderer_host/media/audio_renderer_host.cc b/content/browser/renderer_host/media/audio_renderer_host.cc
index 947c00cd..61647894 100644
--- a/content/browser/renderer_host/media/audio_renderer_host.cc
+++ b/content/browser/renderer_host/media/audio_renderer_host.cc
@@ -109,6 +109,13 @@
     *params = media::AudioParameters::UnavailableDeviceParams();
 }
 
+void UMALogDeviceAuthorizationTime(base::TimeTicks auth_start_time) {
+  UMA_HISTOGRAM_CUSTOM_TIMES("Media.Audio.OutputDeviceAuthorizationTime",
+                              base::TimeTicks::Now() - auth_start_time,
+                              base::TimeDelta::FromMilliseconds(1),
+                              base::TimeDelta::FromMilliseconds(5000), 50);
+}
+
 }  // namespace
 
 class AudioRendererHost::AudioEntry
@@ -398,6 +405,8 @@
     const std::string& device_id,
     const url::Origin& security_origin) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  const base::TimeTicks auth_start_time = base::TimeTicks::Now();
+
   DVLOG(1) << "AudioRendererHost@" << this << "::OnRequestDeviceAuthorization"
            << "(stream_id=" << stream_id
            << ", render_frame_id=" << render_frame_id
@@ -408,6 +417,7 @@
     return;
 
   if (!IsValidDeviceId(device_id)) {
+    UMALogDeviceAuthorizationTime(auth_start_time);
     Send(new AudioMsg_NotifyDeviceAuthorized(
         stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND,
         media::AudioParameters::UnavailableDeviceParams(), std::string()));
@@ -432,6 +442,7 @@
       authorizations_.insert(MakeAuthorizationData(
           stream_id, true, info->device.matched_output_device_id));
       MaybeFixAudioParameters(&output_params);
+      UMALogDeviceAuthorizationTime(auth_start_time);
       // Hash matched device id and pass it to the renderer
       Send(new AudioMsg_NotifyDeviceAuthorized(
           stream_id, media::OUTPUT_DEVICE_STATUS_OK, output_params,
@@ -446,22 +457,26 @@
   CheckOutputDeviceAccess(
       render_frame_id, device_id, security_origin,
       base::Bind(&AudioRendererHost::OnDeviceAuthorized, this, stream_id,
-                 device_id, security_origin));
+                 device_id, security_origin, auth_start_time));
 }
 
 void AudioRendererHost::OnDeviceAuthorized(int stream_id,
                                            const std::string& device_id,
                                            const url::Origin& security_origin,
+                                           base::TimeTicks auth_start_time,
                                            bool have_access) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   const auto& auth_data = authorizations_.find(stream_id);
 
   // A close request was received while access check was in progress.
-  if (auth_data == authorizations_.end())
+  if (auth_data == authorizations_.end()) {
+    UMALogDeviceAuthorizationTime(auth_start_time);
     return;
+  }
 
   if (!have_access) {
     authorizations_.erase(auth_data);
+    UMALogDeviceAuthorizationTime(auth_start_time);
     Send(new AudioMsg_NotifyDeviceAuthorized(
         stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED,
         media::AudioParameters::UnavailableDeviceParams(), std::string()));
@@ -479,29 +494,33 @@
         audio_manager_->GetTaskRunner(), FROM_HERE,
         base::Bind(&GetDefaultDeviceInfoOnDeviceThread, audio_manager_),
         base::Bind(&AudioRendererHost::OnDeviceIDTranslated, this, stream_id,
-                   true));
+                   auth_start_time, true));
   } else {
     media_stream_manager_->audio_output_device_enumerator()->Enumerate(
         base::Bind(&AudioRendererHost::TranslateDeviceID, this, device_id,
                    security_origin,
                    base::Bind(&AudioRendererHost::OnDeviceIDTranslated, this,
-                              stream_id)));
+                              stream_id, auth_start_time)));
   }
 }
 
 void AudioRendererHost::OnDeviceIDTranslated(
     int stream_id,
+    base::TimeTicks auth_start_time,
     bool device_found,
     const AudioOutputDeviceInfo& device_info) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   const auto& auth_data = authorizations_.find(stream_id);
 
   // A close request was received while translation was in progress
-  if (auth_data == authorizations_.end())
+  if (auth_data == authorizations_.end()) {
+    UMALogDeviceAuthorizationTime(auth_start_time);
     return;
+  }
 
   if (!device_found) {
     authorizations_.erase(auth_data);
+    UMALogDeviceAuthorizationTime(auth_start_time);
     Send(new AudioMsg_NotifyDeviceAuthorized(
         stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND,
         media::AudioParameters::UnavailableDeviceParams(), std::string()));
@@ -513,6 +532,7 @@
 
   media::AudioParameters output_params = device_info.output_params;
   MaybeFixAudioParameters(&output_params);
+  UMALogDeviceAuthorizationTime(auth_start_time);
   Send(new AudioMsg_NotifyDeviceAuthorized(
       stream_id, media::OUTPUT_DEVICE_STATUS_OK, output_params, std::string()));
 }
diff --git a/content/browser/renderer_host/media/audio_renderer_host.h b/content/browser/renderer_host/media/audio_renderer_host.h
index 7252086..3e5374a 100644
--- a/content/browser/renderer_host/media/audio_renderer_host.h
+++ b/content/browser/renderer_host/media/audio_renderer_host.h
@@ -174,10 +174,12 @@
   void OnDeviceAuthorized(int stream_id,
                           const std::string& device_id,
                           const url::Origin& security_origin,
+                          base::TimeTicks auth_start_time,
                           bool have_access);
 
   // Proceed with device authorization after translating device ID.
   void OnDeviceIDTranslated(int stream_id,
+                            base::TimeTicks auth_start_time,
                             bool device_found,
                             const AudioOutputDeviceInfo& device_info);
 
diff --git a/content/browser/renderer_host/offscreen_canvas_surface_impl.cc b/content/browser/renderer_host/offscreen_canvas_surface_impl.cc
index 8e56b014..5689bff4 100644
--- a/content/browser/renderer_host/offscreen_canvas_surface_impl.cc
+++ b/content/browser/renderer_host/offscreen_canvas_surface_impl.cc
@@ -69,7 +69,7 @@
   std::vector<uint32_t> sequences;
   sequences.push_back(sequence.sequence);
   cc::SurfaceManager* manager = GetSurfaceManager();
-  manager->DidSatisfySequences(sequence.id_namespace, &sequences);
+  manager->DidSatisfySequences(sequence.client_id, &sequences);
 }
 
 // TODO(619136): Implement cc::SurfaceFactoryClient functions for resources
diff --git a/content/browser/renderer_host/p2p/socket_dispatcher_host.cc b/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
index 1204067..8cbb0d6 100644
--- a/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
+++ b/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
@@ -64,8 +64,8 @@
 
     // Add period at the end to make sure that we only resolve
     // fully-qualified names.
-    if (host_name_.at(host_name_.size() - 1) != '.')
-      host_name_ = host_name_ + '.';
+    if (host_name_.back() != '.')
+      host_name_ += '.';
 
     net::HostResolver::RequestInfo info(net::HostPortPair(host_name_, 0));
     int result = resolver_.Resolve(
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc
index 1b43ff2..023cb5fa 100644
--- a/content/browser/renderer_host/render_view_host_impl.cc
+++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -381,8 +381,8 @@
   // If the RWHV has not yet been set, the surface ID namespace will get
   // passed down by the call to SetView().
   if (GetWidget()->GetView()) {
-    Send(new ViewMsg_SetSurfaceIdNamespace(
-        GetRoutingID(), GetWidget()->GetView()->GetSurfaceIdNamespace()));
+    Send(new ViewMsg_SetSurfaceClientId(
+        GetRoutingID(), GetWidget()->GetView()->GetSurfaceClientId()));
   }
 
   // If it's enabled, tell the renderer to set up the Javascript bindings for
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 00ebb223..becd856 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -330,8 +330,8 @@
   // If the renderer has not yet been initialized, then the surface ID
   // namespace will be sent during initialization.
   if (view_ && renderer_initialized_) {
-    Send(new ViewMsg_SetSurfaceIdNamespace(routing_id_,
-                                           view_->GetSurfaceIdNamespace()));
+    Send(new ViewMsg_SetSurfaceClientId(routing_id_,
+                                        view_->GetSurfaceClientId()));
   }
 
   synthetic_gesture_controller_.reset();
@@ -403,8 +403,8 @@
   // If the RWHV has not yet been set, the surface ID namespace will get
   // passed down by the call to SetView().
   if (view_) {
-    Send(new ViewMsg_SetSurfaceIdNamespace(routing_id_,
-                                           view_->GetSurfaceIdNamespace()));
+    Send(new ViewMsg_SetSurfaceClientId(routing_id_,
+                                        view_->GetSurfaceClientId()));
   }
 
   SendScreenRects();
@@ -1568,9 +1568,7 @@
     view_->DidReceiveRendererFrame();
   } else {
     cc::CompositorFrameAck ack;
-    if (frame.gl_frame_data) {
-      ack.gl_frame_data = std::move(frame.gl_frame_data);
-    } else if (frame.delegated_frame_data) {
+    if (frame.delegated_frame_data) {
       cc::TransferableResource::ReturnResources(
           frame.delegated_frame_data->resource_list, &ack.resources);
     }
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.cc b/content/browser/renderer_host/render_widget_host_input_event_router.cc
index 0df21e1e..9786dad 100644
--- a/content/browser/renderer_host/render_widget_host_input_event_router.cc
+++ b/content/browser/renderer_host/render_widget_host_input_event_router.cc
@@ -122,10 +122,10 @@
   // hit testing, and reflect transformations that would normally be applied in
   // the renderer process if the event was being routed between frames within a
   // single process with only one RenderWidgetHost.
-  uint32_t surface_id_namespace =
-      root_view->SurfaceIdNamespaceAtPoint(&delegate, point, transformed_point);
-  const SurfaceIdNamespaceOwnerMap::iterator iter =
-      owner_map_.find(surface_id_namespace);
+  uint32_t surface_client_id =
+      root_view->SurfaceClientIdAtPoint(&delegate, point, transformed_point);
+  const SurfaceClientIdOwnerMap::iterator iter =
+      owner_map_.find(surface_client_id);
   // If the point hit a Surface whose namspace is no longer in the map, then
   // it likely means the RenderWidgetHostView has been destroyed but its
   // parent frame has not sent a new compositor frame since that happened.
@@ -345,7 +345,7 @@
   }
 }
 
-void RenderWidgetHostInputEventRouter::AddSurfaceIdNamespaceOwner(
+void RenderWidgetHostInputEventRouter::AddSurfaceClientIdOwner(
     uint32_t id,
     RenderWidgetHostViewBase* owner) {
   DCHECK(owner_map_.find(id) == owner_map_.end());
@@ -355,8 +355,7 @@
   owner_map_.insert(std::make_pair(id, owner));
 }
 
-void RenderWidgetHostInputEventRouter::RemoveSurfaceIdNamespaceOwner(
-    uint32_t id) {
+void RenderWidgetHostInputEventRouter::RemoveSurfaceClientIdOwner(uint32_t id) {
   auto it_to_remove = owner_map_.find(id);
   if (it_to_remove != owner_map_.end()) {
     it_to_remove->second->RemoveObserver(this);
@@ -364,7 +363,7 @@
   }
 
   for (auto it = hittest_data_.begin(); it != hittest_data_.end();) {
-    if (it->first.id_namespace() == id)
+    if (it->first.client_id() == id)
       it = hittest_data_.erase(it);
     else
       ++it;
@@ -373,7 +372,7 @@
 
 void RenderWidgetHostInputEventRouter::OnHittestData(
     const FrameHostMsg_HittestData_Params& params) {
-  if (owner_map_.find(params.surface_id.id_namespace()) == owner_map_.end()) {
+  if (owner_map_.find(params.surface_id.client_id()) == owner_map_.end()) {
     return;
   }
   HittestData data;
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.h b/content/browser/renderer_host/render_widget_host_input_event_router.h
index 18f7172..70f8b05b 100644
--- a/content/browser/renderer_host/render_widget_host_input_event_router.h
+++ b/content/browser/renderer_host/render_widget_host_input_event_router.h
@@ -70,8 +70,8 @@
                          const blink::WebGestureEvent& event);
   void CancelScrollBubbling(RenderWidgetHostViewBase* target_view);
 
-  void AddSurfaceIdNamespaceOwner(uint32_t id, RenderWidgetHostViewBase* owner);
-  void RemoveSurfaceIdNamespaceOwner(uint32_t id);
+  void AddSurfaceClientIdOwner(uint32_t id, RenderWidgetHostViewBase* owner);
+  void RemoveSurfaceClientIdOwner(uint32_t id);
 
   bool is_registered(uint32_t id) {
     return owner_map_.find(id) != owner_map_.end();
@@ -98,7 +98,7 @@
         hittest_data_;
   };
 
-  using SurfaceIdNamespaceOwnerMap =
+  using SurfaceClientIdOwnerMap =
       base::hash_map<uint32_t, RenderWidgetHostViewBase*>;
   struct TargetData {
     RenderWidgetHostViewBase* target;
@@ -129,7 +129,7 @@
   void SendGestureScrollEnd(RenderWidgetHostViewBase* view,
                             const blink::WebGestureEvent& event);
 
-  SurfaceIdNamespaceOwnerMap owner_map_;
+  SurfaceClientIdOwnerMap owner_map_;
   TargetQueue touchscreen_gesture_target_queue_;
   TargetData touch_target_;
   TargetData touchscreen_gesture_target_;
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index 37703597..a196842 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -99,7 +99,7 @@
                      const cc::SurfaceSequence& sequence) {
   std::vector<uint32_t> sequences;
   sequences.push_back(sequence.sequence);
-  manager->DidSatisfySequences(sequence.id_namespace, &sequences);
+  manager->DidSatisfySequences(sequence.client_id, &sequences);
 }
 
 void RequireCallback(cc::SurfaceManager* manager,
@@ -1678,9 +1678,9 @@
     content_view_core_->DidStopFlinging();
 }
 
-uint32_t RenderWidgetHostViewAndroid::GetSurfaceIdNamespace() {
+uint32_t RenderWidgetHostViewAndroid::GetSurfaceClientId() {
   if (id_allocator_)
-    return id_allocator_->id_namespace();
+    return id_allocator_->client_id();
   return 0;
 }
 
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h
index ae0f8d5..1ecee2e 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.h
+++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -155,7 +155,7 @@
   void ClearCompositorFrame() override;
   void DidOverscroll(const DidOverscrollParams& params) override;
   void DidStopFlinging() override;
-  uint32_t GetSurfaceIdNamespace() override;
+  uint32_t GetSurfaceClientId() override;
   void ShowDisambiguationPopup(const gfx::Rect& rect_pixels,
                                const SkBitmap& zoomed_bitmap) override;
   std::unique_ptr<SyntheticGestureTarget> CreateSyntheticGestureTarget()
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index 94f1d0d..d032576 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -475,8 +475,8 @@
   // Let the page-level input event router know about our surface ID
   // namespace for surface-based hit testing.
   if (host_->delegate() && host_->delegate()->GetInputEventRouter()) {
-    host_->delegate()->GetInputEventRouter()->AddSurfaceIdNamespaceOwner(
-        GetSurfaceIdNamespace(), this);
+    host_->delegate()->GetInputEventRouter()->AddSurfaceClientIdOwner(
+        GetSurfaceClientId(), this);
   }
 
   // We should start observing the TextInputManager for IME-related events as
@@ -1994,7 +1994,7 @@
     event->SetHandled();
 }
 
-uint32_t RenderWidgetHostViewAura::SurfaceIdNamespaceAtPoint(
+uint32_t RenderWidgetHostViewAura::SurfaceClientIdAtPoint(
     cc::SurfaceHittestDelegate* delegate,
     const gfx::Point& point,
     gfx::Point* transformed_point) {
@@ -2012,8 +2012,8 @@
   // It is possible that the renderer has not yet produced a surface, in which
   // case we return our current namespace.
   if (id.is_null())
-    return GetSurfaceIdNamespace();
-  return id.id_namespace();
+    return GetSurfaceClientId();
+  return id.client_id();
 }
 
 void RenderWidgetHostViewAura::ProcessMouseEvent(
@@ -2941,6 +2941,10 @@
     begin_frame_source_->AddObserver(this);
 }
 
+bool RenderWidgetHostViewAura::IsAutoResizeEnabled() const {
+  return host_->auto_resize_enabled();
+}
+
 void RenderWidgetHostViewAura::OnDidNavigateMainFrameToNewPage() {
   ui::GestureRecognizer::Get()->CancelActiveTouches(window_);
 }
@@ -2953,8 +2957,8 @@
   NOTIMPLEMENTED();
 }
 
-uint32_t RenderWidgetHostViewAura::GetSurfaceIdNamespace() {
-  return delegated_frame_host_->GetSurfaceIdNamespace();
+uint32_t RenderWidgetHostViewAura::GetSurfaceClientId() {
+  return delegated_frame_host_->GetSurfaceClientId();
 }
 
 cc::SurfaceId RenderWidgetHostViewAura::SurfaceIdForTesting() const {
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h
index 6c06169..3d51104 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -189,10 +189,10 @@
   void OnDidNavigateMainFrameToNewPage() override;
   void LockCompositingSurface() override;
   void UnlockCompositingSurface() override;
-  uint32_t GetSurfaceIdNamespace() override;
-  uint32_t SurfaceIdNamespaceAtPoint(cc::SurfaceHittestDelegate* delegate,
-                                     const gfx::Point& point,
-                                     gfx::Point* transformed_point) override;
+  uint32_t GetSurfaceClientId() override;
+  uint32_t SurfaceClientIdAtPoint(cc::SurfaceHittestDelegate* delegate,
+                                  const gfx::Point& point,
+                                  gfx::Point* transformed_point) override;
   void ProcessMouseEvent(const blink::WebMouseEvent& event,
                          const ui::LatencyInfo& latency) override;
   void ProcessMouseWheelEvent(const blink::WebMouseWheelEvent& event,
@@ -463,6 +463,7 @@
       const base::TimeTicks& timebase,
       const base::TimeDelta& interval) override;
   void SetBeginFrameSource(cc::BeginFrameSource* source) override;
+  bool IsAutoResizeEnabled() const override;
 
   // TextInputManager::Observer implementation.
   void OnUpdateTextInputStateCalled(TextInputManager* text_input_manager,
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
index 47c1db5..11a59b6 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -3863,20 +3863,20 @@
 
 // Tests the RenderWidgetHostImpl sends the correct surface ID namespace to
 // the renderer process.
-TEST_F(RenderWidgetHostViewAuraTest, SurfaceIdNamespaceInitialized) {
+TEST_F(RenderWidgetHostViewAuraTest, SurfaceClientIdInitialized) {
   gfx::Size size(5, 5);
 
   const IPC::Message* msg =
-      sink_->GetUniqueMessageMatching(ViewMsg_SetSurfaceIdNamespace::ID);
+      sink_->GetUniqueMessageMatching(ViewMsg_SetSurfaceClientId::ID);
   EXPECT_TRUE(msg);
-  ViewMsg_SetSurfaceIdNamespace::Param params;
-  ViewMsg_SetSurfaceIdNamespace::Read(msg, &params);
+  ViewMsg_SetSurfaceClientId::Param params;
+  ViewMsg_SetSurfaceClientId::Read(msg, &params);
   view_->InitAsChild(NULL);
   view_->Show();
   view_->SetSize(size);
   view_->OnSwapCompositorFrame(0,
                                MakeDelegatedFrame(1.f, size, gfx::Rect(size)));
-  EXPECT_EQ(view_->GetSurfaceIdNamespace(), std::get<0>(params));
+  EXPECT_EQ(view_->GetSurfaceClientId(), std::get<0>(params));
 }
 
 // This class provides functionality to test a RenderWidgetHostViewAura
diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc
index ab346c0..cd9a5cd3 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.cc
+++ b/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -377,11 +377,11 @@
 void RenderWidgetHostViewBase::OnDidNavigateMainFrameToNewPage() {
 }
 
-uint32_t RenderWidgetHostViewBase::GetSurfaceIdNamespace() {
+uint32_t RenderWidgetHostViewBase::GetSurfaceClientId() {
   return 0;
 }
 
-uint32_t RenderWidgetHostViewBase::SurfaceIdNamespaceAtPoint(
+uint32_t RenderWidgetHostViewBase::SurfaceClientIdAtPoint(
     cc::SurfaceHittestDelegate* delegate,
     const gfx::Point& point,
     gfx::Point* transformed_point) {
diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h
index 185d11a6..45edb87 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.h
+++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -219,17 +219,16 @@
 
   // Returns the compositing surface ID namespace, or 0 if Surfaces are not
   // enabled.
-  virtual uint32_t GetSurfaceIdNamespace();
+  virtual uint32_t GetSurfaceClientId();
 
   // When there are multiple RenderWidgetHostViews for a single page, input
   // events need to be targeted to the correct one for handling. The following
   // methods are invoked on the RenderWidgetHostView that should be able to
   // properly handle the event (i.e. it has focus for keyboard events, or has
   // been identified by hit testing mouse, touch or gesture events).
-  virtual uint32_t SurfaceIdNamespaceAtPoint(
-      cc::SurfaceHittestDelegate* delegate,
-      const gfx::Point& point,
-      gfx::Point* transformed_point);
+  virtual uint32_t SurfaceClientIdAtPoint(cc::SurfaceHittestDelegate* delegate,
+                                          const gfx::Point& point,
+                                          gfx::Point* transformed_point);
   virtual void ProcessKeyboardEvent(const NativeWebKeyboardEvent& event) {}
   virtual void ProcessMouseEvent(const blink::WebMouseEvent& event,
                                  const ui::LatencyInfo& latency) {}
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h
index 625346a..d497c84 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.h
+++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -330,10 +330,10 @@
   std::unique_ptr<SyntheticGestureTarget> CreateSyntheticGestureTarget()
       override;
 
-  uint32_t GetSurfaceIdNamespace() override;
-  uint32_t SurfaceIdNamespaceAtPoint(cc::SurfaceHittestDelegate* delegate,
-                                     const gfx::Point& point,
-                                     gfx::Point* transformed_point) override;
+  uint32_t GetSurfaceClientId() override;
+  uint32_t SurfaceClientIdAtPoint(cc::SurfaceHittestDelegate* delegate,
+                                  const gfx::Point& point,
+                                  gfx::Point* transformed_point) override;
   // Returns true when we can do SurfaceHitTesting for the event type.
   bool ShouldRouteEvent(const blink::WebInputEvent& event) const;
   void ProcessMouseEvent(const blink::WebMouseEvent& event,
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index 79c311e0..090a20e3 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -524,7 +524,7 @@
       render_widget_host_->delegate()->GetInputEventRouter()) {
     render_widget_host_->delegate()
         ->GetInputEventRouter()
-        ->AddSurfaceIdNamespaceOwner(GetSurfaceIdNamespace(), this);
+        ->AddSurfaceClientIdOwner(GetSurfaceClientId(), this);
   }
 }
 
@@ -920,7 +920,7 @@
 }
 
 void RenderWidgetHostViewMac::Destroy() {
-  // SurfaceIdNamespaces registered with RenderWidgetHostInputEventRouter
+  // SurfaceClientIds registered with RenderWidgetHostInputEventRouter
   // have already been cleared when RenderWidgetHostViewBase notified its
   // observers of our impending destruction.
   [[NSNotificationCenter defaultCenter]
@@ -1391,11 +1391,11 @@
       new SyntheticGestureTargetMac(host, cocoa_view_));
 }
 
-uint32_t RenderWidgetHostViewMac::GetSurfaceIdNamespace() {
-  return browser_compositor_->GetDelegatedFrameHost()->GetSurfaceIdNamespace();
+uint32_t RenderWidgetHostViewMac::GetSurfaceClientId() {
+  return browser_compositor_->GetDelegatedFrameHost()->GetSurfaceClientId();
 }
 
-uint32_t RenderWidgetHostViewMac::SurfaceIdNamespaceAtPoint(
+uint32_t RenderWidgetHostViewMac::SurfaceClientIdAtPoint(
     cc::SurfaceHittestDelegate* delegate,
     const gfx::Point& point,
     gfx::Point* transformed_point) {
@@ -1413,8 +1413,8 @@
   // It is possible that the renderer has not yet produced a surface, in which
   // case we return our current namespace.
   if (id.is_null())
-    return GetSurfaceIdNamespace();
-  return id.id_namespace();
+    return GetSurfaceClientId();
+  return id.client_id();
 }
 
 bool RenderWidgetHostViewMac::ShouldRouteEvent(
diff --git a/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc b/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc
index 4544838b..4fd1f5c 100644
--- a/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc
+++ b/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc
@@ -117,20 +117,17 @@
  protected:
   // Adds |n| connections. Returns true if succeeded.
   bool AddMultipleChannels(int number_of_channels) {
-    GURL socket_url("ws://example.com/test");
-    std::vector<std::string> requested_protocols;
-    url::Origin origin(GURL("http://example.com"));
-    int render_frame_id = -3;
-
     for (int i = 0; i < number_of_channels; ++i) {
       int routing_id = next_routing_id_++;
-      WebSocketHostMsg_AddChannelRequest message(
-          routing_id,
-          socket_url,
-          requested_protocols,
-          origin,
-          "",
-          render_frame_id);
+
+      WebSocketHostMsg_AddChannelRequest_Params params;
+      params.socket_url = GURL("ws://example.com/test");
+      params.origin = url::Origin(GURL("http://example.com"));
+      params.first_party_for_cookies = GURL("http://example.com");
+      params.user_agent_override = "";
+      params.render_frame_id = -3;
+
+      WebSocketHostMsg_AddChannelRequest message(routing_id, params);
       if (!dispatcher_host_->OnMessageReceived(message))
         return false;
     }
@@ -140,20 +137,18 @@
 
   // Adds and cancels |n| connections. Returns true if succeeded.
   bool AddAndCancelMultipleChannels(int number_of_channels) {
-    GURL socket_url("ws://example.com/test");
-    std::vector<std::string> requested_protocols;
-    url::Origin origin(GURL("http://example.com"));
-    int render_frame_id = -3;
-
     for (int i = 0; i < number_of_channels; ++i) {
       int routing_id = next_routing_id_++;
+
+      WebSocketHostMsg_AddChannelRequest_Params params;
+      params.socket_url = GURL("ws://example.com/test");
+      params.origin = url::Origin(GURL("http://example.com"));
+      params.first_party_for_cookies = GURL("http://example.com");
+      params.user_agent_override = "";
+      params.render_frame_id = -3;
+
       WebSocketHostMsg_AddChannelRequest messageAddChannelRequest(
-          routing_id,
-          socket_url,
-          requested_protocols,
-          origin,
-          "",
-          render_frame_id);
+          routing_id, params);
       if (!dispatcher_host_->OnMessageReceived(messageAddChannelRequest))
         return false;
 
@@ -222,13 +217,18 @@
 
 TEST_F(WebSocketDispatcherHostTest, AddChannelRequest) {
   int routing_id = 123;
-  GURL socket_url("ws://example.com/test");
   std::vector<std::string> requested_protocols;
   requested_protocols.push_back("hello");
-  url::Origin origin(GURL("http://example.com"));
-  int render_frame_id = -2;
-  WebSocketHostMsg_AddChannelRequest message(
-      routing_id, socket_url, requested_protocols, origin, "", render_frame_id);
+
+  WebSocketHostMsg_AddChannelRequest_Params params;
+  params.socket_url = GURL("ws://example.com/test");
+  params.requested_protocols = requested_protocols;
+  params.origin = url::Origin(GURL("http://example.com"));
+  params.first_party_for_cookies = GURL("http://example.com");
+  params.user_agent_override = "";
+  params.render_frame_id = -2;
+
+  WebSocketHostMsg_AddChannelRequest message(routing_id, params);
 
   ASSERT_TRUE(dispatcher_host_->OnMessageReceived(message));
 
@@ -256,13 +256,18 @@
 TEST_F(WebSocketDispatcherHostTest, SendFrame) {
   int routing_id = 123;
 
-  GURL socket_url("ws://example.com/test");
   std::vector<std::string> requested_protocols;
   requested_protocols.push_back("hello");
-  url::Origin origin(GURL("http://example.com"));
-  int render_frame_id = -2;
-  WebSocketHostMsg_AddChannelRequest add_channel_message(
-      routing_id, socket_url, requested_protocols, origin, "", render_frame_id);
+
+  WebSocketHostMsg_AddChannelRequest_Params params;
+  params.socket_url = GURL("ws://example.com/test");
+  params.requested_protocols = requested_protocols;
+  params.origin = url::Origin(GURL("http://example.com"));
+  params.first_party_for_cookies = GURL("http://example.com");
+  params.user_agent_override = "";
+  params.render_frame_id = -2;
+
+  WebSocketHostMsg_AddChannelRequest add_channel_message(routing_id, params);
 
   ASSERT_TRUE(dispatcher_host_->OnMessageReceived(add_channel_message));
 
@@ -289,12 +294,25 @@
 }
 
 TEST_F(WebSocketDispatcherHostTest, Destruct) {
-  WebSocketHostMsg_AddChannelRequest message1(
-      123, GURL("ws://example.com/test"), std::vector<std::string>(),
-      url::Origin(GURL("http://example.com")), "", -1);
-  WebSocketHostMsg_AddChannelRequest message2(
-      456, GURL("ws://example.com/test2"), std::vector<std::string>(),
-      url::Origin(GURL("http://example.com")), "", -1);
+  WebSocketHostMsg_AddChannelRequest_Params params1;
+  params1.socket_url = GURL("ws://example.com/test");
+  params1.requested_protocols = std::vector<std::string>();
+  params1.origin = url::Origin(GURL("http://example.com"));
+  params1.first_party_for_cookies = GURL("http://example.com");
+  params1.user_agent_override = "";
+  params1.render_frame_id = -1;
+
+  WebSocketHostMsg_AddChannelRequest message1(123, params1);
+
+  WebSocketHostMsg_AddChannelRequest_Params params2;
+  params2.socket_url = GURL("ws://example.com/test2");
+  params2.requested_protocols = std::vector<std::string>();
+  params2.origin = url::Origin(GURL("http://example.com"));
+  params2.first_party_for_cookies = GURL("http://example.com");
+  params2.user_agent_override = "";
+  params2.render_frame_id = -1;
+
+  WebSocketHostMsg_AddChannelRequest message2(456, params2);
 
   ASSERT_TRUE(dispatcher_host_->OnMessageReceived(message1));
   ASSERT_TRUE(dispatcher_host_->OnMessageReceived(message2));
@@ -415,13 +433,19 @@
 // This is a regression test for https://crrev.com/998173003/.
 TEST_F(WebSocketDispatcherHostTest, InvalidScheme) {
   int routing_id = 123;
-  GURL socket_url("http://example.com/test");
+
   std::vector<std::string> requested_protocols;
   requested_protocols.push_back("hello");
-  url::Origin origin(GURL("http://example.com"));
-  int render_frame_id = -2;
-  WebSocketHostMsg_AddChannelRequest message(
-      routing_id, socket_url, requested_protocols, origin, "", render_frame_id);
+
+  WebSocketHostMsg_AddChannelRequest_Params params;
+  params.socket_url = GURL("http://example.com/test");
+  params.requested_protocols = requested_protocols;
+  params.origin = url::Origin(GURL("http://example.com"));
+  params.first_party_for_cookies = GURL("http://example.com");
+  params.user_agent_override = "";
+  params.render_frame_id = -2;
+
+  WebSocketHostMsg_AddChannelRequest message(routing_id, params);
 
   ASSERT_TRUE(dispatcher_host_->OnMessageReceived(message));
 
diff --git a/content/browser/renderer_host/websocket_host.cc b/content/browser/renderer_host/websocket_host.cc
index 6f1ebde..513789a 100644
--- a/content/browser/renderer_host/websocket_host.cc
+++ b/content/browser/renderer_host/websocket_host.cc
@@ -396,16 +396,15 @@
 }
 
 void WebSocketHost::OnAddChannelRequest(
-    const GURL& socket_url,
-    const std::vector<std::string>& requested_protocols,
-    const url::Origin& origin,
-    const std::string& user_agent_override,
-    int render_frame_id) {
+    const WebSocketHostMsg_AddChannelRequest_Params& params) {
   DVLOG(3) << "WebSocketHost::OnAddChannelRequest"
-           << " routing_id=" << routing_id_ << " socket_url=\"" << socket_url
-           << "\" requested_protocols=\""
-           << base::JoinString(requested_protocols, ", ") << "\" origin=\""
-           << origin << "\" user_agent_override=\"" << user_agent_override
+           << " routing_id=" << routing_id_ << " socket_url=\""
+           << params.socket_url << "\" requested_protocols=\""
+           << base::JoinString(params.requested_protocols, ", ")
+           << "\" origin=\"" << params.origin
+           << "\" first_party_for_cookies=\""
+           << params.first_party_for_cookies << "\" user_agent_override=\""
+           << params.user_agent_override
            << "\"";
 
   DCHECK(!channel_);
@@ -413,12 +412,15 @@
     base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
         FROM_HERE,
         base::Bind(&WebSocketHost::AddChannel, weak_ptr_factory_.GetWeakPtr(),
-                  socket_url, requested_protocols, origin,
-                  user_agent_override, render_frame_id),
+                   params.socket_url, params.requested_protocols,
+                   params.origin, params.first_party_for_cookies,
+                   params.user_agent_override, params.render_frame_id),
         delay_);
   } else {
-    AddChannel(socket_url, requested_protocols, origin,
-               user_agent_override, render_frame_id);
+    AddChannel(
+        params.socket_url, params.requested_protocols, params.origin,
+        params.first_party_for_cookies, params.user_agent_override,
+        params.render_frame_id);
   }
   // |this| may have been deleted here.
 }
@@ -427,13 +429,15 @@
     const GURL& socket_url,
     const std::vector<std::string>& requested_protocols,
     const url::Origin& origin,
+    const GURL& first_party_for_cookies,
     const std::string& user_agent_override,
     int render_frame_id) {
   DVLOG(3) << "WebSocketHost::AddChannel"
            << " routing_id=" << routing_id_ << " socket_url=\"" << socket_url
            << "\" requested_protocols=\""
            << base::JoinString(requested_protocols, ", ") << "\" origin=\""
-           << origin << "\" user_agent_override=\""
+           << origin << "\" first_party_for_cookies=\""
+           << first_party_for_cookies << "\" user_agent_override=\""
            << user_agent_override << "\"";
 
   DCHECK(!channel_);
@@ -469,8 +473,8 @@
                                             user_agent_override.c_str());
   }
   channel_->SendAddChannelRequest(
-          socket_url, requested_protocols, origin,
-          additional_headers);
+      socket_url, requested_protocols, origin, first_party_for_cookies,
+      additional_headers);
   // |this| may have been deleted here.
 }
 
diff --git a/content/browser/renderer_host/websocket_host.h b/content/browser/renderer_host/websocket_host.h
index adbe3b9c..3488ef0 100644
--- a/content/browser/renderer_host/websocket_host.h
+++ b/content/browser/renderer_host/websocket_host.h
@@ -18,6 +18,7 @@
 #include "content/common/websocket.h"
 
 class GURL;
+struct WebSocketHostMsg_AddChannelRequest_Params;
 
 namespace url {
 class Origin;
@@ -66,15 +67,13 @@
   // Handlers for each message type, dispatched by OnMessageReceived(), as
   // defined in content/common/websocket_messages.h
 
-  void OnAddChannelRequest(const GURL& socket_url,
-                           const std::vector<std::string>& requested_protocols,
-                           const url::Origin& origin,
-                           const std::string& user_agent_override,
-                           int render_frame_id);
+  void OnAddChannelRequest(
+      const WebSocketHostMsg_AddChannelRequest_Params& request);
 
   void AddChannel(const GURL& socket_url,
                   const std::vector<std::string>& requested_protocols,
                   const url::Origin& origin,
+                  const GURL& first_party_for_cookies,
                   const std::string& user_agent_override,
                   int render_frame_id);
 
diff --git a/content/browser/tracing/tracing_controller_impl.cc b/content/browser/tracing/tracing_controller_impl.cc
index 5756c73..e5f5a9b 100644
--- a/content/browser/tracing/tracing_controller_impl.cc
+++ b/content/browser/tracing/tracing_controller_impl.cc
@@ -168,6 +168,13 @@
   metadata_dict->SetBoolean("highres-ticks",
                             base::TimeTicks::IsHighResolution());
 
+  base::Time::Exploded ctime;
+  base::Time::Now().UTCExplode(&ctime);
+  std::string time_string = base::StringPrintf("%u-%u-%u %d:%d:%d",
+      ctime.year, ctime.month, ctime.day_of_month, ctime.hour,
+      ctime.minute, ctime.second);
+  metadata_dict->SetString("trace-capture-datetime", time_string);
+
   return metadata_dict;
 }
 
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 23a03d9..83636c4 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -3107,10 +3107,6 @@
   manifest_manager_host_->GetManifest(GetMainFrame(), callback);
 }
 
-void WebContentsImpl::HasManifest(const HasManifestCallback& callback) {
-  manifest_manager_host_->HasManifest(GetMainFrame(), callback);
-}
-
 void WebContentsImpl::ExitFullscreen(bool will_cause_resize) {
   // Clean up related state and initiate the fullscreen exit.
   GetRenderViewHost()->GetWidget()->RejectMouseLockOrUnlockIfNecessary();
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index ad392c7..a772de2 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -391,7 +391,6 @@
   void InsertCSS(const std::string& css) override;
   bool WasRecentlyAudible() override;
   void GetManifest(const GetManifestCallback& callback) override;
-  void HasManifest(const HasManifestCallback& callback) override;
   void ExitFullscreen(bool will_cause_resize) override;
   void ResumeLoadingCreatedWebContents() override;
   void OnMediaSessionStateChanged();
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc
index 2ac8745a..5c82189 100644
--- a/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/macros.h"
+#include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "build/build_config.h"
@@ -1207,6 +1208,18 @@
   loop_runner->Run();
 }
 
+void ExpectNoValidImageCallback(const base::Closure& quit_closure,
+                                int id,
+                                int status_code,
+                                const GURL& image_url,
+                                const std::vector<SkBitmap>& bitmap,
+                                const std::vector<gfx::Size>& sizes) {
+  EXPECT_EQ(200, status_code);
+  EXPECT_TRUE(bitmap.empty());
+  EXPECT_TRUE(sizes.empty());
+  quit_closure.Run();
+}
+
 }  // anonymous namespace
 
 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
@@ -1224,4 +1237,16 @@
   DownloadImageTestInternal(shell(), kImageUrl, 0);
 }
 
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, DownloadImage_NoValidImage) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+  const GURL kImageUrl = embedded_test_server()->GetURL("/invalid.ico");
+  shell()->LoadURL(GURL("about:blank"));
+  base::RunLoop run_loop;
+  shell()->web_contents()->DownloadImage(
+      kImageUrl, false, 2, false,
+      base::Bind(&ExpectNoValidImageCallback, run_loop.QuitClosure()));
+
+  run_loop.Run();
+}
+
 }  // namespace content
diff --git a/content/child/resource_dispatcher.cc b/content/child/resource_dispatcher.cc
index 461da5c..55fa5554 100644
--- a/content/child/resource_dispatcher.cc
+++ b/content/child/resource_dispatcher.cc
@@ -226,7 +226,8 @@
 void ResourceDispatcher::OnReceivedInlinedDataChunk(
     int request_id,
     const std::vector<char>& data,
-    int encoded_data_length) {
+    int encoded_data_length,
+    int encoded_body_length) {
   TRACE_EVENT0("loader", "ResourceDispatcher::OnReceivedInlinedDataChunk");
   DCHECK(!data.empty());
   DCHECK(base::FeatureList::IsEnabled(
@@ -254,7 +255,8 @@
 void ResourceDispatcher::OnReceivedData(int request_id,
                                         int data_offset,
                                         int data_length,
-                                        int encoded_data_length) {
+                                        int encoded_data_length,
+                                        int encoded_body_length) {
   TRACE_EVENT0("loader", "ResourceDispatcher::OnReceivedData");
   DCHECK_GT(data_length, 0);
   PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
diff --git a/content/child/resource_dispatcher.h b/content/child/resource_dispatcher.h
index 11062c6..8a56030 100644
--- a/content/child/resource_dispatcher.h
+++ b/content/child/resource_dispatcher.h
@@ -178,11 +178,13 @@
                        base::ProcessId renderer_pid);
   void OnReceivedInlinedDataChunk(int request_id,
                                   const std::vector<char>& data,
-                                  int encoded_data_length);
+                                  int encoded_data_length,
+                                  int encoded_body_length);
   void OnReceivedData(int request_id,
                       int data_offset,
                       int data_length,
-                      int encoded_data_length);
+                      int encoded_data_length,
+                      int encoded_body_length);
   void OnDownloadedData(int request_id, int data_len, int encoded_data_length);
   void OnRequestComplete(
       int request_id,
diff --git a/content/child/resource_dispatcher_unittest.cc b/content/child/resource_dispatcher_unittest.cc
index 07fbecf..5d072120 100644
--- a/content/child/resource_dispatcher_unittest.cc
+++ b/content/child/resource_dispatcher_unittest.cc
@@ -13,6 +13,7 @@
 #include <utility>
 #include <vector>
 
+#include "base/feature_list.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/shared_memory.h"
@@ -30,6 +31,7 @@
 #include "content/public/child/fixed_received_data.h"
 #include "content/public/child/request_peer.h"
 #include "content/public/child/resource_dispatcher_delegate.h"
+#include "content/public/common/content_features.h"
 #include "content/public/common/resource_response.h"
 #include "net/base/net_errors.h"
 #include "net/http/http_response_headers.h"
@@ -275,11 +277,19 @@
     memcpy(shared_memory_map_[request_id]->memory(), data.c_str(),
            data.length());
 
-    EXPECT_TRUE(dispatcher_->OnMessageReceived(
-        ResourceMsg_DataReceived(request_id, 0, data.length(), data.length())));
+    EXPECT_TRUE(dispatcher_->OnMessageReceived(ResourceMsg_DataReceived(
+        request_id, 0, data.length(), data.length(), data.length())));
   }
 
-  void NotifyDataDownloaded(int request_id, int decoded_length,
+  void NotifyInlinedDataChunkReceived(int request_id,
+                                      const std::vector<char>& data) {
+    auto size = data.size();
+    EXPECT_TRUE(dispatcher_->OnMessageReceived(
+        ResourceMsg_InlinedDataChunkReceived(request_id, data, size, size)));
+  }
+
+  void NotifyDataDownloaded(int request_id,
+                            int decoded_length,
                             int encoded_length) {
     EXPECT_TRUE(dispatcher_->OnMessageReceived(ResourceMsg_DataDownloaded(
         request_id, decoded_length, encoded_length)));
@@ -369,6 +379,35 @@
   EXPECT_EQ(0u, queued_messages());
 }
 
+// A simple request with an inline data response.
+TEST_F(ResourceDispatcherTest, ResponseWithInlinedData) {
+  auto feature_list = base::MakeUnique<base::FeatureList>();
+  feature_list->InitializeFromCommandLine(
+      features::kOptimizeLoadingIPCForSmallResources.name, std::string());
+  base::FeatureList::ClearInstanceForTesting();
+  base::FeatureList::SetInstance(std::move(feature_list));
+  std::unique_ptr<RequestInfo> request_info(CreateRequestInfo(false));
+  TestRequestPeer::Context peer_context;
+  StartAsync(*request_info.get(), NULL, &peer_context);
+
+  int id = ConsumeRequestResource();
+  EXPECT_EQ(0u, queued_messages());
+
+  NotifyReceivedResponse(id);
+  EXPECT_EQ(0u, queued_messages());
+  EXPECT_TRUE(peer_context.received_response);
+
+  std::vector<char> data(kTestPageContents,
+                         kTestPageContents + strlen(kTestPageContents));
+  NotifyInlinedDataChunkReceived(id, data);
+  EXPECT_EQ(0u, queued_messages());
+
+  NotifyRequestComplete(id, strlen(kTestPageContents));
+  EXPECT_EQ(kTestPageContents, peer_context.data);
+  EXPECT_TRUE(peer_context.complete);
+  EXPECT_EQ(0u, queued_messages());
+}
+
 // Tests that the request IDs are straight when there are two interleaving
 // requests.
 TEST_F(ResourceDispatcherTest, MultipleRequests) {
diff --git a/content/child/web_url_loader_impl.cc b/content/child/web_url_loader_impl.cc
index b3b2cdaf..9edfe9a 100644
--- a/content/child/web_url_loader_impl.cc
+++ b/content/child/web_url_loader_impl.cc
@@ -607,7 +607,6 @@
                       request_.reportRawHeaders());
 
   WebURLRequest new_request;
-  new_request.initialize();
   PopulateURLRequestForRedirect(
       request_, redirect_info, referrer_policy_,
       info.was_fetched_via_service_worker
diff --git a/content/child/web_url_loader_impl_unittest.cc b/content/child/web_url_loader_impl_unittest.cc
index d71e1aa..8168d0f 100644
--- a/content/child/web_url_loader_impl_unittest.cc
+++ b/content/child/web_url_loader_impl_unittest.cc
@@ -277,7 +277,6 @@
 
   void DoStartAsyncRequest() {
     blink::WebURLRequest request;
-    request.initialize();
     request.setURL(GURL(kTestURL));
     client()->loader()->loadAsynchronously(request, client());
     ASSERT_TRUE(peer());
@@ -286,7 +285,6 @@
   void DoStartAsyncRequestWithPriority(
       blink::WebURLRequest::Priority priority) {
     blink::WebURLRequest request;
-    request.initialize();
     request.setPriority(priority);
     request.setURL(GURL(kTestURL));
     client()->loader()->loadAsynchronously(request, client());
@@ -446,7 +444,6 @@
 
 TEST_F(WebURLLoaderImplTest, DeleteBeforeResponseDataURL) {
   blink::WebURLRequest request;
-  request.initialize();
   request.setURL(GURL("data:text/html;charset=utf-8,blah!"));
   client()->loader()->loadAsynchronously(request, client());
   client()->DeleteLoader();
@@ -458,7 +455,6 @@
 
 TEST_F(WebURLLoaderImplTest, DataURL) {
   blink::WebURLRequest request;
-  request.initialize();
   request.setURL(GURL("data:text/html;charset=utf-8,blah!"));
   client()->loader()->loadAsynchronously(request, client());
   base::RunLoop().RunUntilIdle();
@@ -470,7 +466,6 @@
 
 TEST_F(WebURLLoaderImplTest, DataURLDeleteOnReceiveResponse) {
   blink::WebURLRequest request;
-  request.initialize();
   request.setURL(GURL("data:text/html;charset=utf-8,blah!"));
   client()->set_delete_on_receive_response();
   client()->loader()->loadAsynchronously(request, client());
@@ -482,7 +477,6 @@
 
 TEST_F(WebURLLoaderImplTest, DataURLDeleteOnReceiveData) {
   blink::WebURLRequest request;
-  request.initialize();
   request.setURL(GURL("data:text/html;charset=utf-8,blah!"));
   client()->set_delete_on_receive_data();
   client()->loader()->loadAsynchronously(request, client());
@@ -494,7 +488,6 @@
 
 TEST_F(WebURLLoaderImplTest, DataURLDeleteOnFinish) {
   blink::WebURLRequest request;
-  request.initialize();
   request.setURL(GURL("data:text/html;charset=utf-8,blah!"));
   client()->set_delete_on_finish();
   client()->loader()->loadAsynchronously(request, client());
@@ -506,7 +499,6 @@
 
 TEST_F(WebURLLoaderImplTest, DataURLDefersLoading) {
   blink::WebURLRequest request;
-  request.initialize();
   request.setURL(GURL("data:text/html;charset=utf-8,blah!"));
   client()->loader()->loadAsynchronously(request, client());
 
@@ -614,7 +606,6 @@
   const GURL kStreamURL = GURL("http://bar");
   const std::string kMimeType = "text/html";
   blink::WebURLRequest request;
-  request.initialize();
   request.setURL(kNavigationURL);
   request.setFrameType(blink::WebURLRequest::FrameTypeTopLevel);
   request.setRequestContext(blink::WebURLRequest::RequestContextFrame);
diff --git a/content/child/websocket_bridge.cc b/content/child/websocket_bridge.cc
index d603fc5..bd94b42 100644
--- a/content/child/websocket_bridge.cc
+++ b/content/child/websocket_bridge.cc
@@ -206,6 +206,7 @@
 void WebSocketBridge::connect(const WebURL& url,
                               const WebVector<WebString>& protocols,
                               const WebSecurityOrigin& origin,
+                              const WebURL& first_party_for_cookies,
                               const WebString& user_agent_override,
                               WebSocketHandleClient* client) {
   DCHECK_EQ(kInvalidChannelId, channel_id_);
@@ -222,10 +223,17 @@
            << base::JoinString(protocols_to_pass, ", ") << "), "
            << origin.toString().utf8() << ")";
 
+  WebSocketHostMsg_AddChannelRequest_Params params;
+  params.socket_url = url;
+  params.requested_protocols = protocols_to_pass;
+  params.origin = origin;
+  params.first_party_for_cookies = first_party_for_cookies;
+  params.user_agent_override = user_agent_override.latin1();
+  params.render_frame_id = render_frame_id_;
+
   // Headers (ie: User-Agent) are ISO Latin 1.
   ChildThreadImpl::current()->Send(new WebSocketHostMsg_AddChannelRequest(
-      channel_id_, url, protocols_to_pass, origin,
-      user_agent_override.latin1(), render_frame_id_));
+      channel_id_, params));
 }
 
 void WebSocketBridge::send(bool fin,
diff --git a/content/child/websocket_bridge.h b/content/child/websocket_bridge.h
index ad2247e..d8ccc2b 100644
--- a/content/child/websocket_bridge.h
+++ b/content/child/websocket_bridge.h
@@ -34,6 +34,7 @@
   void connect(const blink::WebURL& url,
                const blink::WebVector<blink::WebString>& protocols,
                const blink::WebSecurityOrigin& origin,
+               const blink::WebURL& first_party_for_cookies,
                const blink::WebString& user_agent_override,
                blink::WebSocketHandleClient* client) override;
   void send(bool fin,
diff --git a/content/common/manifest_manager_messages.h b/content/common/manifest_manager_messages.h
index c052f27..ae4a2d2 100644
--- a/content/common/manifest_manager_messages.h
+++ b/content/common/manifest_manager_messages.h
@@ -48,24 +48,12 @@
 IPC_MESSAGE_ROUTED1(ManifestManagerMsg_RequestManifest,
                     int /* request_id */)
 
-// The browser process requests whether the document loaded in the associated
-// RenderFrame has a manifest link URL. The render process will respond with
-// a HasManifestResponse IPC message, along with a bool indicating the presence
-// of a manifest link, and the |request_id| that was initially given.
-IPC_MESSAGE_ROUTED1(ManifestManagerMsg_HasManifest,
-                    int /* request_id */)
-
 // The render process' response to a RequestManifest. The |request_id| will
-// match the one that was initially received. The |manifest_url| and |manifest|
-// will be empty in case of any failure.
+// match the one that was initially received. |manifest_url| will be empty if
+// there is no manifest specified in the associated RenderFrame's document.
+// |manifest| will be empty if a manifest was specified, but could not be
+// parsed correctly.
 IPC_MESSAGE_ROUTED3(ManifestManagerHostMsg_RequestManifestResponse,
                     int, /* request_id */
                     GURL, /* manifest URL */
                     content::Manifest /* manifest */)
-
-// The render process' response to a HasManifest. The |request_id| is the one
-// sent from the browser. The |bool| will be true if the current document has a
-// manifest link URL, and false otherwise.
-IPC_MESSAGE_ROUTED2(ManifestManagerHostMsg_HasManifestResponse,
-                    int, /* request_id */
-                    bool /* true if the document has a manifest link */)
diff --git a/content/common/resource_messages.h b/content/common/resource_messages.h
index 0f343e72..a918d54 100644
--- a/content/common/resource_messages.h
+++ b/content/common/resource_messages.h
@@ -159,6 +159,7 @@
   IPC_STRUCT_TRAITS_MEMBER(has_major_certificate_errors)
   IPC_STRUCT_TRAITS_MEMBER(content_length)
   IPC_STRUCT_TRAITS_MEMBER(encoded_data_length)
+  IPC_STRUCT_TRAITS_MEMBER(encoded_body_length)
   IPC_STRUCT_TRAITS_MEMBER(appcache_id)
   IPC_STRUCT_TRAITS_MEMBER(appcache_manifest_url)
   IPC_STRUCT_TRAITS_MEMBER(load_timing)
@@ -307,19 +308,21 @@
 // Sent when a chunk of data from a resource request is ready, and the resource
 // is expected to be small enough to fit in the inlined buffer.
 // The data is sent as a part of IPC message.
-IPC_MESSAGE_CONTROL3(ResourceMsg_InlinedDataChunkReceived,
+IPC_MESSAGE_CONTROL4(ResourceMsg_InlinedDataChunkReceived,
                      int /* request_id */,
                      std::vector<char> /* data */,
-                     int /* encoded_data_length */)
+                     int /* encoded_data_length */,
+                     int /* encoded_body_length */)
 
 // Sent when some data from a resource request is ready.  The data offset and
 // length specify a byte range into the shared memory buffer provided by the
 // SetDataBuffer message.
-IPC_MESSAGE_CONTROL4(ResourceMsg_DataReceived,
+IPC_MESSAGE_CONTROL5(ResourceMsg_DataReceived,
                      int /* request_id */,
                      int /* data_offset */,
                      int /* data_length */,
-                     int /* encoded_data_length */)
+                     int /* encoded_data_length */,
+                     int /* encoded_body_length */)
 
 // Sent when some data from a resource request has been downloaded to
 // file. This is only called in the 'download_to_file' case and replaces
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index a70cb9c..4b65c5a 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -816,7 +816,7 @@
 
 // Sent by browser to give renderer compositor a new namespace ID for any
 // SurfaceSequences it has to create.
-IPC_MESSAGE_ROUTED1(ViewMsg_SetSurfaceIdNamespace,
+IPC_MESSAGE_ROUTED1(ViewMsg_SetSurfaceClientId,
                     uint32_t /* surface_id_namespace */)
 
 IPC_MESSAGE_ROUTED0(ViewMsg_SelectWordAroundCaret)
diff --git a/content/common/websocket_messages.h b/content/common/websocket_messages.h
index 2054354..ce250780b 100644
--- a/content/common/websocket_messages.h
+++ b/content/common/websocket_messages.h
@@ -46,6 +46,15 @@
 IPC_ENUM_TRAITS_MAX_VALUE(content::WebSocketMessageType,
                           content::WEB_SOCKET_MESSAGE_TYPE_LAST)
 
+IPC_STRUCT_BEGIN(WebSocketHostMsg_AddChannelRequest_Params)
+  IPC_STRUCT_MEMBER(GURL, socket_url)
+  IPC_STRUCT_MEMBER(std::vector<std::string>, requested_protocols)
+  IPC_STRUCT_MEMBER(url::Origin, origin)
+  IPC_STRUCT_MEMBER(GURL, first_party_for_cookies)
+  IPC_STRUCT_MEMBER(std::string, user_agent_override)
+  IPC_STRUCT_MEMBER(int, render_frame_id)
+IPC_STRUCT_END()
+
 IPC_STRUCT_TRAITS_BEGIN(content::WebSocketHandshakeRequest)
   IPC_STRUCT_TRAITS_MEMBER(url)
   IPC_STRUCT_TRAITS_MEMBER(headers)
@@ -67,12 +76,8 @@
 // Open new WebSocket connection to |socket_url|. |requested_protocols| is a
 // list of tokens identifying sub-protocols the renderer would like to use, as
 // described in RFC6455 "Subprotocols Using the WebSocket Protocol".
-IPC_MESSAGE_ROUTED5(WebSocketHostMsg_AddChannelRequest,
-                    GURL /* socket_url */,
-                    std::vector<std::string> /* requested_protocols */,
-                    url::Origin /* origin */,
-                    std::string /* user_agent_override */,
-                    int /* render_frame_id */)
+IPC_MESSAGE_ROUTED1(WebSocketHostMsg_AddChannelRequest,
+                    WebSocketHostMsg_AddChannelRequest_Params)
 
 // Send a complete binary WebSocket message consisting of the Blob identified by
 // |uuid|. The message will be split into frames as necessary. |expected_size|
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index 1d634bc..bc70a69 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -507,6 +507,7 @@
       'browser/indexed_db/mock_indexed_db_database_callbacks.h',
       'browser/indexed_db/mock_indexed_db_factory.cc',
       'browser/indexed_db/mock_indexed_db_factory.h',
+      'browser/loader/async_resource_handler_unittest.cc',
       'browser/loader/async_revalidation_driver_unittest.cc',
       'browser/loader/async_revalidation_manager_unittest.cc',
       'browser/loader/mime_type_resource_handler_unittest.cc',
diff --git a/content/public/browser/download_item.h b/content/public/browser/download_item.h
index b499639..be2e77a9b 100644
--- a/content/public/browser/download_item.h
+++ b/content/public/browser/download_item.h
@@ -328,10 +328,6 @@
   // Mark the download to be auto-opened when completed.
   virtual void SetOpenWhenComplete(bool open) = 0;
 
-  // Mark the download as temporary (not visible in persisted store or
-  // SearchDownloads(), removed from main UI upon completion).
-  virtual void SetIsTemporary(bool temporary) = 0;
-
   // Mark the download as having been opened (without actually opening it).
   virtual void SetOpened(bool opened) = 0;
 
diff --git a/content/public/browser/resource_dispatcher_host_delegate.cc b/content/public/browser/resource_dispatcher_host_delegate.cc
index 26b2dcc..0ce62b3 100644
--- a/content/public/browser/resource_dispatcher_host_delegate.cc
+++ b/content/public/browser/resource_dispatcher_host_delegate.cc
@@ -77,9 +77,7 @@
 void ResourceDispatcherHostDelegate::OnResponseStarted(
     net::URLRequest* request,
     ResourceContext* resource_context,
-    ResourceResponse* response,
-    IPC::Sender* sender) {
-}
+    ResourceResponse* response) {}
 
 void ResourceDispatcherHostDelegate::OnRequestRedirected(
     const GURL& redirect_url,
diff --git a/content/public/browser/resource_dispatcher_host_delegate.h b/content/public/browser/resource_dispatcher_host_delegate.h
index 18681a0..f32fe44 100644
--- a/content/public/browser/resource_dispatcher_host_delegate.h
+++ b/content/public/browser/resource_dispatcher_host_delegate.h
@@ -17,10 +17,6 @@
 class GURL;
 template <class T> class ScopedVector;
 
-namespace IPC {
-class Sender;
-}
-
 namespace net {
 class AuthChallengeInfo;
 class ClientCertStore;
@@ -115,8 +111,7 @@
   // Informs the delegate that a response has started.
   virtual void OnResponseStarted(net::URLRequest* request,
                                  ResourceContext* resource_context,
-                                 ResourceResponse* response,
-                                 IPC::Sender* sender);
+                                 ResourceResponse* response);
 
   // Informs the delegate that a request has been redirected.
   virtual void OnRequestRedirected(const GURL& redirect_url,
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h
index 8cf454c..36996f0 100644
--- a/content/public/browser/web_contents.h
+++ b/content/public/browser/web_contents.h
@@ -691,19 +691,15 @@
   // Returns true if audio has recently been audible from the WebContents.
   virtual bool WasRecentlyAudible() = 0;
 
+  // The callback invoked when the renderer responds to a request for the main
+  // frame document's manifest. The url will be empty if the document specifies
+  // no manifest, and the manifest will be empty if any other failures occurred.
   typedef base::Callback<void(const GURL&, const Manifest&)>
       GetManifestCallback;
 
   // Requests the manifest URL and the Manifest of the main frame's document.
   virtual void GetManifest(const GetManifestCallback& callback) = 0;
 
-  typedef base::Callback<void(bool)> HasManifestCallback;
-
-  // Returns true if the main frame has a <link> to a web manifest, otherwise
-  // false. This method does not guarantee that the manifest exists at the
-  // specified location or is valid.
-  virtual void HasManifest(const HasManifestCallback& callback) = 0;
-
   // Requests the renderer to exit fullscreen.
   // |will_cause_resize| indicates whether the fullscreen change causes a
   // view resize. e.g. This will be false when going from tab fullscreen to
diff --git a/content/public/common/resource_response.cc b/content/public/common/resource_response.cc
index 3633eba8..0b94574 100644
--- a/content/public/common/resource_response.cc
+++ b/content/public/common/resource_response.cc
@@ -23,6 +23,7 @@
       head.has_major_certificate_errors;
   new_response->head.content_length = head.content_length;
   new_response->head.encoded_data_length = head.encoded_data_length;
+  new_response->head.encoded_body_length = head.encoded_body_length;
   new_response->head.appcache_id = head.appcache_id;
   new_response->head.appcache_manifest_url = head.appcache_manifest_url;
   new_response->head.load_timing = head.load_timing;
diff --git a/content/public/common/resource_response_info.cc b/content/public/common/resource_response_info.cc
index d471f2df..eed1a98ed 100644
--- a/content/public/common/resource_response_info.cc
+++ b/content/public/common/resource_response_info.cc
@@ -13,6 +13,7 @@
     : has_major_certificate_errors(false),
       content_length(-1),
       encoded_data_length(-1),
+      encoded_body_length(-1),
       appcache_id(kAppCacheNoCacheId),
       was_fetched_via_spdy(false),
       was_npn_negotiated(false),
diff --git a/content/public/common/resource_response_info.h b/content/public/common/resource_response_info.h
index 9c004aa..3c7a9c5 100644
--- a/content/public/common/resource_response_info.h
+++ b/content/public/common/resource_response_info.h
@@ -64,6 +64,10 @@
   // no data, contains -1.
   int64_t encoded_data_length;
 
+  // Length of the response body data before decompression. -1 unless the body
+  // has been read to the end.
+  int64_t encoded_body_length;
+
   // The appcache this response was loaded from, or kAppCacheNoCacheId.
   int64_t appcache_id;
 
diff --git a/content/public/test/mock_download_item.h b/content/public/test/mock_download_item.h
index 2ac6bbcdc..6f9f2e2 100644
--- a/content/public/test/mock_download_item.h
+++ b/content/public/test/mock_download_item.h
@@ -100,7 +100,6 @@
   MOCK_CONST_METHOD0(GetWebContents, WebContents*());
   MOCK_METHOD1(OnContentCheckCompleted, void(DownloadDangerType));
   MOCK_METHOD1(SetOpenWhenComplete, void(bool));
-  MOCK_METHOD1(SetIsTemporary, void(bool));
   MOCK_METHOD1(SetOpened, void(bool));
   MOCK_METHOD1(SetDisplayName, void(const base::FilePath&));
   MOCK_CONST_METHOD1(DebugString, std::string(bool));
diff --git a/content/renderer/android/synchronous_compositor_output_surface.cc b/content/renderer/android/synchronous_compositor_output_surface.cc
index 7919e83a..2cbcf4d 100644
--- a/content/renderer/android/synchronous_compositor_output_surface.cc
+++ b/content/renderer/android/synchronous_compositor_output_surface.cc
@@ -44,7 +44,7 @@
 namespace {
 
 const int64_t kFallbackTickTimeoutInMilliseconds = 100;
-const uint32_t kCompositorSurfaceNamespace = 1;
+const uint32_t kCompositorClientId = 1;
 
 // Do not limit number of resources, so use an unrealistically high value.
 const size_t kNumResourcesLimit = 10 * 1000 * 1000;
@@ -97,8 +97,7 @@
       memory_policy_(0u),
       frame_swap_message_queue_(frame_swap_message_queue),
       surface_manager_(new cc::SurfaceManager),
-      surface_id_allocator_(
-          new cc::SurfaceIdAllocator(kCompositorSurfaceNamespace)),
+      surface_id_allocator_(new cc::SurfaceIdAllocator(kCompositorClientId)),
       surface_factory_(new cc::SurfaceFactory(surface_manager_.get(), this)) {
   DCHECK(registry_);
   DCHECK(sender_);
@@ -107,7 +106,7 @@
   capabilities_.delegated_rendering = true;
   memory_policy_.priority_cutoff_when_visible =
       gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE;
-  surface_id_allocator_->RegisterSurfaceIdNamespace(surface_manager_.get());
+  surface_id_allocator_->RegisterSurfaceClientId(surface_manager_.get());
 }
 
 SynchronousCompositorOutputSurface::~SynchronousCompositorOutputSurface() {}
@@ -145,7 +144,7 @@
   registered_ = true;
 
   surface_manager_->RegisterSurfaceFactoryClient(
-      surface_id_allocator_->id_namespace(), this);
+      surface_id_allocator_->client_id(), this);
 
   cc::RendererSettings software_renderer_settings;
 
@@ -156,7 +155,7 @@
   display_.reset(new cc::Display(
       surface_manager_.get(), nullptr /* shared_bitmap_manager */,
       nullptr /* gpu_memory_buffer_manager */, software_renderer_settings,
-      surface_id_allocator_->id_namespace(), nullptr /* begin_frame_source */,
+      surface_id_allocator_->client_id(), nullptr /* begin_frame_source */,
       base::MakeUnique<SoftwareOutputSurface>(
           base::MakeUnique<SoftwareDevice>(&current_sw_canvas_)),
       nullptr /* scheduler */, nullptr /* texture_mailbox_deleter */));
@@ -173,7 +172,7 @@
   if (!delegated_surface_id_.is_null())
     surface_factory_->Destroy(delegated_surface_id_);
   surface_manager_->UnregisterSurfaceFactoryClient(
-      surface_id_allocator_->id_namespace());
+      surface_id_allocator_->client_id());
   display_ = nullptr;
   surface_factory_ = nullptr;
   surface_id_allocator_ = nullptr;
diff --git a/content/renderer/child_frame_compositing_helper.cc b/content/renderer/child_frame_compositing_helper.cc
index 9b98bc69..80e0b67 100644
--- a/content/renderer/child_frame_compositing_helper.cc
+++ b/content/renderer/child_frame_compositing_helper.cc
@@ -67,13 +67,6 @@
 ChildFrameCompositingHelper::~ChildFrameCompositingHelper() {
 }
 
-BrowserPluginManager* ChildFrameCompositingHelper::GetBrowserPluginManager() {
-  if (!browser_plugin_)
-    return nullptr;
-
-  return BrowserPluginManager::Get();
-}
-
 blink::WebPluginContainer* ChildFrameCompositingHelper::GetContainer() {
   if (!browser_plugin_)
     return nullptr;
@@ -81,13 +74,6 @@
   return browser_plugin_->container();
 }
 
-int ChildFrameCompositingHelper::GetInstanceID() {
-  if (!browser_plugin_)
-    return 0;
-
-  return browser_plugin_->browser_plugin_instance_id();
-}
-
 void ChildFrameCompositingHelper::UpdateWebLayer(blink::WebLayer* layer) {
   if (GetContainer()) {
     GetContainer()->setWebLayer(layer);
diff --git a/content/renderer/child_frame_compositing_helper.h b/content/renderer/child_frame_compositing_helper.h
index 09548c71..bd33dde 100644
--- a/content/renderer/child_frame_compositing_helper.h
+++ b/content/renderer/child_frame_compositing_helper.h
@@ -84,9 +84,7 @@
 
   virtual ~ChildFrameCompositingHelper();
 
-  BrowserPluginManager* GetBrowserPluginManager();
   blink::WebPluginContainer* GetContainer();
-  int GetInstanceID();
 
   void CheckSizeAndAdjustLayerProperties(const gfx::Size& new_size,
                                          float device_scale_factor,
diff --git a/content/renderer/fetchers/resource_fetcher_impl.cc b/content/renderer/fetchers/resource_fetcher_impl.cc
index 5187849..a1a760fd 100644
--- a/content/renderer/fetchers/resource_fetcher_impl.cc
+++ b/content/renderer/fetchers/resource_fetcher_impl.cc
@@ -122,8 +122,8 @@
   }
   loader_->loadAsynchronously(request_, this);
 
-  // No need to hold on to the request.
-  request_.reset();
+  // No need to hold on to the request; reset it now.
+  request_ = blink::WebURLRequest();
 }
 
 void ResourceFetcherImpl::SetTimeout(const base::TimeDelta& timeout) {
diff --git a/content/renderer/fetchers/resource_fetcher_impl.h b/content/renderer/fetchers/resource_fetcher_impl.h
index 731ca48..1dfa051 100644
--- a/content/renderer/fetchers/resource_fetcher_impl.h
+++ b/content/renderer/fetchers/resource_fetcher_impl.h
@@ -66,7 +66,7 @@
   // Options to send to the loader.
   blink::WebURLLoaderOptions options_;
 
-  // Request to send.  Released once Start() is called.
+  // Request to send.
   blink::WebURLRequest request_;
 
   // Callback when we're done.
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc
index c73ca064..513c8a6 100644
--- a/content/renderer/gpu/render_widget_compositor.cc
+++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -1125,9 +1125,8 @@
   delegate_->ForwardCompositorProto(serialized);
 }
 
-void RenderWidgetCompositor::SetSurfaceIdNamespace(
-    uint32_t surface_id_namespace) {
-  layer_tree_host_->set_surface_id_namespace(surface_id_namespace);
+void RenderWidgetCompositor::SetSurfaceClientId(uint32_t surface_client_id) {
+  layer_tree_host_->set_surface_client_id(surface_client_id);
 }
 
 void RenderWidgetCompositor::OnHandleCompositorProto(
diff --git a/content/renderer/gpu/render_widget_compositor.h b/content/renderer/gpu/render_widget_compositor.h
index 68349ec..5ed5908 100644
--- a/content/renderer/gpu/render_widget_compositor.h
+++ b/content/renderer/gpu/render_widget_compositor.h
@@ -97,7 +97,7 @@
       std::unique_ptr<base::Value> value,
       const base::Callback<void(std::unique_ptr<base::Value>)>& callback);
   bool SendMessageToMicroBenchmark(int id, std::unique_ptr<base::Value> value);
-  void SetSurfaceIdNamespace(uint32_t surface_id_namespace);
+  void SetSurfaceClientId(uint32_t surface_id_namespace);
   void OnHandleCompositorProto(const std::vector<uint8_t>& proto);
   void SetPaintedDeviceScaleFactor(float device_scale);
 
diff --git a/content/renderer/image_downloader/image_downloader_impl.cc b/content/renderer/image_downloader/image_downloader_impl.cc
index 139abbc..3c67180f 100644
--- a/content/renderer/image_downloader/image_downloader_impl.cc
+++ b/content/renderer/image_downloader/image_downloader_impl.cc
@@ -107,7 +107,11 @@
     return;
   // Proportionally resize the minimal image to fit in a box of size
   // |max_image_size|.
-  images->push_back(ResizeImage(*min_image, max_image_size));
+  SkBitmap resized = ResizeImage(*min_image, max_image_size);
+  // Drop null or empty SkBitmap.
+  if (resized.drawsNothing())
+    return;
+  images->push_back(resized);
   original_image_sizes->push_back(
       gfx::Size(min_image->width(), min_image->height()));
 }
@@ -154,8 +158,10 @@
 
   if (image_url.SchemeIs(url::kDataScheme)) {
     SkBitmap data_image = ImageFromDataUrl(image_url);
-    if (!data_image.empty()) {
-      result_images.push_back(ResizeImage(data_image, max_bitmap_size));
+    SkBitmap resized = ResizeImage(data_image, max_bitmap_size);
+    // Drop null or empty SkBitmap.
+    if (!resized.drawsNothing()) {
+      result_images.push_back(resized);
       result_original_image_sizes.push_back(
           gfx::Size(data_image.width(), data_image.height()));
     }
diff --git a/content/renderer/manifest/manifest_manager.cc b/content/renderer/manifest/manifest_manager.cc
index 6e78236..e23c99af 100644
--- a/content/renderer/manifest/manifest_manager.cc
+++ b/content/renderer/manifest/manifest_manager.cc
@@ -38,7 +38,6 @@
   bool handled = true;
 
   IPC_BEGIN_MESSAGE_MAP(ManifestManager, message)
-    IPC_MESSAGE_HANDLER(ManifestManagerMsg_HasManifest, OnHasManifest)
     IPC_MESSAGE_HANDLER(ManifestManagerMsg_RequestManifest, OnRequestManifest)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
@@ -46,14 +45,6 @@
   return handled;
 }
 
-void ManifestManager::OnHasManifest(int request_id) {
-  GURL url(render_frame()->GetWebFrame()->document().manifestURL());
-
-  bool has_manifest = may_have_manifest_ && !url.is_empty();
-  Send(new ManifestManagerHostMsg_HasManifestResponse(
-      routing_id(), request_id, has_manifest));
-}
-
 void ManifestManager::OnRequestManifest(int request_id) {
   GetManifest(base::Bind(&ManifestManager::OnRequestManifestComplete,
                          base::Unretained(this), request_id));
@@ -115,6 +106,7 @@
 void ManifestManager::DidChangeManifest() {
   may_have_manifest_ = true;
   manifest_dirty_ = true;
+  manifest_url_ = GURL();
 }
 
 void ManifestManager::DidCommitProvisionalLoad(
@@ -125,18 +117,19 @@
 
   may_have_manifest_ = false;
   manifest_dirty_ = true;
+  manifest_url_ = GURL();
 }
 
 void ManifestManager::FetchManifest() {
-  GURL url(render_frame()->GetWebFrame()->document().manifestURL());
+  manifest_url_ = render_frame()->GetWebFrame()->document().manifestURL();
 
-  if (url.is_empty()) {
+  if (manifest_url_.is_empty()) {
     ManifestUmaUtil::FetchFailed(ManifestUmaUtil::FETCH_EMPTY_URL);
     ResolveCallbacks(ResolveStateFailure);
     return;
   }
 
-  fetcher_.reset(new ManifestFetcher(url));
+  fetcher_.reset(new ManifestFetcher(manifest_url_));
   fetcher_->Start(
       render_frame()->GetWebFrame(),
       render_frame()->GetWebFrame()->document().manifestUseCredentials(),
@@ -194,10 +187,14 @@
 }
 
 void ManifestManager::ResolveCallbacks(ResolveState state) {
-  if (state == ResolveStateFailure) {
-    manifest_url_ = GURL();
+  // Do not reset |manifest_url_| on failure here. If manifest_url_ is
+  // non-empty, that means the link 404s, we failed to fetch it, or it was
+  // unparseable. However, the site still tried to specify a manifest, so
+  // preserve that information in the URL for the callbacks.
+  // |manifest_url| will be reset on navigation or if we receive a didchange
+  // event.
+  if (state == ResolveStateFailure)
     manifest_ = Manifest();
-  }
 
   manifest_dirty_ = state != ResolveStateSuccess;
 
diff --git a/content/renderer/manifest/manifest_manager.h b/content/renderer/manifest/manifest_manager.h
index 2c62a9e..fec22fdf 100644
--- a/content/renderer/manifest/manifest_manager.h
+++ b/content/renderer/manifest/manifest_manager.h
@@ -60,7 +60,6 @@
 
   // Called when receiving a ManifestManagerMsg_RequestManifest from the browser
   // process.
-  void OnHasManifest(int request_id);
   void OnRequestManifest(int request_id);
   void OnRequestManifestComplete(int request_id,
                                  const GURL&,
diff --git a/content/renderer/media/audio_device_factory.cc b/content/renderer/media/audio_device_factory.cc
index 9f9b8c1..d192fbf 100644
--- a/content/renderer/media/audio_device_factory.cc
+++ b/content/renderer/media/audio_device_factory.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 
 #include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
 #include "build/build_config.h"
 #include "content/common/content_constants_internal.h"
 #include "content/renderer/media/audio_input_message_filter.h"
@@ -128,6 +129,8 @@
     return NewMixableSink(source_type, render_frame_id, session_id, device_id,
                           security_origin);
 
+  UMA_HISTOGRAM_BOOLEAN("Media.Audio.Render.SinkCache.UsedForSinkCreation",
+                        false);
   return NewFinalAudioRendererSink(render_frame_id, session_id, device_id,
                                    security_origin);
 }
diff --git a/content/renderer/media/audio_renderer_sink_cache_impl.cc b/content/renderer/media/audio_renderer_sink_cache_impl.cc
index 9fef7d0..4b427323 100644
--- a/content/renderer/media/audio_renderer_sink_cache_impl.cc
+++ b/content/renderer/media/audio_renderer_sink_cache_impl.cc
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/synchronization/lock.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "content/renderer/media/audio_device_factory.h"
@@ -19,6 +20,25 @@
 
 constexpr int kDeleteTimeoutMs = 5000;
 
+namespace {
+
+enum GetOutputDeviceInfoCacheUtilization {
+  // No cached sink found.
+  SINK_CACHE_MISS_NO_SINK = 0,
+
+  // If session id is used to specify a device, we always have to create and
+  // cache a new sink.
+  SINK_CACHE_MISS_CANNOT_LOOKUP_BY_SESSION_ID = 1,
+
+  // Output parmeters for an already-cached sink are requested.
+  SINK_CACHE_HIT = 2,
+
+  // For UMA.
+  SINK_CACHE_LAST_ENTRY
+};
+
+}  // namespace
+
 // Cached sink data.
 struct AudioRendererSinkCacheImpl::CacheEntry {
   int source_render_frame_id;
@@ -74,6 +94,9 @@
     // Cache a newly-created sink.
     base::AutoLock auto_lock(cache_lock_);
     cache_.push_back(cache_entry);
+    UMA_HISTOGRAM_ENUMERATION(
+        "Media.Audio.Render.SinkCache.GetOutputDeviceInfoCacheUtilization",
+        SINK_CACHE_MISS_CANNOT_LOOKUP_BY_SESSION_ID, SINK_CACHE_LAST_ENTRY);
 
   } else {
     // Ignore session id.
@@ -88,6 +111,9 @@
       DVLOG(1) << "GetSinkInfo: address: " << cache_iter->sink.get()
                << " - reused a cached sink.";
 
+      UMA_HISTOGRAM_ENUMERATION(
+          "Media.Audio.Render.SinkCache.GetOutputDeviceInfoCacheUtilization",
+          SINK_CACHE_HIT, SINK_CACHE_LAST_ENTRY);
       return cache_iter->sink->GetOutputDeviceInfo();
     }
 
@@ -101,6 +127,9 @@
 
     // Cache a newly-created sink.
     cache_.push_back(cache_entry);
+    UMA_HISTOGRAM_ENUMERATION(
+        "Media.Audio.Render.SinkCache.GetOutputDeviceInfoCacheUtilization",
+        SINK_CACHE_MISS_NO_SINK, SINK_CACHE_LAST_ENTRY);
   }
 
   // Schedule it for deletion.
@@ -118,6 +147,9 @@
     int source_render_frame_id,
     const std::string& device_id,
     const url::Origin& security_origin) {
+  UMA_HISTOGRAM_BOOLEAN("Media.Audio.Render.SinkCache.UsedForSinkCreation",
+                        true);
+
   base::AutoLock auto_lock(cache_lock_);
 
   auto cache_iter =
@@ -130,6 +162,8 @@
              << " - found unused cached sink, reusing it.";
 
     cache_iter->used = true;
+    UMA_HISTOGRAM_BOOLEAN(
+        "Media.Audio.Renderer.SinkCache.InfoSinkReusedForOutput", true);
     return cache_iter->sink;
   }
 
@@ -205,8 +239,11 @@
 
     // To stop the sink before deletion if it's not used, we need to hold
     // a ref to it.
-    if (!cache_iter->used)
+    if (!cache_iter->used) {
       sink_to_stop = cache_iter->sink;
+      UMA_HISTOGRAM_BOOLEAN(
+          "Media.Audio.Renderer.SinkCache.InfoSinkReusedForOutput", false);
+    }
 
     cache_.erase(cache_iter);
     DVLOG(1) << "DeleteSink: address: " << sink_ptr;
diff --git a/content/renderer/media/image_capture_frame_grabber.cc b/content/renderer/media/image_capture_frame_grabber.cc
index faeb43f8..5d39b3e 100644
--- a/content/renderer/media/image_capture_frame_grabber.cc
+++ b/content/renderer/media/image_capture_frame_grabber.cc
@@ -25,16 +25,44 @@
   callbacks->onError();
 }
 
-// This internal method receives a |frame| and converts its pixels into a
-// SkImage via an internal SkSurface and SkPixmap. Alpha channel, if any, is
-// copied.
-void OnVideoFrame(const ImageCaptureFrameGrabber::SkImageDeliverCB& callback,
-                  const scoped_refptr<media::VideoFrame>& frame,
-                  base::TimeTicks /* current_time */) {
+}  // anonymous namespace
+
+// Ref-counted class to receive a single VideoFrame on IO thread, convert it and
+// send it to |main_task_runner_|, where this class is created and destroyed.
+class ImageCaptureFrameGrabber::SingleShotFrameHandler
+    : public base::RefCountedThreadSafe<SingleShotFrameHandler> {
+ public:
+  SingleShotFrameHandler() : first_frame_received_(false) {}
+
+  // Receives a |frame| and converts its pixels into a SkImage via an internal
+  // SkSurface and SkPixmap. Alpha channel, if any, is copied.
+  void OnVideoFrameOnIOThread(SkImageDeliverCB callback,
+                              const scoped_refptr<media::VideoFrame>& frame,
+                              base::TimeTicks current_time);
+
+ private:
+  friend class base::RefCountedThreadSafe<SingleShotFrameHandler>;
+  virtual ~SingleShotFrameHandler() {}
+
+  // Flag to indicate that the first frames has been processed, and subsequent
+  // ones can be safely discarded.
+  bool first_frame_received_;
+
+  DISALLOW_COPY_AND_ASSIGN(SingleShotFrameHandler);
+};
+
+void ImageCaptureFrameGrabber::SingleShotFrameHandler::OnVideoFrameOnIOThread(
+    SkImageDeliverCB callback,
+    const scoped_refptr<media::VideoFrame>& frame,
+    base::TimeTicks /* current_time */) {
   DCHECK(frame->format() == media::PIXEL_FORMAT_YV12 ||
          frame->format() == media::PIXEL_FORMAT_I420 ||
          frame->format() == media::PIXEL_FORMAT_YV12A);
 
+  if (first_frame_received_)
+    return;
+  first_frame_received_ = true;
+
   const SkAlphaType alpha = media::IsOpaque(frame->format())
                                 ? kOpaque_SkAlphaType
                                 : kPremul_SkAlphaType;
@@ -73,8 +101,6 @@
   callback.Run(surface->makeImageSnapshot());
 }
 
-}  // anonymous namespace
-
 ImageCaptureFrameGrabber::ImageCaptureFrameGrabber() : weak_factory_(this) {}
 
 ImageCaptureFrameGrabber::~ImageCaptureFrameGrabber() {
@@ -84,7 +110,6 @@
 void ImageCaptureFrameGrabber::grabFrame(
     blink::WebMediaStreamTrack* track,
     WebImageCaptureGrabFrameCallbacks* callbacks) {
-  DVLOG(1) << __FUNCTION__;
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(!!callbacks);
 
@@ -94,22 +119,24 @@
   ScopedWebCallbacks<WebImageCaptureGrabFrameCallbacks> scoped_callbacks =
       make_scoped_web_callbacks(callbacks, base::Bind(&OnError));
 
-  // ConnectToTrack() must happen on render's Main Thread, whereas VideoFrames
-  // are delivered on a background thread though, so we Bind the callback to our
-  // current thread.
+  // A SingleShotFrameHandler is bound and given to the Track to guarantee that
+  // only one VideoFrame is converted and delivered to OnSkImage(), otherwise
+  // SKImages might be sent to resolved |callbacks| while DisconnectFromTrack()
+  // is being processed, which might be further held up if UI is busy, see
+  // https://crbug.com/623042.
   MediaStreamVideoSink::ConnectToTrack(
-      *track,
-      base::Bind(&OnVideoFrame, media::BindToCurrentLoop(base::Bind(
-                                    &ImageCaptureFrameGrabber::OnSkImage,
-                                    weak_factory_.GetWeakPtr(),
-                                    base::Passed(&scoped_callbacks)))),
+      *track, base::Bind(&SingleShotFrameHandler::OnVideoFrameOnIOThread,
+                         make_scoped_refptr(new SingleShotFrameHandler),
+                         media::BindToCurrentLoop(
+                             base::Bind(&ImageCaptureFrameGrabber::OnSkImage,
+                                        weak_factory_.GetWeakPtr(),
+                                        base::Passed(&scoped_callbacks)))),
       false);
 }
 
 void ImageCaptureFrameGrabber::OnSkImage(
-    ScopedWebCallbacks<WebImageCaptureGrabFrameCallbacks> callbacks,
+    ScopedWebCallbacks<blink::WebImageCaptureGrabFrameCallbacks> callbacks,
     sk_sp<SkImage> image) {
-  DVLOG(1) << __FUNCTION__;
   DCHECK(thread_checker_.CalledOnValidThread());
 
   MediaStreamVideoSink::DisconnectFromTrack();
diff --git a/content/renderer/media/image_capture_frame_grabber.h b/content/renderer/media/image_capture_frame_grabber.h
index 78543e4a..df33626 100644
--- a/content/renderer/media/image_capture_frame_grabber.h
+++ b/content/renderer/media/image_capture_frame_grabber.h
@@ -18,17 +18,13 @@
 class WebMediaStreamTrack;
 }
 
-namespace media {
-class VideoFrame;
-}
-
 namespace content {
 
 // This class grabs Video Frames from a given Media Stream Video Track, binding
-// a function every time grabFrame() is called. This function receives an
-// incoming VideoFrame on a background thread and converts it into the
-// appropriate SkBitmap which is sent back to OnSkBitmap(). This class is single
-// threaded throughout.
+// a method of an ephemeral SingleShotFrameHandler every time grabFrame() is
+// called. This method receives an incoming media::VideoFrame on a background
+// thread and converts it into the appropriate SkBitmap which is sent back to
+// OnSkBitmap(). This class is single threaded throughout.
 class CONTENT_EXPORT ImageCaptureFrameGrabber final
     : NON_EXPORTED_BASE(public blink::WebImageCaptureFrameGrabber),
       NON_EXPORTED_BASE(public MediaStreamVideoSink) {
@@ -43,6 +39,9 @@
                  blink::WebImageCaptureGrabFrameCallbacks* callbacks) override;
 
  private:
+  // Internal class to receive, convert and forward one frame.
+  class SingleShotFrameHandler;
+
   void OnSkImage(
       ScopedWebCallbacks<blink::WebImageCaptureGrabFrameCallbacks> callbacks,
       sk_sp<SkImage> image);
diff --git a/content/renderer/media/video_track_recorder.cc b/content/renderer/media/video_track_recorder.cc
index d65e238..e5d477a 100644
--- a/content/renderer/media/video_track_recorder.cc
+++ b/content/renderer/media/video_track_recorder.cc
@@ -39,13 +39,13 @@
 
 using media::VideoFrame;
 using media::VideoFrameMetadata;
+using video_track_recorder::kVEAEncoderMinResolutionWidth;
+using video_track_recorder::kVEAEncoderMinResolutionHeight;
 
 namespace content {
 
 namespace {
 
-const int kVEAEncoderMinResolutionWidth = 640;
-const int kVEAEncoderMinResolutionHeight = 480;
 const int kVEAEncoderOutputBufferCount = 4;
 
 static struct {
@@ -71,13 +71,15 @@
 #if defined(OS_CHROMEOS)
   return media::VIDEO_CODEC_PROFILE_UNKNOWN;
 #endif  // defined(OS_CHROMEOS)
-  content::RenderThreadImpl* render_thread_impl =
+  content::RenderThreadImpl* const render_thread_impl =
       content::RenderThreadImpl::current();
-  if (!render_thread_impl)
+  if (!render_thread_impl) {
+    DVLOG(3) << "Couldn't access the render thread";
     return media::VIDEO_CODEC_PROFILE_UNKNOWN;
+  }
 
-  media::GpuVideoAcceleratorFactories* gpu_factories =
-      content::RenderThreadImpl::current()->GetGpuFactories();
+  media::GpuVideoAcceleratorFactories* const gpu_factories =
+      render_thread_impl->GetGpuFactories();
   if (!gpu_factories || !gpu_factories->IsGpuVideoAcceleratorEnabled()) {
     DVLOG(3) << "Couldn't initialize GpuVideoAcceleratorFactories";
     return media::VIDEO_CODEC_PROFILE_UNKNOWN;
@@ -250,7 +252,8 @@
   VEAEncoder(
       const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback,
       int32_t bits_per_second,
-      media::VideoCodecProfile codec);
+      media::VideoCodecProfile codec,
+      const gfx::Size& size);
 
   // media::VideoEncodeAccelerator::Client implementation.
   void RequireBitstreamBuffers(unsigned int input_count,
@@ -291,8 +294,8 @@
   // Tracks error status.
   bool error_notified_;
 
-  // Tracks the first frame to encode.
-  std::unique_ptr<VideoFrameAndTimestamp> first_frame_;
+  // Tracks the last frame that we delay the encode.
+  std::unique_ptr<VideoFrameAndTimestamp> last_frame_;
 
   // Size used to initialize encoder.
   gfx::Size input_size_;
@@ -392,7 +395,8 @@
 VEAEncoder::VEAEncoder(
     const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback,
     int32_t bits_per_second,
-    media::VideoCodecProfile codec)
+    media::VideoCodecProfile codec,
+    const gfx::Size& size)
     : Encoder(on_encoded_video_callback,
               bits_per_second,
               RenderThreadImpl::current()->GetGpuFactories()->GetTaskRunner()),
@@ -400,6 +404,12 @@
       codec_(codec),
       error_notified_(false) {
   DCHECK(gpu_factories_);
+  DCHECK_GE(size.width(), kVEAEncoderMinResolutionWidth);
+  DCHECK_GE(size.height(), kVEAEncoderMinResolutionHeight);
+
+  encoding_task_runner_->PostTask(
+      FROM_HERE, base::Bind(&VEAEncoder::ConfigureEncoderOnEncodingTaskRunner,
+                            this, size));
 }
 
 VEAEncoder::~VEAEncoder() {
@@ -485,12 +495,8 @@
     video_encoder_.reset();
   }
 
-  if (!video_encoder_) {
+  if (!video_encoder_)
     ConfigureEncoderOnEncodingTaskRunner(frame->visible_rect().size());
-    first_frame_.reset(
-        new std::pair<scoped_refptr<VideoFrame>, base::TimeTicks>(
-            frame, capture_timestamp));
-  }
 
   if (error_notified_) {
     DVLOG(3) << "An error occurred in VEA encoder";
@@ -500,14 +506,17 @@
   // Drop frames if there is no output buffers available.
   if (output_buffers_.empty()) {
     // TODO(emircan): Investigate if resetting encoder would help.
-    DVLOG(3) << "Dropped frame.";
+    DVLOG(3) << "Might drop frame.";
+    last_frame_.reset(
+        new std::pair<scoped_refptr<VideoFrame>, base::TimeTicks>(
+            frame, capture_timestamp));
     return;
   }
 
   // If first frame hasn't been encoded, do it first.
-  if (first_frame_) {
-    std::unique_ptr<VideoFrameAndTimestamp> first_frame(first_frame_.release());
-    EncodeOnEncodingTaskRunner(first_frame->first, first_frame->second);
+  if (last_frame_) {
+    std::unique_ptr<VideoFrameAndTimestamp> last_frame(last_frame_.release());
+    EncodeOnEncodingTaskRunner(last_frame->first, last_frame->second);
   }
 
   // Lower resolutions may fall back to SW encoder in some platforms, i.e. Mac.
@@ -936,21 +945,81 @@
     const blink::WebMediaStreamTrack& track,
     const OnEncodedVideoCB& on_encoded_video_callback,
     int32_t bits_per_second)
-    : track_(track) {
+    : track_(track),
+      paused_before_init_(false),
+      weak_ptr_factory_(this) {
   DCHECK(main_render_thread_checker_.CalledOnValidThread());
   DCHECK(!track_.isNull());
   DCHECK(track_.getTrackData());
 
+  initialize_encoder_callback_ = base::Bind(
+      &VideoTrackRecorder::InitializeEncoder, weak_ptr_factory_.GetWeakPtr(),
+      codec, on_encoded_video_callback, bits_per_second);
+
+  // InitializeEncoder() will be called on Render Main thread.
+  MediaStreamVideoSink::ConnectToTrack(
+      track_, media::BindToCurrentLoop(initialize_encoder_callback_), false);
+}
+
+VideoTrackRecorder::~VideoTrackRecorder() {
+  DCHECK(main_render_thread_checker_.CalledOnValidThread());
+  MediaStreamVideoSink::DisconnectFromTrack();
+  track_.reset();
+}
+
+void VideoTrackRecorder::Pause() {
+  DCHECK(main_render_thread_checker_.CalledOnValidThread());
+  if (encoder_)
+    encoder_->SetPaused(true);
+  else
+    paused_before_init_ = true;
+}
+
+void VideoTrackRecorder::Resume() {
+  DCHECK(main_render_thread_checker_.CalledOnValidThread());
+  if (encoder_)
+    encoder_->SetPaused(false);
+  else
+    paused_before_init_ = false;
+}
+
+void VideoTrackRecorder::OnVideoFrameForTesting(
+    const scoped_refptr<media::VideoFrame>& frame,
+    base::TimeTicks timestamp) {
+  DVLOG(3) << __FUNCTION__;
+
+  if (!encoder_) {
+    DCHECK(!initialize_encoder_callback_.is_null());
+    initialize_encoder_callback_.Run(frame, timestamp);
+  }
+
+  encoder_->StartFrameEncode(frame, timestamp);
+}
+
+void VideoTrackRecorder::InitializeEncoder(
+    CodecId codec,
+    const OnEncodedVideoCB& on_encoded_video_callback,
+    int32_t bits_per_second,
+    const scoped_refptr<media::VideoFrame>& frame,
+    base::TimeTicks capture_time) {
+  DVLOG(3) << __FUNCTION__ << frame->visible_rect().size().ToString();
+  DCHECK(main_render_thread_checker_.CalledOnValidThread());
+
+  MediaStreamVideoSink::DisconnectFromTrack();
+
+  const gfx::Size& input_size = frame->visible_rect().size();
   const auto& vea_supported_profile = CodecIdToVEAProfile(codec);
-  // TODO(emircan): Prioritize software based encoders in lower resolutions.
-  if (vea_supported_profile != media::VIDEO_CODEC_PROFILE_UNKNOWN) {
+  if (vea_supported_profile != media::VIDEO_CODEC_PROFILE_UNKNOWN &&
+      input_size.width() >= kVEAEncoderMinResolutionWidth &&
+      input_size.height() >= kVEAEncoderMinResolutionHeight) {
     encoder_ = new VEAEncoder(on_encoded_video_callback, bits_per_second,
-                              vea_supported_profile);
+                              vea_supported_profile, input_size);
   } else {
     switch (codec) {
 #if BUILDFLAG(RTC_USE_H264)
       case CodecId::H264:
-        encoder_ = new H264Encoder(on_encoded_video_callback, bits_per_second);
+        encoder_ =
+            new H264Encoder(on_encoded_video_callback, bits_per_second);
         break;
 #endif
       case CodecId::VP8:
@@ -963,6 +1032,9 @@
     }
   }
 
+  if (paused_before_init_)
+    encoder_->SetPaused(paused_before_init_);
+
   // StartFrameEncode() will be called on Render IO thread.
   MediaStreamVideoSink::ConnectToTrack(
       track_,
@@ -970,28 +1042,4 @@
       false);
 }
 
-VideoTrackRecorder::~VideoTrackRecorder() {
-  DCHECK(main_render_thread_checker_.CalledOnValidThread());
-  MediaStreamVideoSink::DisconnectFromTrack();
-  track_.reset();
-}
-
-void VideoTrackRecorder::Pause() {
-  DCHECK(main_render_thread_checker_.CalledOnValidThread());
-  DCHECK(encoder_);
-  encoder_->SetPaused(true);
-}
-
-void VideoTrackRecorder::Resume() {
-  DCHECK(main_render_thread_checker_.CalledOnValidThread());
-  DCHECK(encoder_);
-  encoder_->SetPaused(false);
-}
-
-void VideoTrackRecorder::OnVideoFrameForTesting(
-    const scoped_refptr<media::VideoFrame>& frame,
-    base::TimeTicks timestamp) {
-  encoder_->StartFrameEncode(frame, timestamp);
-}
-
 }  // namespace content
diff --git a/content/renderer/media/video_track_recorder.h b/content/renderer/media/video_track_recorder.h
index 5e6245492..e8de7d9 100644
--- a/content/renderer/media/video_track_recorder.h
+++ b/content/renderer/media/video_track_recorder.h
@@ -9,6 +9,8 @@
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/single_thread_task_runner.h"
 #include "base/threading/thread_checker.h"
 #include "content/public/common/features.h"
 #include "content/public/renderer/media_stream_video_sink.h"
@@ -18,6 +20,11 @@
 class VideoFrame;
 }  // namespace media
 
+namespace video_track_recorder {
+const int kVEAEncoderMinResolutionWidth = 640;
+const int kVEAEncoderMinResolutionHeight = 480;
+}  // namespace video_track_recorder
+
 namespace content {
 
 // VideoTrackRecorder is a MediaStreamVideoSink that encodes the video frames
@@ -56,6 +63,12 @@
  private:
   friend class VideoTrackRecorderTest;
 
+  void InitializeEncoder(CodecId codec,
+                         const OnEncodedVideoCB& on_encoded_video_callback,
+                         int32_t bits_per_second,
+                         const scoped_refptr<media::VideoFrame>& frame,
+                         base::TimeTicks capture_time);
+
   // Used to check that we are destroyed on the same thread we were created.
   base::ThreadChecker main_render_thread_checker_;
 
@@ -65,6 +78,15 @@
   // Inner class to encode using whichever codec is configured.
   scoped_refptr<Encoder> encoder_;
 
+  base::Callback<void(const scoped_refptr<media::VideoFrame>& frame,
+                      base::TimeTicks capture_time)>
+      initialize_encoder_callback_;
+
+  // Used to track the paused state during the initialization process.
+  bool paused_before_init_;
+
+  base::WeakPtrFactory<VideoTrackRecorder> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(VideoTrackRecorder);
 };
 
diff --git a/content/renderer/media/video_track_recorder_unittest.cc b/content/renderer/media/video_track_recorder_unittest.cc
index a839082..6d6808c 100644
--- a/content/renderer/media/video_track_recorder_unittest.cc
+++ b/content/renderer/media/video_track_recorder_unittest.cc
@@ -24,6 +24,8 @@
 #include "third_party/WebKit/public/web/WebHeap.h"
 
 using media::VideoFrame;
+using video_track_recorder::kVEAEncoderMinResolutionWidth;
+using video_track_recorder::kVEAEncoderMinResolutionHeight;
 
 using ::testing::_;
 using ::testing::DoAll;
@@ -47,9 +49,15 @@
     , VideoTrackRecorder::CodecId::H264
 #endif
 };
+const gfx::Size kTrackRecorderTestSize[] = {
+    gfx::Size(kVEAEncoderMinResolutionWidth / 2,
+              kVEAEncoderMinResolutionHeight / 2),
+    gfx::Size(kVEAEncoderMinResolutionWidth, kVEAEncoderMinResolutionHeight)};
+static const int kTrackRecorderTestSizeDiff = 20;
 
 class VideoTrackRecorderTest
-    : public TestWithParam<VideoTrackRecorder::CodecId> {
+    : public TestWithParam<
+          testing::tuple<VideoTrackRecorder::CodecId, gfx::Size>> {
  public:
   VideoTrackRecorderTest()
       : mock_source_(new MockMediaStreamVideoSource(false)) {
@@ -68,7 +76,7 @@
     blink_track_.setTrackData(track_);
 
     video_track_recorder_.reset(new VideoTrackRecorder(
-        GetParam() /* codec */, blink_track_,
+        testing::get<0>(GetParam()) /* codec */, blink_track_,
         base::Bind(&VideoTrackRecorderTest::OnEncodedVideo,
                    base::Unretained(this)),
         0 /* bits_per_second */));
@@ -130,7 +138,7 @@
 // of larger size is sent and is expected to be encoded as a keyframe.
 TEST_P(VideoTrackRecorderTest, VideoEncoding) {
   // |frame_size| cannot be arbitrarily small, should be reasonable.
-  const gfx::Size frame_size(160, 80);
+  const gfx::Size& frame_size = testing::get<1>(GetParam());
   const scoped_refptr<VideoFrame> video_frame =
       VideoFrame::CreateBlackFrame(frame_size);
   const double kFrameRate = 60.0f;
@@ -154,7 +162,8 @@
   Encode(video_frame, timeticks_later);
 
   // Send another Video Frame and expect only an DoOnEncodedVideo() callback.
-  const gfx::Size frame_size2(180, 80);
+  const gfx::Size frame_size2(frame_size.width() + kTrackRecorderTestSizeDiff,
+                              frame_size.height());
   const scoped_refptr<VideoFrame> video_frame2 =
       VideoFrame::CreateBlackFrame(frame_size2);
 
@@ -180,6 +189,7 @@
 
 INSTANTIATE_TEST_CASE_P(,
                         VideoTrackRecorderTest,
-                        ValuesIn(kTrackRecorderTestCodec));
+                        ::testing::Combine(ValuesIn(kTrackRecorderTestCodec),
+                                           ValuesIn(kTrackRecorderTestSize)));
 
 }  // namespace content
diff --git a/content/renderer/pepper/ppb_graphics_3d_impl.cc b/content/renderer/pepper/ppb_graphics_3d_impl.cc
index 30cf4f68..a7bed46 100644
--- a/content/renderer/pepper/ppb_graphics_3d_impl.cc
+++ b/content/renderer/pepper/ppb_graphics_3d_impl.cc
@@ -175,8 +175,7 @@
 }
 
 int32_t PPB_Graphics3D_Impl::DoSwapBuffers(const gpu::SyncToken& sync_token,
-                                           int32_t width,
-                                           int32_t height) {
+                                           const gfx::Size& size) {
   DCHECK(command_buffer_);
   if (taken_front_buffer_.IsZero()) {
     DLOG(ERROR) << "TakeFrontBuffer should be called before DoSwapBuffers";
@@ -191,16 +190,11 @@
     //
     // Don't need to check for NULL from GetPluginInstance since when we're
     // bound, we know our instance is valid.
-    if (width < 0 || height < 0) {
-      width = original_width_;
-      height = original_height_;
-    }
     bool is_overlay_candidate = use_image_chromium_;
     GLenum target =
         is_overlay_candidate ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D;
     cc::TextureMailbox texture_mailbox(taken_front_buffer_, sync_token, target,
-                                       gfx::Size(width, height),
-                                       is_overlay_candidate, false);
+                                       size, is_overlay_candidate, false);
     taken_front_buffer_.SetZero();
     HostGlobals::Get()
         ->GetInstance(pp_instance())
@@ -268,8 +262,6 @@
       std::move(channel), gpu::kNullSurfaceHandle, share_buffer,
       gpu::GPU_STREAM_DEFAULT, gpu::GpuStreamPriority::NORMAL, attrib_helper,
       GURL::EmptyGURL(), base::ThreadTaskRunnerHandle::Get());
-  original_width_ = attrib_helper.offscreen_framebuffer_size.width();
-  original_height_ = attrib_helper.offscreen_framebuffer_size.height();
   if (!command_buffer_)
     return false;
 
diff --git a/content/renderer/pepper/ppb_graphics_3d_impl.h b/content/renderer/pepper/ppb_graphics_3d_impl.h
index 9255e02..dca5aaa 100644
--- a/content/renderer/pepper/ppb_graphics_3d_impl.h
+++ b/content/renderer/pepper/ppb_graphics_3d_impl.h
@@ -75,8 +75,7 @@
   gpu::CommandBuffer* GetCommandBuffer() override;
   gpu::GpuControl* GetGpuControl() override;
   int32_t DoSwapBuffers(const gpu::SyncToken& sync_token,
-                        int32_t width,
-                        int32_t height) override;
+                        const gfx::Size& size) override;
 
  private:
   explicit PPB_Graphics3D_Impl(PP_Instance instance);
@@ -116,12 +115,6 @@
   bool lost_context_ = false;
 #endif
 
-  // The width and height of the command buffer back buffer are first sized from
-  // this process, but then resized by the pepper process. Cache the original
-  // size.
-  int32_t original_width_ = 0;
-  int32_t original_height_ = 0;
-
   bool has_alpha_;
   bool use_image_chromium_;
   std::unique_ptr<gpu::CommandBufferProxyImpl> command_buffer_;
diff --git a/content/renderer/pepper/url_request_info_util.cc b/content/renderer/pepper/url_request_info_util.cc
index 4d8aa14..952994a 100644
--- a/content/renderer/pepper/url_request_info_util.cc
+++ b/content/renderer/pepper/url_request_info_util.cc
@@ -169,7 +169,6 @@
      name_version = "internal_testing_only";
    }
 
-  dest->initialize();
   dest->setURL(frame->document().completeURL(WebString::fromUTF8(data->url)));
   dest->setDownloadToFile(data->stream_to_file);
   dest->setReportUploadProgress(data->record_upload_progress);
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index db7242b..ef2740f 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -4428,14 +4428,12 @@
   FOR_EACH_OBSERVER(RenderFrameObserver, observers_, DidChangeManifest());
 }
 
-bool RenderFrameImpl::enterFullscreen() {
+void RenderFrameImpl::enterFullscreen() {
   Send(new FrameHostMsg_ToggleFullscreen(routing_id_, true));
-  return true;
 }
 
-bool RenderFrameImpl::exitFullscreen() {
+void RenderFrameImpl::exitFullscreen() {
   Send(new FrameHostMsg_ToggleFullscreen(routing_id_, false));
-  return true;
 }
 
 blink::WebPermissionClient* RenderFrameImpl::permissionClient() {
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 2ff0dd7..cf3f825 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -623,8 +623,8 @@
       const blink::WebAXObject& end_object,
       int end_offset) override;
   void didChangeManifest() override;
-  bool enterFullscreen() override;
-  bool exitFullscreen() override;
+  void enterFullscreen() override;
+  void exitFullscreen() override;
   blink::WebPermissionClient* permissionClient() override;
   blink::WebAppBannerClient* appBannerClient() override;
   void registerProtocolHandler(const blink::WebString& scheme,
diff --git a/content/renderer/render_frame_proxy.cc b/content/renderer/render_frame_proxy.cc
index 74bcd08..344692b 100644
--- a/content/renderer/render_frame_proxy.cc
+++ b/content/renderer/render_frame_proxy.cc
@@ -380,7 +380,7 @@
 }
 
 void RenderFrameProxy::OnWillEnterFullscreen() {
-  web_frame_->willEnterFullScreen();
+  web_frame_->willEnterFullscreen();
 }
 
 void RenderFrameProxy::frameDetached(DetachType type) {
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index 129ed07..1bc7b2f 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -490,7 +490,7 @@
     IPC_MESSAGE_HANDLER(ViewMsg_SetTextDirection, OnSetTextDirection)
     IPC_MESSAGE_HANDLER(ViewMsg_Move_ACK, OnRequestMoveAck)
     IPC_MESSAGE_HANDLER(ViewMsg_UpdateScreenRects, OnUpdateScreenRects)
-    IPC_MESSAGE_HANDLER(ViewMsg_SetSurfaceIdNamespace, OnSetSurfaceIdNamespace)
+    IPC_MESSAGE_HANDLER(ViewMsg_SetSurfaceClientId, OnSetSurfaceClientId)
     IPC_MESSAGE_HANDLER(ViewMsg_WaitForNextFrameForTests,
                         OnWaitNextFrameForTests)
 #if defined(OS_ANDROID)
@@ -1449,9 +1449,9 @@
   }
 }
 
-void RenderWidget::OnSetSurfaceIdNamespace(uint32_t surface_id_namespace) {
+void RenderWidget::OnSetSurfaceClientId(uint32_t surface_id_namespace) {
   if (compositor_)
-    compositor_->SetSurfaceIdNamespace(surface_id_namespace);
+    compositor_->SetSurfaceClientId(surface_id_namespace);
 }
 
 void RenderWidget::OnHandleCompositorProto(const std::vector<uint8_t>& proto) {
@@ -1618,9 +1618,9 @@
     return;
 
   if (is_fullscreen_granted_) {
-    webwidget_->didEnterFullScreen();
+    webwidget_->didEnterFullscreen();
   } else {
-    webwidget_->didExitFullScreen();
+    webwidget_->didExitFullscreen();
   }
 }
 
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h
index 8cb00106..f3d391a 100644
--- a/content/renderer/render_widget.h
+++ b/content/renderer/render_widget.h
@@ -469,7 +469,7 @@
                            const gfx::Rect& window_screen_rect);
   void OnUpdateWindowScreenRect(const gfx::Rect& window_screen_rect);
   void OnShowImeIfNeeded();
-  void OnSetSurfaceIdNamespace(uint32_t surface_id_namespace);
+  void OnSetSurfaceClientId(uint32_t surface_id_namespace);
   void OnHandleCompositorProto(const std::vector<uint8_t>& proto);
 
 #if defined(OS_ANDROID)
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
index 7990efe5..0e1d607 100644
--- a/content/renderer/renderer_blink_platform_impl.cc
+++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -49,6 +49,7 @@
 #include "content/public/common/webplugininfo.h"
 #include "content/public/renderer/content_renderer_client.h"
 #include "content/public/renderer/media_stream_utils.h"
+#include "content/public/renderer/render_frame.h"
 #include "content/renderer/cache_storage/webserviceworkercachestorage_impl.h"
 #include "content/renderer/device_sensors/device_light_event_pump.h"
 #include "content/renderer/device_sensors/device_motion_event_pump.h"
@@ -58,6 +59,7 @@
 #include "content/renderer/dom_storage/webstoragenamespace_impl.h"
 #include "content/renderer/gamepad_shared_memory_reader.h"
 #include "content/renderer/media/audio_decoder.h"
+#include "content/renderer/media/audio_device_factory.h"
 #include "content/renderer/media/canvas_capture_handler.h"
 #include "content/renderer/media/html_audio_element_capturer_source.h"
 #include "content/renderer/media/html_video_element_capturer_source.h"
@@ -79,7 +81,6 @@
 #include "gpu/ipc/common/gpu_stream_constants.h"
 #include "ipc/ipc_sync_message_filter.h"
 #include "media/audio/audio_output_device.h"
-#include "media/base/audio_hardware_config.h"
 #include "media/base/mime_util.h"
 #include "media/blink/webcontentdecryptionmodule_impl.h"
 #include "media/filters/stream_parser_factory.h"
@@ -102,6 +103,7 @@
 #include "third_party/WebKit/public/platform/mime_registry.mojom.h"
 #include "third_party/WebKit/public/platform/modules/device_orientation/WebDeviceMotionListener.h"
 #include "third_party/WebKit/public/platform/modules/device_orientation/WebDeviceOrientationListener.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
 #include "url/gurl.h"
 
 #if defined(OS_MACOSX)
@@ -178,6 +180,16 @@
 base::LazyInstance<blink::WebDeviceOrientationData>::Leaky
     g_test_device_orientation_data = LAZY_INSTANCE_INITIALIZER;
 
+media::AudioParameters GetAudioHardwareParams() {
+  blink::WebLocalFrame* const web_frame =
+      blink::WebLocalFrame::frameForCurrentContext();
+  RenderFrame* const render_frame = RenderFrame::FromWebFrame(web_frame);
+  return AudioDeviceFactory::GetOutputDeviceInfo(render_frame->GetRoutingID(),
+                                                 0, std::string(),
+                                                 web_frame->getSecurityOrigin())
+      .output_params();
+}
+
 }  // namespace
 
 //------------------------------------------------------------------------------
@@ -685,18 +697,15 @@
 }
 
 double RendererBlinkPlatformImpl::audioHardwareSampleRate() {
-  RenderThreadImpl* thread = RenderThreadImpl::current();
-  return thread->GetAudioHardwareConfig()->GetOutputSampleRate();
+  return GetAudioHardwareParams().sample_rate();
 }
 
 size_t RendererBlinkPlatformImpl::audioHardwareBufferSize() {
-  RenderThreadImpl* thread = RenderThreadImpl::current();
-  return thread->GetAudioHardwareConfig()->GetOutputBufferSize();
+  return GetAudioHardwareParams().frames_per_buffer();
 }
 
 unsigned RendererBlinkPlatformImpl::audioHardwareOutputChannels() {
-  RenderThreadImpl* thread = RenderThreadImpl::current();
-  return thread->GetAudioHardwareConfig()->GetOutputChannels();
+  return GetAudioHardwareParams().channels();
 }
 
 WebDatabaseObserver* RendererBlinkPlatformImpl::databaseObserver() {
diff --git a/content/shell/browser/shell_views.cc b/content/shell/browser/shell_views.cc
index e8e4552..5dcc775 100644
--- a/content/shell/browser/shell_views.cc
+++ b/content/shell/browser/shell_views.cc
@@ -71,7 +71,7 @@
   bool IsCommandIdChecked(int command_id) const override { return false; }
   bool IsCommandIdEnabled(int command_id) const override { return true; }
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override {
+                                  ui::Accelerator* accelerator) const override {
     return false;
   }
   void ExecuteCommand(int command_id, int event_flags) override {
diff --git a/content/test/data/invalid.ico b/content/test/data/invalid.ico
new file mode 100644
index 0000000..f6c9094
--- /dev/null
+++ b/content/test/data/invalid.ico
Binary files differ
diff --git a/content/test/gpu/generate_buildbot_json.py b/content/test/gpu/generate_buildbot_json.py
index 61db377..5bee81c 100755
--- a/content/test/gpu/generate_buildbot_json.py
+++ b/content/test/gpu/generate_buildbot_json.py
@@ -920,10 +920,6 @@
           # http://crbug.com/599451: this test is currently too slow
           # to run on x64 in Debug mode. Need to shard the tests.
           'Win7 x64 Debug (NVIDIA)',
-          # http://crbug.com/540543: Linux Intel driver is GL 3.0 and
-          # doesn't support features needed for ES3
-          'Linux Release (New Intel)',
-          'Linux Debug (New Intel)',
         ],
       },
     ],
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
index 2745c1c..ca1b79b2 100644
--- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -34,14 +34,10 @@
     # Too slow (take about one hour to run)
     self.Skip('deqp/functional/gles3/builtinprecision/*.html', bug=619403)
 
-    self.Fail('deqp/functional/gles3/framebufferblit/depth_stencil.html',
-        bug=483282)
     self.Fail('deqp/data/gles3/shaders/linkage.html', bug=601821)
 
     self.Flaky('deqp/functional/gles3/negativefragmentapi.html', bug=604794)
 
-    self.Fail('deqp/data/gles3/shaders/preprocessor.html', bug=483282)
-
     self.Fail('conformance2/glsl3/forbidden-operators.html', bug=483282)
 
     self.Flaky('conformance2/query/occlusion-query.html', bug=603168)
@@ -51,6 +47,9 @@
     self.Fail('conformance2/transform_feedback/' +
         'unwritten-output-defaults-to-zero.html', bug=1441) # ANGLE bug
 
+    # Likely move this to WebGL 2.0.1.
+    self.Fail('conformance2/glsl3/tricky-loop-conditions.html', bug=483282)
+
     # Avoid a conflict with a Mac expectation by setting
     self.Fail('conformance2/textures/misc/tex-input-validation.html',
         ['d3d9', 'd3d11', 'opengl'], bug=483282)
@@ -67,29 +66,6 @@
     self.Fail('deqp/functional/gles3/shaderloop_do_while.html',
         ['win'], bug=617817)
 
-    self.Fail('deqp/functional/gles3/shadertexturefunction/texturelod.html',
-        ['win'], bug=483282)
-    self.Fail('deqp/functional/gles3/shadertexturefunction/' +
-        'texturelodoffset.html',
-        ['win'], bug=483282)
-    self.Fail('deqp/functional/gles3/shadertexturefunction/' +
-        'textureprojlod.html',
-        ['win'], bug=483282)
-    self.Fail('deqp/functional/gles3/shadertexturefunction/' +
-        'textureprojlodoffset.html',
-        ['win'], bug=483282)
-    self.Fail('deqp/functional/gles3/shadertexturefunction/texturegrad.html',
-        ['win'], bug=483282)
-    self.Fail('deqp/functional/gles3/shadertexturefunction/' +
-        'texturegradoffset.html',
-        ['win'], bug=483282)
-    self.Fail('deqp/functional/gles3/shadertexturefunction/' +
-        'textureprojgrad.html',
-        ['win'], bug=483282)
-    self.Fail('deqp/functional/gles3/shadertexturefunction/' +
-        'textureprojgradoffset.html',
-        ['win'], bug=483282)
-
     self.Fail('conformance2/glsl3/array-in-complex-expression.html',
         ['win'], bug=483282)
     self.Skip('conformance2/reading/read-pixels-pack-parameters.html',
diff --git a/content/test/test_render_view_host.cc b/content/test/test_render_view_host.cc
index 8f9c990..29fc6f7 100644
--- a/content/test/test_render_view_host.cc
+++ b/content/test/test_render_view_host.cc
@@ -205,11 +205,11 @@
 void TestRenderWidgetHostView::UnlockMouse() {
 }
 
-uint32_t TestRenderWidgetHostView::GetSurfaceIdNamespace() {
+uint32_t TestRenderWidgetHostView::GetSurfaceClientId() {
   // See constructor.  If a test needs this, its harness needs to construct an
   // ImageTransportFactory.
   DCHECK(surface_id_allocator_);
-  return surface_id_allocator_->id_namespace();
+  return surface_id_allocator_->client_id();
 }
 
 TestRenderViewHost::TestRenderViewHost(
diff --git a/content/test/test_render_view_host.h b/content/test/test_render_view_host.h
index a21fc48f..082d369 100644
--- a/content/test/test_render_view_host.h
+++ b/content/test/test_render_view_host.h
@@ -122,7 +122,7 @@
   gfx::Rect GetBoundsInRootWindow() override;
   bool LockMouse() override;
   void UnlockMouse() override;
-  uint32_t GetSurfaceIdNamespace() override;
+  uint32_t GetSurfaceClientId() override;
 
   bool is_showing() const { return is_showing_; }
   bool is_occluded() const { return is_occluded_; }
diff --git a/extensions/common/api/_api_features.json b/extensions/common/api/_api_features.json
index ac12ff9..faf3636d 100644
--- a/extensions/common/api/_api_features.json
+++ b/extensions/common/api/_api_features.json
@@ -293,6 +293,7 @@
     "matches": [
       "chrome://md-settings/*",
       "chrome://network/*",
+      "chrome://oobe/*",
       "chrome://settings/*",
       "chrome://settings-frame/*"
     ]
diff --git a/extensions/renderer/api/display_source/wifi_display/DEPS b/extensions/renderer/api/display_source/wifi_display/DEPS
index 4e30f49a..6dd95bf 100644
--- a/extensions/renderer/api/display_source/wifi_display/DEPS
+++ b/extensions/renderer/api/display_source/wifi_display/DEPS
@@ -2,6 +2,7 @@
   # TODO(Mikhail): Consider removing when https://crbug.com/432381 is fixed.
   "+media/base",
   "+media/video",
+  "+services/shell/public/cpp",
   "+third_party/openh264/src/codec/api",
   "+third_party/wds/src/libwds/public",
 ]
diff --git a/extensions/renderer/api/display_source/wifi_display/wifi_display_media_manager.cc b/extensions/renderer/api/display_source/wifi_display/wifi_display_media_manager.cc
index 7358146..02bf1381 100644
--- a/extensions/renderer/api/display_source/wifi_display/wifi_display_media_manager.cc
+++ b/extensions/renderer/api/display_source/wifi_display/wifi_display_media_manager.cc
@@ -7,7 +7,6 @@
 #include "base/logging.h"
 #include "base/rand_util.h"
 #include "base/task_runner_util.h"
-#include "content/public/common/service_registry.h"
 #include "content/public/renderer/media_stream_utils.h"
 #include "content/public/renderer/media_stream_video_sink.h"
 #include "content/public/renderer/render_thread.h"
@@ -16,6 +15,7 @@
 #include "extensions/renderer/api/display_source/wifi_display/wifi_display_elementary_stream_info.h"
 #include "extensions/renderer/api/display_source/wifi_display/wifi_display_media_pipeline.h"
 #include "media/base/bind_to_current_loop.h"
+#include "services/shell/public/cpp/interface_provider.h"
 
 namespace extensions {
 
@@ -86,11 +86,11 @@
     const blink::WebMediaStreamTrack& video_track,
     const blink::WebMediaStreamTrack& audio_track,
     const std::string& sink_ip_address,
-    content::ServiceRegistry* service_registry,
+    shell::InterfaceProvider* interface_provider,
     const ErrorCallback& error_callback)
     : video_track_(video_track),
       audio_track_(audio_track),
-      service_registry_(service_registry),
+      interface_provider_(interface_provider),
       sink_ip_address_(sink_ip_address),
       player_(nullptr),
       io_task_runner_(content::RenderThread::Get()->GetIOTaskRunner()),
@@ -99,7 +99,7 @@
       is_initialized_(false),
       weak_factory_(this) {
   DCHECK(!video_track.isNull() || !audio_track.isNull());
-  DCHECK(service_registry_);
+  DCHECK(interface_provider_);
   DCHECK(!error_callback_.is_null());
 }
 
@@ -488,7 +488,7 @@
 void WiFiDisplayMediaManager::ConnectToRemoteService(
     WiFiDisplayMediaServiceRequest request) {
   DCHECK(content::RenderThread::Get());
-  service_registry_->ConnectToRemoteService(std::move(request));
+  interface_provider_->GetInterface(std::move(request));
 }
 
 }  // namespace extensions
diff --git a/extensions/renderer/api/display_source/wifi_display/wifi_display_media_manager.h b/extensions/renderer/api/display_source/wifi_display/wifi_display_media_manager.h
index 4506ff7..9f69f2c 100644
--- a/extensions/renderer/api/display_source/wifi_display/wifi_display_media_manager.h
+++ b/extensions/renderer/api/display_source/wifi_display/wifi_display_media_manager.h
@@ -18,9 +18,9 @@
 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
 #include "third_party/wds/src/libwds/public/media_manager.h"
 
-namespace content {
-class ServiceRegistry;
-}  // namespace content
+namespace shell {
+class InterfaceProvider;
+}  // namespace shell
 
 namespace extensions {
 class WiFiDisplayAudioSink;
@@ -36,7 +36,7 @@
       const blink::WebMediaStreamTrack& video_track,
       const blink::WebMediaStreamTrack& audio_track,
       const std::string& sink_ip_address,
-      content::ServiceRegistry* service_registry,
+      shell::InterfaceProvider* interface_provider,
       const ErrorCallback& error_callback);
 
   ~WiFiDisplayMediaManager() override;
@@ -79,7 +79,7 @@
   std::unique_ptr<WiFiDisplayAudioSink> audio_sink_;
   std::unique_ptr<WiFiDisplayVideoSink> video_sink_;
 
-  content::ServiceRegistry* service_registry_;
+  shell::InterfaceProvider* interface_provider_;
   std::string sink_ip_address_;
   std::pair<int, int> sink_rtp_ports_;
   wds::H264VideoFormat optimal_video_format_;
diff --git a/extensions/renderer/api/display_source/wifi_display/wifi_display_session.cc b/extensions/renderer/api/display_source/wifi_display/wifi_display_session.cc
index 93e9c4d..eefbb1a 100644
--- a/extensions/renderer/api/display_source/wifi_display/wifi_display_session.cc
+++ b/extensions/renderer/api/display_source/wifi_display/wifi_display_session.cc
@@ -8,9 +8,9 @@
 
 #include "base/logging.h"
 #include "base/timer/timer.h"
-#include "content/public/common/service_registry.h"
 #include "content/public/renderer/render_frame.h"
 #include "extensions/renderer/api/display_source/wifi_display/wifi_display_media_manager.h"
+#include "services/shell/public/cpp/interface_provider.h"
 #include "third_party/wds/src/libwds/public/logging.h"
 #include "third_party/wds/src/libwds/public/media_manager.h"
 
@@ -42,8 +42,7 @@
     weak_factory_(this) {
   DCHECK(params_.render_frame);
   wds::LogSystem::set_error_func(&LogWDSError);
-  params.render_frame->GetServiceRegistry()->ConnectToRemoteService(
-      mojo::GetProxy(&service_));
+  params.render_frame->GetRemoteInterfaces()->GetInterface(&service_);
   service_.set_connection_error_handler(base::Bind(
           &WiFiDisplaySession::OnIPCConnectionError,
           weak_factory_.GetWeakPtr()));
@@ -84,7 +83,7 @@
           params_.video_track,
           params_.audio_track,
           sink_ip_address,
-          params_.render_frame->GetServiceRegistry(),
+          params_.render_frame->GetRemoteInterfaces(),
           base::Bind(
               &WiFiDisplaySession::OnMediaError,
               weak_factory_.GetWeakPtr())));
diff --git a/google_apis/drive/drive_api_requests.cc b/google_apis/drive/drive_api_requests.cc
index 307e541..eefaa35 100644
--- a/google_apis/drive/drive_api_requests.cc
+++ b/google_apis/drive/drive_api_requests.cc
@@ -15,6 +15,8 @@
 #include "base/sequenced_task_runner.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/task_runner_util.h"
 #include "base/values.h"
@@ -144,37 +146,6 @@
   return json_string;
 }
 
-// Splits |string| into lines by |kHttpBr|.
-// Each line does not include |kHttpBr|.
-void SplitIntoLines(const std::string& string,
-                    std::vector<base::StringPiece>* output) {
-  const size_t br_size = std::string(kHttpBr).size();
-  std::string::const_iterator it = string.begin();
-  std::vector<base::StringPiece> lines;
-  while (true) {
-    const std::string::const_iterator next_pos =
-        std::search(it, string.end(), kHttpBr, kHttpBr + br_size);
-    lines.push_back(base::StringPiece(it, next_pos));
-    if (next_pos == string.end())
-      break;
-    it = next_pos + br_size;
-  }
-  output->swap(lines);
-}
-
-// Remove transport padding (spaces and tabs at the end of line) from |piece|.
-base::StringPiece TrimTransportPadding(const base::StringPiece& piece) {
-  size_t trim_size = 0;
-  while (trim_size < piece.size() &&
-         (piece[piece.size() - 1 - trim_size] == ' ' ||
-          piece[piece.size() - 1 - trim_size] == '\t')) {
-    ++trim_size;
-  }
-  return piece.substr(0, piece.size() - trim_size);
-}
-
-void EmptyClosure(std::unique_ptr<BatchableDelegate>) {}
-
 }  // namespace
 
 MultipartHttpResponse::MultipartHttpResponse() : code(HTTP_SUCCESS) {
@@ -231,8 +202,8 @@
   const std::string header = "--" + boundary;
   const std::string terminator = "--" + boundary + "--";
 
-  std::vector<base::StringPiece> lines;
-  SplitIntoLines(response, &lines);
+  std::vector<base::StringPiece> lines = base::SplitStringPieceUsingSubstr(
+      response, kHttpBr, base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
 
   enum {
     STATE_START,
@@ -274,7 +245,8 @@
       body.clear();
       continue;
     }
-    const base::StringPiece chopped_line = TrimTransportPadding(line);
+    const base::StringPiece chopped_line =
+        base::TrimString(line, " \t", base::TRIM_TRAILING);
     const bool is_new_part = chopped_line == header;
     const bool was_last_part = chopped_line == terminator;
     if (is_new_part || was_last_part) {
@@ -1346,10 +1318,7 @@
     child->data_size = data.size();
     total_size += data.size();
 
-    parts.push_back(ContentTypeAndData());
-    parts.back().type = kHttpContentType;
-    parts.back().data = header;
-    parts.back().data.append(data);
+    parts.push_back(ContentTypeAndData({kHttpContentType, header + data}));
   }
 
   UMA_HISTOGRAM_COUNTS_100(kUMADriveTotalFileCountInBatchUpload, parts.size());
@@ -1420,12 +1389,12 @@
   }
 
   for (size_t i = 0; i < parts.size(); ++i) {
-    BatchableDelegate* const delegate = child_requests_[i]->request.get();
-    // Pass onwership of |delegate| so that child_requests_.clear() won't
+    BatchableDelegate* delegate = child_requests_[i]->request.get();
+    // Pass ownership of |delegate| so that child_requests_.clear() won't
     // kill the delegate. It has to be deleted after the notification.
-    delegate->NotifyResult(
-        parts[i].code, parts[i].body,
-        base::Bind(&EmptyClosure, base::Passed(&child_requests_[i]->request)));
+    delegate->NotifyResult(parts[i].code, parts[i].body,
+                           base::Bind(&base::DeletePointer<BatchableDelegate>,
+                                      child_requests_[i]->request.release()));
   }
   child_requests_.clear();
 
@@ -1433,16 +1402,15 @@
 }
 
 void BatchUploadRequest::RunCallbackOnPrematureFailure(DriveApiErrorCode code) {
-  for (auto child : child_requests_) {
+  for (auto& child : child_requests_)
     child->request->NotifyError(code);
-  }
   child_requests_.clear();
 }
 
 void BatchUploadRequest::OnURLFetchUploadProgress(const net::URLFetcher* source,
                                                   int64_t current,
                                                   int64_t total) {
-  for (auto child : child_requests_) {
+  for (auto& child : child_requests_) {
     if (child->data_offset <= current &&
         current <= child->data_offset + child->data_size) {
       child->request->NotifyUploadProgress(source, current - child->data_offset,
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 6df7f6a2..82fa88e 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -402,7 +402,7 @@
   bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
 
   // Copy the contents of the currently bound frame buffer.
-  void Copy(const gfx::Size& size, GLenum format);
+  void Copy();
 
   // Destroy the render texture. This must be explicitly called before
   // destroying this object.
@@ -2592,15 +2592,14 @@
   return success;
 }
 
-void BackTexture::Copy(const gfx::Size& size, GLenum format) {
+void BackTexture::Copy() {
   DCHECK_NE(id(), 0u);
   ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
                                      decoder_->state_.GetErrorState());
   ScopedTextureBinder binder(&decoder_->state_, id(), Target());
-  glCopyTexImage2D(Target(),
-                   0,  // level
-                   format, 0, 0, size.width(), size.height(),
-                   0);  // border
+  glCopyTexSubImage2D(Target(),
+                      0,  // level
+                      0, 0, 0, 0, size_.width(), size_.height());
 }
 
 void BackTexture::Destroy() {
@@ -13479,9 +13478,7 @@
 
       if (offscreen_target_buffer_preserved_) {
         // Copy the target frame buffer to the saved offscreen texture.
-        offscreen_saved_color_texture_->Copy(
-            offscreen_saved_color_texture_->size(),
-            offscreen_saved_color_format_);
+        offscreen_saved_color_texture_->Copy();
       } else {
         offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
         offscreen_target_frame_buffer_->AttachRenderTexture(
diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc
index aad304c..6d6658cb 100644
--- a/gpu/command_buffer/tests/gl_manager.cc
+++ b/gpu/command_buffer/tests/gl_manager.cc
@@ -188,7 +188,8 @@
       force_shader_name_hashing(false),
       multisampled(false),
       backbuffer_alpha(true),
-      image_factory(nullptr) {}
+      image_factory(nullptr),
+      preserve_backbuffer(false) {}
 
 GLManager::GLManager()
     : sync_point_manager_(nullptr),
@@ -293,6 +294,7 @@
   attribs.should_use_native_gmb_for_backbuffer =
       options.image_factory != nullptr;
   attribs.offscreen_framebuffer_size = options.size;
+  attribs.buffer_preserved = options.preserve_backbuffer;
 
   if (!context_group) {
     GpuDriverBugWorkarounds gpu_driver_bug_workaround(&command_line);
diff --git a/gpu/command_buffer/tests/gl_manager.h b/gpu/command_buffer/tests/gl_manager.h
index 4dff34d7..aa8a49a 100644
--- a/gpu/command_buffer/tests/gl_manager.h
+++ b/gpu/command_buffer/tests/gl_manager.h
@@ -82,6 +82,8 @@
     bool backbuffer_alpha;
     // The ImageFactory to use to generate images for the backbuffer.
     gpu::ImageFactory* image_factory;
+    // Whether to preserve the backbuffer after a call to SwapBuffers().
+    bool preserve_backbuffer;
   };
   GLManager();
   ~GLManager() override;
diff --git a/gpu/command_buffer/tests/gl_native_gmb_backbuffer_unittest.cc b/gpu/command_buffer/tests/gl_native_gmb_backbuffer_unittest.cc
index 2bb44e4..cafe0c6 100644
--- a/gpu/command_buffer/tests/gl_native_gmb_backbuffer_unittest.cc
+++ b/gpu/command_buffer/tests/gl_native_gmb_backbuffer_unittest.cc
@@ -15,21 +15,68 @@
 #include "ui/gl/gl_context.h"
 #include "ui/gl/gl_image.h"
 
+#if defined(OS_MACOSX)
+#include "gpu/ipc/service/gpu_memory_buffer_factory_io_surface.h"
+#endif
+
 namespace gpu {
 
 class GLNativeGMBTest : public testing::Test {
  protected:
   void SetUp() override {
     gl_.Initialize(GLManager::Options());
-    image_factory_.SetRequiredTextureType(GL_TEXTURE_RECTANGLE_ARB);
   }
 
   void TearDown() override {
     gl_.Destroy();
   }
 
+  // Runs a simple battery of tests.
+  void RunBackbufferTestWithOptions(const GLManager::Options& options) {
+    GLManager gl;
+    gl.Initialize(options);
+    gl.MakeCurrent();
+
+    // Clear the back buffer and check that it has the right values.
+    glClearColor(0.0f, 0.25f, 0.5f, 0.7f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    uint8_t pixel[4];
+    memset(pixel, 0, 4);
+    glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
+    EXPECT_NEAR(0u, pixel[0], 2);
+    EXPECT_NEAR(64u, pixel[1], 2);
+    EXPECT_NEAR(127u, pixel[2], 2);
+    uint8_t alpha = options.backbuffer_alpha ? 178 : 255;
+    EXPECT_NEAR(alpha, pixel[3], 2);
+
+    // Resize, then clear the back buffer and check its contents.
+    glResizeCHROMIUM(10, 10, 1, true);
+    glClearColor(0.5f, 0.6f, 0.7f, 0.8f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    memset(pixel, 0, 4);
+    glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
+    EXPECT_NEAR(128u, pixel[0], 2);
+    EXPECT_NEAR(153u, pixel[1], 2);
+    EXPECT_NEAR(178u, pixel[2], 2);
+    uint8_t alpha2 = options.backbuffer_alpha ? 204 : 255;
+    EXPECT_NEAR(alpha2, pixel[3], 2);
+
+    // Swap buffers, then clear the back buffer and check its contents.
+    ::gles2::GetGLContext()->SwapBuffers();
+    glClearColor(0.1f, 0.2f, 0.3f, 0.4f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    memset(pixel, 0, 4);
+    glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
+    EXPECT_NEAR(25u, pixel[0], 2);
+    EXPECT_NEAR(51u, pixel[1], 2);
+    EXPECT_NEAR(76u, pixel[2], 2);
+    uint8_t alpha3 = options.backbuffer_alpha ? 102 : 255;
+    EXPECT_NEAR(alpha3, pixel[3], 2);
+
+    gl.Destroy();
+  }
+
   GLManager gl_;
-  TextureImageFactory image_factory_;
 };
 
 TEST_F(GLNativeGMBTest, TestNativeGMBBackbufferWithDifferentConfigurations) {
@@ -37,55 +84,25 @@
     LOG(INFO) << "GL_ARB_texture_rectangle not supported. Skipping test...";
     return;
   }
+#if defined(OS_MACOSX)
+  GpuMemoryBufferFactoryIOSurface image_factory;
+#else
+  TextureImageFactory image_factory;
+  image_factory.SetRequiredTextureType(GL_TEXTURE_RECTANGLE_ARB);
+#endif
 
   for (int has_alpha = 0; has_alpha <= 1; ++has_alpha) {
     for (int msaa = 0; msaa <= 1; ++msaa) {
-      GLManager::Options options;
-      options.image_factory = &image_factory_;
-      options.multisampled = msaa == 1;
-      options.backbuffer_alpha = has_alpha == 1;
+      for (int preserve_backbuffer = 0; preserve_backbuffer <= 1;
+           ++preserve_backbuffer) {
+        GLManager::Options options;
+        options.image_factory = &image_factory;
+        options.multisampled = msaa == 1;
+        options.backbuffer_alpha = has_alpha == 1;
+        options.preserve_backbuffer = preserve_backbuffer;
 
-      GLManager gl;
-      gl.Initialize(options);
-      gl.MakeCurrent();
-
-      // Clear the back buffer and check that it has the right values.
-      glClearColor(0.0f, 0.25f, 0.5f, 0.7f);
-      glClear(GL_COLOR_BUFFER_BIT);
-      uint8_t pixel[4];
-      memset(pixel, 0, 4);
-      glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
-      EXPECT_NEAR(0u, pixel[0], 2);
-      EXPECT_NEAR(64u, pixel[1], 2);
-      EXPECT_NEAR(127u, pixel[2], 2);
-      uint8_t alpha = has_alpha ? 178 : 255;
-      EXPECT_NEAR(alpha, pixel[3], 2);
-
-      // Resize, then clear the back buffer and check its contents.
-      glResizeCHROMIUM(10, 10, 1, true);
-      glClearColor(0.5f, 0.6f, 0.7f, 0.8f);
-      glClear(GL_COLOR_BUFFER_BIT);
-      memset(pixel, 0, 4);
-      glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
-      EXPECT_NEAR(128u, pixel[0], 2);
-      EXPECT_NEAR(153u, pixel[1], 2);
-      EXPECT_NEAR(178u, pixel[2], 2);
-      uint8_t alpha2 = has_alpha ? 204 : 255;
-      EXPECT_NEAR(alpha2, pixel[3], 2);
-
-      // Swap buffers, then clear the back buffer and check its contents.
-      ::gles2::GetGLContext()->SwapBuffers();
-      glClearColor(0.1f, 0.2f, 0.3f, 0.4f);
-      glClear(GL_COLOR_BUFFER_BIT);
-      memset(pixel, 0, 4);
-      glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
-      EXPECT_NEAR(25u, pixel[0], 2);
-      EXPECT_NEAR(51u, pixel[1], 2);
-      EXPECT_NEAR(76u, pixel[2], 2);
-      uint8_t alpha3 = has_alpha ? 102 : 255;
-      EXPECT_NEAR(alpha3, pixel[3], 2);
-
-      gl.Destroy();
+        RunBackbufferTestWithOptions(options);
+    }
     }
   }
 }
diff --git a/media/base/mac/avfoundation_glue.h b/media/base/mac/avfoundation_glue.h
index fb76958ae..a5b4304 100644
--- a/media/base/mac/avfoundation_glue.h
+++ b/media/base/mac/avfoundation_glue.h
@@ -2,9 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// TODO(mcasas): Remove this whole glue, https://crbug.com/579648. This glue was
-// introduced to support Mac OS X <= 10.6 where AVFoundation was not available,
-// and had to happen in runtime.
+// AVFoundation API is only introduced in Mac OS X > 10.6, and there is only one
+// build of Chromium, so the (potential) linking with AVFoundation has to happen
+// in runtime. For this to be clean, an AVFoundationGlue class is defined to try
+// and load these AVFoundation system libraries. If it succeeds, subsequent
+// clients can use AVFoundation via the rest of the classes declared in this
+// file.
 
 #ifndef MEDIA_BASE_MAC_AVFOUNDATION_GLUE_H_
 #define MEDIA_BASE_MAC_AVFOUNDATION_GLUE_H_
@@ -48,7 +51,6 @@
 
   static Class AVCaptureSessionClass();
   static Class AVCaptureVideoDataOutputClass();
-  static Class AVCaptureStillImageOutputClass();
 #endif  // defined(__OBJC__)
 
  private:
@@ -93,9 +95,6 @@
 
 MEDIA_EXPORT
 @interface CrAVCaptureOutput : NSObject  // Originally from AVCaptureOutput.h.
-
-- (NSArray*)connections;
-
 @end
 
 // Originally AVCaptureSession and coming from AVCaptureSession.h.
@@ -105,7 +104,6 @@
 - (void)release;
 - (void)addInput:(CrAVCaptureInput*)input;
 - (void)removeInput:(CrAVCaptureInput*)input;
-- (NSArray*)outputs;
 - (void)addOutput:(CrAVCaptureOutput*)output;
 - (void)removeOutput:(CrAVCaptureOutput*)output;
 - (BOOL)isRunning;
@@ -158,17 +156,6 @@
 
 @end
 
-// Originally AVCaptureStillImageOutput and coming from AVCaptureOutput.h.
-MEDIA_EXPORT
-@interface CrAVCaptureStillImageOutput : CrAVCaptureOutput
-
-typedef void (^CompletionHandler)(CoreMediaGlue::CMSampleBufferRef, NSError*);
-- (void)
-captureStillImageAsynchronouslyFromConnection:(CrAVCaptureConnection*)connection
-                            completionHandler:(CompletionHandler)handler;
-
-@end
-
 // Class to provide access to class methods of AVCaptureDevice.
 MEDIA_EXPORT
 @interface AVCaptureDeviceGlue : NSObject
diff --git a/media/base/mac/avfoundation_glue.mm b/media/base/mac/avfoundation_glue.mm
index 4bd6d72..56f51aa 100644
--- a/media/base/mac/avfoundation_glue.mm
+++ b/media/base/mac/avfoundation_glue.mm
@@ -167,10 +167,6 @@
   return [AVFoundationBundle() classNamed:@"AVCaptureVideoDataOutput"];
 }
 
-Class AVFoundationGlue::AVCaptureStillImageOutputClass() {
-  return [AVFoundationBundle() classNamed:@"AVCaptureStillImageOutput"];
-}
-
 @implementation AVCaptureDeviceGlue
 
 + (NSArray*)devices {
diff --git a/media/base/mac/coremedia_glue.h b/media/base/mac/coremedia_glue.h
index 093427cd..9f69f96f 100644
--- a/media/base/mac/coremedia_glue.h
+++ b/media/base/mac/coremedia_glue.h
@@ -52,7 +52,6 @@
     kCMPixelFormat_422YpCbCr8_yuvs = 'yuvs',
   };
   enum {
-    kCMVideoCodecType_JPEG = 'jpeg',
     kCMVideoCodecType_JPEG_OpenDML = 'dmb1',
     kCMVideoCodecType_H264 = 'avc1',
   };
diff --git a/media/capture/video/mac/video_capture_device_avfoundation_mac.h b/media/capture/video/mac/video_capture_device_avfoundation_mac.h
index 69082e7a..8198bcd 100644
--- a/media/capture/video/mac/video_capture_device_avfoundation_mac.h
+++ b/media/capture/video/mac/video_capture_device_avfoundation_mac.h
@@ -21,9 +21,8 @@
 @class CrAVCaptureDevice;
 @class CrAVCaptureSession;
 @class CrAVCaptureVideoDataOutput;
-@class CrAVCaptureStillImageOutput;
 
-// Class used by VideoCaptureDeviceMac (VCDM) for video and image capture using
+// Class used by VideoCaptureDeviceMac (VCDM) for video capture using
 // AVFoundation API. This class lives inside the thread created by its owner
 // VCDM.
 //
@@ -63,7 +62,7 @@
   int frameHeight_;
   float frameRate_;
 
-  base::Lock lock_;  // Protects concurrent setting and using |frameReceiver_|.
+  base::Lock lock_;  // Protects concurrent setting and using of frameReceiver_.
   media::VideoCaptureDeviceMac* frameReceiver_;  // weak.
 
   base::scoped_nsobject<CrAVCaptureSession> captureSession_;
@@ -75,9 +74,6 @@
   CrAVCaptureDeviceInput* captureDeviceInput_;
   base::scoped_nsobject<CrAVCaptureVideoDataOutput> captureVideoDataOutput_;
 
-  // An AVDataOutput specialized for taking pictures out of |captureSession_|.
-  base::scoped_nsobject<CrAVCaptureStillImageOutput> stillImageOutput_;
-
   base::ThreadChecker main_thread_checker_;
 }
 
@@ -118,10 +114,6 @@
 // Stops video capturing and stops listening to notifications.
 - (void)stopCapture;
 
-// Takes a photo. This method should only be called between -startCapture and
-// -stopCapture.
-- (void)takePhoto;
-
 @end
 
 #endif  // MEDIA_CAPTURE_VIDEO_MAC_VIDEO_CAPTURE_DEVICE_AVFOUNDATION_MAC_H_
diff --git a/media/capture/video/mac/video_capture_device_avfoundation_mac.mm b/media/capture/video/mac/video_capture_device_avfoundation_mac.mm
index c47ff9c4..0f89a031 100644
--- a/media/capture/video/mac/video_capture_device_avfoundation_mac.mm
+++ b/media/capture/video/mac/video_capture_device_avfoundation_mac.mm
@@ -95,6 +95,8 @@
   }
 }
 
+}  // anonymous namespace
+
 // This function translates Mac Core Video pixel formats to Chromium pixel
 // formats.
 media::VideoPixelFormat FourCCToChromiumPixelFormat(FourCharCode code) {
@@ -110,26 +112,6 @@
   }
 }
 
-// Extracts |base_address| and |length| out of a SampleBuffer.
-void ExtractBaseAddressAndLength(
-    char** base_address,
-    size_t* length,
-    CoreMediaGlue::CMSampleBufferRef sample_buffer) {
-  CoreMediaGlue::CMBlockBufferRef block_buffer =
-      CoreMediaGlue::CMSampleBufferGetDataBuffer(sample_buffer);
-  DCHECK(block_buffer);
-
-  size_t length_at_offset;
-  const OSStatus status = CoreMediaGlue::CMBlockBufferGetDataPointer(
-      block_buffer, 0, &length_at_offset, length, base_address);
-  DCHECK_EQ(noErr, status);
-  // Expect the (M)JPEG data to be available as a contiguous reference, i.e.
-  // not covered by multiple memory blocks.
-  DCHECK_EQ(length_at_offset, *length);
-}
-
-}  // anonymous namespace
-
 @implementation VideoCaptureDeviceAVFoundation
 
 #pragma mark Class methods
@@ -235,8 +217,6 @@
       // No need to release |captureDeviceInput_|, is owned by the session.
       captureDeviceInput_ = nil;
     }
-    if (stillImageOutput_)
-      [captureSession_ removeOutput:stillImageOutput_];
     return YES;
   }
 
@@ -281,13 +261,6 @@
                         queue:dispatch_get_global_queue(
                                   DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];
   [captureSession_ addOutput:captureVideoDataOutput_];
-
-  // Create and plug the still image capture output. This should happen in
-  // advance of the actual picture to allow for the 3A to stabilize.
-  stillImageOutput_.reset(
-      [[AVFoundationGlue::AVCaptureStillImageOutputClass() alloc] init]);
-  [captureSession_ addOutput:stillImageOutput_];
-
   return YES;
 }
 
@@ -386,48 +359,6 @@
   [[NSNotificationCenter defaultCenter] removeObserver:self];
 }
 
-- (void)takePhoto {
-  DCHECK(main_thread_checker_.CalledOnValidThread());
-  DCHECK([captureSession_ isRunning]);
-
-  DCHECK_EQ(1u, [[stillImageOutput_ connections] count]);
-  CrAVCaptureConnection* const connection =
-      [[stillImageOutput_ connections] firstObject];
-  if (!connection) {
-    base::AutoLock lock(lock_);
-    frameReceiver_->OnPhotoError();
-    return;
-  }
-
-  const auto handler = ^(CoreMediaGlue::CMSampleBufferRef sampleBuffer,
-                         NSError* error) {
-    base::AutoLock lock(lock_);
-    if (!frameReceiver_)
-      return;
-    if (error != nil) {
-      frameReceiver_->OnPhotoError();
-      return;
-    }
-
-    // Recommended compressed pixel format is JPEG, we don't expect surprises.
-    // TODO(mcasas): Consider using [1] for merging EXIF output information:
-    // [1] +(NSData*)jpegStillImageNSDataRepresentation:jpegSampleBuffer;
-    DCHECK_EQ(
-        CoreMediaGlue::kCMVideoCodecType_JPEG,
-        CoreMediaGlue::CMFormatDescriptionGetMediaSubType(
-            CoreMediaGlue::CMSampleBufferGetFormatDescription(sampleBuffer)));
-
-    char* baseAddress = 0;
-    size_t length = 0;
-    ExtractBaseAddressAndLength(&baseAddress, &length, sampleBuffer);
-    frameReceiver_->OnPhotoTaken(reinterpret_cast<uint8_t*>(baseAddress),
-                                 length, "image/jpeg");
-  };
-
-  [stillImageOutput_ captureStillImageAsynchronouslyFromConnection:connection
-                                                 completionHandler:handler];
-}
-
 #pragma mark Private methods
 
 // |captureOutput| is called by the capture device to deliver a new frame.
@@ -450,7 +381,17 @@
   size_t frameSize = 0;
   CVImageBufferRef videoFrame = nil;
   if (fourcc == CoreMediaGlue::kCMVideoCodecType_JPEG_OpenDML) {
-    ExtractBaseAddressAndLength(&baseAddress, &frameSize, sampleBuffer);
+    // If MJPEG, use block buffer instead of pixel buffer.
+    CoreMediaGlue::CMBlockBufferRef blockBuffer =
+        CoreMediaGlue::CMSampleBufferGetDataBuffer(sampleBuffer);
+    if (blockBuffer) {
+      size_t lengthAtOffset;
+      CoreMediaGlue::CMBlockBufferGetDataPointer(
+          blockBuffer, 0, &lengthAtOffset, &frameSize, &baseAddress);
+      // Expect the MJPEG data to be available as a contiguous reference, i.e.
+      // not covered by multiple memory blocks.
+      CHECK_EQ(lengthAtOffset, frameSize);
+    }
   } else {
     videoFrame = CoreMediaGlue::CMSampleBufferGetImageBuffer(sampleBuffer);
     // Lock the frame and calculate frame size.
diff --git a/media/capture/video/mac/video_capture_device_mac.h b/media/capture/video/mac/video_capture_device_mac.h
index 7eff128..88b986b 100644
--- a/media/capture/video/mac/video_capture_device_mac.h
+++ b/media/capture/video/mac/video_capture_device_mac.h
@@ -62,12 +62,10 @@
       const VideoCaptureParams& params,
       std::unique_ptr<VideoCaptureDevice::Client> client) override;
   void StopAndDeAllocate() override;
-  void TakePhoto(TakePhotoCallback callback) override;
 
   bool Init(VideoCaptureDevice::Name::CaptureApiType capture_api_type);
 
-  // Called to deliver captured video frames.  It's safe to call this method
-  // from any thread, including those controlled by AVFoundation.
+  // Called to deliver captured video frames.
   void ReceiveFrame(const uint8_t* video_frame,
                     int video_frame_length,
                     const VideoCaptureFormat& frame_format,
@@ -75,13 +73,6 @@
                     int aspect_denominator,
                     base::TimeDelta timestamp);
 
-  // Callbacks with the result of a still image capture, or in case of error,
-  // respectively. It's safe to call these methods from any thread.
-  void OnPhotoTaken(const uint8_t* image_data,
-                    size_t image_length,
-                    const std::string& mime_type);
-  void OnPhotoError();
-
   // Forwarder to VideoCaptureDevice::Client::OnError().
   void ReceiveError(const tracked_objects::Location& from_here,
                     const std::string& reason);
@@ -108,9 +99,6 @@
 
   base::scoped_nsobject<VideoCaptureDeviceAVFoundation> capture_device_;
 
-  // To hold on to the TakePhotoCallback while the picture is being taken.
-  std::unique_ptr<TakePhotoCallback> photo_callback_;
-
   // Used with Bind and PostTask to ensure that methods aren't called after the
   // VideoCaptureDeviceMac is destroyed.
   // NOTE: Weak pointers must be invalidated before all other member variables.
diff --git a/media/capture/video/mac/video_capture_device_mac.mm b/media/capture/video/mac/video_capture_device_mac.mm
index 6ae6b8c..f032280 100644
--- a/media/capture/video/mac/video_capture_device_mac.mm
+++ b/media/capture/video/mac/video_capture_device_mac.mm
@@ -389,17 +389,6 @@
   state_ = kIdle;
 }
 
-void VideoCaptureDeviceMac::TakePhoto(TakePhotoCallback callback) {
-  DCHECK(task_runner_->BelongsToCurrentThread());
-  DCHECK(state_ == kCapturing) << state_;
-
-  if (photo_callback_)  // Only one picture can be in flight at a time.
-    return;
-
-  photo_callback_.reset(new TakePhotoCallback(std::move(callback)));
-  [capture_device_ takePhoto];
-}
-
 bool VideoCaptureDeviceMac::Init(
     VideoCaptureDevice::Name::CaptureApiType capture_api_type) {
   DCHECK(task_runner_->BelongsToCurrentThread());
@@ -424,6 +413,8 @@
                                          int aspect_numerator,
                                          int aspect_denominator,
                                          base::TimeDelta timestamp) {
+  // This method is safe to call from a device capture thread, i.e. any thread
+  // controlled by AVFoundation.
   if (capture_format_.frame_size != frame_format.frame_size) {
     ReceiveError(FROM_HERE,
                  "Captured resolution " + frame_format.frame_size.ToString() +
@@ -435,26 +426,6 @@
                                   0, base::TimeTicks::Now(), timestamp);
 }
 
-void VideoCaptureDeviceMac::OnPhotoTaken(const uint8_t* image_data,
-                                         size_t image_length,
-                                         const std::string& mime_type) {
-  DCHECK(photo_callback_);
-  if (!image_data || !image_length) {
-    OnPhotoError();
-    return;
-  }
-
-  photo_callback_->Run(mojo::String::From(mime_type),
-                       mojo::Array<uint8_t>(std::vector<uint8_t>(
-                           image_data, image_data + image_length)));
-  photo_callback_.reset();
-}
-
-void VideoCaptureDeviceMac::OnPhotoError() {
-  DLOG(ERROR) << __FUNCTION__ << " error taking picture";
-  photo_callback_.reset();
-}
-
 void VideoCaptureDeviceMac::ReceiveError(
     const tracked_objects::Location& from_here,
     const std::string& reason) {
diff --git a/media/capture/video/video_capture_device_unittest.cc b/media/capture/video/video_capture_device_unittest.cc
index e71fb71..0ea3fb9 100644
--- a/media/capture/video/video_capture_device_unittest.cc
+++ b/media/capture/video/video_capture_device_unittest.cc
@@ -19,7 +19,6 @@
 #include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
-#include "media/base/bind_to_current_loop.h"
 #include "media/base/video_capture_types.h"
 #include "media/capture/video/video_capture_device_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -46,11 +45,9 @@
 #define MAYBE_AllocateBadSize DISABLED_AllocateBadSize
 // We will always get YUYV from the Mac AVFoundation implementations.
 #define MAYBE_CaptureMjpeg DISABLED_CaptureMjpeg
-#define MAYBE_TakePhoto TakePhoto
 #elif defined(OS_WIN)
 #define MAYBE_AllocateBadSize AllocateBadSize
 #define MAYBE_CaptureMjpeg CaptureMjpeg
-#define MAYBE_TakePhoto DISABLED_TakePhoto
 #elif defined(OS_ANDROID)
 // TODO(wjia): enable those tests on Android.
 // On Android, native camera (JAVA) delivers frames on UI thread which is the
@@ -60,7 +57,6 @@
 #define DeAllocateCameraWhileRunning DISABLED_DeAllocateCameraWhileRunning
 #define DeAllocateCameraWhileRunning DISABLED_DeAllocateCameraWhileRunning
 #define MAYBE_CaptureMjpeg DISABLED_CaptureMjpeg
-#define MAYBE_TakePhoto DISABLED_TakePhoto
 #elif defined(OS_LINUX)
 // AllocateBadSize will hang when a real camera is attached and if more than one
 // test is trying to use the camera (even across processes). Do NOT renable
@@ -68,11 +64,9 @@
 // http://crbug.com/94134 http://crbug.com/137260 http://crbug.com/417824
 #define MAYBE_AllocateBadSize DISABLED_AllocateBadSize
 #define MAYBE_CaptureMjpeg CaptureMjpeg
-#define MAYBE_TakePhoto DISABLED_TakePhoto
 #else
 #define MAYBE_AllocateBadSize AllocateBadSize
 #define MAYBE_CaptureMjpeg CaptureMjpeg
-#define MAYBE_TakePhoto DISABLED_TakePhoto
 #endif
 
 using ::testing::_;
@@ -142,30 +136,6 @@
   base::Callback<void(const VideoCaptureFormat&)> frame_cb_;
 };
 
-class MockImageCaptureClient : public base::RefCounted<MockImageCaptureClient> {
- public:
-  // GMock doesn't support move-only arguments, so we use this forward method.
-  void DoOnPhotoTaken(mojo::String mime_type, mojo::Array<uint8_t> data) {
-    EXPECT_STREQ("image/jpeg", mime_type.storage().c_str());
-    ASSERT_GT(data.size(), 4u);
-    // Check some bytes that univocally identify |data| as a JPEG File.
-    // https://en.wikipedia.org/wiki/JPEG_File_Interchange_Format#File_format_structure
-    EXPECT_EQ(0xFF, data[0]);  // First SOI byte
-    EXPECT_EQ(0xD8, data[1]);  // Second SOI byte
-    EXPECT_EQ(0xFF, data[2]);  // First JFIF-APP0 byte
-    EXPECT_EQ(0xE0, data[3]);  // Second JFIF-APP0 byte
-    OnCorrectPhotoTaken();
-  }
-  MOCK_METHOD0(OnCorrectPhotoTaken, void(void));
-  MOCK_METHOD1(
-      OnTakePhotoFailure,
-      void(const base::Callback<void(mojo::String, mojo::Array<uint8_t>)>&));
-
- private:
-  friend class base::RefCounted<MockImageCaptureClient>;
-  virtual ~MockImageCaptureClient() {}
-};
-
 class DeviceEnumerationListener
     : public base::RefCounted<DeviceEnumerationListener> {
  public:
@@ -193,10 +163,10 @@
         video_capture_client_(new MockVideoCaptureClient(
             base::Bind(&VideoCaptureDeviceTest::OnFrameCaptured,
                        base::Unretained(this)))),
-        device_enumeration_listener_(new DeviceEnumerationListener()),
-        image_capture_client_(new MockImageCaptureClient()),
         video_capture_device_factory_(VideoCaptureDeviceFactory::CreateFactory(
-            base::ThreadTaskRunnerHandle::Get())) {}
+            base::ThreadTaskRunnerHandle::Get())) {
+    device_enumeration_listener_ = new DeviceEnumerationListener();
+  }
 
   void SetUp() override {
 #if defined(OS_ANDROID)
@@ -285,14 +255,12 @@
   base::win::ScopedCOMInitializer initialize_com_;
 #endif
   std::unique_ptr<VideoCaptureDevice::Names> names_;
-  const std::unique_ptr<base::MessageLoop> loop_;
+  std::unique_ptr<base::MessageLoop> loop_;
   std::unique_ptr<base::RunLoop> run_loop_;
   std::unique_ptr<MockVideoCaptureClient> video_capture_client_;
-  const scoped_refptr<DeviceEnumerationListener> device_enumeration_listener_;
-  const scoped_refptr<MockImageCaptureClient> image_capture_client_;
+  scoped_refptr<DeviceEnumerationListener> device_enumeration_listener_;
   VideoCaptureFormat last_format_;
-  const std::unique_ptr<VideoCaptureDeviceFactory>
-      video_capture_device_factory_;
+  std::unique_ptr<VideoCaptureDeviceFactory> video_capture_device_factory_;
 };
 
 // Cause hangs on Windows Debug. http://crbug.com/417824
@@ -357,7 +325,8 @@
   VideoCaptureParams capture_params;
   capture_params.requested_format.frame_size.SetSize(width, height);
   capture_params.requested_format.frame_rate = 30.0f;
-  capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420;
+  capture_params.requested_format.pixel_format =
+      PIXEL_FORMAT_I420;
   device->AllocateAndStart(capture_params, std::move(video_capture_client_));
   // Get captured video frames.
   WaitForCapturedFrame();
@@ -392,7 +361,8 @@
   VideoCaptureParams capture_params;
   capture_params.requested_format.frame_size.SetSize(637, 472);
   capture_params.requested_format.frame_rate = 35;
-  capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420;
+  capture_params.requested_format.pixel_format =
+      PIXEL_FORMAT_I420;
   device->AllocateAndStart(capture_params, std::move(video_capture_client_));
   WaitForCapturedFrame();
   device->StopAndDeAllocate();
@@ -514,42 +484,10 @@
   // GetDeviceSupportedFormats().
   std::unique_ptr<VideoCaptureDevice::Name> name =
       GetFirstDeviceNameSupportingPixelFormat(PIXEL_FORMAT_MAX);
-  // Verify no camera returned for PIXEL_FORMAT_MAX. Nothing else to test here
+  // Verify no camera returned for PIXEL_FORMAT_MAX. Nothing else
+  // to test here
   // since we cannot forecast the hardware capabilities.
   ASSERT_FALSE(name);
 }
 
-// Start the camera and take a photo.
-TEST_F(VideoCaptureDeviceTest, MAYBE_TakePhoto) {
-  names_ = EnumerateDevices();
-  if (names_->empty()) {
-    VLOG(1) << "No camera available. Exiting test.";
-    return;
-  }
-  std::unique_ptr<VideoCaptureDevice> device(
-      video_capture_device_factory_->Create(names_->front()));
-  ASSERT_TRUE(device);
-
-  EXPECT_CALL(*video_capture_client_, OnError(_, _)).Times(0);
-
-  VideoCaptureParams capture_params;
-  capture_params.requested_format.frame_size.SetSize(640, 480);
-  capture_params.requested_format.frame_rate = 30;
-  capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420;
-  device->AllocateAndStart(capture_params, std::move(video_capture_client_));
-  WaitForCapturedFrame();
-
-  VideoCaptureDevice::TakePhotoCallback scoped_callback(
-      base::Bind(&MockImageCaptureClient::DoOnPhotoTaken,
-                 image_capture_client_),
-      media::BindToCurrentLoop(base::Bind(
-          &MockImageCaptureClient::OnTakePhotoFailure, image_capture_client_)));
-
-  EXPECT_CALL(*image_capture_client_.get(), OnCorrectPhotoTaken()).Times(1);
-  device->TakePhoto(std::move(scoped_callback));
-  WaitForCapturedFrame();
-
-  device->StopAndDeAllocate();
-}
-
 };  // namespace media
diff --git a/media/cast/BUILD.gn b/media/cast/BUILD.gn
index fce89dd..68912bf 100644
--- a/media/cast/BUILD.gn
+++ b/media/cast/BUILD.gn
@@ -365,23 +365,11 @@
   if (is_android) {
     deps += [ "//testing/android/native_test:native_test_native_code" ]
   }
-}
 
-# TODO(miu): This can be rolled into cast_unittests now that FFMPEG dependency
-# issues are resolved for iOS; but there are bot/isolates to update too.
-if (is_ios || is_mac) {
-  test("cast_h264_vt_encoder_unittests") {
-    sources = [
-      "sender/h264_vt_encoder_unittest.cc",
-    ]
-    deps = [
-      ":common",
-      ":sender",
-      ":test_support",
-      "//testing/gmock",
-      "//testing/gtest",
-      "//third_party/ffmpeg",
-    ]
+  if (is_ios || is_mac) {
+    sources += [ "sender/h264_vt_encoder_unittest.cc" ]
+
+    deps += [ "//third_party/ffmpeg" ]
   }
 }
 
diff --git a/media/cast/cast_config.cc b/media/cast/cast_config.cc
index f1a4a69..0683925 100644
--- a/media/cast/cast_config.cc
+++ b/media/cast/cast_config.cc
@@ -4,79 +4,43 @@
 
 #include "media/cast/cast_config.h"
 
-namespace {
-
-const float kDefaultCongestionControlBackOff = 0.875f;
-
-enum {
-  // Minimum and Maximum VP8 quantizer in default configuration.
-  kDefaultMaxQp = 63,
-  kDefaultMinQp = 4,
-
-  kDefaultMaxCpuSaverQp = 25,
-
-  // Number of video buffers in default configuration (applies only to certain
-  // external codecs).
-  kDefaultNumberOfVideoBuffers = 1,
-};
-
-}  // namespace
-
 namespace media {
 namespace cast {
 
-// TODO(miu): Revisit code factoring of these structs.  There are a number of
-// common elements between them all, so it might be reasonable to only have one
-// or two structs; or, at least a common base class.
+VideoCodecParams::VideoCodecParams()
+    : max_qp(kDefaultMaxQp),
+      min_qp(kDefaultMinQp),
+      max_cpu_saver_qp(kDefaultMaxCpuSaverQp),
+      max_number_of_video_buffers_used(kDefaultNumberOfVideoBuffers),
+      number_of_encode_threads(1) {}
 
-// TODO(miu): Make sure all POD members are initialized by ctors.  Policy
-// decision: Reasonable defaults or use invalid placeholder values to expose
-// unset members?
+VideoCodecParams::VideoCodecParams(const VideoCodecParams& other) = default;
+
+VideoCodecParams::~VideoCodecParams() {}
 
 // TODO(miu): Provide IsValidConfig() functions?
 
-// TODO(miu): Throughout the code, there is a lot of copy-and-paste of the same
-// calculations based on these config values.  So, why don't we add methods to
-// these classes to centralize the logic?
-
-VideoSenderConfig::VideoSenderConfig()
-    : ssrc(0),
+FrameSenderConfig::FrameSenderConfig()
+    : sender_ssrc(0),
       receiver_ssrc(0),
+      min_playout_delay(
+          base::TimeDelta::FromMilliseconds(kDefaultRtpMaxDelayMs)),
       max_playout_delay(
           base::TimeDelta::FromMilliseconds(kDefaultRtpMaxDelayMs)),
+      animated_playout_delay(min_playout_delay),
       rtp_payload_type(RtpPayloadType::UNKNOWN),
       use_external_encoder(false),
-      congestion_control_back_off(kDefaultCongestionControlBackOff),
-      max_bitrate(kDefaultMaxVideoKbps * 1000),
-      min_bitrate(kDefaultMinVideoKbps * 1000),
-      start_bitrate(kDefaultMaxVideoKbps * 1000),
-      max_qp(kDefaultMaxQp),
-      min_qp(kDefaultMinQp),
-      max_cpu_saver_qp(kDefaultMaxCpuSaverQp),
-      max_frame_rate(kDefaultMaxFrameRate),
-      max_number_of_video_buffers_used(kDefaultNumberOfVideoBuffers),
-      codec(CODEC_VIDEO_VP8),
-      number_of_encode_threads(1) {}
-
-VideoSenderConfig::VideoSenderConfig(const VideoSenderConfig& other) = default;
-
-VideoSenderConfig::~VideoSenderConfig() {}
-
-AudioSenderConfig::AudioSenderConfig()
-    : ssrc(0),
-      receiver_ssrc(0),
-      max_playout_delay(
-          base::TimeDelta::FromMilliseconds(kDefaultRtpMaxDelayMs)),
-      rtp_payload_type(RtpPayloadType::UNKNOWN),
-      use_external_encoder(false),
-      frequency(0),
+      rtp_timebase(0),
       channels(0),
-      bitrate(kDefaultAudioEncoderBitrate),
-      codec(CODEC_AUDIO_OPUS) {}
+      max_bitrate(0),
+      min_bitrate(0),
+      start_bitrate(0),
+      max_frame_rate(kDefaultMaxFrameRate),
+      codec(CODEC_UNKNOWN) {}
 
-AudioSenderConfig::AudioSenderConfig(const AudioSenderConfig& other) = default;
+FrameSenderConfig::FrameSenderConfig(const FrameSenderConfig& other) = default;
 
-AudioSenderConfig::~AudioSenderConfig() {}
+FrameSenderConfig::~FrameSenderConfig() {}
 
 FrameReceiverConfig::FrameReceiverConfig()
     : receiver_ssrc(0),
diff --git a/media/cast/cast_config.h b/media/cast/cast_config.h
index f99358a..bad2432 100644
--- a/media/cast/cast_config.h
+++ b/media/cast/cast_config.h
@@ -46,84 +46,26 @@
 
   // Suggested minimum and maximum video bitrates for general-purpose use (up to
   // 1080p, 30 FPS).
-  kDefaultMinVideoKbps = 300,
-  kDefaultMaxVideoKbps = 5000,
+  kDefaultMinVideoBitrate = 300000,
+  kDefaultMaxVideoBitrate = 5000000,
+
+  // Minimum and Maximum VP8 quantizer in default configuration.
+  kDefaultMaxQp = 63,
+  kDefaultMinQp = 4,
+
+  kDefaultMaxCpuSaverQp = 25,
+
+  // Number of video buffers in default configuration (applies only to certain
+  // external codecs).
+  kDefaultNumberOfVideoBuffers = 1,
 };
 
-// TODO(miu): Merge AudioSenderConfig and VideoSenderConfig and make their
-// naming/documentation consistent with FrameReceiverConfig.
-// http://crbug.com/530839
-struct AudioSenderConfig {
-  AudioSenderConfig();
-  AudioSenderConfig(const AudioSenderConfig& other);
-  ~AudioSenderConfig();
+// These parameters are only for video encoders.
+struct VideoCodecParams {
+  VideoCodecParams();
+  VideoCodecParams(const VideoCodecParams& other);
+  ~VideoCodecParams();
 
-  // Identifier referring to the sender, used by the receiver.
-  uint32_t ssrc;
-
-  // The receiver's SSRC identifier.
-  uint32_t receiver_ssrc;
-
-  // The total amount of time between a frame's capture/recording on the sender
-  // and its playback on the receiver (i.e., shown to a user).  This should be
-  // set to a value large enough to give the system sufficient time to encode,
-  // transmit/retransmit, receive, decode, and render; given its run-time
-  // environment (sender/receiver hardware performance, network conditions,
-  // etc.).
-  base::TimeDelta min_playout_delay;
-  base::TimeDelta max_playout_delay;
-
-  // Starting playout delay when streaming animated content.
-  base::TimeDelta animated_playout_delay;
-
-  // RTP payload type enum: Specifies the type/encoding of frame data.
-  RtpPayloadType rtp_payload_type;
-
-  bool use_external_encoder;
-  int frequency;
-  int channels;
-  int bitrate;  // Set to <= 0 for "auto variable bitrate" (libopus knows best).
-  Codec codec;
-
-  // The AES crypto key and initialization vector.  Each of these strings
-  // contains the data in binary form, of size kAesKeySize.  If they are empty
-  // strings, crypto is not being used.
-  std::string aes_key;
-  std::string aes_iv_mask;
-};
-
-struct VideoSenderConfig {
-  VideoSenderConfig();
-  VideoSenderConfig(const VideoSenderConfig& other);
-  ~VideoSenderConfig();
-
-  // Identifier referring to the sender, used by the receiver.
-  uint32_t ssrc;
-
-  // The receiver's SSRC identifier.
-  uint32_t receiver_ssrc;
-
-  // The total amount of time between a frame's capture/recording on the sender
-  // and its playback on the receiver (i.e., shown to a user).  This should be
-  // set to a value large enough to give the system sufficient time to encode,
-  // transmit/retransmit, receive, decode, and render; given its run-time
-  // environment (sender/receiver hardware performance, network conditions,
-  // etc.).
-  base::TimeDelta min_playout_delay;
-  base::TimeDelta max_playout_delay;
-
-  // Starting playout delay when streaming animated content.
-  base::TimeDelta animated_playout_delay;
-
-  // RTP payload type enum: Specifies the type/encoding of frame data.
-  RtpPayloadType rtp_payload_type;
-
-  bool use_external_encoder;
-
-  float congestion_control_back_off;
-  int max_bitrate;
-  int min_bitrate;
-  int start_bitrate;
   int max_qp;
   int min_qp;
 
@@ -133,12 +75,12 @@
   // the maximum quantizer that the encoder might produce better quality video
   // at this resolution than lowering resolution with similar CPU usage and
   // smaller quantizer. The set value has to be between |min_qp| and |max_qp|.
-  // Suggested value range: [4, 30].
+  // Suggested value range: [4, 30]. It is only used by software VP8 codec.
   int max_cpu_saver_qp;
 
-  int max_frame_rate;  // TODO(miu): Should be double, not int.
-
-  // This field is used differently by various encoders. It defaults to 1.
+  // This field is used differently by various encoders.
+  //
+  // It defaults to 1.
   //
   // For VP8, this field is ignored.
   //
@@ -148,14 +90,67 @@
   // choose a suitable value for the platform and other encoding settings.
   int max_number_of_video_buffers_used;
 
-  Codec codec;
   int number_of_encode_threads;
+};
+
+struct FrameSenderConfig {
+  FrameSenderConfig();
+  FrameSenderConfig(const FrameSenderConfig& other);
+  ~FrameSenderConfig();
+
+  // The sender's SSRC identifier.
+  uint32_t sender_ssrc;
+
+  // The receiver's SSRC identifier.
+  uint32_t receiver_ssrc;
+
+  // The total amount of time between a frame's capture/recording on the sender
+  // and its playback on the receiver (i.e., shown to a user).  This should be
+  // set to a value large enough to give the system sufficient time to encode,
+  // transmit/retransmit, receive, decode, and render; given its run-time
+  // environment (sender/receiver hardware performance, network conditions,
+  // etc.).
+  base::TimeDelta min_playout_delay;
+  base::TimeDelta max_playout_delay;
+
+  // Starting playout delay when streaming animated content.
+  base::TimeDelta animated_playout_delay;
+
+  // RTP payload type enum: Specifies the type/encoding of frame data.
+  RtpPayloadType rtp_payload_type;
+
+  // If true, use an external HW encoder rather than the built-in
+  // software-based one.
+  bool use_external_encoder;
+
+  // RTP timebase: The number of RTP units advanced per one second.  For audio,
+  // this is the sampling rate.  For video, by convention, this is 90 kHz.
+  int rtp_timebase;
+
+  // Number of channels.  For audio, this is normally 2.  For video, this must
+  // be 1 as Cast does not have support for stereoscopic video.
+  int channels;
+
+  // For now, only fixed bitrate is used for audio encoding. So for audio,
+  // |max_bitrate| is used, and the other two will be overriden if they are not
+  // equal to |max_bitrate|.
+  int max_bitrate;
+  int min_bitrate;
+  int start_bitrate;
+
+  double max_frame_rate;
+
+  // Codec used for the compression of signal data.
+  Codec codec;
 
   // The AES crypto key and initialization vector.  Each of these strings
   // contains the data in binary form, of size kAesKeySize.  If they are empty
   // strings, crypto is not being used.
   std::string aes_key;
   std::string aes_iv_mask;
+
+  // These are codec specific parameters for video streams only.
+  VideoCodecParams video_codec_params;
 };
 
 // TODO(miu): Naming and minor type changes are badly needed in a later CL.
@@ -192,7 +187,7 @@
   // The target frame rate.  For audio, this is normally 100 (i.e., frames have
   // a duration of 10ms each).  For video, this is normally 30, but any frame
   // rate is supported.
-  int target_frame_rate;
+  double target_frame_rate;
 
   // Codec used for the compression of signal data.
   // TODO(miu): Merge the AudioCodec and VideoCodec enums into one so this union
diff --git a/media/cast/cast_sender.h b/media/cast/cast_sender.h
index 9e02c35..12c570b7 100644
--- a/media/cast/cast_sender.h
+++ b/media/cast/cast_sender.h
@@ -104,7 +104,7 @@
   // Initialize the audio stack. Must be called in order to send audio frames.
   // |status_change_cb| will be run as operational status changes.
   virtual void InitializeAudio(
-      const AudioSenderConfig& audio_config,
+      const FrameSenderConfig& audio_config,
       const StatusChangeCallback& status_change_cb) = 0;
 
   // Initialize the video stack. Must be called in order to send video frames.
@@ -112,7 +112,7 @@
   //
   // TODO(miu): Remove the VEA-specific callbacks.  http://crbug.com/454029
   virtual void InitializeVideo(
-      const VideoSenderConfig& video_config,
+      const FrameSenderConfig& video_config,
       const StatusChangeCallback& status_change_cb,
       const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
       const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb) = 0;
diff --git a/media/cast/cast_sender_impl.cc b/media/cast/cast_sender_impl.cc
index 06fc1894..07a4cc1 100644
--- a/media/cast/cast_sender_impl.cc
+++ b/media/cast/cast_sender_impl.cc
@@ -108,7 +108,7 @@
 }
 
 void CastSenderImpl::InitializeAudio(
-    const AudioSenderConfig& audio_config,
+    const FrameSenderConfig& audio_config,
     const StatusChangeCallback& status_change_cb) {
   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
   CHECK(audio_config.use_external_encoder ||
@@ -130,7 +130,7 @@
 }
 
 void CastSenderImpl::InitializeVideo(
-    const VideoSenderConfig& video_config,
+    const FrameSenderConfig& video_config,
     const StatusChangeCallback& status_change_cb,
     const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
     const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb) {
diff --git a/media/cast/cast_sender_impl.h b/media/cast/cast_sender_impl.h
index 511c458..a16bc0f9 100644
--- a/media/cast/cast_sender_impl.h
+++ b/media/cast/cast_sender_impl.h
@@ -27,14 +27,13 @@
   CastSenderImpl(scoped_refptr<CastEnvironment> cast_environment,
                  CastTransport* const transport_sender);
 
-  void InitializeAudio(const AudioSenderConfig& audio_config,
+  void InitializeAudio(const FrameSenderConfig& audio_config,
                        const StatusChangeCallback& status_change_cb) final;
   void InitializeVideo(
-      const VideoSenderConfig& video_config,
+      const FrameSenderConfig& video_config,
       const StatusChangeCallback& status_change_cb,
       const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
-      const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb)
-      final;
+      const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb) final;
 
   void SetTargetPlayoutDelay(base::TimeDelta new_target_playout_delay) final;
 
diff --git a/media/cast/cast_testing.gypi b/media/cast/cast_testing.gypi
index 8700d32..08b2a03 100644
--- a/media/cast/cast_testing.gypi
+++ b/media/cast/cast_testing.gypi
@@ -142,35 +142,19 @@
             '<(DEPTH)/testing/android/native_test.gyp:native_test_native_code',
           ],
         }],
+        ['OS=="ios" or OS=="mac"', {
+          'sources': [
+            'sender/h264_vt_encoder_unittest.cc',
+          ],
+
+          'dependencies': [
+            '<(DEPTH)/third_party/ffmpeg/ffmpeg.gyp:ffmpeg',
+          ],
+        }] # OS=="ios" or OS=="mac"
       ], # conditions
     },
   ], # targets
   'conditions': [
-    ['OS=="ios" or OS=="mac"', {
-      'targets': [
-        {
-          # GN version: //media/cast:cast_h264_vt_encoder_unittests
-          # TODO(miu): This can be rolled into cast_unittests now that FFMPEG
-          # dependency issues are resolved for iOS; but there are bot/isolates
-          # to update too.
-          'target_name': 'cast_h264_vt_encoder_unittests',
-          'type': '<(gtest_target_type)',
-          'include_dirs': [
-            '<(DEPTH)/',
-          ],
-          'dependencies': [
-            'cast_common',
-            'cast_sender',
-            'cast_test_utility',
-            '<(DEPTH)/testing/gmock.gyp:gmock',
-            '<(DEPTH)/testing/gtest.gyp:gtest',
-            '<(DEPTH)/third_party/ffmpeg/ffmpeg.gyp:ffmpeg',
-          ],
-          'sources': [
-            'sender/h264_vt_encoder_unittest.cc',
-          ],
-      }], # targets
-    }], # OS=="ios" or OS=="mac"
     ['OS=="android"', {
       'targets': [
         {
diff --git a/media/cast/receiver/frame_receiver.cc b/media/cast/receiver/frame_receiver.cc
index 0e5d2581..8787f09 100644
--- a/media/cast/receiver/frame_receiver.cc
+++ b/media/cast/receiver/frame_receiver.cc
@@ -48,14 +48,15 @@
       rtp_timebase_(config.rtp_timebase),
       target_playout_delay_(
           base::TimeDelta::FromMilliseconds(config.rtp_max_delay_ms)),
-      expected_frame_duration_(base::TimeDelta::FromSeconds(1) /
-                               config.target_frame_rate),
+      expected_frame_duration_(
+          base::TimeDelta::FromSecondsD(1.0 / config.target_frame_rate)),
       reports_are_scheduled_(false),
       framer_(cast_environment->Clock(),
               this,
               config.sender_ssrc,
               true,
-              config.rtp_max_delay_ms * config.target_frame_rate / 1000),
+              static_cast<int>(
+                  config.rtp_max_delay_ms * config.target_frame_rate / 1000)),
       rtcp_(cast_environment_->Clock(),
             config.receiver_ssrc,
             config.sender_ssrc),
diff --git a/media/cast/receiver/video_decoder_unittest.cc b/media/cast/receiver/video_decoder_unittest.cc
index 39d55d1b..da3d1266 100644
--- a/media/cast/receiver/video_decoder_unittest.cc
+++ b/media/cast/receiver/video_decoder_unittest.cc
@@ -31,8 +31,8 @@
 const int kStartingHeight = 240;
 const int kFrameRate = 10;
 
-VideoSenderConfig GetVideoSenderConfigForTest() {
-  VideoSenderConfig config = GetDefaultVideoSenderConfig();
+FrameSenderConfig GetVideoSenderConfigForTest() {
+  FrameSenderConfig config = GetDefaultVideoSenderConfig();
   config.max_frame_rate = kFrameRate;
   return config;
 }
diff --git a/media/cast/sender/audio_sender.cc b/media/cast/sender/audio_sender.cc
index 12580f8c..634afa6 100644
--- a/media/cast/sender/audio_sender.cc
+++ b/media/cast/sender/audio_sender.cc
@@ -18,31 +18,27 @@
 namespace cast {
 
 AudioSender::AudioSender(scoped_refptr<CastEnvironment> cast_environment,
-                         const AudioSenderConfig& audio_config,
+                         const FrameSenderConfig& audio_config,
                          const StatusChangeCallback& status_change_cb,
                          CastTransport* const transport_sender)
     : FrameSender(cast_environment,
                   true,
                   transport_sender,
-                  audio_config.frequency,
-                  audio_config.ssrc,
+                  audio_config.rtp_timebase,
+                  audio_config.sender_ssrc,
                   0,  // |max_frame_rate_| is set after encoder initialization.
                   audio_config.min_playout_delay,
                   audio_config.max_playout_delay,
                   audio_config.animated_playout_delay,
-                  NewFixedCongestionControl(audio_config.bitrate)),
+                  NewFixedCongestionControl(audio_config.max_bitrate)),
       samples_in_encoder_(0),
       weak_factory_(this) {
   if (!audio_config.use_external_encoder) {
-    audio_encoder_.reset(
-        new AudioEncoder(cast_environment,
-                         audio_config.channels,
-                         audio_config.frequency,
-                         audio_config.bitrate,
-                         audio_config.codec,
-                         base::Bind(&AudioSender::OnEncodedAudioFrame,
-                                    weak_factory_.GetWeakPtr(),
-                                    audio_config.bitrate)));
+    audio_encoder_.reset(new AudioEncoder(
+        cast_environment, audio_config.channels, audio_config.rtp_timebase,
+        audio_config.max_bitrate, audio_config.codec,
+        base::Bind(&AudioSender::OnEncodedAudioFrame,
+                   weak_factory_.GetWeakPtr(), audio_config.max_bitrate)));
   }
 
   // AudioEncoder provides no operational status changes during normal use.
@@ -59,10 +55,10 @@
   // initialization parameters. Now that we have an encoder, we can calculate
   // the maximum frame rate.
   max_frame_rate_ =
-      audio_config.frequency / audio_encoder_->GetSamplesPerFrame();
+      audio_config.rtp_timebase / audio_encoder_->GetSamplesPerFrame();
 
   media::cast::CastTransportRtpConfig transport_config;
-  transport_config.ssrc = audio_config.ssrc;
+  transport_config.ssrc = audio_config.sender_ssrc;
   transport_config.feedback_ssrc = audio_config.receiver_ssrc;
   transport_config.rtp_payload_type = audio_config.rtp_payload_type;
   transport_config.aes_key = audio_config.aes_key;
diff --git a/media/cast/sender/audio_sender.h b/media/cast/sender/audio_sender.h
index 3abbfc8..17fda1f7 100644
--- a/media/cast/sender/audio_sender.h
+++ b/media/cast/sender/audio_sender.h
@@ -35,7 +35,7 @@
                     public base::SupportsWeakPtr<AudioSender> {
  public:
   AudioSender(scoped_refptr<CastEnvironment> cast_environment,
-              const AudioSenderConfig& audio_config,
+              const FrameSenderConfig& audio_config,
               const StatusChangeCallback& status_change_cb,
               CastTransport* const transport_sender);
 
diff --git a/media/cast/sender/audio_sender_unittest.cc b/media/cast/sender/audio_sender_unittest.cc
index 6737ffd..f7c76257 100644
--- a/media/cast/sender/audio_sender_unittest.cc
+++ b/media/cast/sender/audio_sender_unittest.cc
@@ -103,9 +103,9 @@
                             task_runner_, task_runner_, task_runner_);
     audio_config_.codec = CODEC_AUDIO_OPUS;
     audio_config_.use_external_encoder = false;
-    audio_config_.frequency = kDefaultAudioSamplingRate;
+    audio_config_.rtp_timebase = kDefaultAudioSamplingRate;
     audio_config_.channels = 2;
-    audio_config_.bitrate = kDefaultAudioEncoderBitrate;
+    audio_config_.max_bitrate = kDefaultAudioEncoderBitrate;
     audio_config_.rtp_payload_type = RtpPayloadType::AUDIO_OPUS;
 
     transport_ = new TestPacketSender();
@@ -131,13 +131,13 @@
   scoped_refptr<FakeSingleThreadTaskRunner> task_runner_;
   std::unique_ptr<AudioSender> audio_sender_;
   scoped_refptr<CastEnvironment> cast_environment_;
-  AudioSenderConfig audio_config_;
+  FrameSenderConfig audio_config_;
 };
 
 TEST_F(AudioSenderTest, Encode20ms) {
   const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(20);
   std::unique_ptr<AudioBus> bus(
-      TestAudioBusFactory(audio_config_.channels, audio_config_.frequency,
+      TestAudioBusFactory(audio_config_.channels, audio_config_.rtp_timebase,
                           TestAudioBusFactory::kMiddleANoteFreq, 0.5f)
           .NextAudioBus(kDuration));
 
@@ -150,7 +150,7 @@
 TEST_F(AudioSenderTest, RtcpTimer) {
   const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(20);
   std::unique_ptr<AudioBus> bus(
-      TestAudioBusFactory(audio_config_.channels, audio_config_.frequency,
+      TestAudioBusFactory(audio_config_.channels, audio_config_.rtp_timebase,
                           TestAudioBusFactory::kMiddleANoteFreq, 0.5f)
           .NextAudioBus(kDuration));
 
diff --git a/media/cast/sender/external_video_encoder.cc b/media/cast/sender/external_video_encoder.cc
index bff088c..1348f7f 100644
--- a/media/cast/sender/external_video_encoder.cc
+++ b/media/cast/sender/external_video_encoder.cc
@@ -124,7 +124,7 @@
       const scoped_refptr<CastEnvironment>& cast_environment,
       const scoped_refptr<base::SingleThreadTaskRunner>& encoder_task_runner,
       std::unique_ptr<media::VideoEncodeAccelerator> vea,
-      int max_frame_rate,
+      double max_frame_rate,
       const StatusChangeCallback& status_change_cb,
       const CreateVideoEncodeMemoryCallback& create_video_encode_memory_cb)
       : cast_environment_(cast_environment),
@@ -176,8 +176,8 @@
     DCHECK(task_runner_->RunsTasksOnCurrentThread());
 
     requested_bit_rate_ = bit_rate;
-    video_encode_accelerator_->RequestEncodingParametersChange(bit_rate,
-                                                               max_frame_rate_);
+    video_encode_accelerator_->RequestEncodingParametersChange(
+        bit_rate, static_cast<uint32_t>(max_frame_rate_ + 0.5));
   }
 
   // The destruction call back of the copied video frame to free its use of
@@ -592,7 +592,7 @@
 
   const scoped_refptr<CastEnvironment> cast_environment_;
   const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-  const int max_frame_rate_;
+  const double max_frame_rate_;
   const StatusChangeCallback status_change_cb_;  // Must be run on MAIN thread.
   const CreateVideoEncodeMemoryCallback create_video_encode_memory_cb_;
   std::unique_ptr<media::VideoEncodeAccelerator> video_encode_accelerator_;
@@ -647,7 +647,7 @@
 };
 
 // static
-bool ExternalVideoEncoder::IsSupported(const VideoSenderConfig& video_config) {
+bool ExternalVideoEncoder::IsSupported(const FrameSenderConfig& video_config) {
   if (video_config.codec != CODEC_VIDEO_VP8 &&
       video_config.codec != CODEC_VIDEO_H264)
     return false;
@@ -661,7 +661,7 @@
 
 ExternalVideoEncoder::ExternalVideoEncoder(
     const scoped_refptr<CastEnvironment>& cast_environment,
-    const VideoSenderConfig& video_config,
+    const FrameSenderConfig& video_config,
     const gfx::Size& frame_size,
     FrameId first_frame_id,
     const StatusChangeCallback& status_change_cb,
@@ -730,7 +730,7 @@
 }
 
 void ExternalVideoEncoder::OnCreateVideoEncodeAccelerator(
-    const VideoSenderConfig& video_config,
+    const FrameSenderConfig& video_config,
     FrameId first_frame_id,
     const StatusChangeCallback& status_change_cb,
     scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner,
@@ -782,7 +782,7 @@
 
 SizeAdaptableExternalVideoEncoder::SizeAdaptableExternalVideoEncoder(
     const scoped_refptr<CastEnvironment>& cast_environment,
-    const VideoSenderConfig& video_config,
+    const FrameSenderConfig& video_config,
     const StatusChangeCallback& status_change_cb,
     const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
     const CreateVideoEncodeMemoryCallback& create_video_encode_memory_cb)
diff --git a/media/cast/sender/external_video_encoder.h b/media/cast/sender/external_video_encoder.h
index f5cbd8b..fb926f5e 100644
--- a/media/cast/sender/external_video_encoder.h
+++ b/media/cast/sender/external_video_encoder.h
@@ -28,11 +28,11 @@
  public:
   // Returns true if the current platform and system configuration supports
   // using ExternalVideoEncoder with the given |video_config|.
-  static bool IsSupported(const VideoSenderConfig& video_config);
+  static bool IsSupported(const FrameSenderConfig& video_config);
 
   ExternalVideoEncoder(
       const scoped_refptr<CastEnvironment>& cast_environment,
-      const VideoSenderConfig& video_config,
+      const FrameSenderConfig& video_config,
       const gfx::Size& frame_size,
       FrameId first_frame_id,
       const StatusChangeCallback& status_change_cb,
@@ -56,7 +56,7 @@
   // VEAClientImpl to own and interface with a new |vea|.  Upon return,
   // |client_| holds a reference to the new VEAClientImpl.
   void OnCreateVideoEncodeAccelerator(
-      const VideoSenderConfig& video_config,
+      const FrameSenderConfig& video_config,
       FrameId first_frame_id,
       const StatusChangeCallback& status_change_cb,
       scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner,
@@ -86,7 +86,7 @@
  public:
   SizeAdaptableExternalVideoEncoder(
       const scoped_refptr<CastEnvironment>& cast_environment,
-      const VideoSenderConfig& video_config,
+      const FrameSenderConfig& video_config,
       const StatusChangeCallback& status_change_cb,
       const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
       const CreateVideoEncodeMemoryCallback& create_video_encode_memory_cb);
diff --git a/media/cast/sender/fake_software_video_encoder.cc b/media/cast/sender/fake_software_video_encoder.cc
index a919046..7a24750 100644
--- a/media/cast/sender/fake_software_video_encoder.cc
+++ b/media/cast/sender/fake_software_video_encoder.cc
@@ -18,11 +18,13 @@
 namespace cast {
 
 FakeSoftwareVideoEncoder::FakeSoftwareVideoEncoder(
-    const VideoSenderConfig& video_config)
+    const FrameSenderConfig& video_config)
     : video_config_(video_config),
       next_frame_is_key_(true),
       frame_id_(FrameId::first()),
-      frame_size_(0) {}
+      frame_size_(0) {
+  DCHECK_GT(video_config_.max_frame_rate, 0);
+}
 
 FakeSoftwareVideoEncoder::~FakeSoftwareVideoEncoder() {}
 
diff --git a/media/cast/sender/fake_software_video_encoder.h b/media/cast/sender/fake_software_video_encoder.h
index 6be2d256..7061b7e 100644
--- a/media/cast/sender/fake_software_video_encoder.h
+++ b/media/cast/sender/fake_software_video_encoder.h
@@ -16,7 +16,7 @@
 
 class FakeSoftwareVideoEncoder : public SoftwareVideoEncoder {
  public:
-  FakeSoftwareVideoEncoder(const VideoSenderConfig& video_config);
+  FakeSoftwareVideoEncoder(const FrameSenderConfig& video_config);
   ~FakeSoftwareVideoEncoder() final;
 
   // SoftwareVideoEncoder implementations.
@@ -28,7 +28,7 @@
   void GenerateKeyFrame() final;
 
  private:
-  VideoSenderConfig video_config_;
+  const FrameSenderConfig video_config_;
   gfx::Size last_frame_size_;
   bool next_frame_is_key_;
   FrameId frame_id_;
diff --git a/media/cast/sender/h264_vt_encoder.cc b/media/cast/sender/h264_vt_encoder.cc
index 7031c54..c11f6db 100644
--- a/media/cast/sender/h264_vt_encoder.cc
+++ b/media/cast/sender/h264_vt_encoder.cc
@@ -147,13 +147,13 @@
 
 // static
 bool H264VideoToolboxEncoder::IsSupported(
-    const VideoSenderConfig& video_config) {
+    const FrameSenderConfig& video_config) {
   return video_config.codec == CODEC_VIDEO_H264 && VideoToolboxGlue::Get();
 }
 
 H264VideoToolboxEncoder::H264VideoToolboxEncoder(
     const scoped_refptr<CastEnvironment>& cast_environment,
-    const VideoSenderConfig& video_config,
+    const FrameSenderConfig& video_config,
     const StatusChangeCallback& status_change_cb)
     : cast_environment_(cast_environment),
       videotoolbox_glue_(VideoToolboxGlue::Get()),
@@ -322,7 +322,7 @@
       (video_config_.min_bitrate + video_config_.max_bitrate) / 2);
   session_property_setter.Set(
       videotoolbox_glue_->kVTCompressionPropertyKey_ExpectedFrameRate(),
-      video_config_.max_frame_rate);
+      static_cast<int>(video_config_.max_frame_rate + 0.5));
   // Keep these attachment settings in-sync with those in Initialize().
   session_property_setter.Set(
       videotoolbox_glue_->kVTCompressionPropertyKey_ColorPrimaries(),
@@ -333,10 +333,10 @@
   session_property_setter.Set(
       videotoolbox_glue_->kVTCompressionPropertyKey_YCbCrMatrix(),
       kCVImageBufferYCbCrMatrix_ITU_R_709_2);
-  if (video_config_.max_number_of_video_buffers_used > 0) {
+  if (video_config_.video_codec_params.max_number_of_video_buffers_used > 0) {
     session_property_setter.Set(
         videotoolbox_glue_->kVTCompressionPropertyKey_MaxFrameDelayCount(),
-        video_config_.max_number_of_video_buffers_used);
+        video_config_.video_codec_params.max_number_of_video_buffers_used);
   }
 }
 
diff --git a/media/cast/sender/h264_vt_encoder.h b/media/cast/sender/h264_vt_encoder.h
index b6dbd9d..2e4c3f0 100644
--- a/media/cast/sender/h264_vt_encoder.h
+++ b/media/cast/sender/h264_vt_encoder.h
@@ -33,11 +33,11 @@
  public:
   // Returns true if the current platform and system configuration supports
   // using H264VideoToolboxEncoder with the given |video_config|.
-  static bool IsSupported(const VideoSenderConfig& video_config);
+  static bool IsSupported(const FrameSenderConfig& video_config);
 
   H264VideoToolboxEncoder(
       const scoped_refptr<CastEnvironment>& cast_environment,
-      const VideoSenderConfig& video_config,
+      const FrameSenderConfig& video_config,
       const StatusChangeCallback& status_change_cb);
   ~H264VideoToolboxEncoder() final;
 
@@ -92,7 +92,7 @@
   // VideoSenderConfig copy so we can create compression sessions on demand.
   // This is needed to recover from backgrounding and other events that can
   // invalidate compression sessions.
-  const VideoSenderConfig video_config_;
+  const FrameSenderConfig video_config_;
 
   // Frame size of the current compression session. Can be changed by submitting
   // a frame of a different size, which will cause a compression session reset.
diff --git a/media/cast/sender/h264_vt_encoder_unittest.cc b/media/cast/sender/h264_vt_encoder_unittest.cc
index 7d6c69d..5a33ffa 100644
--- a/media/cast/sender/h264_vt_encoder_unittest.cc
+++ b/media/cast/sender/h264_vt_encoder_unittest.cc
@@ -55,18 +55,6 @@
 
 }  // namespace
 
-int main(int argc, char** argv) {
-  {
-    base::AtExitManager at_exit_manager;
-    CHECK(VideoToolboxGlue::Get())
-        << "VideoToolbox is not available. Requires OS X 10.8 or iOS 8.0.";
-  }
-  MediaTestSuite test_suite(argc, argv);
-  return base::LaunchUnitTests(
-      argc, argv,
-      base::Bind(&MediaTestSuite::Run, base::Unretained(&test_suite)));
-}
-
 namespace media {
 namespace cast {
 
@@ -222,6 +210,8 @@
   H264VideoToolboxEncoderTest() = default;
 
   void SetUp() final {
+    CHECK(VideoToolboxGlue::Get())
+        << "VideoToolbox is not available. Requires OS X 10.8 or iOS 8.0.";
     clock_ = new base::SimpleTestTickClock();
     clock_->Advance(base::TimeTicks::Now() - base::TimeTicks());
 
@@ -264,7 +254,7 @@
   static void TearDownTestCase() { frame_ = nullptr; }
 
   static scoped_refptr<media::VideoFrame> frame_;
-  static VideoSenderConfig video_sender_config_;
+  static FrameSenderConfig video_sender_config_;
 
   base::SimpleTestTickClock* clock_;  // Owned by CastEnvironment.
   base::MessageLoop message_loop_;
@@ -280,9 +270,10 @@
 
 // static
 scoped_refptr<media::VideoFrame> H264VideoToolboxEncoderTest::frame_;
-VideoSenderConfig H264VideoToolboxEncoderTest::video_sender_config_;
+FrameSenderConfig H264VideoToolboxEncoderTest::video_sender_config_;
 
-TEST_F(H264VideoToolboxEncoderTest, CheckFrameMetadataSequence) {
+// Failed on mac_chromium_rel_ng trybot. http://crbug.com/627260
+TEST_F(H264VideoToolboxEncoderTest, DISABLED_CheckFrameMetadataSequence) {
   scoped_refptr<MetadataRecorder> metadata_recorder(new MetadataRecorder());
   VideoEncoder::FrameEncodedCallback cb = base::Bind(
       &MetadataRecorder::CompareFrameWithExpected, metadata_recorder.get());
@@ -311,7 +302,8 @@
 }
 
 #if defined(USE_PROPRIETARY_CODECS)
-TEST_F(H264VideoToolboxEncoderTest, CheckFramesAreDecodable) {
+// Failed on mac_chromium_rel_ng trybot. http://crbug.com/627260
+TEST_F(H264VideoToolboxEncoderTest, DISABLED_CheckFramesAreDecodable) {
   VideoDecoderConfig config(kCodecH264, H264PROFILE_MAIN, frame_->format(),
                             COLOR_SPACE_UNSPECIFIED, frame_->coded_size(),
                             frame_->visible_rect(), frame_->natural_size(),
diff --git a/media/cast/sender/size_adaptable_video_encoder_base.cc b/media/cast/sender/size_adaptable_video_encoder_base.cc
index a803347..f4464cc 100644
--- a/media/cast/sender/size_adaptable_video_encoder_base.cc
+++ b/media/cast/sender/size_adaptable_video_encoder_base.cc
@@ -15,7 +15,7 @@
 
 SizeAdaptableVideoEncoderBase::SizeAdaptableVideoEncoderBase(
     const scoped_refptr<CastEnvironment>& cast_environment,
-    const VideoSenderConfig& video_config,
+    const FrameSenderConfig& video_config,
     const StatusChangeCallback& status_change_cb)
     : cast_environment_(cast_environment),
       video_config_(video_config),
diff --git a/media/cast/sender/size_adaptable_video_encoder_base.h b/media/cast/sender/size_adaptable_video_encoder_base.h
index ac2fd23..8443e2c 100644
--- a/media/cast/sender/size_adaptable_video_encoder_base.h
+++ b/media/cast/sender/size_adaptable_video_encoder_base.h
@@ -30,7 +30,7 @@
  public:
   SizeAdaptableVideoEncoderBase(
       const scoped_refptr<CastEnvironment>& cast_environment,
-      const VideoSenderConfig& video_config,
+      const FrameSenderConfig& video_config,
       const StatusChangeCallback& status_change_cb);
 
   ~SizeAdaptableVideoEncoderBase() override;
@@ -50,9 +50,7 @@
   CastEnvironment* cast_environment() const {
     return cast_environment_.get();
   }
-  const VideoSenderConfig& video_config() const {
-    return video_config_;
-  }
+  const FrameSenderConfig& video_config() const { return video_config_; }
   const gfx::Size& frame_size() const {
     return frame_size_;
   }
@@ -93,7 +91,7 @@
 
   // This is not const since |video_config_.starting_bitrate| is modified by
   // SetBitRate(), for when a replacement encoder is spawned.
-  VideoSenderConfig video_config_;
+  FrameSenderConfig video_config_;
 
   // Run whenever the underlying encoder reports a status change.
   const StatusChangeCallback status_change_cb_;
diff --git a/media/cast/sender/video_encoder.cc b/media/cast/sender/video_encoder.cc
index 46bb6d42..e6e5c1c 100644
--- a/media/cast/sender/video_encoder.cc
+++ b/media/cast/sender/video_encoder.cc
@@ -18,7 +18,7 @@
 // static
 std::unique_ptr<VideoEncoder> VideoEncoder::Create(
     const scoped_refptr<CastEnvironment>& cast_environment,
-    const VideoSenderConfig& video_config,
+    const FrameSenderConfig& video_config,
     const StatusChangeCallback& status_change_cb,
     const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
     const CreateVideoEncodeMemoryCallback& create_video_encode_memory_cb) {
diff --git a/media/cast/sender/video_encoder.h b/media/cast/sender/video_encoder.h
index e82315d..74cec93 100644
--- a/media/cast/sender/video_encoder.h
+++ b/media/cast/sender/video_encoder.h
@@ -38,7 +38,7 @@
   // TODO(miu): Remove the CreateVEA callbacks.  http://crbug.com/454029
   static std::unique_ptr<VideoEncoder> Create(
       const scoped_refptr<CastEnvironment>& cast_environment,
-      const VideoSenderConfig& video_config,
+      const FrameSenderConfig& video_config,
       const StatusChangeCallback& status_change_cb,
       const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
       const CreateVideoEncodeMemoryCallback& create_video_encode_memory_cb);
diff --git a/media/cast/sender/video_encoder_impl.cc b/media/cast/sender/video_encoder_impl.cc
index 3a8042b8..41651729 100644
--- a/media/cast/sender/video_encoder_impl.cc
+++ b/media/cast/sender/video_encoder_impl.cc
@@ -51,7 +51,7 @@
 }  // namespace
 
 // static
-bool VideoEncoderImpl::IsSupported(const VideoSenderConfig& video_config) {
+bool VideoEncoderImpl::IsSupported(const FrameSenderConfig& video_config) {
 #ifndef OFFICIAL_BUILD
   if (video_config.codec == CODEC_VIDEO_FAKE)
     return true;
@@ -61,7 +61,7 @@
 
 VideoEncoderImpl::VideoEncoderImpl(
     scoped_refptr<CastEnvironment> cast_environment,
-    const VideoSenderConfig& video_config,
+    const FrameSenderConfig& video_config,
     const StatusChangeCallback& status_change_cb)
     : cast_environment_(cast_environment) {
   CHECK(cast_environment_->HasVideoThread());
diff --git a/media/cast/sender/video_encoder_impl.h b/media/cast/sender/video_encoder_impl.h
index fa5b9c3b..cd350e6 100644
--- a/media/cast/sender/video_encoder_impl.h
+++ b/media/cast/sender/video_encoder_impl.h
@@ -28,10 +28,10 @@
   };
 
   // Returns true if VideoEncoderImpl can be used with the given |video_config|.
-  static bool IsSupported(const VideoSenderConfig& video_config);
+  static bool IsSupported(const FrameSenderConfig& video_config);
 
   VideoEncoderImpl(scoped_refptr<CastEnvironment> cast_environment,
-                   const VideoSenderConfig& video_config,
+                   const FrameSenderConfig& video_config,
                    const StatusChangeCallback& status_change_cb);
 
   ~VideoEncoderImpl() final;
diff --git a/media/cast/sender/video_encoder_unittest.cc b/media/cast/sender/video_encoder_unittest.cc
index b907e3c..0c71b63 100644
--- a/media/cast/sender/video_encoder_unittest.cc
+++ b/media/cast/sender/video_encoder_unittest.cc
@@ -66,7 +66,7 @@
 
   void CreateEncoder() {
     ASSERT_EQ(STATUS_UNINITIALIZED, operational_status_);
-    video_config_.max_number_of_video_buffers_used = 1;
+    video_config_.video_codec_params.max_number_of_video_buffers_used = 1;
     video_encoder_ = VideoEncoder::Create(
         cast_environment_, video_config_,
         base::Bind(&VideoEncoderTest::OnOperationalStatusChange,
@@ -121,6 +121,7 @@
   }
 
   void RunTasksAndAdvanceClock() const {
+    DCHECK_GT(video_config_.max_frame_rate, 0);
     const base::TimeDelta frame_duration = base::TimeDelta::FromMicroseconds(
         1000000.0 / video_config_.max_frame_rate);
 #if defined(OS_MACOSX)
@@ -247,7 +248,8 @@
     } else {
       if (expected_frame_id != expected_last_referenced_frame_id) {
         EXPECT_EQ(EncodedFrame::DEPENDENT, encoded_frame->dependency);
-      } else if (video_config_.max_number_of_video_buffers_used == 1) {
+      } else if (video_config_.video_codec_params
+                     .max_number_of_video_buffers_used == 1) {
         EXPECT_EQ(EncodedFrame::KEY, encoded_frame->dependency);
       }
       EXPECT_EQ(expected_last_referenced_frame_id,
@@ -265,7 +267,7 @@
   base::SimpleTestTickClock* const testing_clock_;  // Owned by CastEnvironment.
   const scoped_refptr<FakeSingleThreadTaskRunner> task_runner_;
   const scoped_refptr<CastEnvironment> cast_environment_;
-  VideoSenderConfig video_config_;
+  FrameSenderConfig video_config_;
   std::unique_ptr<FakeVideoEncodeAcceleratorFactory> vea_factory_;
   base::TimeTicks first_frame_time_;
   OperationalStatus operational_status_;
@@ -414,7 +416,7 @@
   values.push_back(std::make_pair(CODEC_VIDEO_VP8, true));
 #if defined(OS_MACOSX)
   // VideoToolbox encoder (when VideoToolbox is present).
-  VideoSenderConfig video_config = GetDefaultVideoSenderConfig();
+  FrameSenderConfig video_config = GetDefaultVideoSenderConfig();
   video_config.use_external_encoder = false;
   video_config.codec = CODEC_VIDEO_H264;
   if (H264VideoToolboxEncoder::IsSupported(video_config))
diff --git a/media/cast/sender/video_sender.cc b/media/cast/sender/video_sender.cc
index b4a2ff63..07639b8 100644
--- a/media/cast/sender/video_sender.cc
+++ b/media/cast/sender/video_sender.cc
@@ -89,7 +89,7 @@
 // See details: crbug.com/392086.
 VideoSender::VideoSender(
     scoped_refptr<CastEnvironment> cast_environment,
-    const VideoSenderConfig& video_config,
+    const FrameSenderConfig& video_config,
     const StatusChangeCallback& status_change_cb,
     const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
     const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb,
@@ -100,7 +100,7 @@
           false,
           transport_sender,
           kVideoFrequency,
-          video_config.ssrc,
+          video_config.sender_ssrc,
           video_config.max_frame_rate,
           video_config.min_playout_delay,
           video_config.max_playout_delay,
@@ -133,7 +133,7 @@
   }
 
   media::cast::CastTransportRtpConfig transport_config;
-  transport_config.ssrc = video_config.ssrc;
+  transport_config.ssrc = video_config.sender_ssrc;
   transport_config.feedback_ssrc = video_config.receiver_ssrc;
   transport_config.rtp_payload_type = video_config.rtp_payload_type;
   transport_config.aes_key = video_config.aes_key;
diff --git a/media/cast/sender/video_sender.h b/media/cast/sender/video_sender.h
index b2cd320b..778ba03 100644
--- a/media/cast/sender/video_sender.h
+++ b/media/cast/sender/video_sender.h
@@ -43,7 +43,7 @@
                     public base::SupportsWeakPtr<VideoSender> {
  public:
   VideoSender(scoped_refptr<CastEnvironment> cast_environment,
-              const VideoSenderConfig& video_config,
+              const FrameSenderConfig& video_config,
               const StatusChangeCallback& status_change_cb,
               const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
               const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb,
diff --git a/media/cast/sender/video_sender_unittest.cc b/media/cast/sender/video_sender_unittest.cc
index 480edd1..acfe83c 100644
--- a/media/cast/sender/video_sender_unittest.cc
+++ b/media/cast/sender/video_sender_unittest.cc
@@ -113,7 +113,7 @@
  public:
   PeerVideoSender(
       scoped_refptr<CastEnvironment> cast_environment,
-      const VideoSenderConfig& video_config,
+      const FrameSenderConfig& video_config,
       const StatusChangeCallback& status_change_cb,
       const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
       const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb,
@@ -178,7 +178,7 @@
   // If |external| is true then external video encoder (VEA) is used.
   // |expect_init_success| is true if initialization is expected to succeed.
   void InitEncoder(bool external, bool expect_init_success) {
-    VideoSenderConfig video_config = GetDefaultVideoSenderConfig();
+    FrameSenderConfig video_config = GetDefaultVideoSenderConfig();
     video_config.use_external_encoder = external;
 
     ASSERT_EQ(operational_status_, STATUS_UNINITIALIZED);
diff --git a/media/cast/sender/vp8_encoder.cc b/media/cast/sender/vp8_encoder.cc
index f6bad07..39c8971 100644
--- a/media/cast/sender/vp8_encoder.cc
+++ b/media/cast/sender/vp8_encoder.cc
@@ -63,12 +63,12 @@
 
 }  // namespace
 
-Vp8Encoder::Vp8Encoder(const VideoSenderConfig& video_config)
+Vp8Encoder::Vp8Encoder(const FrameSenderConfig& video_config)
     : cast_config_(video_config),
       target_encoder_utilization_(
-          video_config.number_of_encode_threads > 2
+          video_config.video_codec_params.number_of_encode_threads > 2
               ? kHiTargetEncoderUtilization
-              : (video_config.number_of_encode_threads > 1
+              : (video_config.video_codec_params.number_of_encode_threads > 1
                      ? kMidTargetEncoderUtilization
                      : kLoTargetEncoderUtilization)),
       key_frame_requested_(true),
@@ -79,8 +79,10 @@
           base::TimeDelta::FromMicroseconds(kEncodingSpeedAccHalfLife)),
       encoding_speed_(kHighestEncodingSpeed) {
   config_.g_timebase.den = 0;  // Not initialized.
-  DCHECK_LE(cast_config_.min_qp, cast_config_.max_cpu_saver_qp);
-  DCHECK_LE(cast_config_.max_cpu_saver_qp, cast_config_.max_qp);
+  DCHECK_LE(cast_config_.video_codec_params.min_qp,
+            cast_config_.video_codec_params.max_cpu_saver_qp);
+  DCHECK_LE(cast_config_.video_codec_params.max_cpu_saver_qp,
+            cast_config_.video_codec_params.max_qp);
 
   thread_checker_.DetachFromThread();
 }
@@ -110,7 +112,7 @@
                << frame_size.ToString();
       config_.g_w = frame_size.width();
       config_.g_h = frame_size.height();
-      config_.rc_min_quantizer = cast_config_.min_qp;
+      config_.rc_min_quantizer = cast_config_.video_codec_params.min_qp;
       if (vpx_codec_enc_config_set(&encoder_, &config_) == VPX_CODEC_OK)
         return;
       DVLOG(1) << "libvpx rejected the attempt to use a smaller frame size in "
@@ -130,7 +132,7 @@
   CHECK_EQ(vpx_codec_enc_config_default(vpx_codec_vp8_cx(), &config_, 0),
            VPX_CODEC_OK);
 
-  config_.g_threads = cast_config_.number_of_encode_threads;
+  config_.g_threads = cast_config_.video_codec_params.number_of_encode_threads;
   config_.g_w = frame_size.width();
   config_.g_h = frame_size.height();
   // Set the timebase to match that of base::TimeDelta.
@@ -147,8 +149,8 @@
   config_.rc_resize_allowed = 0;  // TODO(miu): Why not?  Investigate this.
   config_.rc_end_usage = VPX_CBR;
   config_.rc_target_bitrate = bitrate_kbit_;
-  config_.rc_min_quantizer = cast_config_.min_qp;
-  config_.rc_max_quantizer = cast_config_.max_qp;
+  config_.rc_min_quantizer = cast_config_.video_codec_params.min_qp;
+  config_.rc_max_quantizer = cast_config_.video_codec_params.max_qp;
   // TODO(miu): Revisit these now that the encoder is being successfully
   // micro-managed.
   config_.rc_undershoot_pct = 100;
@@ -351,7 +353,7 @@
     double actual_encoding_speed =
         encoding_speed_ +
         kEquivalentEncodingSpeedStepPerQpStep *
-            std::max(0, quantizer - cast_config_.min_qp);
+            std::max(0, quantizer - cast_config_.video_codec_params.min_qp);
     double adjusted_encoding_speed = actual_encoding_speed *
                                      encoded_frame->encoder_utilization /
                                      target_encoder_utilization_;
@@ -370,12 +372,13 @@
       next_encoding_speed = kHighestEncodingSpeed;
       next_min_qp =
           static_cast<int>(remainder / kEquivalentEncodingSpeedStepPerQpStep +
-                           cast_config_.min_qp + 0.5);
-      next_min_qp = std::min(next_min_qp, cast_config_.max_cpu_saver_qp);
+                           cast_config_.video_codec_params.min_qp + 0.5);
+      next_min_qp = std::min(next_min_qp,
+                             cast_config_.video_codec_params.max_cpu_saver_qp);
     } else {
       next_encoding_speed =
           std::max<double>(kLowestEncodingSpeed, next_encoding_speed) + 0.5;
-      next_min_qp = cast_config_.min_qp;
+      next_min_qp = cast_config_.video_codec_params.min_qp;
     }
     if (encoding_speed_ != static_cast<int>(next_encoding_speed)) {
       encoding_speed_ = static_cast<int>(next_encoding_speed);
diff --git a/media/cast/sender/vp8_encoder.h b/media/cast/sender/vp8_encoder.h
index 703c22d1..d89f9e19 100644
--- a/media/cast/sender/vp8_encoder.h
+++ b/media/cast/sender/vp8_encoder.h
@@ -26,7 +26,7 @@
 
 class Vp8Encoder : public SoftwareVideoEncoder {
  public:
-  explicit Vp8Encoder(const VideoSenderConfig& video_config);
+  explicit Vp8Encoder(const FrameSenderConfig& video_config);
 
   ~Vp8Encoder() final;
 
@@ -51,7 +51,7 @@
   // |encoder_| instance.
   void ConfigureForNewFrameSize(const gfx::Size& frame_size);
 
-  const VideoSenderConfig cast_config_;
+  const FrameSenderConfig cast_config_;
 
   const double target_encoder_utilization_;
 
diff --git a/media/cast/sender/vp8_quantizer_parser_unittest.cc b/media/cast/sender/vp8_quantizer_parser_unittest.cc
index e323a89..65db392 100644
--- a/media/cast/sender/vp8_quantizer_parser_unittest.cc
+++ b/media/cast/sender/vp8_quantizer_parser_unittest.cc
@@ -26,14 +26,14 @@
 const int kFrameRate = 10;
 const int kQp = 20;
 
-VideoSenderConfig GetVideoConfigForTest() {
-  VideoSenderConfig config = GetDefaultVideoSenderConfig();
+FrameSenderConfig GetVideoConfigForTest() {
+  FrameSenderConfig config = GetDefaultVideoSenderConfig();
   config.codec = CODEC_VIDEO_VP8;
   config.use_external_encoder = false;
   config.max_frame_rate = kFrameRate;
-  config.min_qp = kQp;
-  config.max_qp = kQp;
-  config.max_cpu_saver_qp = kQp;
+  config.video_codec_params.min_qp = kQp;
+  config.video_codec_params.max_qp = kQp;
+  config.video_codec_params.max_cpu_saver_qp = kQp;
   return config;
 }
 }  // unnamed namespace
@@ -58,9 +58,9 @@
   // Update the vp8 encoder with the new quantizer.
   void UpdateQuantizer(int qp) {
     DCHECK((qp > 3) && (qp < 64));
-    video_config_.min_qp = qp;
-    video_config_.max_qp = qp;
-    video_config_.max_cpu_saver_qp = qp;
+    video_config_.video_codec_params.min_qp = qp;
+    video_config_.video_codec_params.max_qp = qp;
+    video_config_.video_codec_params.max_cpu_saver_qp = qp;
     RecreateVp8Encoder();
   }
 
@@ -79,7 +79,7 @@
   }
 
   base::TimeDelta next_frame_timestamp_;
-  VideoSenderConfig video_config_;
+  FrameSenderConfig video_config_;
   std::unique_ptr<Vp8Encoder> vp8_encoder_;
 
   DISALLOW_COPY_AND_ASSIGN(Vp8QuantizerParserTest);
diff --git a/media/cast/test/cast_benchmarks.cc b/media/cast/test/cast_benchmarks.cc
index 4bebe4a0..018b287c2 100644
--- a/media/cast/test/cast_benchmarks.cc
+++ b/media/cast/test/cast_benchmarks.cc
@@ -258,8 +258,9 @@
     video_receiver_config_.rtp_max_delay_ms = kTargetPlayoutDelayMs;
     video_receiver_config_.codec = video_codec;
 
-    frame_duration_ = base::TimeDelta::FromSeconds(1) /
-        video_sender_config_.max_frame_rate;
+    DCHECK_GT(video_sender_config_.max_frame_rate, 0);
+    frame_duration_ = base::TimeDelta::FromSecondsD(
+        1.0 / video_sender_config_.max_frame_rate);
   }
 
   void SetSenderClockSkew(double skew, base::TimeDelta offset) {
@@ -285,8 +286,8 @@
   }
 
   base::TimeDelta VideoTimestamp(int frame_number) {
-    return (frame_number * base::TimeDelta::FromSeconds(1)) /
-        video_sender_config_.max_frame_rate;
+    return frame_number * base::TimeDelta::FromSecondsD(
+                              1.0 / video_sender_config_.max_frame_rate);
   }
 
   void SendFakeVideoFrame() {
@@ -410,8 +411,8 @@
  private:
   FrameReceiverConfig audio_receiver_config_;
   FrameReceiverConfig video_receiver_config_;
-  AudioSenderConfig audio_sender_config_;
-  VideoSenderConfig video_sender_config_;
+  FrameSenderConfig audio_sender_config_;
+  FrameSenderConfig video_sender_config_;
 
   base::TimeTicks start_time_;
 
diff --git a/media/cast/test/end2end_unittest.cc b/media/cast/test/end2end_unittest.cc
index c29e3cc..c101232 100644
--- a/media/cast/test/end2end_unittest.cc
+++ b/media/cast/test/end2end_unittest.cc
@@ -432,15 +432,15 @@
   }
 
   void Configure(Codec video_codec, Codec audio_codec) {
-    audio_sender_config_.ssrc = 1;
+    audio_sender_config_.sender_ssrc = 1;
     audio_sender_config_.receiver_ssrc = 2;
     audio_sender_config_.max_playout_delay =
         base::TimeDelta::FromMilliseconds(kTargetPlayoutDelayMs);
     audio_sender_config_.rtp_payload_type = RtpPayloadType::AUDIO_OPUS;
     audio_sender_config_.use_external_encoder = false;
-    audio_sender_config_.frequency = kDefaultAudioSamplingRate;
+    audio_sender_config_.rtp_timebase = kDefaultAudioSamplingRate;
     audio_sender_config_.channels = kAudioChannels;
-    audio_sender_config_.bitrate = kDefaultAudioEncoderBitrate;
+    audio_sender_config_.max_bitrate = kDefaultAudioEncoderBitrate;
     audio_sender_config_.codec = audio_codec;
     audio_sender_config_.aes_iv_mask =
         ConvertFromBase16String("abcdeffedcba12345678900987654321");
@@ -449,11 +449,11 @@
 
     audio_receiver_config_.receiver_ssrc =
         audio_sender_config_.receiver_ssrc;
-    audio_receiver_config_.sender_ssrc = audio_sender_config_.ssrc;
+    audio_receiver_config_.sender_ssrc = audio_sender_config_.sender_ssrc;
     audio_receiver_config_.rtp_max_delay_ms = kTargetPlayoutDelayMs;
     audio_receiver_config_.rtp_payload_type =
         audio_sender_config_.rtp_payload_type;
-    audio_receiver_config_.rtp_timebase = audio_sender_config_.frequency;
+    audio_receiver_config_.rtp_timebase = audio_sender_config_.rtp_timebase;
     audio_receiver_config_.channels = kAudioChannels;
     audio_receiver_config_.target_frame_rate = 100;
     audio_receiver_config_.codec = audio_sender_config_.codec;
@@ -463,7 +463,7 @@
     test_receiver_audio_callback_->SetExpectedSamplingFrequency(
         audio_receiver_config_.rtp_timebase);
 
-    video_sender_config_.ssrc = 3;
+    video_sender_config_.sender_ssrc = 3;
     video_sender_config_.receiver_ssrc = 4;
     video_sender_config_.max_playout_delay =
         base::TimeDelta::FromMilliseconds(kTargetPlayoutDelayMs);
@@ -472,8 +472,8 @@
     video_sender_config_.max_bitrate = 50000;
     video_sender_config_.min_bitrate = 10000;
     video_sender_config_.start_bitrate = 10000;
-    video_sender_config_.max_qp = 30;
-    video_sender_config_.min_qp = 4;
+    video_sender_config_.video_codec_params.max_qp = 30;
+    video_sender_config_.video_codec_params.min_qp = 4;
     video_sender_config_.max_frame_rate = 30;
     video_sender_config_.codec = video_codec;
     video_sender_config_.aes_iv_mask =
@@ -483,7 +483,7 @@
 
     video_receiver_config_.receiver_ssrc =
         video_sender_config_.receiver_ssrc;
-    video_receiver_config_.sender_ssrc = video_sender_config_.ssrc;
+    video_receiver_config_.sender_ssrc = video_sender_config_.sender_ssrc;
     video_receiver_config_.rtp_max_delay_ms = kTargetPlayoutDelayMs;
     video_receiver_config_.rtp_payload_type =
         video_sender_config_.rtp_payload_type;
@@ -834,8 +834,8 @@
 
   FrameReceiverConfig audio_receiver_config_;
   FrameReceiverConfig video_receiver_config_;
-  AudioSenderConfig audio_sender_config_;
-  VideoSenderConfig video_sender_config_;
+  FrameSenderConfig audio_sender_config_;
+  FrameSenderConfig video_sender_config_;
 
   base::TimeTicks start_time_;
 
@@ -958,7 +958,7 @@
   video_frame_input_ = cast_sender_->video_frame_input();
 
   audio_bus_factory_.reset(new TestAudioBusFactory(
-      audio_sender_config_.channels, audio_sender_config_.frequency,
+      audio_sender_config_.channels, audio_sender_config_.rtp_timebase,
       kSoundFrequency, kSoundVolume));
 }
 
diff --git a/media/cast/test/fake_media_source.cc b/media/cast/test/fake_media_source.cc
index d038eda..006b12ba 100644
--- a/media/cast/test/fake_media_source.cc
+++ b/media/cast/test/fake_media_source.cc
@@ -76,15 +76,15 @@
 FakeMediaSource::FakeMediaSource(
     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
     base::TickClock* clock,
-    const AudioSenderConfig& audio_config,
-    const VideoSenderConfig& video_config,
+    const FrameSenderConfig& audio_config,
+    const FrameSenderConfig& video_config,
     bool keep_frames)
     : task_runner_(task_runner),
       output_audio_params_(AudioParameters::AUDIO_PCM_LINEAR,
                            media::GuessChannelLayout(audio_config.channels),
-                           audio_config.frequency,
+                           audio_config.rtp_timebase,
                            32,
-                           audio_config.frequency / kAudioPacketsPerSecond),
+                           audio_config.rtp_timebase / kAudioPacketsPerSecond),
       video_config_(video_config),
       keep_frames_(keep_frames),
       variable_frame_size_mode_(false),
@@ -102,10 +102,9 @@
       video_first_pts_set_(false),
       weak_factory_(this) {
   CHECK(output_audio_params_.IsValid());
-  audio_bus_factory_.reset(new TestAudioBusFactory(audio_config.channels,
-                                                   audio_config.frequency,
-                                                   kSoundFrequency,
-                                                   kSoundVolume));
+  audio_bus_factory_.reset(
+      new TestAudioBusFactory(audio_config.channels, audio_config.rtp_timebase,
+                              kSoundFrequency, kSoundVolume));
 }
 
 FakeMediaSource::~FakeMediaSource() {
diff --git a/media/cast/test/fake_media_source.h b/media/cast/test/fake_media_source.h
index 8fb9fab..f8affbd 100644
--- a/media/cast/test/fake_media_source.h
+++ b/media/cast/test/fake_media_source.h
@@ -55,8 +55,8 @@
   // |keep_frames| is true if all VideoFrames are saved in a queue.
   FakeMediaSource(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
                   base::TickClock* clock,
-                  const AudioSenderConfig& audio_config,
-                  const VideoSenderConfig& video_config,
+                  const FrameSenderConfig& audio_config,
+                  const FrameSenderConfig& video_config,
                   bool keep_frames);
   ~FakeMediaSource() final;
 
@@ -71,7 +71,7 @@
   void Start(scoped_refptr<AudioFrameInput> audio_frame_input,
              scoped_refptr<VideoFrameInput> video_frame_input);
 
-  const VideoSenderConfig& get_video_config() const { return video_config_; }
+  const FrameSenderConfig& get_video_config() const { return video_config_; }
 
   scoped_refptr<media::VideoFrame> PopOldestInsertedVideoFrame();
 
@@ -118,7 +118,7 @@
 
   const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
   const media::AudioParameters output_audio_params_;
-  const VideoSenderConfig video_config_;
+  const FrameSenderConfig video_config_;
   const bool keep_frames_;
   bool variable_frame_size_mode_;
   gfx::Size current_frame_size_;
diff --git a/media/cast/test/sender.cc b/media/cast/test/sender.cc
index 0938377..b2be793 100644
--- a/media/cast/test/sender.cc
+++ b/media/cast/test/sender.cc
@@ -224,9 +224,9 @@
   LOG(INFO) << "Sending to " << remote_ip_address << ":" << remote_port
             << ".";
 
-  media::cast::AudioSenderConfig audio_config =
+  media::cast::FrameSenderConfig audio_config =
       media::cast::GetDefaultAudioSenderConfig();
-  media::cast::VideoSenderConfig video_config =
+  media::cast::FrameSenderConfig video_config =
       media::cast::GetDefaultVideoSenderConfig();
 
   // Running transport on the main thread.
diff --git a/media/cast/test/simulator.cc b/media/cast/test/simulator.cc
index 0e2f1ea..160eae65 100644
--- a/media/cast/test/simulator.cc
+++ b/media/cast/test/simulator.cc
@@ -356,7 +356,7 @@
   sender_env->logger()->Subscribe(&video_event_subscriber);
 
   // Audio sender config.
-  AudioSenderConfig audio_sender_config = GetDefaultAudioSenderConfig();
+  FrameSenderConfig audio_sender_config = GetDefaultAudioSenderConfig();
   audio_sender_config.min_playout_delay =
       audio_sender_config.max_playout_delay = base::TimeDelta::FromMilliseconds(
           GetIntegerSwitchValue(kTargetDelay, 400));
@@ -368,7 +368,7 @@
       audio_sender_config.max_playout_delay.InMilliseconds();
 
   // Video sender config.
-  VideoSenderConfig video_sender_config = GetDefaultVideoSenderConfig();
+  FrameSenderConfig video_sender_config = GetDefaultVideoSenderConfig();
   video_sender_config.max_bitrate = 2500000;
   video_sender_config.min_bitrate = 2000000;
   video_sender_config.start_bitrate = 2000000;
diff --git a/media/cast/test/utility/default_config.cc b/media/cast/test/utility/default_config.cc
index 30768b0..c89afb7 100644
--- a/media/cast/test/utility/default_config.cc
+++ b/media/cast/test/utility/default_config.cc
@@ -55,38 +55,41 @@
   return config;
 }
 
-AudioSenderConfig GetDefaultAudioSenderConfig() {
+FrameSenderConfig GetDefaultAudioSenderConfig() {
   FrameReceiverConfig recv_config = GetDefaultAudioReceiverConfig();
-  AudioSenderConfig config;
-  config.ssrc = recv_config.sender_ssrc;
+  FrameSenderConfig config;
+  config.sender_ssrc = recv_config.sender_ssrc;
   config.receiver_ssrc = recv_config.receiver_ssrc;
   config.rtp_payload_type = recv_config.rtp_payload_type;
   config.use_external_encoder = false;
-  config.frequency = recv_config.rtp_timebase;
+  config.rtp_timebase = recv_config.rtp_timebase;
   config.channels = recv_config.channels;
-  config.bitrate = kDefaultAudioEncoderBitrate;
+  config.max_bitrate = config.min_bitrate = config.start_bitrate =
+      kDefaultAudioEncoderBitrate;
+  config.max_frame_rate = recv_config.target_frame_rate;
   config.codec = recv_config.codec;
-  config.max_playout_delay =
-      base::TimeDelta::FromMilliseconds(kDefaultRtpMaxDelayMs);
   return config;
 }
 
-VideoSenderConfig GetDefaultVideoSenderConfig() {
+FrameSenderConfig GetDefaultVideoSenderConfig() {
   FrameReceiverConfig recv_config = GetDefaultVideoReceiverConfig();
-  VideoSenderConfig config;
-  config.ssrc = recv_config.sender_ssrc;
+  FrameSenderConfig config;
+  config.sender_ssrc = recv_config.sender_ssrc;
   config.receiver_ssrc = recv_config.receiver_ssrc;
   config.rtp_payload_type = recv_config.rtp_payload_type;
   config.use_external_encoder = false;
-  config.max_bitrate = 4000000;
-  config.min_bitrate = 2000000;
-  config.start_bitrate = 4000000;
+  config.rtp_timebase = recv_config.rtp_timebase;
+  config.max_bitrate = kDefaultMaxVideoBitrate;
+  config.min_bitrate = kDefaultMinVideoBitrate;
+  config.start_bitrate = config.max_bitrate;
   config.max_frame_rate = recv_config.target_frame_rate;
-  config.max_number_of_video_buffers_used = 1;
   config.codec = recv_config.codec;
-  config.number_of_encode_threads = 2;
-  config.max_playout_delay =
-      base::TimeDelta::FromMilliseconds(kDefaultRtpMaxDelayMs);
+  config.video_codec_params.max_qp = kDefaultMaxQp;
+  config.video_codec_params.min_qp = kDefaultMinQp;
+  config.video_codec_params.max_cpu_saver_qp = kDefaultMaxCpuSaverQp;
+  config.video_codec_params.max_number_of_video_buffers_used =
+      kDefaultNumberOfVideoBuffers;
+  config.video_codec_params.number_of_encode_threads = 2;
   return config;
 }
 
diff --git a/media/cast/test/utility/default_config.h b/media/cast/test/utility/default_config.h
index 2cc52a7..0357a973 100644
--- a/media/cast/test/utility/default_config.h
+++ b/media/cast/test/utility/default_config.h
@@ -20,14 +20,14 @@
 // name.
 FrameReceiverConfig GetDefaultVideoReceiverConfig();
 
-// Returns a AudioSenderConfig initialized to default values. This means
+// Returns a FrameSenderConfig initialized to default values. This means
 // 48 kHz, 2-channel Opus-coded audio. Default values for SSRCs and payload
 // type.
-AudioSenderConfig GetDefaultAudioSenderConfig();
+FrameSenderConfig GetDefaultAudioSenderConfig();
 
-// Returns a VideoSenderConfig initialized to default values. This means
+// Returns a FrameSenderConfig initialized to default values. This means
 // 30 Hz VP8 coded code. Default values for SSRCs and payload type.
-VideoSenderConfig GetDefaultVideoSenderConfig();
+FrameSenderConfig GetDefaultVideoSenderConfig();
 
 // Returns a callback that does nothing.
 CreateVideoEncodeAcceleratorCallback
diff --git a/media/filters/audio_renderer_algorithm.cc b/media/filters/audio_renderer_algorithm.cc
index df2e5369..ebe334a 100644
--- a/media/filters/audio_renderer_algorithm.cc
+++ b/media/filters/audio_renderer_algorithm.cc
@@ -146,6 +146,7 @@
   if (playback_rate == 0)
     return 0;
 
+  DCHECK_GT(playback_rate, 0);
   DCHECK_EQ(channels_, dest->channels());
 
   // Optimize the muted case to issue a single clear instead of performing
@@ -160,7 +161,10 @@
     // only skip over complete frames, so a partial frame may remain for next
     // time.
     muted_partial_frame_ += frames_to_render * playback_rate;
-    int seek_frames = static_cast<int>(muted_partial_frame_);
+    // Handle the case where muted_partial_frame_ rounds up to
+    // audio_buffer_.frames()+1.
+    int seek_frames = std::min(static_cast<int>(muted_partial_frame_),
+                               audio_buffer_.frames());
     dest->ZeroFramesPartial(dest_offset, frames_to_render);
     audio_buffer_.SeekFrames(seek_frames);
 
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn
index 31e23274..b928d0b9 100644
--- a/media/gpu/BUILD.gn
+++ b/media/gpu/BUILD.gn
@@ -131,6 +131,9 @@
   if (is_chromeos && use_v4lplugin) {
     defines += [ "USE_LIBV4L2" ]
   }
+  if (is_chromeos && use_v4l2_codec) {
+    defines += [ "USE_V4L2_CODEC" ]
+  }
 }
 
 component("gpu") {
@@ -257,7 +260,6 @@
       deps += [ ":libv4l2_generate_stubs" ]
     }
     if (use_v4l2_codec) {
-      defines += [ "USE_V4L2_CODEC" ]
       deps += [ "//third_party/libyuv" ]
       sources += [
         "generic_v4l2_device.cc",
diff --git a/media/gpu/ipc/service/BUILD.gn b/media/gpu/ipc/service/BUILD.gn
index 17acc26..0b167ed 100644
--- a/media/gpu/ipc/service/BUILD.gn
+++ b/media/gpu/ipc/service/BUILD.gn
@@ -38,6 +38,8 @@
     "//third_party/mesa:mesa_headers",
   ]
 
+  configs += [ "//media/gpu:gpu_config" ]
+
   if (is_chromeos && current_cpu != "arm") {
     configs += [ "//third_party/libva:libva_config" ]
   }
diff --git a/mojo/edk/system/node_channel.cc b/mojo/edk/system/node_channel.cc
index eb83f2e..ce094c16 100644
--- a/mojo/edk/system/node_channel.cc
+++ b/mojo/edk/system/node_channel.cc
@@ -503,7 +503,7 @@
 
 
   if (payload_size <= sizeof(Header)) {
-    delegate_->OnChannelError(remote_node_name_);
+    delegate_->OnChannelError(remote_node_name_, this);
     return;
   }
 
@@ -733,7 +733,7 @@
   }
 
   DLOG(ERROR) << "Received invalid message. Closing channel.";
-  delegate_->OnChannelError(remote_node_name_);
+  delegate_->OnChannelError(remote_node_name_, this);
 }
 
 void NodeChannel::OnChannelError() {
@@ -746,7 +746,7 @@
   // to the name name after that destruction. So may a copy of
   // |remote_node_name_| so it can be used if |this| becomes destroyed.
   ports::NodeName node_name = remote_node_name_;
-  delegate_->OnChannelError(node_name);
+  delegate_->OnChannelError(node_name, this);
 }
 
 #if defined(OS_MACOSX) && !defined(OS_IOS)
diff --git a/mojo/edk/system/node_channel.h b/mojo/edk/system/node_channel.h
index 658553c..5a5fc8a 100644
--- a/mojo/edk/system/node_channel.h
+++ b/mojo/edk/system/node_channel.h
@@ -77,7 +77,8 @@
                                          Channel::MessagePtr message) = 0;
 #endif
 
-    virtual void OnChannelError(const ports::NodeName& node) = 0;
+    virtual void OnChannelError(const ports::NodeName& node,
+                                NodeChannel* channel) = 0;
 
 #if defined(OS_MACOSX) && !defined(OS_IOS)
     virtual MachPortRelay* GetMachPortRelay() = 0;
diff --git a/mojo/edk/system/node_controller.cc b/mojo/edk/system/node_controller.cc
index a7f247a..28343b3a 100644
--- a/mojo/edk/system/node_controller.cc
+++ b/mojo/edk/system/node_controller.cc
@@ -310,6 +310,7 @@
   }
 
   scoped_refptr<NodeChannel> parent;
+  bool reject_merge = false;
   {
     // Hold |pending_port_merges_lock_| while getting |parent|. Otherwise,
     // there is a race where the parent can be set, and |pending_port_merges_|
@@ -317,11 +318,21 @@
     // |pending_port_merges_|.
     base::AutoLock lock(pending_port_merges_lock_);
     parent = GetParentChannel();
-    if (!parent) {
+    if (reject_pending_merges_) {
+      reject_merge = true;
+    } else if (!parent) {
       pending_port_merges_.push_back(std::make_pair(token, port));
       return;
     }
   }
+  if (reject_merge) {
+    node_->ClosePort(port);
+    DVLOG(2) << "Rejecting port merge for token " << token
+             << " due to closed parent channel.";
+    AcceptIncomingMessages();
+    return;
+  }
+
   parent->RequestPortMerge(port.name(), token);
 }
 
@@ -495,7 +506,8 @@
   }
 }
 
-void NodeController::DropPeer(const ports::NodeName& name) {
+void NodeController::DropPeer(const ports::NodeName& name,
+                              NodeChannel* channel) {
   DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
 
   {
@@ -542,6 +554,23 @@
     }
   }
 
+  bool is_parent;
+  {
+    base::AutoLock lock(parent_lock_);
+    is_parent = (name == parent_name_ || channel == bootstrap_parent_channel_);
+  }
+  // If the error comes from the parent channel, we also need to cancel any
+  // port merge requests, so that errors can be propagated to the message
+  // pipes.
+  if (is_parent) {
+    base::AutoLock lock(pending_port_merges_lock_);
+    reject_pending_merges_ = true;
+
+    for (const auto& port : pending_port_merges_)
+      ports_to_close.push_back(port.second);
+    pending_port_merges_.clear();
+  }
+
   for (const auto& port : ports_to_close)
     node_->ClosePort(port);
 
@@ -651,6 +680,16 @@
 
 void NodeController::ProcessIncomingMessages() {
   RequestContext request_context(RequestContext::Source::SYSTEM);
+
+  {
+    base::AutoLock lock(messages_lock_);
+    // Allow a new incoming messages processing task to be posted. This can't be
+    // done after AcceptIncomingMessages() otherwise a message might be missed.
+    // Doing it here may result in at most two tasks existing at the same time;
+    // this running one, and one pending in the task runner.
+    incoming_messages_task_posted_ = false;
+  }
+
   AcceptIncomingMessages();
 }
 
@@ -708,16 +747,18 @@
     // (synchronously) in response to Node's ClosePort, SendMessage, or
     // AcceptMessage, we flush the queue after calling any of those methods.
     base::AutoLock lock(messages_lock_);
-    schedule_pump_task = incoming_messages_.empty();
+    // |io_task_runner_| may be null in tests or processes that don't require
+    // multi-process Mojo.
+    schedule_pump_task = incoming_messages_.empty() && io_task_runner_ &&
+        !incoming_messages_task_posted_;
+    incoming_messages_task_posted_ |= schedule_pump_task;
     incoming_messages_.emplace(std::move(message));
     incoming_messages_flag_.Set(true);
   } else {
     SendPeerMessage(node, std::move(message));
   }
 
-  // |io_task_runner_| may be null in tests or processes that don't require
-  // multi-process Mojo.
-  if (schedule_pump_task && io_task_runner_) {
+  if (schedule_pump_task) {
     // Normally, the queue is processed after the action that added the local
     // message is done (i.e. SendMessage, ClosePort, etc). However, it's also
     // possible for a local message to be added as a result of a remote message,
@@ -778,7 +819,7 @@
 
   if (!parent) {
     DLOG(ERROR) << "Unexpected AcceptChild message from " << from_node;
-    DropPeer(from_node);
+    DropPeer(from_node, nullptr);
     return;
   }
 
@@ -801,7 +842,7 @@
   if (it == pending_children_.end() || token != from_node) {
     DLOG(ERROR) << "Received unexpected AcceptParent message from "
                 << from_node;
-    DropPeer(from_node);
+    DropPeer(from_node, nullptr);
     return;
   }
 
@@ -858,7 +899,7 @@
 
   if (GetPeerChannel(client_name)) {
     DLOG(ERROR) << "Ignoring AddBrokerClient for known client.";
-    DropPeer(from_node);
+    DropPeer(from_node, nullptr);
     return;
   }
 
@@ -989,7 +1030,7 @@
   if (!ParsePortsMessage(channel_message.get(), &data, &num_data_bytes,
                          &num_header_bytes, &num_payload_bytes,
                          &num_ports_bytes)) {
-    DropPeer(from_node);
+    DropPeer(from_node, nullptr);
     return;
   }
 
@@ -1040,7 +1081,7 @@
   if (from_node == name || name == ports::kInvalidNodeName || !requestor) {
     DLOG(ERROR) << "Rejecting invalid OnRequestIntroduction message from "
                 << from_node;
-    DropPeer(from_node);
+    DropPeer(from_node, nullptr);
     return;
   }
 
@@ -1086,13 +1127,13 @@
   if (!ParsePortsMessage(message.get(), &data, &num_data_bytes,
                          &num_header_bytes, &num_payload_bytes,
                          &num_ports_bytes)) {
-    DropPeer(from_node);
+    DropPeer(from_node, nullptr);
     return;
   }
 
   // Broadcast messages must not contain ports.
   if (num_ports_bytes > 0) {
-    DropPeer(from_node);
+    DropPeer(from_node, nullptr);
     return;
   }
 
@@ -1117,7 +1158,7 @@
   if (GetBrokerChannel()) {
     // Only the broker should be asked to relay a message.
     LOG(ERROR) << "Non-broker refusing to relay message.";
-    DropPeer(from_node);
+    DropPeer(from_node, nullptr);
     return;
   }
 
@@ -1178,7 +1219,7 @@
                                              Channel::MessagePtr message) {
   if (GetPeerChannel(from_node) != GetBrokerChannel()) {
     LOG(ERROR) << "Refusing relayed message from non-broker node.";
-    DropPeer(from_node);
+    DropPeer(from_node, nullptr);
     return;
   }
 
@@ -1186,9 +1227,10 @@
 }
 #endif
 
-void NodeController::OnChannelError(const ports::NodeName& from_node) {
+void NodeController::OnChannelError(const ports::NodeName& from_node,
+                                    NodeChannel* channel) {
   if (io_task_runner_->RunsTasksOnCurrentThread()) {
-    DropPeer(from_node);
+    DropPeer(from_node, channel);
     // DropPeer may have caused local port closures, so be sure to process any
     // pending local messages.
     AcceptIncomingMessages();
@@ -1196,7 +1238,7 @@
     io_task_runner_->PostTask(
         FROM_HERE,
         base::Bind(&NodeController::OnChannelError, base::Unretained(this),
-                   from_node));
+                   from_node, channel));
   }
 }
 
diff --git a/mojo/edk/system/node_controller.h b/mojo/edk/system/node_controller.h
index c96b4f44..2cdcd90 100644
--- a/mojo/edk/system/node_controller.h
+++ b/mojo/edk/system/node_controller.h
@@ -153,7 +153,7 @@
   void AddPeer(const ports::NodeName& name,
                scoped_refptr<NodeChannel> channel,
                bool start_channel);
-  void DropPeer(const ports::NodeName& name);
+  void DropPeer(const ports::NodeName& name, NodeChannel* channel);
   void SendPeerMessage(const ports::NodeName& name,
                        ports::ScopedMessage message);
   void AcceptIncomingMessages();
@@ -206,7 +206,8 @@
                                const ports::NodeName& source_node,
                                Channel::MessagePtr message) override;
 #endif
-  void OnChannelError(const ports::NodeName& from_node) override;
+  void OnChannelError(const ports::NodeName& from_node,
+                      NodeChannel* channel) override;
 #if defined(OS_MACOSX) && !defined(OS_IOS)
   MachPortRelay* GetMachPortRelay() override;
 #endif
@@ -246,12 +247,16 @@
   // have one yet :(
   std::unordered_map<ports::NodeName, std::string> pending_child_tokens_;
 
-  // Guards |pending_port_merges_|.
+  // Guards |pending_port_merges_| and |reject_pending_merges_|.
   base::Lock pending_port_merges_lock_;
 
   // A set of port merge requests awaiting parent connection.
   std::vector<std::pair<std::string, ports::PortRef>> pending_port_merges_;
 
+  // Indicates that new merge requests should be rejected because the parent has
+  // disconnected.
+  bool reject_pending_merges_ = false;
+
   // Guards |parent_name_| and |bootstrap_parent_channel_|.
   base::Lock parent_lock_;
 
@@ -275,9 +280,12 @@
   std::unordered_map<ports::NodeName, OutgoingMessageQueue>
       pending_relay_messages_;
 
-  // Guards |incoming_messages_|.
+  // Guards |incoming_messages_| and |incoming_messages_task_posted_|.
   base::Lock messages_lock_;
   std::queue<ports::ScopedMessage> incoming_messages_;
+  // Ensures that there is only one incoming messages task posted to the IO
+  // thread.
+  bool incoming_messages_task_posted_ = false;
   // Flag to fast-path checking |incoming_messages_|.
   AtomicFlag incoming_messages_flag_;
 
diff --git a/mojo/public/cpp/bindings/lib/validation_context.cc b/mojo/public/cpp/bindings/lib/validation_context.cc
index e2688c4..a95e07e 100644
--- a/mojo/public/cpp/bindings/lib/validation_context.cc
+++ b/mojo/public/cpp/bindings/lib/validation_context.cc
@@ -16,7 +16,7 @@
 namespace internal {
 
 ValidationContext::ValidationContext(const void* data,
-                                     uint32_t data_num_bytes,
+                                     size_t data_num_bytes,
                                      size_t num_handles,
                                      Message* message,
                                      const base::StringPiece& description)
diff --git a/mojo/public/cpp/bindings/lib/validation_context.h b/mojo/public/cpp/bindings/lib/validation_context.h
index 5b02a59..6045ca82 100644
--- a/mojo/public/cpp/bindings/lib/validation_context.h
+++ b/mojo/public/cpp/bindings/lib/validation_context.h
@@ -31,7 +31,7 @@
   // provided, the MojoNotifyBadMessage API will be used to notify the system of
   // such errors.
   ValidationContext(const void* data,
-                    uint32_t data_num_bytes,
+                    size_t data_num_bytes,
                     size_t num_handles,
                     Message* message = nullptr,
                     const base::StringPiece& description = "");
diff --git a/net/cert/internal/parse_ocsp.cc b/net/cert/internal/parse_ocsp.cc
index 0243d95..21ce878b 100644
--- a/net/cert/internal/parse_ocsp.cc
+++ b/net/cert/internal/parse_ocsp.cc
@@ -7,6 +7,7 @@
 #include "base/sha1.h"
 #include "crypto/sha2.h"
 #include "net/cert/internal/parse_ocsp.h"
+#include "net/der/encode_values.h"
 
 namespace net {
 
@@ -529,4 +530,28 @@
   return found;
 }
 
+bool CheckOCSPDateValid(const OCSPSingleResponse& response,
+                        const base::Time& verify_time,
+                        const base::TimeDelta& max_age) {
+  der::GeneralizedTime verify_time_der;
+  if (!der::EncodeTimeAsGeneralizedTime(verify_time, &verify_time_der))
+    return false;
+
+  if (response.this_update > verify_time_der)
+    return false;  // Response is not yet valid.
+
+  if (response.has_next_update && (response.next_update <= verify_time_der))
+    return false;  // Response is no longer valid.
+
+  der::GeneralizedTime earliest_this_update;
+  if (!der::EncodeTimeAsGeneralizedTime(verify_time - max_age,
+                                        &earliest_this_update)) {
+    return false;
+  }
+  if (response.this_update < earliest_this_update)
+    return false;  // Response is too old.
+
+  return true;
+}
+
 }  // namespace net
diff --git a/net/cert/internal/parse_ocsp.h b/net/cert/internal/parse_ocsp.h
index b9052ae..af5541d 100644
--- a/net/cert/internal/parse_ocsp.h
+++ b/net/cert/internal/parse_ocsp.h
@@ -17,6 +17,10 @@
 #include "net/der/parser.h"
 #include "net/der/tag.h"
 
+namespace base {
+class Time;
+}
+
 namespace net {
 
 // OCSPCertID contains a representation of a DER-encoded RFC 6960 "CertID".
@@ -278,6 +282,15 @@
     const der::Input& cert_tbs_certificate_tlv,
     OCSPCertStatus* out);
 
+// Returns true if |response|, a valid OCSP response with a thisUpdate field and
+// potentially a nextUpdate field, is valid at |verify_time| and not older than
+// |max_age|. Expressed differently, returns true if |response.thisUpdate| <=
+// |verify_time| < response.nextUpdate, and |response.thisUpdate| >=
+// |verify_time| - |max_age|.
+NET_EXPORT_PRIVATE bool CheckOCSPDateValid(const OCSPSingleResponse& response,
+                                           const base::Time& verify_time,
+                                           const base::TimeDelta& max_age);
+
 }  // namespace net
 
 #endif  // NET_CERT_INTERNAL_PARSE_OCSP_H_
diff --git a/net/cert/internal/parse_ocsp_unittest.cc b/net/cert/internal/parse_ocsp_unittest.cc
index c0fc061b..bc4e1e1e 100644
--- a/net/cert/internal/parse_ocsp_unittest.cc
+++ b/net/cert/internal/parse_ocsp_unittest.cc
@@ -8,6 +8,7 @@
 #include "base/logging.h"
 #include "net/cert/internal/test_helpers.h"
 #include "net/cert/x509_certificate.h"
+#include "net/der/encode_values.h"
 #include "net/test/test_data_directory.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -15,6 +16,8 @@
 
 namespace {
 
+const base::TimeDelta kOCSPAgeOneWeek = base::TimeDelta::FromDays(7);
+
 std::string GetFilePath(const std::string& file_name) {
   return std::string("net/data/parse_ocsp_unittest/") + file_name;
 }
@@ -182,4 +185,131 @@
   ASSERT_EQ(PARSE_OCSP_SINGLE_RESPONSE, ParseOCSP("missing_response.pem"));
 }
 
+TEST(OCSPDateTest, Valid) {
+  OCSPSingleResponse response;
+
+  base::Time now = base::Time::Now();
+  base::Time this_update = now - base::TimeDelta::FromHours(1);
+  ASSERT_TRUE(
+      der::EncodeTimeAsGeneralizedTime(this_update, &response.this_update));
+  response.has_next_update = false;
+  EXPECT_TRUE(CheckOCSPDateValid(response, now, kOCSPAgeOneWeek));
+
+  base::Time next_update = this_update + base::TimeDelta::FromDays(7);
+  ASSERT_TRUE(
+      der::EncodeTimeAsGeneralizedTime(next_update, &response.next_update));
+  response.has_next_update = true;
+  EXPECT_TRUE(CheckOCSPDateValid(response, now, kOCSPAgeOneWeek));
+}
+
+TEST(OCSPDateTest, ThisUpdateInTheFuture) {
+  OCSPSingleResponse response;
+
+  base::Time now = base::Time::Now();
+  base::Time this_update = now + base::TimeDelta::FromHours(1);
+  ASSERT_TRUE(
+      der::EncodeTimeAsGeneralizedTime(this_update, &response.this_update));
+  response.has_next_update = false;
+  EXPECT_FALSE(CheckOCSPDateValid(response, now, kOCSPAgeOneWeek));
+
+  base::Time next_update = this_update + base::TimeDelta::FromDays(7);
+  ASSERT_TRUE(
+      der::EncodeTimeAsGeneralizedTime(next_update, &response.next_update));
+  response.has_next_update = true;
+  EXPECT_FALSE(CheckOCSPDateValid(response, now, kOCSPAgeOneWeek));
+}
+
+TEST(OCSPDateTest, NextUpdatePassed) {
+  OCSPSingleResponse response;
+
+  base::Time now = base::Time::Now();
+  base::Time this_update = now - base::TimeDelta::FromDays(6);
+  ASSERT_TRUE(
+      der::EncodeTimeAsGeneralizedTime(this_update, &response.this_update));
+  response.has_next_update = false;
+  EXPECT_TRUE(CheckOCSPDateValid(response, now, kOCSPAgeOneWeek));
+
+  base::Time next_update = now - base::TimeDelta::FromHours(1);
+  ASSERT_TRUE(
+      der::EncodeTimeAsGeneralizedTime(next_update, &response.next_update));
+  response.has_next_update = true;
+  EXPECT_FALSE(CheckOCSPDateValid(response, now, kOCSPAgeOneWeek));
+}
+
+TEST(OCSPDateTest, NextUpdateBeforeThisUpdate) {
+  OCSPSingleResponse response;
+
+  base::Time now = base::Time::Now();
+  base::Time this_update = now - base::TimeDelta::FromDays(1);
+  ASSERT_TRUE(
+      der::EncodeTimeAsGeneralizedTime(this_update, &response.this_update));
+  response.has_next_update = false;
+  EXPECT_TRUE(CheckOCSPDateValid(response, now, kOCSPAgeOneWeek));
+
+  base::Time next_update = this_update - base::TimeDelta::FromDays(1);
+  ASSERT_TRUE(
+      der::EncodeTimeAsGeneralizedTime(next_update, &response.next_update));
+  response.has_next_update = true;
+  EXPECT_FALSE(CheckOCSPDateValid(response, now, kOCSPAgeOneWeek));
+}
+
+TEST(OCSPDateTest, ThisUpdateOlderThanMaxAge) {
+  OCSPSingleResponse response;
+
+  base::Time now = base::Time::Now();
+  base::Time this_update = now - kOCSPAgeOneWeek;
+  ASSERT_TRUE(
+      der::EncodeTimeAsGeneralizedTime(this_update, &response.this_update));
+  response.has_next_update = false;
+  EXPECT_TRUE(CheckOCSPDateValid(response, now, kOCSPAgeOneWeek));
+
+  base::Time next_update = now + base::TimeDelta::FromHours(1);
+  ASSERT_TRUE(
+      der::EncodeTimeAsGeneralizedTime(next_update, &response.next_update));
+  response.has_next_update = true;
+  EXPECT_TRUE(CheckOCSPDateValid(response, now, kOCSPAgeOneWeek));
+
+  ASSERT_TRUE(der::EncodeTimeAsGeneralizedTime(
+      this_update - base::TimeDelta::FromSeconds(1), &response.this_update));
+  response.has_next_update = false;
+  EXPECT_FALSE(CheckOCSPDateValid(response, now, kOCSPAgeOneWeek));
+  response.has_next_update = true;
+  EXPECT_FALSE(CheckOCSPDateValid(response, now, kOCSPAgeOneWeek));
+}
+
+TEST(OCSPDateTest, VerifyTimeFromBeforeWindowsEpoch) {
+  OCSPSingleResponse response;
+  base::Time windows_epoch;
+  base::Time verify_time = windows_epoch - base::TimeDelta::FromDays(1);
+
+  base::Time now = base::Time::Now();
+  base::Time this_update = now - base::TimeDelta::FromHours(1);
+  ASSERT_TRUE(
+      der::EncodeTimeAsGeneralizedTime(this_update, &response.this_update));
+  response.has_next_update = false;
+  EXPECT_FALSE(CheckOCSPDateValid(response, verify_time, kOCSPAgeOneWeek));
+
+  base::Time next_update = this_update + kOCSPAgeOneWeek;
+  ASSERT_TRUE(
+      der::EncodeTimeAsGeneralizedTime(next_update, &response.next_update));
+  response.has_next_update = true;
+  EXPECT_FALSE(CheckOCSPDateValid(response, verify_time, kOCSPAgeOneWeek));
+}
+
+TEST(OCSPDateTest, VerifyTimeMinusAgeFromBeforeWindowsEpoch) {
+  OCSPSingleResponse response;
+  base::Time windows_epoch;
+  base::Time verify_time = windows_epoch + base::TimeDelta::FromDays(1);
+
+  base::Time this_update = windows_epoch;
+  ASSERT_TRUE(
+      der::EncodeTimeAsGeneralizedTime(this_update, &response.this_update));
+  response.has_next_update = false;
+#ifdef OS_WIN
+  EXPECT_FALSE(CheckOCSPDateValid(response, verify_time, kOCSPAgeOneWeek));
+#else
+  EXPECT_TRUE(CheckOCSPDateValid(response, verify_time, kOCSPAgeOneWeek));
+#endif
+}
+
 }  // namespace net
diff --git a/net/der/encode_values.cc b/net/der/encode_values.cc
new file mode 100644
index 0000000..af7098a
--- /dev/null
+++ b/net/der/encode_values.cc
@@ -0,0 +1,30 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/time/time.h"
+#include "net/der/encode_values.h"
+
+namespace net {
+
+namespace der {
+
+bool EncodeTimeAsGeneralizedTime(const base::Time& time,
+                                 der::GeneralizedTime* generalized_time) {
+  base::Time::Exploded exploded;
+  time.UTCExplode(&exploded);
+  if (!exploded.HasValidValues())
+    return false;
+
+  generalized_time->year = exploded.year;
+  generalized_time->month = exploded.month;
+  generalized_time->day = exploded.day_of_month;
+  generalized_time->hours = exploded.hour;
+  generalized_time->minutes = exploded.minute;
+  generalized_time->seconds = exploded.second;
+  return true;
+}
+
+}  // namespace der
+
+}  // namespace net
diff --git a/net/der/encode_values.h b/net/der/encode_values.h
new file mode 100644
index 0000000..e0b04423
--- /dev/null
+++ b/net/der/encode_values.h
@@ -0,0 +1,29 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_DER_ENCODE_VALUES_H_
+#define NET_DER_ENCODE_VALUES_H_
+
+#include "net/base/net_export.h"
+#include "net/der/parse_values.h"
+
+namespace base {
+class Time;
+}
+
+namespace net {
+
+namespace der {
+
+// Encodes |time|, a UTC-based time, to DER |generalized_time|, for comparing
+// against other GeneralizedTime objects.
+NET_EXPORT bool EncodeTimeAsGeneralizedTime(
+    const base::Time& time,
+    der::GeneralizedTime* generalized_time);
+
+}  // namespace der
+
+}  // namespace net
+
+#endif  // NET_DER_ENCODE_VALUES_H
diff --git a/net/der/encode_values_unittest.cc b/net/der/encode_values_unittest.cc
new file mode 100644
index 0000000..52672cf
--- /dev/null
+++ b/net/der/encode_values_unittest.cc
@@ -0,0 +1,96 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/time/time.h"
+#include "net/der/encode_values.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace der {
+namespace test {
+
+TEST(EncodeValuesTest, EncodeTimeAsGeneralizedTime) {
+  // Fri, 24 Jun 2016 17:04:54 GMT
+  base::Time time =
+      base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(1466787894);
+  GeneralizedTime generalized_time;
+  ASSERT_TRUE(EncodeTimeAsGeneralizedTime(time, &generalized_time));
+  EXPECT_EQ(2016, generalized_time.year);
+  EXPECT_EQ(6, generalized_time.month);
+  EXPECT_EQ(24, generalized_time.day);
+  EXPECT_EQ(17, generalized_time.hours);
+  EXPECT_EQ(4, generalized_time.minutes);
+  EXPECT_EQ(54, generalized_time.seconds);
+}
+
+// ASN.1 GeneralizedTime can represent dates from year 0000 to 9999, and
+// although base::Time can represent times from before the Windows epoch and
+// after the 32-bit time_t maximum, the conversion between base::Time and
+// der::GeneralizedTime goes through the time representation of the underlying
+// platform, which might not be able to handle the full GeneralizedTime date
+// range. Out-of-range times should not be converted to der::GeneralizedTime. In
+// tests, possibly-out-of-range test times are specified as a
+// base::Time::Exploded, and then converted to a base::Time. If the conversion
+// fails, this signals the underlying platform cannot handle the time, and the
+// test aborts early. If the underlying platform can represent the time, then
+// the conversion is successful, and the encoded GeneralizedTime can should
+// match the test time.
+//
+// Thu, 1 Jan 1570 00:00:00 GMT. This time is unrepresentable by the Windows
+// native time libraries.
+TEST(EncodeValuesTest, EncodeTimeFromBeforeWindowsEpoch) {
+  base::Time::Exploded exploded;
+  exploded.year = 1570;
+  exploded.month = 1;
+  exploded.day_of_week = 5;
+  exploded.hour = 0;
+  exploded.minute = 0;
+  exploded.second = 0;
+  exploded.millisecond = 0;
+
+  base::Time time;
+  if (!base::Time::FromUTCExploded(exploded, &time))
+    return;
+
+  GeneralizedTime generalized_time;
+  ASSERT_TRUE(EncodeTimeAsGeneralizedTime(time, &generalized_time));
+  EXPECT_EQ(1570, generalized_time.year);
+  EXPECT_EQ(1, generalized_time.month);
+  EXPECT_EQ(1, generalized_time.day);
+  EXPECT_EQ(0, generalized_time.hours);
+  EXPECT_EQ(0, generalized_time.minutes);
+  EXPECT_EQ(0, generalized_time.seconds);
+}
+
+// Sat, 1 Jan 2039 00:00:00 GMT. See above comment. This time may be
+// unrepresentable on 32-bit systems.
+TEST(EncodeValuesTest, EncodeTimeAfterTimeTMax) {
+  base::Time::Exploded exploded;
+  exploded.year = 2039;
+  exploded.month = 1;
+  exploded.day_of_week = 7;
+  exploded.hour = 0;
+  exploded.minute = 0;
+  exploded.second = 0;
+  exploded.millisecond = 0;
+
+  base::Time time;
+  if (!base::Time::FromUTCExploded(exploded, &time))
+    return;
+
+  GeneralizedTime generalized_time;
+  ASSERT_TRUE(EncodeTimeAsGeneralizedTime(time, &generalized_time));
+  EXPECT_EQ(2039, generalized_time.year);
+  EXPECT_EQ(1, generalized_time.month);
+  EXPECT_EQ(1, generalized_time.day);
+  EXPECT_EQ(0, generalized_time.hours);
+  EXPECT_EQ(0, generalized_time.minutes);
+  EXPECT_EQ(0, generalized_time.seconds);
+}
+
+}  // namespace test
+
+}  // namespace der
+
+}  // namespace net
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index 9254739..658dc7d 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -1653,83 +1653,6 @@
                                               arraysize(data_reads));
   EXPECT_THAT(out.rv, IsError(ERR_EMPTY_RESPONSE));
 }
-//
-//// Test that network access can be deferred and resumed.
-// TEST_P(HttpNetworkTransactionTest, ThrottleBeforeNetworkStart) {
-//  HttpRequestInfo request;
-//  request.method = "GET";
-//  request.url = GURL("http://www.example.org/");
-//  request.load_flags = 0;
-//
-//  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
-//  std::unique_ptr<HttpTransaction> trans(
-//      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
-//
-//  // Defer on OnBeforeNetworkStart.
-//  BeforeNetworkStartHandler net_start_handler(true);  // defer
-//  trans->SetBeforeNetworkStartCallback(
-//      base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
-//                 base::Unretained(&net_start_handler)));
-//
-//  MockRead data_reads[] = {
-//    MockRead("HTTP/1.0 200 OK\r\n"),
-//    MockRead("Content-Length: 5\r\n\r\n"),
-//    MockRead("hello"),
-//    MockRead(SYNCHRONOUS, 0),
-//  };
-//  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
-//  session_deps_.socket_factory->AddSocketDataProvider(&data);
-//
-//  TestCompletionCallback callback;
-//
-//  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
-//  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
-//  base::RunLoop().RunUntilIdle();
-//
-//  // Should have deferred for network start.
-//  EXPECT_TRUE(net_start_handler.observed_before_network_start());
-//  EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
-//
-//  trans->ResumeNetworkStart();
-//  rv = callback.WaitForResult();
-//  EXPECT_THAT(rv, IsOk());
-//  EXPECT_TRUE(trans->GetResponseInfo());
-//
-//  scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
-//  rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
-//  if (rv == ERR_IO_PENDING)
-//    rv = callback.WaitForResult();
-//  EXPECT_EQ(5, rv);
-//  trans.reset();
-//}
-//
-//// Test that network use can be deferred and canceled.
-// TEST_P(HttpNetworkTransactionTest, ThrottleAndCancelBeforeNetworkStart) {
-//  HttpRequestInfo request;
-//  request.method = "GET";
-//  request.url = GURL("http://www.example.org/");
-//  request.load_flags = 0;
-//
-//  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
-//  std::unique_ptr<HttpTransaction> trans(
-//      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
-//
-//  // Defer on OnBeforeNetworkStart.
-//  BeforeNetworkStartHandler net_start_handler(true);  // defer
-//  trans->SetBeforeNetworkStartCallback(
-//      base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
-//                 base::Unretained(&net_start_handler)));
-//
-//  TestCompletionCallback callback;
-//
-//  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
-//  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
-//  base::RunLoop().RunUntilIdle();
-//
-//  // Should have deferred for network start.
-//  EXPECT_TRUE(net_start_handler.observed_before_network_start());
-//  EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
-//}
 
 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
 // tests. There was a bug causing HttpNetworkTransaction to hang in the
diff --git a/net/http/http_util.cc b/net/http/http_util.cc
index 1f1ef91..313da11 100644
--- a/net/http/http_util.cc
+++ b/net/http/http_util.cc
@@ -347,9 +347,8 @@
 
 // static
 bool HttpUtil::IsValidHeaderValue(const std::string& value) {
-  // Just a sanity check: disallow NUL and CRLF.
-  return value.find('\0') == std::string::npos &&
-      value.find("\r\n") == std::string::npos;
+  // Just a sanity check: disallow NUL, CR and LF.
+  return value.find_first_of("\0\r\n", 0, 3) == std::string::npos;
 }
 
 // static
diff --git a/net/http/http_util_unittest.cc b/net/http/http_util_unittest.cc
index 7162d7a0..94fde66 100644
--- a/net/http/http_util_unittest.cc
+++ b/net/http/http_util_unittest.cc
@@ -1367,4 +1367,29 @@
   EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagEmpty, kLastModifiedInvalid));
 }
 
+TEST(HttpUtilTest, IsValidHeaderValue) {
+  const char* const invalid_values[] = {
+      "X-Requested-With: chrome${NUL}Sec-Unsafe: injected",
+      "X-Requested-With: chrome\r\nSec-Unsafe: injected",
+      "X-Requested-With: chrome\nSec-Unsafe: injected",
+      "X-Requested-With: chrome\rSec-Unsafe: injected",
+  };
+  for (const std::string& value : invalid_values) {
+    std::string replaced = value;
+    base::ReplaceSubstringsAfterOffset(&replaced, 0, "${NUL}",
+                                       std::string(1, '\0'));
+    EXPECT_FALSE(HttpUtil::IsValidHeaderValue(replaced)) << replaced;
+  }
+
+  // Check that all characters permitted by RFC7230 3.2.6 are allowed.
+  std::string allowed = "\t";
+  for (char c = '\x20'; c < '\x7F'; ++c) {
+    allowed.append(1, c);
+  }
+  for (int c = 0x80; c <= 0xFF; ++c) {
+    allowed.append(1, static_cast<char>(c));
+  }
+  EXPECT_TRUE(HttpUtil::IsValidHeaderValue(allowed));
+}
+
 }  // namespace net
diff --git a/net/net.gypi b/net/net.gypi
index 744f6e8..9bac24b 100644
--- a/net/net.gypi
+++ b/net/net.gypi
@@ -142,6 +142,8 @@
       'cert/x509_util_openssl.h',
       'der/input.cc',
       'der/input.h',
+      'der/encode_values.cc',
+      'der/encode_values.h',
       'der/parse_values.cc',
       'der/parse_values.h',
       'der/parser.cc',
@@ -922,14 +924,6 @@
       'quic/iovector.h',
       'quic/network_connection.cc',
       'quic/network_connection.h',
-      'quic/p2p/quic_p2p_crypto_config.cc',
-      'quic/p2p/quic_p2p_crypto_config.h',
-      'quic/p2p/quic_p2p_crypto_stream.cc',
-      'quic/p2p/quic_p2p_crypto_stream.h',
-      'quic/p2p/quic_p2p_session.cc',
-      'quic/p2p/quic_p2p_session.h',
-      'quic/p2p/quic_p2p_stream.cc',
-      'quic/p2p/quic_p2p_stream.h',
       'quic/port_suggester.cc',
       'quic/port_suggester.h',
       'quic/quic_address_mismatch.cc',
@@ -1442,6 +1436,7 @@
       'cookies/cookie_util_unittest.cc',
       'cookies/parsed_cookie_unittest.cc',
       'der/input_unittest.cc',
+      'der/encode_values_unittest.cc',
       'der/parse_values_unittest.cc',
       'der/parser_unittest.cc',
       'disk_cache/backend_unittest.cc',
@@ -1627,7 +1622,6 @@
       'quic/interval_test.cc',
       'quic/iovector_test.cc',
       'quic/network_connection_unittest.cc',
-      'quic/p2p/quic_p2p_session_test.cc',
       'quic/port_suggester_unittest.cc',
       'quic/quic_address_mismatch_test.cc',
       'quic/quic_alarm_test.cc',
diff --git a/net/quic/congestion_control/general_loss_algorithm.cc b/net/quic/congestion_control/general_loss_algorithm.cc
index 05491b1b..9dfc7ce9 100644
--- a/net/quic/congestion_control/general_loss_algorithm.cc
+++ b/net/quic/congestion_control/general_loss_algorithm.cc
@@ -64,10 +64,10 @@
   }
   loss_detection_timeout_ = QuicTime::Zero();
   QuicTime::Delta max_rtt =
-      QuicTime::Delta::Max(rtt_stats.previous_srtt(), rtt_stats.latest_rtt());
+      std::max(rtt_stats.previous_srtt(), rtt_stats.latest_rtt());
   QuicTime::Delta loss_delay =
-      QuicTime::Delta::Max(QuicTime::Delta::FromMilliseconds(kMinLossDelayMs),
-                           max_rtt + (max_rtt >> reordering_shift_));
+      std::max(QuicTime::Delta::FromMilliseconds(kMinLossDelayMs),
+               max_rtt + (max_rtt >> reordering_shift_));
   QuicPacketNumber packet_number = unacked_packets.GetLeastUnacked();
   for (QuicUnackedPacketMap::const_iterator it = unacked_packets.begin();
        it != unacked_packets.end() && packet_number <= largest_observed;
@@ -133,7 +133,7 @@
       unacked_packets.GetTransmissionInfo(spurious_retransmission).sent_time;
   // Increase the reordering fraction until enough time would be allowed.
   QuicTime::Delta max_rtt =
-      QuicTime::Delta::Max(rtt_stats.previous_srtt(), rtt_stats.latest_rtt());
+      std::max(rtt_stats.previous_srtt(), rtt_stats.latest_rtt());
   QuicTime::Delta proposed_extra_time(QuicTime::Delta::Zero());
   do {
     proposed_extra_time = max_rtt >> reordering_shift_;
diff --git a/net/quic/congestion_control/pacing_sender.cc b/net/quic/congestion_control/pacing_sender.cc
index 7f366c9..d98dacf 100644
--- a/net/quic/congestion_control/pacing_sender.cc
+++ b/net/quic/congestion_control/pacing_sender.cc
@@ -48,7 +48,7 @@
                                      QuicByteCount bytes_in_flight,
                                      const CongestionVector& acked_packets,
                                      const CongestionVector& lost_packets) {
-  if (FLAGS_quic_allow_noprr && !lost_packets.empty()) {
+  if (!lost_packets.empty()) {
     // Clear any burst tokens when entering recovery.
     burst_tokens_ = 0;
   }
@@ -110,7 +110,7 @@
     }
   } else {
     ideal_next_packet_send_time_ =
-        QuicTime::Max(ideal_next_packet_send_time_ + delay, sent_time + delay);
+        std::max(ideal_next_packet_send_time_ + delay, sent_time + delay);
   }
   return in_flight;
 }
diff --git a/net/quic/congestion_control/pacing_sender_test.cc b/net/quic/congestion_control/pacing_sender_test.cc
index c531a59a..3277cacd 100644
--- a/net/quic/congestion_control/pacing_sender_test.cc
+++ b/net/quic/congestion_control/pacing_sender_test.cc
@@ -299,7 +299,6 @@
 }
 
 TEST_F(PacingSenderTest, NoBurstEnteringRecovery) {
-  ValueRestore<bool> old_flag(&FLAGS_quic_allow_noprr, true);
   // Configure pacing rate of 1 packet per 1 ms with no burst tokens.
   InitPacingRate(0, QuicBandwidth::FromBytesAndTimeDelta(
                         kMaxPacketSize, QuicTime::Delta::FromMilliseconds(1)));
diff --git a/net/quic/congestion_control/send_algorithm_simulator.cc b/net/quic/congestion_control/send_algorithm_simulator.cc
index bb1316f..d1eac0c 100644
--- a/net/quic/congestion_control/send_algorithm_simulator.cc
+++ b/net/quic/congestion_control/send_algorithm_simulator.cc
@@ -380,7 +380,7 @@
                                   ? QuicTime::Zero()
                                   : sent_packets_.back().ack_time +
                                         bandwidth_.TransferTime(kPacketSize);
-    ack_time = QuicTime::Max(ack_time, queue_ack_time);
+    ack_time = std::max(ack_time, queue_ack_time);
     sent_packets_.push_back(SentPacket(sender->last_sent, clock_->Now(),
                                        ack_time, packet_lost, transfer));
   } else {
diff --git a/net/quic/congestion_control/tcp_cubic_sender_base.cc b/net/quic/congestion_control/tcp_cubic_sender_base.cc
index 539eadc..8fb7b711 100644
--- a/net/quic/congestion_control/tcp_cubic_sender_base.cc
+++ b/net/quic/congestion_control/tcp_cubic_sender_base.cc
@@ -87,7 +87,7 @@
       // Slow Start Fast Exit experiment.
       slow_start_large_reduction_ = true;
     }
-    if (FLAGS_quic_allow_noprr && config.HasReceivedConnectionOptions() &&
+    if (config.HasReceivedConnectionOptions() &&
         ContainsQuicTag(config.ReceivedConnectionOptions(), kNPRR)) {
       // Use unity pacing instead of PRR.
       no_prr_ = true;
@@ -224,10 +224,9 @@
   if (rate_based_sending_ && bytes_in_flight > GetCongestionWindow()) {
     // Rate based sending allows sending more than CWND, but reduces the pacing
     // rate when the bytes in flight is more than the CWND to 75% of bandwidth.
-    return bandwidth.Scale(0.75);
+    return 0.75 * bandwidth;
   }
-  return bandwidth.Scale(InSlowStart() ? 2
-                                       : (no_prr_ && InRecovery() ? 1 : 1.25));
+  return bandwidth * (InSlowStart() ? 2 : (no_prr_ && InRecovery() ? 1 : 1.25));
 }
 
 QuicBandwidth TcpCubicSenderBase::BandwidthEstimate() const {
diff --git a/net/quic/congestion_control/tcp_cubic_sender_bytes_test.cc b/net/quic/congestion_control/tcp_cubic_sender_bytes_test.cc
index 6415172f..21fcd17a 100644
--- a/net/quic/congestion_control/tcp_cubic_sender_bytes_test.cc
+++ b/net/quic/congestion_control/tcp_cubic_sender_bytes_test.cc
@@ -779,7 +779,6 @@
 }
 
 TEST_F(TcpCubicSenderBytesTest, NoPRR) {
-  ValueRestore<bool> old_flag(&FLAGS_quic_allow_noprr, true);
   QuicTime::Delta rtt = QuicTime::Delta::FromMilliseconds(100);
   sender_->rtt_stats_.UpdateRtt(rtt, QuicTime::Delta::Zero(), QuicTime::Zero());
 
@@ -828,15 +827,15 @@
 
   EXPECT_TRUE(
       sender_->TimeUntilSend(QuicTime::Zero(), kDefaultTCPMSS).IsZero());
-  EXPECT_EQ(sender_->PacingRate(kDefaultTCPMSS),
-            QuicBandwidth::FromBytesAndTimeDelta(7 * kDefaultTCPMSS, rtt)
-                .Scale(1.25));
+  EXPECT_EQ(
+      sender_->PacingRate(kDefaultTCPMSS),
+      QuicBandwidth::FromBytesAndTimeDelta(7 * kDefaultTCPMSS, rtt) * 1.25);
   for (QuicPacketCount i = cwnd + 1; i < 1.5 * cwnd; ++i) {
     EXPECT_TRUE(
         sender_->TimeUntilSend(QuicTime::Zero(), i * kDefaultTCPMSS).IsZero());
     EXPECT_EQ(sender_->PacingRate(i * kDefaultTCPMSS),
-              QuicBandwidth::FromBytesAndTimeDelta(cwnd * kDefaultTCPMSS, rtt)
-                  .Scale(0.75));
+              QuicBandwidth::FromBytesAndTimeDelta(cwnd * kDefaultTCPMSS, rtt) *
+                  0.75);
   }
   EXPECT_FALSE(
       sender_->TimeUntilSend(QuicTime::Zero(), 11 * kDefaultTCPMSS).IsZero());
diff --git a/net/quic/congestion_control/tcp_cubic_sender_packets_test.cc b/net/quic/congestion_control/tcp_cubic_sender_packets_test.cc
index 57cda3f..ae277d8a 100644
--- a/net/quic/congestion_control/tcp_cubic_sender_packets_test.cc
+++ b/net/quic/congestion_control/tcp_cubic_sender_packets_test.cc
@@ -928,7 +928,6 @@
 }
 
 TEST_F(TcpCubicSenderPacketsTest, NoPRR) {
-  ValueRestore<bool> old_flag(&FLAGS_quic_allow_noprr, true);
   QuicTime::Delta rtt = QuicTime::Delta::FromMilliseconds(100);
   sender_->rtt_stats_.UpdateRtt(rtt, QuicTime::Delta::Zero(), QuicTime::Zero());
 
@@ -977,15 +976,15 @@
 
   EXPECT_TRUE(
       sender_->TimeUntilSend(QuicTime::Zero(), kDefaultTCPMSS).IsZero());
-  EXPECT_EQ(sender_->PacingRate(kDefaultTCPMSS),
-            QuicBandwidth::FromBytesAndTimeDelta(7 * kDefaultTCPMSS, rtt)
-                .Scale(1.25));
+  EXPECT_EQ(
+      sender_->PacingRate(kDefaultTCPMSS),
+      QuicBandwidth::FromBytesAndTimeDelta(7 * kDefaultTCPMSS, rtt) * 1.25);
   for (QuicPacketCount i = cwnd + 1; i < 1.5 * cwnd; ++i) {
     EXPECT_TRUE(
         sender_->TimeUntilSend(QuicTime::Zero(), i * kDefaultTCPMSS).IsZero());
     EXPECT_EQ(sender_->PacingRate(i * kDefaultTCPMSS),
-              QuicBandwidth::FromBytesAndTimeDelta(cwnd * kDefaultTCPMSS, rtt)
-                  .Scale(0.75));
+              QuicBandwidth::FromBytesAndTimeDelta(cwnd * kDefaultTCPMSS, rtt) *
+                  0.75);
   }
   EXPECT_FALSE(
       sender_->TimeUntilSend(QuicTime::Zero(), 11 * kDefaultTCPMSS).IsZero());
diff --git a/net/quic/congestion_control/windowed_filter_test.cc b/net/quic/congestion_control/windowed_filter_test.cc
index fd540d0c..c6bf279f 100644
--- a/net/quic/congestion_control/windowed_filter_test.cc
+++ b/net/quic/congestion_control/windowed_filter_test.cc
@@ -65,7 +65,7 @@
               << windowed_max_bw_.GetSecondBest().ToBitsPerSecond() << " "
               << windowed_max_bw_.GetThirdBest().ToBitsPerSecond();
       now = now + QuicTime::Delta::FromMilliseconds(25);
-      bw_sample = bw_sample.Subtract(QuicBandwidth::FromBitsPerSecond(100));
+      bw_sample = bw_sample - QuicBandwidth::FromBitsPerSecond(100);
     }
     EXPECT_EQ(QuicBandwidth::FromBitsPerSecond(900),
               windowed_max_bw_.GetBest());
@@ -150,7 +150,7 @@
   // decreasing.
   for (int i = 0; i < 6; ++i) {
     now = now + QuicTime::Delta::FromMilliseconds(25);
-    bw_sample = bw_sample.Subtract(QuicBandwidth::FromBitsPerSecond(100));
+    bw_sample = bw_sample - QuicBandwidth::FromBitsPerSecond(100);
     windowed_max_bw_.Update(bw_sample, now);
     VLOG(1) << "i: " << i << " sample: " << bw_sample.ToBitsPerSecond()
             << " maxs: "
@@ -193,7 +193,7 @@
   InitializeMaxFilter();
   // BW sample higher than the third-choice max sets that, but nothing else.
   QuicBandwidth bw_sample =
-      windowed_max_bw_.GetThirdBest().Add(QuicBandwidth::FromBitsPerSecond(50));
+      windowed_max_bw_.GetThirdBest() + QuicBandwidth::FromBitsPerSecond(50);
   // Latest sample was recorded at 100ms.
   QuicTime now = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(101);
   windowed_max_bw_.Update(bw_sample, now);
@@ -225,8 +225,8 @@
   InitializeMaxFilter();
   // BW sample higher than the second-choice max sets that and also
   // the third-choice max.
-  QuicBandwidth bw_sample = windowed_max_bw_.GetSecondBest().Add(
-      QuicBandwidth::FromBitsPerSecond(50));
+  QuicBandwidth bw_sample =
+      windowed_max_bw_.GetSecondBest() + QuicBandwidth::FromBitsPerSecond(50);
   // Latest sample was recorded at 100ms.
   QuicTime now = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(101);
   windowed_max_bw_.Update(bw_sample, now);
@@ -257,7 +257,7 @@
   // BW sample higher than the first-choice max sets that and also
   // the second and third-choice maxs.
   QuicBandwidth bw_sample =
-      windowed_max_bw_.GetBest().Add(QuicBandwidth::FromBitsPerSecond(50));
+      windowed_max_bw_.GetBest() + QuicBandwidth::FromBitsPerSecond(50);
   // Latest sample was recorded at 100ms.
   QuicTime now = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(101);
   windowed_max_bw_.Update(bw_sample, now);
@@ -285,7 +285,7 @@
   QuicBandwidth old_third_best = windowed_max_bw_.GetThirdBest();
   QuicBandwidth old_second_best = windowed_max_bw_.GetSecondBest();
   QuicBandwidth bw_sample =
-      old_third_best.Subtract(QuicBandwidth::FromBitsPerSecond(50));
+      old_third_best - QuicBandwidth::FromBitsPerSecond(50);
   // Best max sample was recorded at 25ms, so expiry time is 124ms.
   QuicTime now = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(125);
   windowed_max_bw_.Update(bw_sample, now);
@@ -311,7 +311,7 @@
   InitializeMaxFilter();
   QuicBandwidth old_third_best = windowed_max_bw_.GetThirdBest();
   QuicBandwidth bw_sample =
-      old_third_best.Subtract(QuicBandwidth::FromBitsPerSecond(50));
+      old_third_best - QuicBandwidth::FromBitsPerSecond(50);
   // Second best max sample was recorded at 75ms, so expiry time is 174ms.
   QuicTime now = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(175);
   windowed_max_bw_.Update(bw_sample, now);
@@ -339,8 +339,8 @@
 
 TEST_F(WindowedFilterTest, ExpireAllMaxs) {
   InitializeMaxFilter();
-  QuicBandwidth bw_sample = windowed_max_bw_.GetThirdBest().Subtract(
-      QuicBandwidth::FromBitsPerSecond(50));
+  QuicBandwidth bw_sample =
+      windowed_max_bw_.GetThirdBest() - QuicBandwidth::FromBitsPerSecond(50);
   // Third best max sample was recorded at 100ms, so expiry time is 199ms.
   QuicTime now = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(200);
   windowed_max_bw_.Update(bw_sample, now);
diff --git a/net/quic/crypto/crypto_handshake_message.cc b/net/quic/crypto/crypto_handshake_message.cc
index aef8dbf..b07eac8 100644
--- a/net/quic/crypto/crypto_handshake_message.cc
+++ b/net/quic/crypto/crypto_handshake_message.cc
@@ -28,23 +28,29 @@
     : tag_(other.tag_),
       tag_value_map_(other.tag_value_map_),
       minimum_size_(other.minimum_size_) {
-  // Don't copy serialized_. scoped_ptr doesn't have a copy constructor.
+  // Don't copy serialized_. unique_ptr doesn't have a copy constructor.
   // The new object can lazily reconstruct serialized_.
 }
 
+CryptoHandshakeMessage::CryptoHandshakeMessage(CryptoHandshakeMessage&& other) =
+    default;
+
 CryptoHandshakeMessage::~CryptoHandshakeMessage() {}
 
 CryptoHandshakeMessage& CryptoHandshakeMessage::operator=(
     const CryptoHandshakeMessage& other) {
   tag_ = other.tag_;
   tag_value_map_ = other.tag_value_map_;
-  // Don't copy serialized_. scoped_ptr doesn't have an assignment operator.
+  // Don't copy serialized_. unique_ptr doesn't have an assignment operator.
   // However, invalidate serialized_.
   serialized_.reset();
   minimum_size_ = other.minimum_size_;
   return *this;
 }
 
+CryptoHandshakeMessage& CryptoHandshakeMessage::operator=(
+    CryptoHandshakeMessage&& other) = default;
+
 void CryptoHandshakeMessage::Clear() {
   tag_ = 0;
   tag_value_map_.clear();
diff --git a/net/quic/crypto/crypto_handshake_message.h b/net/quic/crypto/crypto_handshake_message.h
index 6e4da16..fc98754 100644
--- a/net/quic/crypto/crypto_handshake_message.h
+++ b/net/quic/crypto/crypto_handshake_message.h
@@ -25,9 +25,11 @@
  public:
   CryptoHandshakeMessage();
   CryptoHandshakeMessage(const CryptoHandshakeMessage& other);
+  CryptoHandshakeMessage(CryptoHandshakeMessage&& other);
   ~CryptoHandshakeMessage();
 
   CryptoHandshakeMessage& operator=(const CryptoHandshakeMessage& other);
+  CryptoHandshakeMessage& operator=(CryptoHandshakeMessage&& other);
 
   // Clears state.
   void Clear();
diff --git a/net/quic/crypto/crypto_handshake_message_test.cc b/net/quic/crypto/crypto_handshake_message_test.cc
index e8a5e4f9..7197174 100644
--- a/net/quic/crypto/crypto_handshake_message_test.cc
+++ b/net/quic/crypto/crypto_handshake_message_test.cc
@@ -13,37 +13,108 @@
 namespace {
 
 TEST(CryptoHandshakeMessageTest, DebugString) {
+  const char* str = "SHLO<\n>";
+
   CryptoHandshakeMessage message;
   message.set_tag(kSHLO);
-  EXPECT_EQ("SHLO<\n>", message.DebugString());
+  EXPECT_EQ(str, message.DebugString());
+
+  // Test copy
+  CryptoHandshakeMessage message2(message);
+  EXPECT_EQ(str, message2.DebugString());
+
+  // Test move
+  CryptoHandshakeMessage message3(std::move(message));
+  EXPECT_EQ(str, message3.DebugString());
+
+  // Test assign
+  CryptoHandshakeMessage message4 = message3;
+  EXPECT_EQ(str, message4.DebugString());
+
+  // Test move-assign
+  CryptoHandshakeMessage message5 = std::move(message3);
+  EXPECT_EQ(str, message5.DebugString());
 }
 
 TEST(CryptoHandshakeMessageTest, DebugStringWithUintVector) {
+  const char* str =
+      "REJ <\n  RREJ: "
+      "SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE,"
+      "CLIENT_NONCE_NOT_UNIQUE_FAILURE\n>";
+
   CryptoHandshakeMessage message;
   message.set_tag(kREJ);
   std::vector<uint32_t> reasons = {
       SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE,
       CLIENT_NONCE_NOT_UNIQUE_FAILURE};
   message.SetVector(kRREJ, reasons);
-  EXPECT_EQ(
-      "REJ <\n  RREJ: "
-      "SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE,"
-      "CLIENT_NONCE_NOT_UNIQUE_FAILURE\n>",
-      message.DebugString());
+  EXPECT_EQ(str, message.DebugString());
+
+  // Test copy
+  CryptoHandshakeMessage message2(message);
+  EXPECT_EQ(str, message2.DebugString());
+
+  // Test move
+  CryptoHandshakeMessage message3(std::move(message));
+  EXPECT_EQ(str, message3.DebugString());
+
+  // Test assign
+  CryptoHandshakeMessage message4 = message3;
+  EXPECT_EQ(str, message4.DebugString());
+
+  // Test move-assign
+  CryptoHandshakeMessage message5 = std::move(message3);
+  EXPECT_EQ(str, message5.DebugString());
 }
 
 TEST(CryptoHandshakeMessageTest, DebugStringWithTagVector) {
+  const char* str = "CHLO<\n  COPT: 'TBBR','PAD ','BYTE'\n>";
+
   CryptoHandshakeMessage message;
   message.set_tag(kCHLO);
   message.SetVector(kCOPT, QuicTagVector{kTBBR, kPAD, kBYTE});
-  EXPECT_EQ("CHLO<\n  COPT: 'TBBR','PAD ','BYTE'\n>", message.DebugString());
+  EXPECT_EQ(str, message.DebugString());
+
+  // Test copy
+  CryptoHandshakeMessage message2(message);
+  EXPECT_EQ(str, message2.DebugString());
+
+  // Test move
+  CryptoHandshakeMessage message3(std::move(message));
+  EXPECT_EQ(str, message3.DebugString());
+
+  // Test assign
+  CryptoHandshakeMessage message4 = message3;
+  EXPECT_EQ(str, message4.DebugString());
+
+  // Test move-assign
+  CryptoHandshakeMessage message5 = std::move(message3);
+  EXPECT_EQ(str, message5.DebugString());
 }
 
 TEST(CryptoHandshakeMessageTest, ServerDesignatedConnectionId) {
+  const char* str = "SREJ<\n  RCID: 18364758544493064720\n>";
+
   CryptoHandshakeMessage message;
   message.set_tag(kSREJ);
   message.SetValue(kRCID, UINT64_C(18364758544493064720));
-  EXPECT_EQ("SREJ<\n  RCID: 18364758544493064720\n>", message.DebugString());
+  EXPECT_EQ(str, message.DebugString());
+
+  // Test copy
+  CryptoHandshakeMessage message2(message);
+  EXPECT_EQ(str, message2.DebugString());
+
+  // Test move
+  CryptoHandshakeMessage message3(std::move(message));
+  EXPECT_EQ(str, message3.DebugString());
+
+  // Test assign
+  CryptoHandshakeMessage message4 = message3;
+  EXPECT_EQ(str, message4.DebugString());
+
+  // Test move-assign
+  CryptoHandshakeMessage message5 = std::move(message3);
+  EXPECT_EQ(str, message5.DebugString());
 }
 
 }  // namespace
diff --git a/net/quic/crypto/proof_test.cc b/net/quic/crypto/proof_test.cc
index a343cf66..d2669a84 100644
--- a/net/quic/crypto/proof_test.cc
+++ b/net/quic/crypto/proof_test.cc
@@ -239,7 +239,7 @@
 }
 
 TEST_P(ProofTest, UseAfterFree) {
-  ProofSource* source = CryptoTestUtils::ProofSourceForTesting();
+  std::unique_ptr<ProofSource> source(CryptoTestUtils::ProofSourceForTesting());
 
   const string server_config = "server config bytes";
   const string hostname = "test.example.com";
@@ -254,7 +254,7 @@
 
   // Make sure we can safely access results after deleting where they came from.
   EXPECT_FALSE(chain->HasOneRef());
-  delete source;
+  source = nullptr;
   EXPECT_TRUE(chain->HasOneRef());
 
   EXPECT_FALSE(chain->certs.empty());
diff --git a/net/quic/crypto/quic_crypto_client_config.cc b/net/quic/crypto/quic_crypto_client_config.cc
index b31a737..50eed98 100644
--- a/net/quic/crypto/quic_crypto_client_config.cc
+++ b/net/quic/crypto/quic_crypto_client_config.cc
@@ -54,8 +54,9 @@
 
 }  // namespace
 
-QuicCryptoClientConfig::QuicCryptoClientConfig(ProofVerifier* proof_verifier)
-    : proof_verifier_(proof_verifier), disable_ecdsa_(false) {
+QuicCryptoClientConfig::QuicCryptoClientConfig(
+    std::unique_ptr<ProofVerifier> proof_verifier)
+    : proof_verifier_(std::move(proof_verifier)), disable_ecdsa_(false) {
   DCHECK(proof_verifier_.get());
   SetDefaults();
 }
diff --git a/net/quic/crypto/quic_crypto_client_config.h b/net/quic/crypto/quic_crypto_client_config.h
index 6a7a5c99..f4662872 100644
--- a/net/quic/crypto/quic_crypto_client_config.h
+++ b/net/quic/crypto/quic_crypto_client_config.h
@@ -194,7 +194,8 @@
     DISALLOW_COPY_AND_ASSIGN(CachedState);
   };
 
-  explicit QuicCryptoClientConfig(ProofVerifier* proof_verifier);
+  explicit QuicCryptoClientConfig(
+      std::unique_ptr<ProofVerifier> proof_verifier);
   ~QuicCryptoClientConfig();
 
   // LookupOrCreate returns a CachedState for the given |server_id|. If no such
diff --git a/net/quic/crypto/quic_crypto_server_config.cc b/net/quic/crypto/quic_crypto_server_config.cc
index 4f0e1144..11b96ffd 100644
--- a/net/quic/crypto/quic_crypto_server_config.cc
+++ b/net/quic/crypto/quic_crypto_server_config.cc
@@ -211,14 +211,14 @@
 QuicCryptoServerConfig::QuicCryptoServerConfig(
     StringPiece source_address_token_secret,
     QuicRandom* server_nonce_entropy,
-    ProofSource* proof_source)
+    std::unique_ptr<ProofSource> proof_source)
     : replay_protection_(true),
       chlo_multiplier_(kMultiplier),
       configs_lock_(),
       primary_config_(nullptr),
       next_config_promotion_time_(QuicWallTime::Zero()),
       server_nonce_strike_register_lock_(),
-      proof_source_(proof_source),
+      proof_source_(std::move(proof_source)),
       strike_register_no_startup_period_(false),
       strike_register_max_entries_(1 << 10),
       strike_register_window_secs_(600),
@@ -531,6 +531,13 @@
   }
 
   if (result->error_code == QUIC_NO_ERROR) {
+    if (FLAGS_quic_refresh_proof && version > QUIC_VERSION_30) {
+      // QUIC v31 and above require a new proof for each CHLO so clear the
+      // existing proof, if any.
+      crypto_proof->chain = nullptr;
+      crypto_proof->signature = "";
+      crypto_proof->cert_sct = "";
+    }
     EvaluateClientHello(server_ip, version, primary_orbit, requested_config,
                         primary_config, crypto_proof, result, done_cb);
   } else {
@@ -611,6 +618,7 @@
   DCHECK(proof_source_.get());
   string chlo_hash;
   CryptoUtils::HashHandshakeMessage(client_hello, &chlo_hash);
+  // No need to get a new proof if one was already generated.
   if (!crypto_proof->chain &&
       !proof_source_->GetProof(
           server_ip, info.sni.as_string(), primary_config->serialized, version,
@@ -1062,7 +1070,13 @@
     string serialized_config = primary_config->serialized;
     string chlo_hash;
     CryptoUtils::HashHandshakeMessage(client_hello, &chlo_hash);
-    if (!proof_source_->GetProof(
+    bool need_proof = true;
+    if (FLAGS_quic_refresh_proof) {
+      need_proof = !crypto_proof->chain;
+    }
+    // No need to get a new proof if one was already generated.
+    if (need_proof &&
+        !proof_source_->GetProof(
             server_ip, info->sni.as_string(), serialized_config, version,
             chlo_hash, x509_ecdsa_supported, &crypto_proof->chain,
             &crypto_proof->signature, &crypto_proof->cert_sct)) {
@@ -1219,6 +1233,121 @@
   return true;
 }
 
+void QuicCryptoServerConfig::BuildServerConfigUpdateMessage(
+    QuicVersion version,
+    StringPiece chlo_hash,
+    const SourceAddressTokens& previous_source_address_tokens,
+    const IPAddress& server_ip,
+    const IPAddress& client_ip,
+    const QuicClock* clock,
+    QuicRandom* rand,
+    QuicCompressedCertsCache* compressed_certs_cache,
+    const QuicCryptoNegotiatedParameters& params,
+    const CachedNetworkParameters* cached_network_params,
+    std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const {
+  string serialized;
+  string source_address_token;
+  const CommonCertSets* common_cert_sets;
+  {
+    base::AutoLock locked(configs_lock_);
+    serialized = primary_config_->serialized;
+    common_cert_sets = primary_config_->common_cert_sets;
+    source_address_token = NewSourceAddressToken(
+        *primary_config_, previous_source_address_tokens, client_ip, rand,
+        clock->WallNow(), cached_network_params);
+  }
+
+  CryptoHandshakeMessage message;
+  message.set_tag(kSCUP);
+  message.SetStringPiece(kSCFG, serialized);
+  message.SetStringPiece(kSourceAddressTokenTag, source_address_token);
+
+  std::unique_ptr<BuildServerConfigUpdateMessageProofSourceCallback>
+      proof_source_cb(new BuildServerConfigUpdateMessageProofSourceCallback(
+          this, version, compressed_certs_cache, common_cert_sets, params,
+          std::move(message), std::move(cb)));
+
+  if (FLAGS_quic_use_hash_in_scup) {
+    proof_source_->GetProof(server_ip, params.sni, serialized, version,
+                            chlo_hash, params.x509_ecdsa_supported,
+                            std::move(proof_source_cb));
+  } else {
+    proof_source_->GetProof(server_ip, params.sni, serialized, version,
+                            params.client_nonce, params.x509_ecdsa_supported,
+                            std::move(proof_source_cb));
+  }
+}
+
+QuicCryptoServerConfig::BuildServerConfigUpdateMessageProofSourceCallback::
+    ~BuildServerConfigUpdateMessageProofSourceCallback() {}
+
+QuicCryptoServerConfig::BuildServerConfigUpdateMessageProofSourceCallback::
+    BuildServerConfigUpdateMessageProofSourceCallback(
+        const QuicCryptoServerConfig* config,
+        QuicVersion version,
+        QuicCompressedCertsCache* compressed_certs_cache,
+        const CommonCertSets* common_cert_sets,
+        const QuicCryptoNegotiatedParameters& params,
+        CryptoHandshakeMessage message,
+        std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb)
+    : config_(config),
+      version_(version),
+      compressed_certs_cache_(compressed_certs_cache),
+      common_cert_sets_(common_cert_sets),
+      client_common_set_hashes_(params.client_common_set_hashes),
+      client_cached_cert_hashes_(params.client_cached_cert_hashes),
+      sct_supported_by_client_(params.sct_supported_by_client),
+      message_(std::move(message)),
+      cb_(std::move(cb)) {}
+
+void QuicCryptoServerConfig::BuildServerConfigUpdateMessageProofSourceCallback::
+    Run(bool ok,
+        const scoped_refptr<ProofSource::Chain>& chain,
+        const string& signature,
+        const string& leaf_cert_sct) {
+  config_->FinishBuildServerConfigUpdateMessage(
+      version_, compressed_certs_cache_, common_cert_sets_,
+      client_common_set_hashes_, client_cached_cert_hashes_,
+      sct_supported_by_client_, ok, chain, signature, leaf_cert_sct,
+      std::move(message_), std::move(cb_));
+}
+
+void QuicCryptoServerConfig::FinishBuildServerConfigUpdateMessage(
+    QuicVersion version,
+    QuicCompressedCertsCache* compressed_certs_cache,
+    const CommonCertSets* common_cert_sets,
+    const string& client_common_set_hashes,
+    const string& client_cached_cert_hashes,
+    bool sct_supported_by_client,
+    bool ok,
+    const scoped_refptr<ProofSource::Chain>& chain,
+    const string& signature,
+    const string& leaf_cert_sct,
+    CryptoHandshakeMessage message,
+    std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const {
+  if (!ok) {
+    cb->Run(false, message);
+    return;
+  }
+
+  const string compressed =
+      CompressChain(compressed_certs_cache, chain, client_common_set_hashes,
+                    client_cached_cert_hashes, common_cert_sets);
+
+  message.SetStringPiece(kCertificateTag, compressed);
+  message.SetStringPiece(kPROF, signature);
+  if (sct_supported_by_client && version > QUIC_VERSION_29 &&
+      enable_serving_sct_) {
+    if (leaf_cert_sct.empty()) {
+      DLOG(WARNING) << "SCT is expected but it is empty.";
+    } else {
+      message.SetStringPiece(kCertificateSCTTag, leaf_cert_sct);
+    }
+  }
+
+  cb->Run(true, message);
+}
+
 void QuicCryptoServerConfig::BuildRejection(
     QuicVersion version,
     const Config& config,
@@ -1311,12 +1440,12 @@
   }
 }
 
-const string QuicCryptoServerConfig::CompressChain(
+string QuicCryptoServerConfig::CompressChain(
     QuicCompressedCertsCache* compressed_certs_cache,
     const scoped_refptr<ProofSource::Chain>& chain,
     const string& client_common_set_hashes,
     const string& client_cached_cert_hashes,
-    const CommonCertSets* common_sets) const {
+    const CommonCertSets* common_sets) {
   // Check whether the compressed certs is available in the cache.
   DCHECK(compressed_certs_cache);
   const string* cached_value = compressed_certs_cache->GetCompressedCert(
diff --git a/net/quic/crypto/quic_crypto_server_config.h b/net/quic/crypto/quic_crypto_server_config.h
index a43bd78..4b7985f 100644
--- a/net/quic/crypto/quic_crypto_server_config.h
+++ b/net/quic/crypto/quic_crypto_server_config.h
@@ -115,6 +115,18 @@
   DISALLOW_COPY_AND_ASSIGN(ValidateClientHelloResultCallback);
 };
 
+// Callback used to receive the results of a call to
+// BuildServerConfigUpdateMessage.
+class BuildServerConfigUpdateMessageResultCallback {
+ public:
+  BuildServerConfigUpdateMessageResultCallback() = default;
+  virtual ~BuildServerConfigUpdateMessageResultCallback() {}
+  virtual void Run(bool ok, const CryptoHandshakeMessage& message) = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BuildServerConfigUpdateMessageResultCallback);
+};
+
 // QuicCryptoServerConfig contains the crypto configuration of a QUIC server.
 // Unlike a client, a QUIC server can have multiple configurations active in
 // order to support clients resuming with a previous configuration.
@@ -159,7 +171,7 @@
   //     takes ownership of |proof_source|.
   QuicCryptoServerConfig(base::StringPiece source_address_token_secret,
                          QuicRandom* server_nonce_entropy,
-                         ProofSource* proof_source);
+                         std::unique_ptr<ProofSource> proof_source);
   ~QuicCryptoServerConfig();
 
   // TESTING is a magic parameter for passing to the constructor in tests.
@@ -297,6 +309,8 @@
   // filled |out|.
   //
   // |cached_network_params| is optional, and can be nullptr.
+  //
+  // TODO(gredner): remove this when --FLAGS_enable_async_get_proof is removed.
   bool BuildServerConfigUpdateMessage(
       QuicVersion version,
       base::StringPiece chlo_hash,
@@ -310,6 +324,29 @@
       const CachedNetworkParameters* cached_network_params,
       CryptoHandshakeMessage* out) const;
 
+  // BuildServerConfigUpdateMessage invokes |cb| with a SCUP message containing
+  // the current primary config, an up to date source-address token, and cert
+  // chain and proof in the case of secure QUIC. Passes true to |cb| if the
+  // message was generated successfully, and false otherwise.  This method
+  // assumes ownership of |cb|.
+  //
+  // |cached_network_params| is optional, and can be nullptr.
+  //
+  // TODO(gredner): This method is an async version of the above.  The
+  // synchronous version will eventually be removed.
+  void BuildServerConfigUpdateMessage(
+      QuicVersion version,
+      base::StringPiece chlo_hash,
+      const SourceAddressTokens& previous_source_address_tokens,
+      const IPAddress& server_ip,
+      const IPAddress& client_ip,
+      const QuicClock* clock,
+      QuicRandom* rand,
+      QuicCompressedCertsCache* compressed_certs_cache,
+      const QuicCryptoNegotiatedParameters& params,
+      const CachedNetworkParameters* cached_network_params,
+      std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const;
+
   // SetEphemeralKeySource installs an object that can cache ephemeral keys for
   // a short period of time. This object takes ownership of
   // |ephemeral_key_source|. If not set then ephemeral keys will be generated
@@ -497,12 +534,12 @@
   // sets known locally and |client_common_set_hashes| contains the hashes of
   // the common sets known to the peer. |client_cached_cert_hashes| contains
   // 64-bit, FNV-1a hashes of certificates that the peer already possesses.
-  const std::string CompressChain(
+  static std::string CompressChain(
       QuicCompressedCertsCache* compressed_certs_cache,
       const scoped_refptr<ProofSource::Chain>& chain,
       const std::string& client_common_set_hashes,
       const std::string& client_cached_cert_hashes,
-      const CommonCertSets* common_sets) const;
+      const CommonCertSets* common_sets);
 
   // ParseConfigProtobuf parses the given config protobuf and returns a
   // scoped_refptr<Config> if successful. The caller adopts the reference to the
@@ -583,6 +620,61 @@
                         bool* x509_supported,
                         bool* x509_ecdsa_supported) const;
 
+  // Callback to receive the results of ProofSource::GetProof.  Note: this
+  // callback has no cancellation support, since the lifetime of the ProofSource
+  // is controlled by this object via unique ownership.  If that ownership
+  // stricture changes, this decision may need to be revisited.
+  class BuildServerConfigUpdateMessageProofSourceCallback
+      : public ProofSource::Callback {
+   public:
+    BuildServerConfigUpdateMessageProofSourceCallback(
+        const BuildServerConfigUpdateMessageProofSourceCallback&) = delete;
+    ~BuildServerConfigUpdateMessageProofSourceCallback() override;
+    void operator=(const BuildServerConfigUpdateMessageProofSourceCallback&) =
+        delete;
+    BuildServerConfigUpdateMessageProofSourceCallback(
+        const QuicCryptoServerConfig* config,
+        QuicVersion version,
+        QuicCompressedCertsCache* compressed_certs_cache,
+        const CommonCertSets* common_cert_sets,
+        const QuicCryptoNegotiatedParameters& params,
+        CryptoHandshakeMessage message,
+        std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb);
+
+    void Run(bool ok,
+             const scoped_refptr<ProofSource::Chain>& chain,
+             const std::string& signature,
+             const std::string& leaf_cert_sct) override;
+
+   private:
+    const QuicCryptoServerConfig* config_;
+    const QuicVersion version_;
+    QuicCompressedCertsCache* compressed_certs_cache_;
+    const CommonCertSets* common_cert_sets_;
+    const std::string client_common_set_hashes_;
+    const std::string client_cached_cert_hashes_;
+    const bool sct_supported_by_client_;
+    CryptoHandshakeMessage message_;
+    std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb_;
+  };
+
+  // Invoked by BuildServerConfigUpdateMessageProofSourceCallback::RunImpl once
+  // the proof has been acquired.  Finishes building the server config update
+  // message and invokes |cb|.
+  void FinishBuildServerConfigUpdateMessage(
+      QuicVersion version,
+      QuicCompressedCertsCache* compressed_certs_cache,
+      const CommonCertSets* common_cert_sets,
+      const std::string& client_common_set_hashes,
+      const std::string& client_cached_cert_hashes,
+      bool sct_supported_by_client,
+      bool ok,
+      const scoped_refptr<ProofSource::Chain>& chain,
+      const std::string& signature,
+      const std::string& leaf_cert_sct,
+      CryptoHandshakeMessage message,
+      std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const;
+
   // replay_protection_ controls whether the server enforces that handshakes
   // aren't replays.
   bool replay_protection_;
diff --git a/net/quic/crypto/quic_crypto_server_config_test.cc b/net/quic/crypto/quic_crypto_server_config_test.cc
index f1dab3a..f6bda82a 100644
--- a/net/quic/crypto/quic_crypto_server_config_test.cc
+++ b/net/quic/crypto/quic_crypto_server_config_test.cc
@@ -113,8 +113,8 @@
   vector<string> certs = {"testcert"};
   scoped_refptr<ProofSource::Chain> chain(new ProofSource::Chain(certs));
 
-  string compressed =
-      peer.CompressChain(&compressed_certs_cache, chain, "", "", nullptr);
+  string compressed = QuicCryptoServerConfigPeer::CompressChain(
+      &compressed_certs_cache, chain, "", "", nullptr);
 
   EXPECT_EQ(compressed_certs_cache.Size(), 1u);
 }
@@ -134,13 +134,13 @@
   string common_certs = "";
   string cached_certs = "";
 
-  string compressed = peer.CompressChain(&compressed_certs_cache, chain,
-                                         common_certs, cached_certs, nullptr);
+  string compressed = QuicCryptoServerConfigPeer::CompressChain(
+      &compressed_certs_cache, chain, common_certs, cached_certs, nullptr);
   EXPECT_EQ(compressed_certs_cache.Size(), 1u);
 
   // Compress the same certs, should use cache if available.
-  string compressed2 = peer.CompressChain(&compressed_certs_cache, chain,
-                                          common_certs, cached_certs, nullptr);
+  string compressed2 = QuicCryptoServerConfigPeer::CompressChain(
+      &compressed_certs_cache, chain, common_certs, cached_certs, nullptr);
   EXPECT_EQ(compressed, compressed2);
   EXPECT_EQ(compressed_certs_cache.Size(), 1u);
 }
@@ -161,15 +161,15 @@
   string common_certs = "";
   string cached_certs = "";
 
-  string compressed = peer.CompressChain(&compressed_certs_cache, chain,
-                                         common_certs, cached_certs, nullptr);
+  string compressed = QuicCryptoServerConfigPeer::CompressChain(
+      &compressed_certs_cache, chain, common_certs, cached_certs, nullptr);
   EXPECT_EQ(compressed_certs_cache.Size(), 1u);
 
   // Compress a similar certs which only differs in the chain.
   scoped_refptr<ProofSource::Chain> chain2(new ProofSource::Chain(certs));
 
-  string compressed2 = peer.CompressChain(&compressed_certs_cache, chain2,
-                                          common_certs, cached_certs, nullptr);
+  string compressed2 = QuicCryptoServerConfigPeer::CompressChain(
+      &compressed_certs_cache, chain2, common_certs, cached_certs, nullptr);
   EXPECT_EQ(compressed_certs_cache.Size(), 2u);
 
   // Compress a similar certs which only differs in common certs field.
@@ -178,9 +178,9 @@
       CryptoTestUtils::MockCommonCertSets(certs[0], set_hash, 1));
   StringPiece different_common_certs(reinterpret_cast<const char*>(&set_hash),
                                      sizeof(set_hash));
-  string compressed3 = peer.CompressChain(&compressed_certs_cache, chain,
-                                          different_common_certs.as_string(),
-                                          cached_certs, common_sets.get());
+  string compressed3 = QuicCryptoServerConfigPeer::CompressChain(
+      &compressed_certs_cache, chain, different_common_certs.as_string(),
+      cached_certs, common_sets.get());
   EXPECT_EQ(compressed_certs_cache.Size(), 3u);
 }
 
diff --git a/net/quic/p2p/quic_p2p_crypto_config.cc b/net/quic/p2p/quic_p2p_crypto_config.cc
deleted file mode 100644
index 6f32056..0000000
--- a/net/quic/p2p/quic_p2p_crypto_config.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/quic/p2p/quic_p2p_crypto_config.h"
-
-#include "net/quic/crypto/crypto_handshake.h"
-#include "net/quic/crypto/crypto_utils.h"
-
-namespace net {
-
-QuicP2PCryptoConfig::QuicP2PCryptoConfig(const std::string& shared_key)
-    : shared_key_(shared_key) {}
-
-QuicP2PCryptoConfig::~QuicP2PCryptoConfig() {}
-
-bool QuicP2PCryptoConfig::GetNegotiatedParameters(
-    Perspective perspective,
-    QuicCryptoNegotiatedParameters* out_params) {
-  out_params->forward_secure_premaster_secret = shared_key_;
-  out_params->aead = aead_;
-  out_params->hkdf_input_suffix = hkdf_input_suffix_;
-
-  std::string hkdf_input;
-  const size_t label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1;
-  hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size());
-  hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel, label_len);
-  hkdf_input.append(out_params->hkdf_input_suffix);
-
-  if (!CryptoUtils::DeriveKeys(
-          out_params->forward_secure_premaster_secret, out_params->aead,
-          out_params->client_nonce, out_params->server_nonce, hkdf_input,
-          perspective, CryptoUtils::Diversification::Never(),
-          &out_params->forward_secure_crypters, &out_params->subkey_secret)) {
-    return false;
-  }
-
-  return true;
-}
-
-}  // namespace net
diff --git a/net/quic/p2p/quic_p2p_crypto_config.h b/net/quic/p2p/quic_p2p_crypto_config.h
deleted file mode 100644
index 786a7e11..0000000
--- a/net/quic/p2p/quic_p2p_crypto_config.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_QUIC_P2P_QUIC_P2P_CRYPTO_CONFIG_H_
-#define NET_QUIC_P2P_QUIC_P2P_CRYPTO_CONFIG_H_
-
-#include <string>
-
-#include "net/quic/crypto/crypto_protocol.h"
-
-namespace net {
-
-struct QuicCryptoNegotiatedParameters;
-
-// Crypto configuration for P2P sessions.
-class NET_EXPORT QuicP2PCryptoConfig {
- public:
-  // |shared_key| specifies a key that's used to generate crypto keys. The key
-  // must be exchanged out-of-bound when the P2P transport is negotiated.
-  explicit QuicP2PCryptoConfig(const std::string& shared_key);
-  ~QuicP2PCryptoConfig();
-
-  void set_aead(QuicTag aead) { aead_ = aead; }
-
-  // Sets suffix for HKDF. E.g. can be channel name to make sure different
-  // channels use different encryption keys derived from the same |shared_key|.
-  // Empty by default.
-  void set_hkdf_input_suffix(const std::string& hkdf_input_suffix) {
-    hkdf_input_suffix_ = hkdf_input_suffix;
-  }
-
-  bool GetNegotiatedParameters(Perspective perspective,
-                               QuicCryptoNegotiatedParameters* out_params);
-
- private:
-  QuicTag aead_ = kAESG;
-  std::string shared_key_;
-  std::string hkdf_input_suffix_;
-};
-
-}  // namespace net
-
-#endif  // NET_QUIC_P2P_QUIC_P2P_CRYPTO_CONFIG_H_
diff --git a/net/quic/p2p/quic_p2p_crypto_stream.cc b/net/quic/p2p/quic_p2p_crypto_stream.cc
deleted file mode 100644
index f5acb98b..0000000
--- a/net/quic/p2p/quic_p2p_crypto_stream.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/quic/p2p/quic_p2p_crypto_stream.h"
-
-#include "crypto/hkdf.h"
-#include "net/quic/crypto/crypto_handshake_message.h"
-#include "net/quic/crypto/quic_decrypter.h"
-#include "net/quic/crypto/quic_encrypter.h"
-#include "net/quic/quic_session.h"
-
-namespace net {
-
-QuicP2PCryptoStream::QuicP2PCryptoStream(QuicSession* session,
-                                         const QuicP2PCryptoConfig& config)
-    : QuicCryptoStream(session), config_(config) {}
-
-QuicP2PCryptoStream::~QuicP2PCryptoStream() {}
-
-bool QuicP2PCryptoStream::Connect() {
-  if (!config_.GetNegotiatedParameters(session()->connection()->perspective(),
-                                       &crypto_negotiated_params_)) {
-    return false;
-  }
-
-  CrypterPair* crypters = &crypto_negotiated_params_.forward_secure_crypters;
-
-  session()->connection()->SetEncrypter(ENCRYPTION_FORWARD_SECURE,
-                                        crypters->encrypter.release());
-  session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
-  session()->connection()->SetAlternativeDecrypter(
-      ENCRYPTION_FORWARD_SECURE, crypters->decrypter.release(),
-      false /* don't latch */);
-  encryption_established_ = true;
-  session()->OnCryptoHandshakeEvent(QuicSession::ENCRYPTION_FIRST_ESTABLISHED);
-  session()->OnConfigNegotiated();
-  session()->connection()->OnHandshakeComplete();
-  handshake_confirmed_ = true;
-  session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
-  if (session()->connection()->perspective() == Perspective::IS_CLIENT) {
-    // Send a ping from the client to the server to satisfy QUIC's version
-    // negotiation.
-    session()->connection()->SendPing();
-  }
-  return true;
-}
-
-}  // namespace net
diff --git a/net/quic/p2p/quic_p2p_crypto_stream.h b/net/quic/p2p/quic_p2p_crypto_stream.h
deleted file mode 100644
index 185a8f8..0000000
--- a/net/quic/p2p/quic_p2p_crypto_stream.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_QUIC_P2P_QUIC_P2P_CRYPTO_STREAM_H_
-#define NET_QUIC_P2P_QUIC_P2P_CRYPTO_STREAM_H_
-
-#include "base/macros.h"
-#include "net/quic/p2p/quic_p2p_crypto_config.h"
-#include "net/quic/quic_crypto_stream.h"
-
-namespace net {
-
-class QuicSession;
-
-class NET_EXPORT_PRIVATE QuicP2PCryptoStream : public QuicCryptoStream {
- public:
-  QuicP2PCryptoStream(QuicSession* session, const QuicP2PCryptoConfig& config);
-  ~QuicP2PCryptoStream() override;
-
-  bool Connect();
-
- private:
-  QuicP2PCryptoConfig config_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicP2PCryptoStream);
-};
-
-}  // namespace net
-
-#endif  // NET_QUIC_P2P_QUIC_P2P_CRYPTO_STREAM_H_
diff --git a/net/quic/p2p/quic_p2p_session.cc b/net/quic/p2p/quic_p2p_session.cc
deleted file mode 100644
index ca38851c..0000000
--- a/net/quic/p2p/quic_p2p_session.cc
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/quic/p2p/quic_p2p_session.h"
-
-#include <utility>
-
-#include "base/callback_helpers.h"
-#include "net/base/io_buffer.h"
-#include "net/base/ip_address.h"
-#include "net/base/net_errors.h"
-#include "net/quic/p2p/quic_p2p_crypto_stream.h"
-#include "net/quic/quic_connection.h"
-#include "net/socket/socket.h"
-
-namespace net {
-
-QuicP2PSession::QuicP2PSession(const QuicConfig& config,
-                               const QuicP2PCryptoConfig& crypto_config,
-                               std::unique_ptr<QuicConnection> connection,
-                               std::unique_ptr<Socket> socket)
-    : QuicSession(connection.release(), config),
-      socket_(std::move(socket)),
-      crypto_stream_(new QuicP2PCryptoStream(this, crypto_config)),
-      read_buffer_(new IOBuffer(static_cast<size_t>(kMaxPacketSize))) {
-  DCHECK(config.negotiated());
-}
-
-QuicP2PSession::~QuicP2PSession() {}
-
-void QuicP2PSession::Initialize() {
-  QuicSession::Initialize();
-  crypto_stream_->Connect();
-  DoReadLoop(OK);
-}
-
-void QuicP2PSession::SetDelegate(Delegate* delegate) {
-  delegate_ = delegate;
-}
-
-int QuicP2PSession::OnWriteError(int error_code,
-                                 scoped_refptr<StringIOBuffer> packet) {
-  return error_code;
-}
-
-QuicCryptoStream* QuicP2PSession::GetCryptoStream() {
-  return crypto_stream_.get();
-}
-
-QuicP2PStream* QuicP2PSession::CreateIncomingDynamicStream(QuicStreamId id) {
-  QuicP2PStream* stream = new QuicP2PStream(id, this);
-  if (delegate_) {
-    delegate_->OnIncomingStream(stream);
-  }
-  ActivateStream(stream);
-  return stream;
-}
-
-QuicP2PStream* QuicP2PSession::CreateOutgoingDynamicStream(
-    SpdyPriority priority) {
-  QuicP2PStream* stream = new QuicP2PStream(GetNextOutgoingStreamId(), this);
-  if (stream) {
-    ActivateStream(stream);
-  }
-  return stream;
-}
-
-void QuicP2PSession::OnConnectionClosed(QuicErrorCode error,
-                                        const std::string& error_details,
-                                        ConnectionCloseSource source) {
-  QuicSession::OnConnectionClosed(error, error_details, source);
-
-  socket_.reset();
-
-  if (delegate_) {
-    Delegate* delegate = delegate_;
-    delegate_ = nullptr;
-    delegate->OnConnectionClosed(error);
-  }
-}
-
-void QuicP2PSession::DoReadLoop(int result) {
-  while (error() == QUIC_NO_ERROR) {
-    switch (read_state_) {
-      case READ_STATE_DO_READ:
-        CHECK_EQ(result, OK);
-        result = DoRead();
-        break;
-      case READ_STATE_DO_READ_COMPLETE:
-        result = DoReadComplete(result);
-        break;
-      default:
-        NOTREACHED() << "read_state_: " << read_state_;
-        break;
-    }
-
-    if (result < 0)
-      break;
-  }
-}
-
-int QuicP2PSession::DoRead() {
-  DCHECK_EQ(read_state_, READ_STATE_DO_READ);
-  read_state_ = READ_STATE_DO_READ_COMPLETE;
-
-  if (!socket_) {
-    return ERR_SOCKET_NOT_CONNECTED;
-  }
-
-  return socket_->Read(
-      read_buffer_.get(), kMaxPacketSize,
-      base::Bind(&QuicP2PSession::DoReadLoop, base::Unretained(this)));
-}
-
-int QuicP2PSession::DoReadComplete(int result) {
-  DCHECK_EQ(read_state_, READ_STATE_DO_READ_COMPLETE);
-  read_state_ = READ_STATE_DO_READ;
-
-  if (result <= 0) {
-    connection()->CloseConnection(QUIC_PACKET_READ_ERROR, "packet read error",
-                                  ConnectionCloseBehavior::SILENT_CLOSE);
-    return result;
-  }
-
-  QuicReceivedPacket packet(read_buffer_->data(), result, clock_.Now());
-  connection()->ProcessUdpPacket(connection()->self_address(),
-                                 connection()->peer_address(), packet);
-  return OK;
-}
-
-}  // namespace net
diff --git a/net/quic/p2p/quic_p2p_session.h b/net/quic/p2p/quic_p2p_session.h
deleted file mode 100644
index 66c1050a..0000000
--- a/net/quic/p2p/quic_p2p_session.h
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_QUIC_P2P_QUIC_P2P_SESSION_H_
-#define NET_QUIC_P2P_QUIC_P2P_SESSION_H_
-
-#include <memory>
-#include <string>
-
-#include "base/macros.h"
-#include "base/strings/string_piece.h"
-#include "net/base/io_buffer.h"
-#include "net/quic/p2p/quic_p2p_stream.h"
-#include "net/quic/quic_chromium_packet_writer.h"
-#include "net/quic/quic_client_session_base.h"
-#include "net/quic/quic_clock.h"
-#include "net/quic/quic_protocol.h"
-
-namespace net {
-
-class QuicConfig;
-class QuicConnection;
-class QuicP2PCryptoStream;
-class QuicP2PCryptoConfig;
-class Socket;
-class IOBuffer;
-
-// QuicP2PSession represents a QUIC session over peer-to-peer transport
-// specified by |socket|. There is no handshake performed by this class, i.e.
-// the handshake is expected to happen out-of-bound before QuicP2PSession is
-// created. The out-of-bound handshake should generate the following parameters
-// passed to the constructor:
-//   1. Negotiated QuicConfig.
-//   2. Secret key exchanged with the peer on the other end of the |socket|.
-//      This key is passed to the constructor as part of the |crypto_config|.
-class NET_EXPORT QuicP2PSession
-    : public QuicSession,
-      public QuicChromiumPacketWriter::WriteErrorObserver {
- public:
-  class Delegate {
-   public:
-    virtual void OnIncomingStream(QuicP2PStream* stream) = 0;
-
-    virtual void OnConnectionClosed(QuicErrorCode error) = 0;
-  };
-
-  // |config| must be already negotiated. |crypto_config| contains a secret key
-  // shared with the peer.
-  QuicP2PSession(const QuicConfig& config,
-                 const QuicP2PCryptoConfig& crypto_config,
-                 std::unique_ptr<QuicConnection> connection,
-                 std::unique_ptr<Socket> socket);
-  ~QuicP2PSession() override;
-
-  // QuicChromiumPacketWriter::WriteErrorObserver override.
-  int OnWriteError(int error_code,
-                   scoped_refptr<StringIOBuffer> last_packet) override;
-
-  // QuicSession overrides.
-  void Initialize() override;
-  QuicP2PStream* CreateOutgoingDynamicStream(
-      net::SpdyPriority priority) override;
-
-  // QuicConnectionVisitorInterface overrides.
-  void OnConnectionClosed(QuicErrorCode error,
-                          const std::string& error_details,
-                          ConnectionCloseSource source) override;
-
-  void SetDelegate(Delegate* delegate);
-
- protected:
-  // QuicSession overrides.
-  QuicCryptoStream* GetCryptoStream() override;
-  QuicP2PStream* CreateIncomingDynamicStream(QuicStreamId id) override;
-
-  QuicP2PSession* CreateDataStream(QuicStreamId id);
-
- private:
-  enum ReadState {
-    READ_STATE_DO_READ,
-    READ_STATE_DO_READ_COMPLETE,
-  };
-
-  void DoReadLoop(int result);
-  int DoRead();
-  int DoReadComplete(int result);
-
-  std::unique_ptr<Socket> socket_;
-  std::unique_ptr<QuicP2PCryptoStream> crypto_stream_;
-
-  Delegate* delegate_ = nullptr;
-
-  ReadState read_state_ = READ_STATE_DO_READ;
-  scoped_refptr<IOBuffer> read_buffer_;
-
-  // For recording receipt time
-  QuicClock clock_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicP2PSession);
-};
-
-}  // namespace net
-
-#endif  // NET_QUIC_P2P_QUIC_P2P_SESSION_H_
diff --git a/net/quic/p2p/quic_p2p_session_test.cc b/net/quic/p2p/quic_p2p_session_test.cc
deleted file mode 100644
index e3335ba..0000000
--- a/net/quic/p2p/quic_p2p_session_test.cc
+++ /dev/null
@@ -1,409 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/quic/p2p/quic_p2p_session.h"
-
-#include <algorithm>
-#include <deque>
-#include <utility>
-#include <vector>
-
-#include "base/callback_helpers.h"
-#include "base/location.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/quic/crypto/quic_random.h"
-#include "net/quic/p2p/quic_p2p_crypto_config.h"
-#include "net/quic/p2p/quic_p2p_stream.h"
-#include "net/quic/quic_chromium_alarm_factory.h"
-#include "net/quic/quic_chromium_connection_helper.h"
-#include "net/quic/quic_chromium_packet_writer.h"
-#include "net/quic/test_tools/quic_session_peer.h"
-#include "net/socket/socket.h"
-#include "net/test/gtest_util.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using net::test::IsOk;
-
-namespace net {
-
-namespace {
-
-const char kTestSharedKey[] = "Shared key exchanged out of bound.";
-
-class FakeP2PDatagramSocket : public Socket {
- public:
-  FakeP2PDatagramSocket() : weak_factory_(this) {}
-  ~FakeP2PDatagramSocket() override {}
-
-  base::WeakPtr<FakeP2PDatagramSocket> GetWeakPtr() {
-    return weak_factory_.GetWeakPtr();
-  }
-
-  void ConnectWith(FakeP2PDatagramSocket* peer_socket) {
-    peer_socket_ = peer_socket->GetWeakPtr();
-    peer_socket->peer_socket_ = GetWeakPtr();
-  }
-
-  void SetReadError(int error) {
-    read_error_ = error;
-    if (!read_callback_.is_null()) {
-      base::ResetAndReturn(&read_callback_).Run(error);
-    }
-  }
-
-  void SetWriteError(int error) { write_error_ = error; }
-
-  void AppendInputPacket(const std::vector<char>& data) {
-    if (!read_callback_.is_null()) {
-      int size = std::min(read_buffer_size_, static_cast<int>(data.size()));
-      memcpy(read_buffer_->data(), &data[0], data.size());
-      read_buffer_ = nullptr;
-      base::ResetAndReturn(&read_callback_).Run(size);
-    } else {
-      incoming_packets_.push_back(data);
-    }
-  }
-
-  // Socket interface.
-  int Read(IOBuffer* buf,
-           int buf_len,
-           const CompletionCallback& callback) override {
-    DCHECK(read_callback_.is_null());
-
-    if (read_error_ != OK) {
-      return read_error_;
-    }
-
-    if (!incoming_packets_.empty()) {
-      scoped_refptr<IOBuffer> buffer(buf);
-      int size =
-          std::min(static_cast<int>(incoming_packets_.front().size()), buf_len);
-      memcpy(buffer->data(), &*incoming_packets_.front().begin(), size);
-      incoming_packets_.pop_front();
-      return size;
-    } else {
-      read_callback_ = callback;
-      read_buffer_ = buf;
-      read_buffer_size_ = buf_len;
-      return ERR_IO_PENDING;
-    }
-  }
-
-  int Write(IOBuffer* buf,
-            int buf_len,
-            const CompletionCallback& callback) override {
-    if (write_error_ != OK) {
-      return write_error_;
-    }
-
-    if (peer_socket_) {
-      base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE,
-          base::Bind(&FakeP2PDatagramSocket::AppendInputPacket, peer_socket_,
-                     std::vector<char>(buf->data(), buf->data() + buf_len)));
-    }
-
-    return buf_len;
-  }
-
-  int SetReceiveBufferSize(int32_t size) override {
-    NOTIMPLEMENTED();
-    return ERR_NOT_IMPLEMENTED;
-  }
-  int SetSendBufferSize(int32_t size) override {
-    NOTIMPLEMENTED();
-    return ERR_NOT_IMPLEMENTED;
-  }
-
- private:
-  int read_error_ = OK;
-  int write_error_ = OK;
-
-  scoped_refptr<IOBuffer> read_buffer_;
-  int read_buffer_size_;
-  CompletionCallback read_callback_;
-
-  std::deque<std::vector<char>> incoming_packets_;
-
-  base::WeakPtr<FakeP2PDatagramSocket> peer_socket_;
-
-  base::WeakPtrFactory<FakeP2PDatagramSocket> weak_factory_;
-};
-
-class TestP2PStreamDelegate : public QuicP2PStream::Delegate {
- public:
-  TestP2PStreamDelegate() {}
-  ~TestP2PStreamDelegate() override {}
-
-  void OnDataReceived(const char* data, int length) override {
-    received_data_.append(data, length);
-  }
-  void OnClose(QuicErrorCode error) override {
-    is_closed_ = true;
-    error_ = error;
-  }
-
-  const std::string& received_data() { return received_data_; }
-  bool is_closed() { return is_closed_; }
-  QuicErrorCode error() { return error_; }
-
- private:
-  std::string received_data_;
-  bool is_closed_ = false;
-  QuicErrorCode error_ = QUIC_NO_ERROR;
-
-  DISALLOW_COPY_AND_ASSIGN(TestP2PStreamDelegate);
-};
-
-class TestP2PSessionDelegate : public QuicP2PSession::Delegate {
- public:
-  void OnIncomingStream(QuicP2PStream* stream) override {
-    last_incoming_stream_ = stream;
-    stream->SetDelegate(next_incoming_stream_delegate_);
-    next_incoming_stream_delegate_ = nullptr;
-    if (!on_incoming_stream_callback_.is_null())
-      base::ResetAndReturn(&on_incoming_stream_callback_).Run();
-  }
-
-  void OnConnectionClosed(QuicErrorCode error) override {
-    is_closed_ = true;
-    error_ = error;
-  }
-
-  void set_next_incoming_stream_delegate(QuicP2PStream::Delegate* delegate) {
-    next_incoming_stream_delegate_ = delegate;
-  }
-  void set_on_incoming_stream_callback(const base::Closure& callback) {
-    on_incoming_stream_callback_ = callback;
-  }
-  QuicP2PStream* last_incoming_stream() { return last_incoming_stream_; }
-  bool is_closed() { return is_closed_; }
-  QuicErrorCode error() { return error_; }
-
- private:
-  QuicP2PStream::Delegate* next_incoming_stream_delegate_ = nullptr;
-  base::Closure on_incoming_stream_callback_;
-  QuicP2PStream* last_incoming_stream_ = nullptr;
-  bool is_closed_ = false;
-  QuicErrorCode error_ = QUIC_NO_ERROR;
-};
-
-}  // namespace
-
-class QuicP2PSessionTest : public ::testing::Test {
- public:
-  void OnWriteResult(int result);
-
- protected:
-  QuicP2PSessionTest()
-      : quic_helper_(&quic_clock_, QuicRandom::GetInstance()),
-        alarm_factory_(base::ThreadTaskRunnerHandle::Get().get(),
-                       &quic_clock_) {
-    // Simulate out-of-bound config handshake.
-    CryptoHandshakeMessage hello_message;
-    config_.ToHandshakeMessage(&hello_message);
-    std::string error_detail;
-    EXPECT_EQ(QUIC_NO_ERROR,
-              config_.ProcessPeerHello(hello_message, CLIENT, &error_detail));
-  }
-
-  void CreateSessions() {
-    std::unique_ptr<FakeP2PDatagramSocket> socket1(new FakeP2PDatagramSocket());
-    std::unique_ptr<FakeP2PDatagramSocket> socket2(new FakeP2PDatagramSocket());
-    socket1->ConnectWith(socket2.get());
-
-    socket1_ = socket1->GetWeakPtr();
-    socket2_ = socket2->GetWeakPtr();
-
-    QuicP2PCryptoConfig crypto_config(kTestSharedKey);
-
-    session1_ = CreateP2PSession(std::move(socket1), crypto_config,
-                                 Perspective::IS_SERVER);
-    session2_ = CreateP2PSession(std::move(socket2), crypto_config,
-                                 Perspective::IS_CLIENT);
-  }
-
-  std::unique_ptr<QuicP2PSession> CreateP2PSession(
-      std::unique_ptr<Socket> socket,
-      QuicP2PCryptoConfig crypto_config,
-      Perspective perspective) {
-    QuicChromiumPacketWriter* writer =
-        new QuicChromiumPacketWriter(socket.get());
-    std::unique_ptr<QuicConnection> quic_connection1(new QuicConnection(
-        0, IPEndPoint(IPAddress::IPv4AllZeros(), 0), &quic_helper_,
-        &alarm_factory_, writer, true /* owns_writer */, perspective,
-        QuicSupportedVersions()));
-
-    std::unique_ptr<QuicP2PSession> result(
-        new QuicP2PSession(config_, crypto_config, std::move(quic_connection1),
-                           std::move(socket)));
-    writer->Initialize(result.get(), quic_connection1.get());
-    result->Initialize();
-    return result;
-  }
-
-  void TestStreamConnection(QuicP2PSession* from_session,
-                            QuicP2PSession* to_session,
-                            QuicStreamId expected_stream_id);
-
-  QuicClock quic_clock_;
-  QuicChromiumConnectionHelper quic_helper_;
-  QuicChromiumAlarmFactory alarm_factory_;
-  QuicConfig config_;
-
-  base::WeakPtr<FakeP2PDatagramSocket> socket1_;
-  std::unique_ptr<QuicP2PSession> session1_;
-
-  base::WeakPtr<FakeP2PDatagramSocket> socket2_;
-  std::unique_ptr<QuicP2PSession> session2_;
-};
-
-void QuicP2PSessionTest::OnWriteResult(int result) {
-  EXPECT_THAT(result, IsOk());
-}
-
-void QuicP2PSessionTest::TestStreamConnection(QuicP2PSession* from_session,
-                                              QuicP2PSession* to_session,
-                                              QuicStreamId expected_stream_id) {
-  QuicP2PStream* outgoing_stream =
-      from_session->CreateOutgoingDynamicStream(kDefaultPriority);
-  EXPECT_TRUE(outgoing_stream);
-  TestP2PStreamDelegate outgoing_stream_delegate;
-  outgoing_stream->SetDelegate(&outgoing_stream_delegate);
-  EXPECT_EQ(expected_stream_id, outgoing_stream->id());
-
-  // Add streams to write_blocked_lists of both QuicSession objects.
-  QuicWriteBlockedList* write_blocked_list1 =
-      test::QuicSessionPeer::GetWriteBlockedStreams(from_session);
-  write_blocked_list1->RegisterStream(expected_stream_id, kV3HighestPriority);
-  QuicWriteBlockedList* write_blocked_list2 =
-      test::QuicSessionPeer::GetWriteBlockedStreams(to_session);
-  write_blocked_list2->RegisterStream(expected_stream_id, kV3HighestPriority);
-
-  // Send a test message to the client.
-  const char kTestMessage[] = "Hi";
-  const char kTestResponse[] = "Response";
-  outgoing_stream->Write(
-      std::string(kTestMessage),
-      base::Bind(&QuicP2PSessionTest::OnWriteResult, base::Unretained(this)));
-
-  // Wait for the incoming stream to be created.
-  TestP2PStreamDelegate incoming_stream_delegate;
-  base::RunLoop run_loop;
-  TestP2PSessionDelegate session_delegate;
-  session_delegate.set_next_incoming_stream_delegate(&incoming_stream_delegate);
-  session_delegate.set_on_incoming_stream_callback(
-      base::Bind(&base::RunLoop::Quit, base::Unretained(&run_loop)));
-  to_session->SetDelegate(&session_delegate);
-  run_loop.Run();
-  to_session->SetDelegate(nullptr);
-
-  QuicP2PStream* incoming_stream = session_delegate.last_incoming_stream();
-  ASSERT_TRUE(incoming_stream);
-  EXPECT_EQ(expected_stream_id, incoming_stream->id());
-  EXPECT_EQ(kTestMessage, incoming_stream_delegate.received_data());
-
-  incoming_stream->Write(
-      std::string(kTestResponse),
-      base::Bind(&QuicP2PSessionTest::OnWriteResult, base::Unretained(this)));
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(kTestResponse, outgoing_stream_delegate.received_data());
-
-  from_session->CloseStream(outgoing_stream->id());
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_TRUE(outgoing_stream_delegate.is_closed());
-  EXPECT_TRUE(incoming_stream_delegate.is_closed());
-}
-
-TEST_F(QuicP2PSessionTest, ClientToServer) {
-  CreateSessions();
-  TestStreamConnection(session2_.get(), session1_.get(), 3);
-}
-
-TEST_F(QuicP2PSessionTest, ServerToClient) {
-  CreateSessions();
-  TestStreamConnection(session1_.get(), session2_.get(), 2);
-}
-
-TEST_F(QuicP2PSessionTest, DestroySocketWhenClosed) {
-  CreateSessions();
-
-  // The socket must be destroyed when connection is closed.
-  EXPECT_TRUE(socket1_);
-  session1_->connection()->CloseConnection(
-      QUIC_NO_ERROR, "test", ConnectionCloseBehavior::SILENT_CLOSE);
-  EXPECT_FALSE(socket1_);
-}
-
-TEST_F(QuicP2PSessionTest, TransportWriteError) {
-  CreateSessions();
-
-  TestP2PSessionDelegate session_delegate;
-  session1_->SetDelegate(&session_delegate);
-
-  QuicP2PStream* stream =
-      session1_->CreateOutgoingDynamicStream(kDefaultPriority);
-  EXPECT_TRUE(stream);
-  TestP2PStreamDelegate stream_delegate;
-  stream->SetDelegate(&stream_delegate);
-  EXPECT_EQ(2U, stream->id());
-
-  // Add stream to write_blocked_list.
-  QuicWriteBlockedList* write_blocked_list =
-      test::QuicSessionPeer::GetWriteBlockedStreams(session1_.get());
-  write_blocked_list->RegisterStream(stream->id(), kV3HighestPriority);
-
-  socket1_->SetWriteError(ERR_INTERNET_DISCONNECTED);
-
-  const char kTestMessage[] = "Hi";
-  stream->Write(
-      std::string(kTestMessage),
-      base::Bind(&QuicP2PSessionTest::OnWriteResult, base::Unretained(this)));
-
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_TRUE(stream_delegate.is_closed());
-  EXPECT_EQ(QUIC_PACKET_WRITE_ERROR, stream_delegate.error());
-  EXPECT_TRUE(session_delegate.is_closed());
-  EXPECT_EQ(QUIC_PACKET_WRITE_ERROR, session_delegate.error());
-
-  // Verify that the socket was destroyed.
-  EXPECT_FALSE(socket1_);
-}
-
-TEST_F(QuicP2PSessionTest, TransportReceiveError) {
-  CreateSessions();
-
-  TestP2PSessionDelegate session_delegate;
-  session1_->SetDelegate(&session_delegate);
-
-  QuicP2PStream* stream =
-      session1_->CreateOutgoingDynamicStream(kDefaultPriority);
-  EXPECT_TRUE(stream);
-  TestP2PStreamDelegate stream_delegate;
-  stream->SetDelegate(&stream_delegate);
-  EXPECT_EQ(2U, stream->id());
-
-  socket1_->SetReadError(ERR_INTERNET_DISCONNECTED);
-
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_TRUE(stream_delegate.is_closed());
-  EXPECT_EQ(QUIC_PACKET_READ_ERROR, stream_delegate.error());
-  EXPECT_TRUE(session_delegate.is_closed());
-  EXPECT_EQ(QUIC_PACKET_READ_ERROR, session_delegate.error());
-
-  // Verify that the socket was destroyed.
-  EXPECT_FALSE(socket1_);
-}
-
-}  // namespace net
diff --git a/net/quic/p2p/quic_p2p_stream.cc b/net/quic/p2p/quic_p2p_stream.cc
deleted file mode 100644
index da01019..0000000
--- a/net/quic/p2p/quic_p2p_stream.cc
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/quic/p2p/quic_p2p_stream.h"
-
-#include "base/callback_helpers.h"
-#include "net/base/net_errors.h"
-#include "net/quic/quic_session.h"
-#include "net/quic/quic_write_blocked_list.h"
-
-namespace net {
-
-QuicP2PStream::QuicP2PStream(QuicStreamId id, QuicSession* session)
-    : ReliableQuicStream(id, session) {}
-
-QuicP2PStream::~QuicP2PStream() {}
-
-void QuicP2PStream::OnDataAvailable() {
-  DCHECK(delegate_);
-
-  struct iovec iov;
-  while (true) {
-    if (sequencer()->GetReadableRegions(&iov, 1) != 1) {
-      // No more data to read.
-      break;
-    }
-    delegate_->OnDataReceived(reinterpret_cast<const char*>(iov.iov_base),
-                              iov.iov_len);
-    sequencer()->MarkConsumed(iov.iov_len);
-  }
-}
-
-void QuicP2PStream::OnClose() {
-  ReliableQuicStream::OnClose();
-
-  if (delegate_) {
-    Delegate* delegate = delegate_;
-    delegate_ = nullptr;
-    delegate->OnClose(connection_error());
-  }
-}
-
-void QuicP2PStream::OnCanWrite() {
-  ReliableQuicStream::OnCanWrite();
-
-  if (!HasBufferedData() && !write_callback_.is_null()) {
-    base::ResetAndReturn(&write_callback_).Run(last_write_size_);
-  }
-}
-
-void QuicP2PStream::WriteHeader(base::StringPiece data) {
-  WriteOrBufferData(data, false, nullptr);
-}
-
-int QuicP2PStream::Write(base::StringPiece data,
-                         const CompletionCallback& callback) {
-  DCHECK(write_callback_.is_null());
-
-  // Writes the data, or buffers it.
-  WriteOrBufferData(data, false, nullptr);
-  if (!HasBufferedData()) {
-    return data.size();
-  }
-
-  write_callback_ = callback;
-  last_write_size_ = data.size();
-  return ERR_IO_PENDING;
-}
-
-void QuicP2PStream::SetDelegate(QuicP2PStream::Delegate* delegate) {
-  DCHECK(!(delegate_ && delegate));
-  delegate_ = delegate;
-}
-
-}  // namespace net
diff --git a/net/quic/p2p/quic_p2p_stream.h b/net/quic/p2p/quic_p2p_stream.h
deleted file mode 100644
index 4e456b2..0000000
--- a/net/quic/p2p/quic_p2p_stream.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_QUIC_P2P_QUIC_P2P_STREAM_H_
-#define NET_QUIC_P2P_QUIC_P2P_STREAM_H_
-
-#include "base/macros.h"
-#include "net/base/completion_callback.h"
-#include "net/base/net_export.h"
-#include "net/quic/reliable_quic_stream.h"
-
-namespace net {
-
-// Streams created by QuicP2PSession.
-class NET_EXPORT QuicP2PStream : public ReliableQuicStream {
- public:
-  // Delegate handles protocol specific behavior of a quic stream.
-  class NET_EXPORT Delegate {
-   public:
-    Delegate() {}
-
-    // Called when data is received.
-    virtual void OnDataReceived(const char* data, int length) = 0;
-
-    // Called when the stream is closed by the peer.
-    virtual void OnClose(QuicErrorCode error) = 0;
-
-   protected:
-    virtual ~Delegate() {}
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(Delegate);
-  };
-
-  QuicP2PStream(QuicStreamId id, QuicSession* session);
-
-  ~QuicP2PStream() override;
-
-  // ReliableQuicStream overrides.
-  void OnDataAvailable() override;
-  void OnClose() override;
-  void OnCanWrite() override;
-
-  void WriteHeader(base::StringPiece data);
-
-  int Write(base::StringPiece data, const CompletionCallback& callback);
-
-  void SetDelegate(Delegate* delegate);
-  Delegate* GetDelegate() { return delegate_; }
-
- private:
-  Delegate* delegate_ = nullptr;
-
-  CompletionCallback write_callback_;
-  int last_write_size_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicP2PStream);
-};
-
-}  // namespace net
-
-#endif  // NET_QUIC_P2P_QUIC_P2P_STREAM_H_
diff --git a/net/quic/quic_bandwidth.cc b/net/quic/quic_bandwidth.cc
index 734858d5..9e25ba0e 100644
--- a/net/quic/quic_bandwidth.cc
+++ b/net/quic/quic_bandwidth.cc
@@ -95,18 +95,6 @@
   return (bits_per_second_ == 0);
 }
 
-QuicBandwidth QuicBandwidth::Add(QuicBandwidth delta) const {
-  return QuicBandwidth(bits_per_second_ + delta.bits_per_second_);
-}
-
-QuicBandwidth QuicBandwidth::Subtract(QuicBandwidth delta) const {
-  return QuicBandwidth(bits_per_second_ - delta.bits_per_second_);
-}
-
-QuicBandwidth QuicBandwidth::Scale(float scale_factor) const {
-  return QuicBandwidth(static_cast<int64_t>(bits_per_second_ * scale_factor));
-}
-
 QuicTime::Delta QuicBandwidth::TransferTime(QuicByteCount bytes) const {
   if (bits_per_second_ == 0) {
     return QuicTime::Delta::Zero();
diff --git a/net/quic/quic_bandwidth.h b/net/quic/quic_bandwidth.h
index 215ee25..1aa2c9a2 100644
--- a/net/quic/quic_bandwidth.h
+++ b/net/quic/quic_bandwidth.h
@@ -52,17 +52,15 @@
 
   bool IsZero() const;
 
-  QuicBandwidth Add(QuicBandwidth delta) const WARN_UNUSED_RESULT;
-
-  QuicBandwidth Subtract(QuicBandwidth delta) const WARN_UNUSED_RESULT;
-
-  QuicBandwidth Scale(float scale_factor) const WARN_UNUSED_RESULT;
-
   QuicTime::Delta TransferTime(QuicByteCount bytes) const;
 
  private:
   explicit QuicBandwidth(int64_t bits_per_second);
   int64_t bits_per_second_;
+
+  friend QuicBandwidth operator+(QuicBandwidth lhs, QuicBandwidth rhs);
+  friend QuicBandwidth operator-(QuicBandwidth lhs, QuicBandwidth rhs);
+  friend QuicBandwidth operator*(QuicBandwidth lhs, float factor);
 };
 
 // Non-member relational operators for QuicBandwidth.
@@ -85,5 +83,19 @@
   return !(lhs < rhs);
 }
 
+// Non-member arithmetic operators for QuicBandwidth.
+inline QuicBandwidth operator+(QuicBandwidth lhs, QuicBandwidth rhs) {
+  return QuicBandwidth(lhs.bits_per_second_ + rhs.bits_per_second_);
+}
+inline QuicBandwidth operator-(QuicBandwidth lhs, QuicBandwidth rhs) {
+  return QuicBandwidth(lhs.bits_per_second_ - rhs.bits_per_second_);
+}
+inline QuicBandwidth operator*(QuicBandwidth lhs, float rhs) {
+  return QuicBandwidth(static_cast<int64_t>(lhs.bits_per_second_ * rhs));
+}
+inline QuicBandwidth operator*(float lhs, QuicBandwidth rhs) {
+  return rhs * lhs;
+}
+
 }  // namespace net
 #endif  // NET_QUIC_QUIC_BANDWIDTH_H_
diff --git a/net/quic/quic_bandwidth_test.cc b/net/quic/quic_bandwidth_test.cc
index 191405c..ebfe005 100644
--- a/net/quic/quic_bandwidth_test.cc
+++ b/net/quic/quic_bandwidth_test.cc
@@ -35,15 +35,15 @@
   QuicBandwidth bandwidht_1 = QuicBandwidth::FromKBitsPerSecond(1);
   QuicBandwidth bandwidht_2 = QuicBandwidth::FromKBytesPerSecond(1);
 
-  EXPECT_EQ(9000, bandwidht_1.Add(bandwidht_2).ToBitsPerSecond());
-  EXPECT_EQ(9000, bandwidht_2.Add(bandwidht_1).ToBitsPerSecond());
+  EXPECT_EQ(9000, (bandwidht_1 + bandwidht_2).ToBitsPerSecond());
+  EXPECT_EQ(9000, (bandwidht_2 + bandwidht_1).ToBitsPerSecond());
 }
 
 TEST_F(QuicBandwidthTest, Subtract) {
   QuicBandwidth bandwidht_1 = QuicBandwidth::FromKBitsPerSecond(1);
   QuicBandwidth bandwidht_2 = QuicBandwidth::FromKBytesPerSecond(1);
 
-  EXPECT_EQ(7000, bandwidht_2.Subtract(bandwidht_1).ToBitsPerSecond());
+  EXPECT_EQ(7000, (bandwidht_2 - bandwidht_1).ToBitsPerSecond());
 }
 
 TEST_F(QuicBandwidthTest, TimeDelta) {
@@ -58,11 +58,11 @@
 
 TEST_F(QuicBandwidthTest, Scale) {
   EXPECT_EQ(QuicBandwidth::FromKBytesPerSecond(500),
-            QuicBandwidth::FromKBytesPerSecond(1000).Scale(0.5f));
+            QuicBandwidth::FromKBytesPerSecond(1000) * 0.5f);
   EXPECT_EQ(QuicBandwidth::FromKBytesPerSecond(750),
-            QuicBandwidth::FromKBytesPerSecond(1000).Scale(0.75f));
+            0.75f * QuicBandwidth::FromKBytesPerSecond(1000));
   EXPECT_EQ(QuicBandwidth::FromKBytesPerSecond(1250),
-            QuicBandwidth::FromKBytesPerSecond(1000).Scale(1.25f));
+            QuicBandwidth::FromKBytesPerSecond(1000) * 1.25f);
 }
 
 TEST_F(QuicBandwidthTest, BytesPerPeriod) {
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc
index 957cc399..96dabd7 100644
--- a/net/quic/quic_connection.cc
+++ b/net/quic/quic_connection.cc
@@ -681,8 +681,12 @@
   PeerAddressChangeType peer_migration_type =
       QuicUtils::DetermineAddressChangeType(peer_address_,
                                             last_packet_source_address_);
+  // Do not migrate connection if the changed address packet is a reordered
+  // packet.
   if (active_peer_migration_type_ == NO_CHANGE &&
-      peer_migration_type != NO_CHANGE) {
+      peer_migration_type != NO_CHANGE &&
+      (!FLAGS_quic_do_not_migrate_on_old_packet ||
+       header.packet_number > received_packet_manager_.GetLargestObserved())) {
     StartPeerMigration(header.path_id, peer_migration_type);
   }
 
@@ -1064,7 +1068,7 @@
         ack_queued_ = true;
       } else if (!ack_alarm_->IsSet()) {
         // Wait the minimum of a quarter min_rtt and the delayed ack time.
-        QuicTime::Delta ack_delay = QuicTime::Delta::Min(
+        QuicTime::Delta ack_delay = std::min(
             DelayedAckTime(), sent_packet_manager_->GetRttStats()->min_rtt() *
                                   ack_decimation_delay_);
         ack_alarm_->Set(clock_->ApproximateNow() + ack_delay);
@@ -1212,8 +1216,7 @@
   ScopedPacketBundler ack_bundler(this, SEND_ACK_IF_PENDING);
   // The optimized path may be used for data only packets which fit into a
   // standard buffer and don't need padding.
-  if (FLAGS_quic_use_optimized_write_path && id != kCryptoStreamId &&
-      !packet_generator_.HasQueuedFrames() &&
+  if (id != kCryptoStreamId && !packet_generator_.HasQueuedFrames() &&
       iov.total_length > kMaxPacketSize) {
     // Use the fast path to send full data packets.
     return packet_generator_.ConsumeDataFastPath(id, iov, offset, fin,
diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc
index c604b4d..0673c26 100644
--- a/net/quic/quic_connection_test.cc
+++ b/net/quic/quic_connection_test.cc
@@ -1113,6 +1113,34 @@
   EXPECT_FALSE(connection_.connected());
 }
 
+TEST_P(QuicConnectionTest, ClientAddressChangeAndPacketReordered) {
+  EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+  set_perspective(Perspective::IS_SERVER);
+  QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
+  // Clear peer address.
+  QuicConnectionPeer::SetPeerAddress(&connection_, IPEndPoint());
+
+  QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 5);
+  QuicStreamFrame stream_frame(1u, false, 0u, StringPiece());
+  EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
+  const IPEndPoint kNewPeerAddress = IPEndPoint(Loopback6(),
+                                                /*port=*/23456);
+  ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
+                                  kNewPeerAddress);
+
+  // Decrease packet number to simulate out-of-order packets.
+  QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 4);
+  if (FLAGS_quic_do_not_migrate_on_old_packet) {
+    // This is an old packet, do not migrate.
+    EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(0);
+  } else {
+    // A connection migration is observed.
+    EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE));
+  }
+  ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
+                                  kPeerAddress);
+}
+
 TEST_P(QuicConnectionTest, MaxPacketSize) {
   EXPECT_EQ(Perspective::IS_CLIENT, connection_.perspective());
   EXPECT_EQ(1350u, connection_.max_packet_length());
diff --git a/net/quic/quic_crypto_server_stream.cc b/net/quic/quic_crypto_server_stream.cc
index 452cd37..d222fe3 100644
--- a/net/quic/quic_crypto_server_stream.cc
+++ b/net/quic/quic_crypto_server_stream.cc
@@ -85,6 +85,7 @@
       validate_client_hello_cb_(nullptr),
       num_handshake_messages_(0),
       num_handshake_messages_with_server_nonces_(0),
+      send_server_config_update_cb_(nullptr),
       num_server_config_update_messages_sent_(0),
       use_stateless_rejects_if_peer_supported_(
           use_stateless_rejects_if_peer_supported),
@@ -102,6 +103,10 @@
     validate_client_hello_cb_->Cancel();
     validate_client_hello_cb_ = nullptr;
   }
+  if (send_server_config_update_cb_ != nullptr) {
+    send_server_config_update_cb_->Cancel();
+    send_server_config_update_cb_ = nullptr;
+  }
 }
 
 void QuicCryptoServerStream::OnHandshakeMessage(
@@ -109,8 +114,11 @@
   QuicCryptoServerStreamBase::OnHandshakeMessage(message);
   ++num_handshake_messages_;
 
-  // This block should be removed with support for QUIC_VERSION_25.
-  if (FLAGS_quic_require_fix && !HasFixedTag(message)) {
+  // It's only safe to deprecate kFIXD where we have deprecated v25
+  bool require_kfixd =
+      !FLAGS_quic_deprecate_kfixd || !FLAGS_quic_disable_pre_30;
+
+  if (require_kfixd && !HasFixedTag(message)) {
     CloseConnectionWithDetails(QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND,
                                "Missing kFIXD");
     return;
@@ -262,6 +270,27 @@
     return;
   }
 
+  if (FLAGS_enable_async_get_proof) {
+    if (send_server_config_update_cb_ != nullptr) {
+      DVLOG(1)
+          << "Skipped server config update since one is already in progress";
+      return;
+    }
+
+    std::unique_ptr<SendServerConfigUpdateCallback> cb(
+        new SendServerConfigUpdateCallback(this));
+    send_server_config_update_cb_ = cb.get();
+    crypto_config_->BuildServerConfigUpdateMessage(
+        session()->connection()->version(), chlo_hash_,
+        previous_source_address_tokens_,
+        session()->connection()->self_address().address(),
+        session()->connection()->peer_address().address(),
+        session()->connection()->clock(),
+        session()->connection()->random_generator(), compressed_certs_cache_,
+        crypto_negotiated_params_, cached_network_params, std::move(cb));
+    return;
+  }
+
   CryptoHandshakeMessage server_config_update_message;
   if (!crypto_config_->BuildServerConfigUpdateMessage(
           session()->connection()->version(), chlo_hash_,
@@ -284,6 +313,43 @@
   ++num_server_config_update_messages_sent_;
 }
 
+QuicCryptoServerStream::SendServerConfigUpdateCallback::
+    SendServerConfigUpdateCallback(QuicCryptoServerStream* parent)
+    : parent_(parent) {}
+
+void QuicCryptoServerStream::SendServerConfigUpdateCallback::Cancel() {
+  parent_ = nullptr;
+}
+
+// From BuildServerConfigUpdateMessageResultCallback
+void QuicCryptoServerStream::SendServerConfigUpdateCallback::Run(
+    bool ok,
+    const CryptoHandshakeMessage& message) {
+  if (parent_ == nullptr) {
+    return;
+  }
+  parent_->FinishSendServerConfigUpdate(ok, message);
+}
+
+void QuicCryptoServerStream::FinishSendServerConfigUpdate(
+    bool ok,
+    const CryptoHandshakeMessage& message) {
+  // Clear the callback that got us here.
+  DCHECK(send_server_config_update_cb_ != nullptr);
+  send_server_config_update_cb_ = nullptr;
+
+  if (!ok) {
+    DVLOG(1) << "Server: Failed to build server config update (SCUP)!";
+    return;
+  }
+
+  DVLOG(1) << "Server: Sending server config update: " << message.DebugString();
+  const QuicData& data = message.GetSerialized();
+  WriteOrBufferData(StringPiece(data.data(), data.length()), false, nullptr);
+
+  ++num_server_config_update_messages_sent_;
+}
+
 void QuicCryptoServerStream::OnServerHelloAcked() {
   session()->connection()->OnHandshakeComplete();
 }
diff --git a/net/quic/quic_crypto_server_stream.h b/net/quic/quic_crypto_server_stream.h
index f3900847..77711b8 100644
--- a/net/quic/quic_crypto_server_stream.h
+++ b/net/quic/quic_crypto_server_stream.h
@@ -157,6 +157,24 @@
     DISALLOW_COPY_AND_ASSIGN(ValidateCallback);
   };
 
+  class SendServerConfigUpdateCallback
+      : public BuildServerConfigUpdateMessageResultCallback {
+   public:
+    explicit SendServerConfigUpdateCallback(QuicCryptoServerStream* parent);
+    SendServerConfigUpdateCallback(const SendServerConfigUpdateCallback&) =
+        delete;
+    void operator=(const SendServerConfigUpdateCallback&) = delete;
+
+    // To allow the parent to detach itself from the callback before deletion.
+    void Cancel();
+
+    // From BuildServerConfigUpdateMessageResultCallback
+    void Run(bool ok, const CryptoHandshakeMessage& message) override;
+
+   private:
+    QuicCryptoServerStream* parent_;
+  };
+
   // Invoked by ValidateCallback::RunImpl once initial validation of
   // the client hello is complete.  Finishes processing of the client
   // hello message and handles handshake success/failure.
@@ -164,6 +182,13 @@
       const CryptoHandshakeMessage& message,
       const ValidateClientHelloResultCallback::Result& result);
 
+  // Invoked by SendServerConfigUpdateCallback::RunImpl once the proof has been
+  // received.  |ok| indicates whether or not the proof was successfully
+  // acquired, and |message| holds the partially-constructed message from
+  // SendServerConfigUpdate.
+  void FinishSendServerConfigUpdate(bool ok,
+                                    const CryptoHandshakeMessage& message);
+
   // crypto_config_ contains crypto parameters for the handshake.
   const QuicCryptoServerConfig* crypto_config_;
 
@@ -193,6 +218,12 @@
   // attempt).
   uint8_t num_handshake_messages_with_server_nonces_;
 
+  // Pointer to the active callback that will receive the result of
+  // BuildServerConfigUpdateMessage and forward it to
+  // FinishSendServerConfigUpdate.  nullptr if no update message is currently
+  // being built.
+  SendServerConfigUpdateCallback* send_server_config_update_cb_;
+
   // Number of server config update (SCUP) messages sent by this stream.
   int num_server_config_update_messages_sent_;
 
diff --git a/net/quic/quic_crypto_server_stream_test.cc b/net/quic/quic_crypto_server_stream_test.cc
index 1cf2d5c..fc5583b2 100644
--- a/net/quic/quic_crypto_server_stream_test.cc
+++ b/net/quic/quic_crypto_server_stream_test.cc
@@ -428,7 +428,8 @@
 
 TEST_P(QuicCryptoServerStreamTest, FailByPolicy) {
   FLAGS_quic_enable_chlo_policy = true;
-  FLAGS_quic_require_fix = false;
+  FLAGS_quic_disable_pre_30 = true;
+  FLAGS_quic_deprecate_kfixd = true;
   Initialize();
   InitializeFakeClient(/* supports_stateless_rejects= */ false);
 
@@ -441,7 +442,8 @@
 }
 
 TEST_P(QuicCryptoServerStreamTest, MessageAfterHandshake) {
-  FLAGS_quic_require_fix = false;
+  FLAGS_quic_disable_pre_30 = true;
+  FLAGS_quic_deprecate_kfixd = true;
   Initialize();
   CompleteCryptoHandshake();
   EXPECT_CALL(
@@ -455,7 +457,8 @@
 }
 
 TEST_P(QuicCryptoServerStreamTest, BadMessageType) {
-  FLAGS_quic_require_fix = false;
+  FLAGS_quic_disable_pre_30 = true;
+  FLAGS_quic_deprecate_kfixd = true;
   Initialize();
 
   message_.set_tag(kSHLO);
diff --git a/net/quic/quic_crypto_stream.cc b/net/quic/quic_crypto_stream.cc
index f904871..271af57a2 100644
--- a/net/quic/quic_crypto_stream.cc
+++ b/net/quic/quic_crypto_stream.cc
@@ -10,6 +10,7 @@
 #include "net/quic/crypto/crypto_handshake.h"
 #include "net/quic/crypto/crypto_utils.h"
 #include "net/quic/quic_connection.h"
+#include "net/quic/quic_flags.h"
 #include "net/quic/quic_session.h"
 #include "net/quic/quic_utils.h"
 
@@ -69,6 +70,9 @@
     const CryptoHandshakeMessage& message,
     QuicAckListenerInterface* listener) {
   DVLOG(1) << ENDPOINT << "Sending " << message.DebugString();
+  if (FLAGS_quic_neuter_unencrypted_when_sending) {
+    session()->connection()->NeuterUnencryptedPackets();
+  }
   session()->OnCryptoHandshakeMessageSent(message);
   const QuicData& data = message.GetSerialized();
   // TODO(wtc): check the return value.
diff --git a/net/quic/quic_flags.cc b/net/quic/quic_flags.cc
index cd92ea6..06a30f0 100644
--- a/net/quic/quic_flags.cc
+++ b/net/quic/quic_flags.cc
@@ -60,9 +60,6 @@
 // If true, Close the connection instead of writing unencrypted stream data.
 bool FLAGS_quic_never_write_unencrypted_data = true;
 
-// If true, reject any incoming QUIC which does not have the FIXD tag.
-bool FLAGS_quic_require_fix = true;
-
 // If true, headers stream will support receiving PUSH_PROMISE frames.
 bool FLAGS_quic_supports_push_promise = true;
 
@@ -92,13 +89,6 @@
 // flags.
 bool FLAGS_quic_use_old_public_reset_packets = true;
 
-// Allow the NPRR connection option which reduces QUIC\'s pacing rate during
-// recovery instead of PRR.
-bool FLAGS_quic_allow_noprr = true;
-
-// Use a write path optimized for StreamFrames.
-bool FLAGS_quic_use_optimized_write_path = true;
-
 // If true, the dispatcher is responsible for generating server designated
 // connection IDs.
 bool FLAGS_quic_dispatcher_creates_id = true;
@@ -155,3 +145,21 @@
 
 // If true, requires support for X509 certificates in QUIC CHLO PDMDs.
 bool FLAGS_quic_require_x509 = false;
+
+// If true, deprecate safeguards for b/26023400.
+bool FLAGS_quic_deprecate_kfixd = false;
+
+// If true, QUIC will refresh the proof for versions 31 and beyond on subsequent
+// CHLOs.
+bool FLAGS_quic_refresh_proof = true;
+
+// If true, a connection does not migrate on an old packet even the peer address
+// changes.
+bool FLAGS_quic_do_not_migrate_on_old_packet = true;
+
+// If true, use async codepaths to invoke ProofSource::GetProof.
+bool FLAGS_enable_async_get_proof = false;
+
+// If true, neuter null encrypted packets before sending the next handshake
+// message.
+bool FLAGS_quic_neuter_unencrypted_when_sending = false;
diff --git a/net/quic/quic_flags.h b/net/quic/quic_flags.h
index 0a54c7b..59c9f9e8 100644
--- a/net/quic/quic_flags.h
+++ b/net/quic/quic_flags.h
@@ -22,7 +22,6 @@
 NET_EXPORT_PRIVATE extern bool FLAGS_quic_measure_headers_hol_blocking_time;
 NET_EXPORT_PRIVATE extern bool FLAGS_quic_disable_pacing_for_perf_tests;
 NET_EXPORT_PRIVATE extern bool FLAGS_quic_never_write_unencrypted_data;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_require_fix;
 NET_EXPORT_PRIVATE extern bool FLAGS_quic_supports_push_promise;
 NET_EXPORT_PRIVATE extern bool FLAGS_quic_supports_push_promise;
 NET_EXPORT_PRIVATE extern bool FLAGS_quic_no_lower_bw_resumption_limit;
@@ -32,8 +31,6 @@
 NET_EXPORT_PRIVATE extern bool FLAGS_quic_only_one_sending_alarm;
 NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_hash_in_scup;
 NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_old_public_reset_packets;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_allow_noprr;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_optimized_write_path;
 NET_EXPORT_PRIVATE extern bool FLAGS_quic_dispatcher_creates_id;
 NET_EXPORT_PRIVATE extern bool FLAGS_quic_enable_chlo_policy;
 NET_EXPORT_PRIVATE extern bool FLAGS_quic_ignore_zero_length_frames;
@@ -50,5 +47,10 @@
 NET_EXPORT_PRIVATE extern bool FLAGS_quic_enable_version_35;
 NET_EXPORT_PRIVATE extern bool FLAGS_quic_enable_version_36;
 NET_EXPORT_PRIVATE extern bool FLAGS_quic_require_x509;
+NET_EXPORT_PRIVATE extern bool FLAGS_quic_deprecate_kfixd;
+NET_EXPORT_PRIVATE extern bool FLAGS_quic_refresh_proof;
+NET_EXPORT_PRIVATE extern bool FLAGS_quic_do_not_migrate_on_old_packet;
+NET_EXPORT_PRIVATE extern bool FLAGS_enable_async_get_proof;
+NET_EXPORT_PRIVATE extern bool FLAGS_quic_neuter_unencrypted_when_sending;
 
 #endif  // NET_QUIC_QUIC_FLAGS_H_
diff --git a/net/quic/quic_headers_stream.cc b/net/quic/quic_headers_stream.cc
index bdf9c9e..c9f3529 100644
--- a/net/quic/quic_headers_stream.cc
+++ b/net/quic/quic_headers_stream.cc
@@ -446,7 +446,7 @@
         break;
       }
       DCHECK(timestamp.IsInitialized());
-      cur_max_timestamp_ = QuicTime::Max(timestamp, cur_max_timestamp_);
+      cur_max_timestamp_ = std::max(timestamp, cur_max_timestamp_);
     } else {
       if (sequencer()->GetReadableRegions(&iov, 1) != 1) {
         // No more data to read.
diff --git a/net/quic/quic_packet_creator.cc b/net/quic/quic_packet_creator.cc
index b940c99..e60e2c80 100644
--- a/net/quic/quic_packet_creator.cc
+++ b/net/quic/quic_packet_creator.cc
@@ -276,7 +276,7 @@
 
   const char* src = static_cast<char*>(iov.iov[iovnum].iov_base) + iov_offset;
   while (true) {
-    memcpy(buffer, src, copy_len);
+    memmove(buffer, src, copy_len);
     length -= copy_len;
     buffer += copy_len;
     if (length == 0 || ++iovnum >= iov.iov_count) {
diff --git a/net/quic/quic_protocol.cc b/net/quic/quic_protocol.cc
index 9829ab46..fe387f08 100644
--- a/net/quic/quic_protocol.cc
+++ b/net/quic/quic_protocol.cc
@@ -504,6 +504,13 @@
   return Empty() || old_min != Min();
 }
 
+void PacketNumberQueue::Complement() {
+  if (Empty()) {
+    return;
+  }
+  packet_number_intervals_.Complement(Min(), Max() + 1);
+}
+
 bool PacketNumberQueue::Contains(QuicPacketNumber packet_number) const {
   return packet_number_intervals_.Contains(packet_number);
 }
diff --git a/net/quic/quic_protocol.h b/net/quic/quic_protocol.h
index c3089f7..d7325c5 100644
--- a/net/quic/quic_protocol.h
+++ b/net/quic/quic_protocol.h
@@ -956,6 +956,11 @@
   // the queue. Returns true if packets were removed.
   bool RemoveUpTo(QuicPacketNumber higher);
 
+  // Mutates packet number set so that it contains only those packet numbers
+  // from minimum to maximum packet number not currently in the set. Do nothing
+  // if packet number set is empty.
+  void Complement();
+
   // Returns true if the queue contains |packet_number|.
   bool Contains(QuicPacketNumber packet_number) const;
 
diff --git a/net/quic/quic_protocol_test.cc b/net/quic/quic_protocol_test.cc
index 126f610..b50e60ec 100644
--- a/net/quic/quic_protocol_test.cc
+++ b/net/quic/quic_protocol_test.cc
@@ -400,6 +400,19 @@
   EXPECT_FALSE(queue.Contains(20));
 }
 
+TEST(PacketNumberQueueTest, Complement) {
+  PacketNumberQueue queue;
+  queue.Add(1, 10);
+  queue.Add(12, 20);
+  queue.Add(22, 30);
+  queue.Complement();
+  EXPECT_EQ(2u, queue.NumIntervals());
+  EXPECT_TRUE(queue.Contains(10));
+  EXPECT_TRUE(queue.Contains(11));
+  EXPECT_TRUE(queue.Contains(20));
+  EXPECT_TRUE(queue.Contains(21));
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace net
diff --git a/net/quic/quic_received_packet_manager.cc b/net/quic/quic_received_packet_manager.cc
index 4ce6945..199fe7f 100644
--- a/net/quic/quic_received_packet_manager.cc
+++ b/net/quic/quic_received_packet_manager.cc
@@ -319,4 +319,8 @@
   return ack_frame_updated_;
 }
 
+QuicPacketNumber QuicReceivedPacketManager::GetLargestObserved() const {
+  return ack_frame_.largest_observed;
+}
+
 }  // namespace net
diff --git a/net/quic/quic_received_packet_manager.h b/net/quic/quic_received_packet_manager.h
index 44a770b..013bde17 100644
--- a/net/quic/quic_received_packet_manager.h
+++ b/net/quic/quic_received_packet_manager.h
@@ -149,6 +149,8 @@
 
   virtual bool ack_frame_updated() const;
 
+  QuicPacketNumber GetLargestObserved() const;
+
   // For logging purposes.
   const QuicAckFrame& ack_frame() const { return ack_frame_; }
 
diff --git a/net/quic/quic_sent_packet_manager.cc b/net/quic/quic_sent_packet_manager.cc
index 7ec63fc..7a26504c 100644
--- a/net/quic/quic_sent_packet_manager.cc
+++ b/net/quic/quic_sent_packet_manager.cc
@@ -816,7 +816,7 @@
       const QuicTime sent_time = unacked_packets_.GetLastPacketSentTime();
       const QuicTime tlp_time = sent_time + GetTailLossProbeDelay();
       // Ensure the TLP timer never gets set to a time in the past.
-      return QuicTime::Max(clock_->ApproximateNow(), tlp_time);
+      return std::max(clock_->ApproximateNow(), tlp_time);
     }
     case RTO_MODE: {
       // The RTO is based on the first outstanding packet.
@@ -825,7 +825,7 @@
       // Wait for TLP packets to be acked before an RTO fires.
       QuicTime tlp_time =
           unacked_packets_.GetLastPacketSentTime() + GetTailLossProbeDelay();
-      return QuicTime::Max(tlp_time, rto_time);
+      return std::max(tlp_time, rto_time);
     }
   }
   DCHECK(false);
@@ -857,9 +857,8 @@
             static_cast<int64_t>(0.5 * srtt.ToMilliseconds())));
   }
   if (!unacked_packets_.HasMultipleInFlightPackets()) {
-    return QuicTime::Delta::Max(2 * srtt,
-                                1.5 * srtt + QuicTime::Delta::FromMilliseconds(
-                                                 kMinRetransmissionTimeMs / 2));
+    return std::max(2 * srtt, 1.5 * srtt + QuicTime::Delta::FromMilliseconds(
+                                               kMinRetransmissionTimeMs / 2));
   }
   return QuicTime::Delta::FromMilliseconds(
       max(kMinTailLossProbeTimeoutMs,
diff --git a/net/quic/quic_spdy_stream.h b/net/quic/quic_spdy_stream.h
index 01f7a29..d8d8d714 100644
--- a/net/quic/quic_spdy_stream.h
+++ b/net/quic/quic_spdy_stream.h
@@ -193,6 +193,10 @@
   // use of the spdy_session_ member.
   void ClearSession();
 
+  // Returns true if the sequencer has delivered the FIN, and no more body bytes
+  // will be available.
+  bool IsClosed() { return sequencer()->IsClosed(); }
+
  protected:
   // Called by OnStreamHeadersComplete depending on which type (initial or
   // trailing) headers are expected next.
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
index 91e442d..990b0cb 100644
--- a/net/quic/quic_stream_factory.cc
+++ b/net/quic/quic_stream_factory.cc
@@ -649,10 +649,11 @@
       socket_performance_watcher_factory_(socket_performance_watcher_factory),
       config_(InitializeQuicConfig(connection_options,
                                    idle_connection_timeout_seconds)),
-      crypto_config_(new ProofVerifierChromium(cert_verifier,
-                                               ct_policy_enforcer,
-                                               transport_security_state,
-                                               cert_transparency_verifier)),
+      crypto_config_(base::WrapUnique(
+          new ProofVerifierChromium(cert_verifier,
+                                    ct_policy_enforcer,
+                                    transport_security_state,
+                                    cert_transparency_verifier))),
       supported_versions_(supported_versions),
       enable_port_selection_(enable_port_selection),
       always_require_handshake_confirmation_(
diff --git a/net/quic/quic_time.h b/net/quic/quic_time.h
index 3c5a670..ffdbb80 100644
--- a/net/quic/quic_time.h
+++ b/net/quic/quic_time.h
@@ -70,16 +70,6 @@
     // Converts the time offset to a rounded number of microseconds.
     inline int64_t ToMicroseconds() const { return time_offset_; }
 
-    // Returns the larger delta of time1 and time2.
-    static inline Delta Max(Delta delta1, Delta delta2) {
-      return delta1 < delta2 ? delta2 : delta1;
-    }
-
-    // Returns the smaller delta of time1 and time2.
-    static inline Delta Min(Delta delta1, Delta delta2) {
-      return delta1 < delta2 ? delta1 : delta2;
-    }
-
     inline bool IsZero() const { return time_offset_ == 0; }
 
     inline bool IsInfinite() const {
@@ -126,11 +116,6 @@
     return QuicTime(Delta::kQuicInfiniteTimeUs);
   }
 
-  // Returns the later time of time1 and time2.
-  static inline QuicTime Max(QuicTime time1, QuicTime time2) {
-    return time1 < time2 ? time2 : time1;
-  }
-
   // Produce the internal value to be used when logging.  This value
   // represents the number of microseconds since some epoch.  It may
   // be the UNIX epoch on some platforms.  On others, it may
diff --git a/net/quic/quic_time_test.cc b/net/quic/quic_time_test.cc
index 9bdba53..be760d7 100644
--- a/net/quic/quic_time_test.cc
+++ b/net/quic/quic_time_test.cc
@@ -63,8 +63,8 @@
 
 TEST(QuicTimeDeltaTest, Max) {
   EXPECT_EQ(QuicTime::Delta::FromMicroseconds(2000),
-            QuicTime::Delta::Max(QuicTime::Delta::FromMicroseconds(1000),
-                                 QuicTime::Delta::FromMicroseconds(2000)));
+            std::max(QuicTime::Delta::FromMicroseconds(1000),
+                     QuicTime::Delta::FromMicroseconds(2000)));
 }
 
 TEST(QuicTimeDeltaTest, NotEqual) {
@@ -113,7 +113,7 @@
   QuicTime time_1 = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(1);
   QuicTime time_2 = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(2);
 
-  EXPECT_EQ(time_2, QuicTime::Max(time_1, time_2));
+  EXPECT_EQ(time_2, std::max(time_1, time_2));
 }
 
 TEST_F(QuicTimeTest, MockClock) {
diff --git a/net/quic/test_tools/crypto_test_utils.h b/net/quic/test_tools/crypto_test_utils.h
index b453cec..176d6878 100644
--- a/net/quic/test_tools/crypto_test_utils.h
+++ b/net/quic/test_tools/crypto_test_utils.h
@@ -142,14 +142,14 @@
   static std::string GetValueForTag(const CryptoHandshakeMessage& message,
                                     QuicTag tag);
 
-  // Returns a |ProofSource| that serves up test certificates.
-  static ProofSource* ProofSourceForTesting();
+  // Returns a new |ProofSource| that serves up test certificates.
+  static std::unique_ptr<ProofSource> ProofSourceForTesting();
 
   // Returns a |ProofVerifier| that uses the QUIC testing root CA.
-  static ProofVerifier* ProofVerifierForTesting();
+  static std::unique_ptr<ProofVerifier> ProofVerifierForTesting();
 
   // Returns a real ProofVerifier (not a fake proof verifier) for testing.
-  static ProofVerifier* RealProofVerifierForTesting();
+  static std::unique_ptr<ProofVerifier> RealProofVerifierForTesting();
 
   // Returns a hash of the leaf test certificate.
   static uint64_t LeafCertHashForTesting();
diff --git a/net/quic/test_tools/crypto_test_utils_chromium.cc b/net/quic/test_tools/crypto_test_utils_chromium.cc
index 1e944e0..ec2be57 100644
--- a/net/quic/test_tools/crypto_test_utils_chromium.cc
+++ b/net/quic/test_tools/crypto_test_utils_chromium.cc
@@ -82,18 +82,19 @@
 }  // namespace
 
 // static
-ProofSource* CryptoTestUtils::ProofSourceForTesting() {
-  ProofSourceChromium* source = new ProofSourceChromium();
+std::unique_ptr<ProofSource> CryptoTestUtils::ProofSourceForTesting() {
+  std::unique_ptr<ProofSourceChromium> source(new ProofSourceChromium());
   base::FilePath certs_dir = GetTestCertsDirectory();
   CHECK(source->Initialize(
       certs_dir.AppendASCII("quic_chain.crt"),
       certs_dir.AppendASCII("quic_test.example.com.key.pkcs8"),
       certs_dir.AppendASCII("quic_test.example.com.key.sct")));
-  return source;
+  return std::move(source);
 }
 
 // static
-ProofVerifier* ProofVerifierForTestingInternal(bool use_real_proof_verifier) {
+std::unique_ptr<ProofVerifier> ProofVerifierForTestingInternal(
+    bool use_real_proof_verifier) {
   // TODO(rch): use a real cert verifier?
   std::unique_ptr<MockCertVerifier> cert_verifier(new MockCertVerifier());
   net::CertVerifyResult verify_result;
@@ -106,24 +107,24 @@
   cert_verifier->AddResultForCertAndHost(verify_result.verified_cert.get(),
                                          "test.example.com", verify_result, OK);
   if (use_real_proof_verifier) {
-    return new TestProofVerifierChromium(
+    return base::WrapUnique(new TestProofVerifierChromium(
         std::move(cert_verifier), base::WrapUnique(new TransportSecurityState),
         base::WrapUnique(new MultiLogCTVerifier),
-        base::WrapUnique(new CTPolicyEnforcer), "quic_root.crt");
+        base::WrapUnique(new CTPolicyEnforcer), "quic_root.crt"));
   }
-  return new TestProofVerifierChromium(
+  return base::WrapUnique(new TestProofVerifierChromium(
       std::move(cert_verifier), base::WrapUnique(new TransportSecurityState),
       base::WrapUnique(new MultiLogCTVerifier),
-      base::WrapUnique(new CTPolicyEnforcer), "quic_root.crt");
+      base::WrapUnique(new CTPolicyEnforcer), "quic_root.crt"));
 }
 
 // static
-ProofVerifier* CryptoTestUtils::ProofVerifierForTesting() {
+std::unique_ptr<ProofVerifier> CryptoTestUtils::ProofVerifierForTesting() {
   return ProofVerifierForTestingInternal(/*use_real_proof_verifier=*/false);
 }
 
 // static
-ProofVerifier* CryptoTestUtils::RealProofVerifierForTesting() {
+std::unique_ptr<ProofVerifier> CryptoTestUtils::RealProofVerifierForTesting() {
   return ProofVerifierForTestingInternal(/*use_real_proof_verifier=*/true);
 }
 
diff --git a/net/quic/test_tools/quic_crypto_server_config_peer.cc b/net/quic/test_tools/quic_crypto_server_config_peer.cc
index 28c67306..12ff38f 100644
--- a/net/quic/test_tools/quic_crypto_server_config_peer.cc
+++ b/net/quic/test_tools/quic_crypto_server_config_peer.cc
@@ -175,15 +175,15 @@
       QuicWallTime::FromUNIXSeconds(seconds));
 }
 
-const string QuicCryptoServerConfigPeer::CompressChain(
+string QuicCryptoServerConfigPeer::CompressChain(
     QuicCompressedCertsCache* compressed_certs_cache,
     const scoped_refptr<ProofSource::Chain>& chain,
     const string& client_common_set_hashes,
     const string& client_cached_cert_hashes,
     const CommonCertSets* common_sets) {
-  return server_config_->CompressChain(compressed_certs_cache, chain,
-                                       client_common_set_hashes,
-                                       client_cached_cert_hashes, common_sets);
+  return QuicCryptoServerConfig::CompressChain(
+      compressed_certs_cache, chain, client_common_set_hashes,
+      client_cached_cert_hashes, common_sets);
 }
 
 uint32_t QuicCryptoServerConfigPeer::source_address_token_future_secs() {
diff --git a/net/quic/test_tools/quic_crypto_server_config_peer.h b/net/quic/test_tools/quic_crypto_server_config_peer.h
index 1341a49..995d64e7 100644
--- a/net/quic/test_tools/quic_crypto_server_config_peer.h
+++ b/net/quic/test_tools/quic_crypto_server_config_peer.h
@@ -81,7 +81,7 @@
 
   void SelectNewPrimaryConfig(int seconds);
 
-  const std::string CompressChain(
+  static std::string CompressChain(
       QuicCompressedCertsCache* compressed_certs_cache,
       const scoped_refptr<ProofSource::Chain>& chain,
       const std::string& client_common_set_hashes,
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc
index 381ebabd..38d2ed1 100644
--- a/net/tools/quic/end_to_end_test.cc
+++ b/net/tools/quic/end_to_end_test.cc
@@ -153,26 +153,30 @@
   // to do 0-RTT across incompatible versions. Chromium only supports
   // a single version at a time anyway. :)
   QuicVersionVector all_supported_versions = QuicSupportedVersions();
-  QuicVersionVector version_buckets[4];
+  QuicVersionVector version_buckets[5];
 
   for (const QuicVersion version : all_supported_versions) {
     if (version <= QUIC_VERSION_25) {
+      // Versions: 25
       // SPDY/4
       version_buckets[0].push_back(version);
-    } else if (version <= QUIC_VERSION_32) {
-      // QUIC_VERSION_26 changes the kdf in a way that is incompatible with
-      // version negotiation across the version 26 boundary.
+    } else if (version <= QUIC_VERSION_30) {
+      // Versions: 26-30
+      // v26 adds a hash of the expected leaf cert in the XLCT tag.
       version_buckets[1].push_back(version);
-    } else if (version <= QUIC_VERSION_33) {
-      // QUIC_VERSION_33 changes the kdf in a way that is incompatible with
-      // version negotiation across the version 33 boundary, by using the
-      // diversification nonce.
+    } else if (version <= QUIC_VERSION_32) {
+      // Versions: 31-32
+      // v31 adds a hash of the CHLO into the proof signature.
       version_buckets[2].push_back(version);
-    } else {
-      // QUIC_VERSION_34 deprecates entropy and uses new ack and stop waiting
-      // wire formats, so it is incompatible with version negotiation across the
-      // version 34 boundary.
+    } else if (version <= QUIC_VERSION_33) {
+      // Versions: 33
+      // v33 adds a diversification nonce into the hkdf.
       version_buckets[3].push_back(version);
+    } else {
+      // Versions: 34+
+      // QUIC_VERSION_34 deprecates entropy and uses new ack and stop waiting
+      // wire formats.
+      version_buckets[4].push_back(version);
     }
   }
 
@@ -299,7 +303,7 @@
   EndToEndTest()
       : initialized_(false),
         server_address_(IPEndPoint(Loopback4(), 0)),
-        server_hostname_("example.com"),
+        server_hostname_("test.example.com"),
         server_started_(false),
         strike_register_no_startup_period_(false),
         chlo_multiplier_(0),
@@ -341,9 +345,9 @@
   }
 
   QuicTestClient* CreateQuicClient(QuicPacketWriterWrapper* writer) {
-    QuicTestClient* client =
-        new QuicTestClient(server_address_, server_hostname_, client_config_,
-                           client_supported_versions_);
+    QuicTestClient* client = new QuicTestClient(
+        server_address_, server_hostname_, client_config_,
+        client_supported_versions_, CryptoTestUtils::ProofVerifierForTesting());
     client->UseWriter(writer);
     client->Connect();
     return client;
@@ -491,7 +495,7 @@
   }
 
   void AddToCache(StringPiece path, int response_code, StringPiece body) {
-    QuicInMemoryCache::GetInstance()->AddSimpleResponse("www.google.com", path,
+    QuicInMemoryCache::GetInstance()->AddSimpleResponse(server_hostname_, path,
                                                         response_code, body);
   }
 
@@ -2466,7 +2470,7 @@
   trailers["some-trailing-header"] = "trailing-header-value";
 
   QuicInMemoryCache::GetInstance()->AddResponse(
-      "www.google.com", "/trailer_url", std::move(headers), kBody,
+      server_hostname_, "/trailer_url", std::move(headers), kBody,
       trailers.Clone());
 
   EXPECT_EQ(kBody, client_->SendSynchronousRequest("/trailer_url"));
diff --git a/net/tools/quic/quic_client.cc b/net/tools/quic/quic_client.cc
index 224859e..651776f 100644
--- a/net/tools/quic/quic_client.cc
+++ b/net/tools/quic/quic_client.cc
@@ -51,27 +51,27 @@
                        const QuicServerId& server_id,
                        const QuicVersionVector& supported_versions,
                        EpollServer* epoll_server,
-                       ProofVerifier* proof_verifier)
+                       std::unique_ptr<ProofVerifier> proof_verifier)
     : QuicClient(server_address,
                  server_id,
                  supported_versions,
                  QuicConfig(),
                  epoll_server,
-                 proof_verifier) {}
+                 std::move(proof_verifier)) {}
 
 QuicClient::QuicClient(IPEndPoint server_address,
                        const QuicServerId& server_id,
                        const QuicVersionVector& supported_versions,
                        const QuicConfig& config,
                        EpollServer* epoll_server,
-                       ProofVerifier* proof_verifier)
+                       std::unique_ptr<ProofVerifier> proof_verifier)
     : QuicClientBase(
           server_id,
           supported_versions,
           config,
           new QuicEpollConnectionHelper(epoll_server, QuicAllocator::SIMPLE),
           new QuicEpollAlarmFactory(epoll_server),
-          proof_verifier),
+          std::move(proof_verifier)),
       server_address_(server_address),
       local_port_(0),
       epoll_server_(epoll_server),
diff --git a/net/tools/quic/quic_client.h b/net/tools/quic/quic_client.h
index 0beccc1..cec0d884 100644
--- a/net/tools/quic/quic_client.h
+++ b/net/tools/quic/quic_client.h
@@ -86,13 +86,13 @@
              const QuicServerId& server_id,
              const QuicVersionVector& supported_versions,
              EpollServer* epoll_server,
-             ProofVerifier* proof_verifier);
+             std::unique_ptr<ProofVerifier> proof_verifier);
   QuicClient(IPEndPoint server_address,
              const QuicServerId& server_id,
              const QuicVersionVector& supported_versions,
              const QuicConfig& config,
              EpollServer* epoll_server,
-             ProofVerifier* proof_verifier);
+             std::unique_ptr<ProofVerifier> proof_verifier);
 
   ~QuicClient() override;
 
diff --git a/net/tools/quic/quic_client_base.cc b/net/tools/quic/quic_client_base.cc
index 211c54d8e..848d17d 100644
--- a/net/tools/quic/quic_client_base.cc
+++ b/net/tools/quic/quic_client_base.cc
@@ -14,10 +14,10 @@
                                const QuicConfig& config,
                                QuicConnectionHelperInterface* helper,
                                QuicAlarmFactory* alarm_factory,
-                               ProofVerifier* proof_verifier)
+                               std::unique_ptr<ProofVerifier> proof_verifier)
     : server_id_(server_id),
       config_(config),
-      crypto_config_(proof_verifier),
+      crypto_config_(std::move(proof_verifier)),
       helper_(helper),
       alarm_factory_(alarm_factory),
       supported_versions_(supported_versions),
diff --git a/net/tools/quic/quic_client_base.h b/net/tools/quic/quic_client_base.h
index 3f9e514..d49f8aad 100644
--- a/net/tools/quic/quic_client_base.h
+++ b/net/tools/quic/quic_client_base.h
@@ -38,7 +38,7 @@
                  const QuicConfig& config,
                  QuicConnectionHelperInterface* helper,
                  QuicAlarmFactory* alarm_factory,
-                 ProofVerifier* proof_verifier);
+                 std::unique_ptr<ProofVerifier> proof_verifier);
 
   ~QuicClientBase();
 
diff --git a/net/tools/quic/quic_client_bin.cc b/net/tools/quic/quic_client_bin.cc
index 1d6d6ec..f2a4b44 100644
--- a/net/tools/quic/quic_client_bin.cc
+++ b/net/tools/quic/quic_client_bin.cc
@@ -254,11 +254,12 @@
   transport_security_state.reset(new TransportSecurityState);
   std::unique_ptr<CTVerifier> ct_verifier(new MultiLogCTVerifier());
   std::unique_ptr<CTPolicyEnforcer> ct_policy_enforcer(new CTPolicyEnforcer());
-  ProofVerifierChromium* proof_verifier = new ProofVerifierChromium(
-      cert_verifier.get(), ct_policy_enforcer.get(),
-      transport_security_state.get(), ct_verifier.get());
+  std::unique_ptr<net::ProofVerifierChromium> proof_verifier(
+      new ProofVerifierChromium(cert_verifier.get(), ct_policy_enforcer.get(),
+                                transport_security_state.get(),
+                                ct_verifier.get()));
   net::QuicClient client(net::IPEndPoint(ip_addr, FLAGS_port), server_id,
-                         versions, &epoll_server, proof_verifier);
+                         versions, &epoll_server, std::move(proof_verifier));
   client.set_initial_max_packet_length(
       FLAGS_initial_mtu != 0 ? FLAGS_initial_mtu : net::kDefaultMaxPacketSize);
   if (!client.Initialize()) {
diff --git a/net/tools/quic/quic_client_test.cc b/net/tools/quic/quic_client_test.cc
index dca06bd..74910aca 100644
--- a/net/tools/quic/quic_client_test.cc
+++ b/net/tools/quic/quic_client_test.cc
@@ -54,7 +54,7 @@
 TEST(QuicClientTest, DoNotLeakFDs) {
   // Create a ProofVerifier before counting the number of open FDs to work
   // around some ASAN weirdness.
-  delete CryptoTestUtils::ProofVerifierForTesting();
+  CryptoTestUtils::ProofVerifierForTesting().reset();
 
   // Make sure that the QuicClient doesn't leak FDs. Doing so could cause port
   // exhaustion in long running processes which repeatedly create clients.
@@ -81,7 +81,7 @@
 TEST(QuicClientTest, CreateAndCleanUpUDPSockets) {
   // Create a ProofVerifier before counting the number of open FDs to work
   // around some ASAN weirdness.
-  delete CryptoTestUtils::ProofVerifierForTesting();
+  CryptoTestUtils::ProofVerifierForTesting().reset();
 
   EpollServer eps;
   int number_of_open_fds = NumOpenFDs();
diff --git a/net/tools/quic/quic_server.cc b/net/tools/quic/quic_server.cc
index 94fdfda..dc53bf0d 100644
--- a/net/tools/quic/quic_server.cc
+++ b/net/tools/quic/quic_server.cc
@@ -47,14 +47,14 @@
 
 }  // namespace
 
-QuicServer::QuicServer(ProofSource* proof_source)
-    : QuicServer(proof_source,
+QuicServer::QuicServer(std::unique_ptr<ProofSource> proof_source)
+    : QuicServer(std::move(proof_source),
                  QuicConfig(),
                  QuicCryptoServerConfig::ConfigOptions(),
                  QuicSupportedVersions()) {}
 
 QuicServer::QuicServer(
-    ProofSource* proof_source,
+    std::unique_ptr<ProofSource> proof_source,
     const QuicConfig& config,
     const QuicCryptoServerConfig::ConfigOptions& crypto_config_options,
     const QuicVersionVector& supported_versions)
@@ -65,7 +65,7 @@
       config_(config),
       crypto_config_(kSourceAddressTokenSecret,
                      QuicRandom::GetInstance(),
-                     proof_source),
+                     std::move(proof_source)),
       crypto_config_options_(crypto_config_options),
       supported_versions_(supported_versions),
       packet_reader_(new QuicPacketReader()) {
diff --git a/net/tools/quic/quic_server.h b/net/tools/quic/quic_server.h
index 76ff17a4..17c80b4 100644
--- a/net/tools/quic/quic_server.h
+++ b/net/tools/quic/quic_server.h
@@ -35,8 +35,8 @@
 
 class QuicServer : public EpollCallbackInterface {
  public:
-  explicit QuicServer(ProofSource* proof_source);
-  QuicServer(ProofSource* proof_source,
+  explicit QuicServer(std::unique_ptr<ProofSource> proof_source);
+  QuicServer(std::unique_ptr<ProofSource> proof_source,
              const QuicConfig& config,
              const QuicCryptoServerConfig::ConfigOptions& server_config_options,
              const QuicVersionVector& supported_versions);
diff --git a/net/tools/quic/quic_server_bin.cc b/net/tools/quic/quic_server_bin.cc
index 983c584..a6119698 100644
--- a/net/tools/quic/quic_server_bin.cc
+++ b/net/tools/quic/quic_server_bin.cc
@@ -22,11 +22,13 @@
 // The port the quic server will listen on.
 int32_t FLAGS_port = 6121;
 
-net::ProofSource* CreateProofSource(const base::FilePath& cert_path,
-                                    const base::FilePath& key_path) {
-  net::ProofSourceChromium* proof_source = new net::ProofSourceChromium();
+std::unique_ptr<net::ProofSource> CreateProofSource(
+    const base::FilePath& cert_path,
+    const base::FilePath& key_path) {
+  std::unique_ptr<net::ProofSourceChromium> proof_source(
+      new net::ProofSourceChromium());
   CHECK(proof_source->Initialize(cert_path, key_path, base::FilePath()));
-  return proof_source;
+  return std::move(proof_source);
 }
 
 int main(int argc, char* argv[]) {
diff --git a/net/tools/quic/quic_simple_client.cc b/net/tools/quic/quic_simple_client.cc
index d179b37..68ed15d 100644
--- a/net/tools/quic/quic_simple_client.cc
+++ b/net/tools/quic/quic_simple_client.cc
@@ -37,33 +37,35 @@
   headers_ = nullptr;
 }
 
-QuicSimpleClient::QuicSimpleClient(IPEndPoint server_address,
-                                   const QuicServerId& server_id,
-                                   const QuicVersionVector& supported_versions,
-                                   ProofVerifier* proof_verifier)
+QuicSimpleClient::QuicSimpleClient(
+    IPEndPoint server_address,
+    const QuicServerId& server_id,
+    const QuicVersionVector& supported_versions,
+    std::unique_ptr<ProofVerifier> proof_verifier)
     : QuicClientBase(server_id,
                      supported_versions,
                      QuicConfig(),
                      CreateQuicConnectionHelper(),
                      CreateQuicAlarmFactory(),
-                     proof_verifier),
+                     std::move(proof_verifier)),
       server_address_(server_address),
       local_port_(0),
       initialized_(false),
       packet_reader_started_(false),
       weak_factory_(this) {}
 
-QuicSimpleClient::QuicSimpleClient(IPEndPoint server_address,
-                                   const QuicServerId& server_id,
-                                   const QuicVersionVector& supported_versions,
-                                   const QuicConfig& config,
-                                   ProofVerifier* proof_verifier)
+QuicSimpleClient::QuicSimpleClient(
+    IPEndPoint server_address,
+    const QuicServerId& server_id,
+    const QuicVersionVector& supported_versions,
+    const QuicConfig& config,
+    std::unique_ptr<ProofVerifier> proof_verifier)
     : QuicClientBase(server_id,
                      supported_versions,
                      config,
                      CreateQuicConnectionHelper(),
                      CreateQuicAlarmFactory(),
-                     proof_verifier),
+                     std::move(proof_verifier)),
       server_address_(server_address),
       local_port_(0),
       initialized_(false),
diff --git a/net/tools/quic/quic_simple_client.h b/net/tools/quic/quic_simple_client.h
index b94399c..aa3c731 100644
--- a/net/tools/quic/quic_simple_client.h
+++ b/net/tools/quic/quic_simple_client.h
@@ -85,12 +85,12 @@
   QuicSimpleClient(IPEndPoint server_address,
                    const QuicServerId& server_id,
                    const QuicVersionVector& supported_versions,
-                   ProofVerifier* proof_verifier);
+                   std::unique_ptr<ProofVerifier> proof_verifier);
   QuicSimpleClient(IPEndPoint server_address,
                    const QuicServerId& server_id,
                    const QuicVersionVector& supported_versions,
                    const QuicConfig& config,
-                   ProofVerifier* proof_verifier);
+                   std::unique_ptr<ProofVerifier> proof_verifier);
 
   ~QuicSimpleClient() override;
 
diff --git a/net/tools/quic/quic_simple_client_bin.cc b/net/tools/quic/quic_simple_client_bin.cc
index 75dca39..25b688c 100644
--- a/net/tools/quic/quic_simple_client_bin.cc
+++ b/net/tools/quic/quic_simple_client_bin.cc
@@ -254,11 +254,12 @@
       new TransportSecurityState);
   std::unique_ptr<CTVerifier> ct_verifier(new MultiLogCTVerifier());
   std::unique_ptr<CTPolicyEnforcer> ct_policy_enforcer(new CTPolicyEnforcer());
-  ProofVerifierChromium* proof_verifier = new ProofVerifierChromium(
-      cert_verifier.get(), ct_policy_enforcer.get(),
-      transport_security_state.get(), ct_verifier.get());
+  std::unique_ptr<ProofVerifierChromium> proof_verifier(
+      new ProofVerifierChromium(cert_verifier.get(), ct_policy_enforcer.get(),
+                                transport_security_state.get(),
+                                ct_verifier.get()));
   net::QuicSimpleClient client(net::IPEndPoint(ip_addr, port), server_id,
-                               versions, proof_verifier);
+                               versions, std::move(proof_verifier));
   client.set_initial_max_packet_length(
       FLAGS_initial_mtu != 0 ? FLAGS_initial_mtu : net::kDefaultMaxPacketSize);
   if (!client.Initialize()) {
diff --git a/net/tools/quic/quic_simple_server.cc b/net/tools/quic/quic_simple_server.cc
index 814feab..d2cc113 100644
--- a/net/tools/quic/quic_simple_server.cc
+++ b/net/tools/quic/quic_simple_server.cc
@@ -68,7 +68,7 @@
 
 }  // namespace
 
-QuicSimpleServer::QuicSimpleServer(ProofSource* proof_source,
+QuicSimpleServer::QuicSimpleServer(std::unique_ptr<ProofSource> proof_source,
                                    const QuicConfig& config,
                                    const QuicVersionVector& supported_versions)
     : helper_(
@@ -79,7 +79,7 @@
       config_(config),
       crypto_config_(kSourceAddressTokenSecret,
                      QuicRandom::GetInstance(),
-                     proof_source),
+                     std::move(proof_source)),
       supported_versions_(supported_versions),
       read_pending_(false),
       synchronous_read_count_(0),
diff --git a/net/tools/quic/quic_simple_server.h b/net/tools/quic/quic_simple_server.h
index 7fe28a4..238393b 100644
--- a/net/tools/quic/quic_simple_server.h
+++ b/net/tools/quic/quic_simple_server.h
@@ -33,7 +33,7 @@
 
 class QuicSimpleServer {
  public:
-  QuicSimpleServer(ProofSource* proof_source,
+  QuicSimpleServer(std::unique_ptr<ProofSource> proof_source,
                    const QuicConfig& config,
                    const QuicVersionVector& supported_versions);
 
diff --git a/net/tools/quic/quic_simple_server_bin.cc b/net/tools/quic/quic_simple_server_bin.cc
index b04bf15..b1db0bb 100644
--- a/net/tools/quic/quic_simple_server_bin.cc
+++ b/net/tools/quic/quic_simple_server_bin.cc
@@ -22,11 +22,13 @@
 // The port the quic server will listen on.
 int32_t FLAGS_port = 6121;
 
-net::ProofSource* CreateProofSource(const base::FilePath& cert_path,
-                                    const base::FilePath& key_path) {
-  net::ProofSourceChromium* proof_source = new net::ProofSourceChromium();
+std::unique_ptr<net::ProofSource> CreateProofSource(
+    const base::FilePath& cert_path,
+    const base::FilePath& key_path) {
+  std::unique_ptr<net::ProofSourceChromium> proof_source(
+      new net::ProofSourceChromium());
   CHECK(proof_source->Initialize(cert_path, key_path, base::FilePath()));
-  return proof_source;
+  return std::move(proof_source);
 }
 
 int main(int argc, char* argv[]) {
diff --git a/net/tools/quic/quic_socket_utils.cc b/net/tools/quic/quic_socket_utils.cc
index 7fcc964..49c213a 100644
--- a/net/tools/quic/quic_socket_utils.cc
+++ b/net/tools/quic/quic_socket_utils.cc
@@ -71,7 +71,7 @@
     for (cmsg = CMSG_FIRSTHDR(hdr); cmsg != nullptr;
          cmsg = CMSG_NXTHDR(hdr, cmsg)) {
       if (cmsg->cmsg_type == SO_RXQ_OVFL) {
-        *dropped_packets = *(reinterpret_cast<int*> CMSG_DATA(cmsg));
+        *dropped_packets = *(reinterpret_cast<uint32_t*> CMSG_DATA(cmsg));
         return true;
       }
     }
diff --git a/net/tools/quic/test_tools/quic_test_client.cc b/net/tools/quic/test_tools/quic_test_client.cc
index ad5748d..19744575 100644
--- a/net/tools/quic/test_tools/quic_test_client.cc
+++ b/net/tools/quic/test_tools/quic_test_client.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <utility>
 
+#include "base/memory/ptr_util.h"
 #include "base/time/time.h"
 #include "net/base/completion_callback.h"
 #include "net/base/net_errors.h"
@@ -15,6 +16,8 @@
 #include "net/quic/crypto/proof_verifier.h"
 #include "net/quic/quic_flags.h"
 #include "net/quic/quic_server_id.h"
+#include "net/quic/quic_utils.h"
+#include "net/quic/test_tools/crypto_test_utils.h"
 #include "net/quic/test_tools/quic_connection_peer.h"
 #include "net/quic/test_tools/quic_spdy_session_peer.h"
 #include "net/quic/test_tools/quic_test_utils.h"
@@ -41,9 +44,14 @@
 namespace {
 
 // RecordingProofVerifier accepts any certificate chain and records the common
-// name of the leaf.
+// name of the leaf and then delegates the actual verfication to an actual
+// verifier. If no optional verifier is provided, then VerifyProof will return
+// success.
 class RecordingProofVerifier : public ProofVerifier {
  public:
+  explicit RecordingProofVerifier(std::unique_ptr<ProofVerifier> verifier)
+      : verifier_(std::move(verifier)) {}
+
   // ProofVerifier interface.
   QuicAsyncStatus VerifyProof(
       const string& hostname,
@@ -80,7 +88,13 @@
     //    common_name_ = cert->subject().GetDisplayName();
     cert_sct_ = cert_sct;
 
-    return QUIC_SUCCESS;
+    if (!verifier_) {
+      return QUIC_SUCCESS;
+    }
+
+    return verifier_->VerifyProof(
+        hostname, port, server_config, quic_version, chlo_hash, certs, cert_sct,
+        signature, context, error_details, details, std::move(callback));
   }
 
   const string& common_name() const { return common_name_; }
@@ -88,6 +102,7 @@
   const string& cert_sct() const { return cert_sct_; }
 
  private:
+  std::unique_ptr<ProofVerifier> verifier_;
   string common_name_;
   string cert_sct_;
 };
@@ -106,7 +121,7 @@
   headers->CopyFrom(*const_headers);
   if (!uri.starts_with("https://") && !uri.starts_with("http://")) {
     // If we have a relative URL, set some defaults.
-    string full_uri = "https://www.google.com";
+    string full_uri = "https://test.example.com";
     full_uri.append(uri.as_string());
     headers->SetRequestUri(full_uri);
   }
@@ -130,12 +145,27 @@
     const QuicConfig& config,
     const QuicVersionVector& supported_versions,
     EpollServer* epoll_server)
+    : MockableQuicClient(server_address,
+                         server_id,
+                         config,
+                         supported_versions,
+                         epoll_server,
+                         nullptr) {}
+
+MockableQuicClient::MockableQuicClient(
+    IPEndPoint server_address,
+    const QuicServerId& server_id,
+    const QuicConfig& config,
+    const QuicVersionVector& supported_versions,
+    EpollServer* epoll_server,
+    std::unique_ptr<ProofVerifier> proof_verifier)
     : QuicClient(server_address,
                  server_id,
                  supported_versions,
                  config,
                  epoll_server,
-                 new RecordingProofVerifier()),
+                 base::WrapUnique(
+                     new RecordingProofVerifier(std::move(proof_verifier)))),
       override_connection_id_(0),
       test_writer_(nullptr) {}
 
@@ -192,6 +222,23 @@
   Initialize();
 }
 
+QuicTestClient::QuicTestClient(IPEndPoint server_address,
+                               const string& server_hostname,
+                               const QuicConfig& config,
+                               const QuicVersionVector& supported_versions,
+                               std::unique_ptr<ProofVerifier> proof_verifier)
+    : client_(new MockableQuicClient(server_address,
+                                     QuicServerId(server_hostname,
+                                                  server_address.port(),
+                                                  PRIVACY_MODE_DISABLED),
+                                     config,
+                                     supported_versions,
+                                     &epoll_server_,
+                                     std::move(proof_verifier))),
+      allow_bidirectional_data_(false) {
+  Initialize();
+}
+
 QuicTestClient::QuicTestClient() : allow_bidirectional_data_(false) {}
 
 QuicTestClient::~QuicTestClient() {
diff --git a/net/tools/quic/test_tools/quic_test_client.h b/net/tools/quic/test_tools/quic_test_client.h
index 47e20621..4a5f6b7a 100644
--- a/net/tools/quic/test_tools/quic_test_client.h
+++ b/net/tools/quic/test_tools/quic_test_client.h
@@ -30,6 +30,7 @@
 
 class ProofVerifier;
 
+class ProofVerifier;
 class QuicPacketWriterWrapper;
 
 namespace test {
@@ -51,6 +52,13 @@
                      const QuicVersionVector& supported_versions,
                      EpollServer* epoll_server);
 
+  MockableQuicClient(IPEndPoint server_address,
+                     const QuicServerId& server_id,
+                     const QuicConfig& config,
+                     const QuicVersionVector& supported_versions,
+                     EpollServer* epoll_server,
+                     std::unique_ptr<ProofVerifier> proof_verifier);
+
   ~MockableQuicClient() override;
   QuicPacketWriter* CreateQuicPacketWriter() override;
   QuicConnectionId GenerateNewConnectionId() override;
@@ -81,6 +89,11 @@
                  const std::string& server_hostname,
                  const QuicConfig& config,
                  const QuicVersionVector& supported_versions);
+  QuicTestClient(IPEndPoint server_address,
+                 const std::string& server_hostname,
+                 const QuicConfig& config,
+                 const QuicVersionVector& supported_versions,
+                 std::unique_ptr<ProofVerifier> proof_verifier);
 
   ~QuicTestClient() override;
 
diff --git a/net/tools/quic/test_tools/quic_test_server.cc b/net/tools/quic/test_tools/quic_test_server.cc
index 1edf41a..0f72c417 100644
--- a/net/tools/quic/test_tools/quic_test_server.cc
+++ b/net/tools/quic/test_tools/quic_test_server.cc
@@ -149,13 +149,13 @@
   QuicTestServer::CryptoStreamFactory* crypto_stream_factory_;  // Not owned.
 };
 
-QuicTestServer::QuicTestServer(ProofSource* proof_source)
-    : QuicServer(proof_source) {}
+QuicTestServer::QuicTestServer(std::unique_ptr<ProofSource> proof_source)
+    : QuicServer(std::move(proof_source)) {}
 
-QuicTestServer::QuicTestServer(ProofSource* proof_source,
+QuicTestServer::QuicTestServer(std::unique_ptr<ProofSource> proof_source,
                                const QuicConfig& config,
                                const QuicVersionVector& supported_versions)
-    : QuicServer(proof_source,
+    : QuicServer(std::move(proof_source),
                  config,
                  QuicCryptoServerConfig::ConfigOptions(),
                  supported_versions) {}
diff --git a/net/tools/quic/test_tools/quic_test_server.h b/net/tools/quic/test_tools/quic_test_server.h
index 0714668..963c43df 100644
--- a/net/tools/quic/test_tools/quic_test_server.h
+++ b/net/tools/quic/test_tools/quic_test_server.h
@@ -60,8 +60,8 @@
         QuicServerSessionBase* session) = 0;
   };
 
-  explicit QuicTestServer(ProofSource* proof_source);
-  QuicTestServer(ProofSource* proof_source,
+  explicit QuicTestServer(std::unique_ptr<ProofSource> proof_source);
+  QuicTestServer(std::unique_ptr<ProofSource> proof_source,
                  const QuicConfig& config,
                  const QuicVersionVector& supported_versions);
 
diff --git a/net/websockets/websocket_channel.cc b/net/websockets/websocket_channel.cc
index ba100ece..a12d4f9 100644
--- a/net/websockets/websocket_channel.cc
+++ b/net/websockets/websocket_channel.cc
@@ -338,11 +338,12 @@
     const GURL& socket_url,
     const std::vector<std::string>& requested_subprotocols,
     const url::Origin& origin,
+    const GURL& first_party_for_cookies,
     const std::string& additional_headers) {
   // Delegate to the tested version.
   SendAddChannelRequestWithSuppliedCreator(
-      socket_url, requested_subprotocols, origin, additional_headers,
-      base::Bind(&WebSocketStream::CreateAndConnectStream));
+      socket_url, requested_subprotocols, origin, first_party_for_cookies,
+      additional_headers, base::Bind(&WebSocketStream::CreateAndConnectStream));
 }
 
 void WebSocketChannel::SetState(State new_state) {
@@ -544,10 +545,12 @@
     const GURL& socket_url,
     const std::vector<std::string>& requested_subprotocols,
     const url::Origin& origin,
+    const GURL& first_party_for_cookies,
     const std::string& additional_headers,
     const WebSocketStreamCreator& creator) {
   SendAddChannelRequestWithSuppliedCreator(socket_url, requested_subprotocols,
-                                           origin, additional_headers, creator);
+                                           origin, first_party_for_cookies,
+                                           additional_headers, creator);
 }
 
 void WebSocketChannel::SetClosingHandshakeTimeoutForTesting(
@@ -564,6 +567,7 @@
     const GURL& socket_url,
     const std::vector<std::string>& requested_subprotocols,
     const url::Origin& origin,
+    const GURL& first_party_for_cookies,
     const std::string& additional_headers,
     const WebSocketStreamCreator& creator) {
   DCHECK_EQ(FRESHLY_CONSTRUCTED, state_);
@@ -578,8 +582,9 @@
   std::unique_ptr<WebSocketStream::ConnectDelegate> connect_delegate(
       new ConnectDelegate(this));
   stream_request_ = creator.Run(socket_url_, requested_subprotocols, origin,
-                                additional_headers, url_request_context_,
-                                BoundNetLog(), std::move(connect_delegate));
+                                first_party_for_cookies, additional_headers,
+                                url_request_context_, BoundNetLog(),
+                                std::move(connect_delegate));
   SetState(CONNECTING);
 }
 
diff --git a/net/websockets/websocket_channel.h b/net/websockets/websocket_channel.h
index 8e7e8c36..ce46388 100644
--- a/net/websockets/websocket_channel.h
+++ b/net/websockets/websocket_channel.h
@@ -50,6 +50,7 @@
       const GURL&,
       const std::vector<std::string>&,
       const url::Origin&,
+      const GURL&,
       const std::string&,
       URLRequestContext*,
       const BoundNetLog&,
@@ -73,6 +74,7 @@
       const GURL& socket_url,
       const std::vector<std::string>& requested_protocols,
       const url::Origin& origin,
+      const GURL& first_party_for_cookies,
       const std::string& additional_headers);
 
   // Sends a data frame to the remote side. It is the responsibility of the
@@ -123,6 +125,7 @@
       const GURL& socket_url,
       const std::vector<std::string>& requested_protocols,
       const url::Origin& origin,
+      const GURL& first_party_for_cookies,
       const std::string& additional_headers,
       const WebSocketStreamCreator& creator);
 
@@ -216,6 +219,7 @@
       const GURL& socket_url,
       const std::vector<std::string>& requested_protocols,
       const url::Origin& origin,
+      const GURL& first_party_for_cookies,
       const std::string& additional_headers,
       const WebSocketStreamCreator& creator);
 
diff --git a/net/websockets/websocket_channel_test.cc b/net/websockets/websocket_channel_test.cc
index 84f8fb97..5fe3c80 100644
--- a/net/websockets/websocket_channel_test.cc
+++ b/net/websockets/websocket_channel_test.cc
@@ -700,6 +700,7 @@
       const GURL& socket_url,
       const std::vector<std::string>& requested_subprotocols,
       const url::Origin& origin,
+      const GURL& first_party_for_cookies,
       const std::string& additional_headers,
       URLRequestContext* url_request_context,
       const BoundNetLog& net_log,
@@ -707,6 +708,7 @@
     this->socket_url = socket_url;
     this->requested_subprotocols = requested_subprotocols;
     this->origin = origin;
+    this->first_party_for_cookies = first_party_for_cookies;
     this->url_request_context = url_request_context;
     this->net_log = net_log;
     this->connect_delegate = std::move(connect_delegate);
@@ -715,6 +717,7 @@
 
   GURL socket_url;
   url::Origin origin;
+  GURL first_party_for_cookies;
   std::vector<std::string> requested_subprotocols;
   URLRequestContext* url_request_context;
   BoundNetLog net_log;
@@ -747,7 +750,7 @@
                                         &connect_data_.url_request_context));
     channel_->SendAddChannelRequestForTesting(
         connect_data_.socket_url, connect_data_.requested_subprotocols,
-        connect_data_.origin, "",
+        connect_data_.origin, connect_data_.first_party_for_cookies, "",
         base::Bind(&ArgumentCopyingWebSocketStreamCreator::Create,
                    base::Unretained(&connect_data_.creator)));
   }
@@ -780,7 +783,10 @@
   // A struct containing the data that will be used to connect the channel.
   // Grouped for readability.
   struct ConnectData {
-    ConnectData() : socket_url("ws://ws/"), origin(GURL("http://ws")) {}
+    ConnectData()
+        : socket_url("ws://ws/"),
+          origin(GURL("http://ws")),
+          first_party_for_cookies("http://ws/") {}
 
     // URLRequestContext object.
     URLRequestContext url_request_context;
@@ -791,6 +797,8 @@
     std::vector<std::string> requested_subprotocols;
     // Origin of the request
     url::Origin origin;
+    // First party for cookies for the request.
+    GURL first_party_for_cookies;
 
     // A fake WebSocketStreamCreator that just records its arguments.
     ArgumentCopyingWebSocketStreamCreator creator;
@@ -1005,6 +1013,7 @@
 TEST_F(WebSocketChannelTest, EverythingIsPassedToTheCreatorFunction) {
   connect_data_.socket_url = GURL("ws://example.com/test");
   connect_data_.origin = url::Origin(GURL("http://example.com"));
+  connect_data_.first_party_for_cookies = GURL("http://example.com/");
   connect_data_.requested_subprotocols.push_back("Sinbad");
 
   CreateChannelAndConnect();
@@ -1017,6 +1026,8 @@
   EXPECT_EQ(connect_data_.requested_subprotocols,
             actual.requested_subprotocols);
   EXPECT_EQ(connect_data_.origin.Serialize(), actual.origin.Serialize());
+  EXPECT_EQ(connect_data_.first_party_for_cookies,
+            actual.first_party_for_cookies);
 }
 
 // Verify that calling SendFlowControl before the connection is established does
diff --git a/net/websockets/websocket_end_to_end_test.cc b/net/websockets/websocket_end_to_end_test.cc
index 18e79b3..be464f6e 100644
--- a/net/websockets/websocket_end_to_end_test.cc
+++ b/net/websockets/websocket_end_to_end_test.cc
@@ -265,11 +265,12 @@
       InitialiseContext();
     }
     url::Origin origin(GURL("http://localhost"));
+    GURL first_party_for_cookies("http://localhost/");
     event_interface_ = new ConnectTestingEventInterface;
     channel_.reset(
         new WebSocketChannel(base::WrapUnique(event_interface_), &context_));
     channel_->SendAddChannelRequest(GURL(socket_url), sub_protocols_, origin,
-                                    "");
+                                    first_party_for_cookies, "");
     event_interface_->WaitForResponse();
     return !event_interface_->failed();
   }
diff --git a/net/websockets/websocket_stream.cc b/net/websockets/websocket_stream.cc
index d1698ae..d621f39 100644
--- a/net/websockets/websocket_stream.cc
+++ b/net/websockets/websocket_stream.cc
@@ -86,6 +86,7 @@
       const GURL& url,
       const URLRequestContext* context,
       const url::Origin& origin,
+      const GURL& first_party_for_cookies,
       const std::string& additional_headers,
       std::unique_ptr<WebSocketStream::ConnectDelegate> connect_delegate,
       std::unique_ptr<WebSocketHandshakeStreamCreateHelper> create_helper)
@@ -105,6 +106,8 @@
     headers.AddHeadersFromString(additional_headers);
 
     url_request_->SetExtraRequestHeaders(headers);
+    url_request_->set_initiator(origin);
+    url_request_->set_first_party_for_cookies(first_party_for_cookies);
 
     // This passes the ownership of |create_helper_| to |url_request_|.
     url_request_->SetUserData(
@@ -336,6 +339,7 @@
     const GURL& socket_url,
     const std::vector<std::string>& requested_subprotocols,
     const url::Origin& origin,
+    const GURL& first_party_for_cookies,
     const std::string& additional_headers,
     URLRequestContext* url_request_context,
     const BoundNetLog& net_log,
@@ -344,8 +348,9 @@
       new WebSocketHandshakeStreamCreateHelper(connect_delegate.get(),
                                                requested_subprotocols));
   std::unique_ptr<StreamRequestImpl> request(new StreamRequestImpl(
-      socket_url, url_request_context, origin, additional_headers,
-      std::move(connect_delegate), std::move(create_helper)));
+      socket_url, url_request_context, origin, first_party_for_cookies,
+      additional_headers, std::move(connect_delegate),
+      std::move(create_helper)));
   request->Start(std::unique_ptr<base::Timer>(new base::Timer(false, false)));
   return std::move(request);
 }
@@ -355,14 +360,16 @@
     const GURL& socket_url,
     std::unique_ptr<WebSocketHandshakeStreamCreateHelper> create_helper,
     const url::Origin& origin,
+    const GURL& first_party_for_cookies,
     const std::string& additional_headers,
     URLRequestContext* url_request_context,
     const BoundNetLog& net_log,
     std::unique_ptr<WebSocketStream::ConnectDelegate> connect_delegate,
     std::unique_ptr<base::Timer> timer) {
   std::unique_ptr<StreamRequestImpl> request(new StreamRequestImpl(
-      socket_url, url_request_context, origin, additional_headers,
-      std::move(connect_delegate), std::move(create_helper)));
+      socket_url, url_request_context, origin, first_party_for_cookies,
+      additional_headers, std::move(connect_delegate),
+      std::move(create_helper)));
   request->Start(std::move(timer));
   return std::move(request);
 }
diff --git a/net/websockets/websocket_stream.h b/net/websockets/websocket_stream.h
index 28c90851..002c21a 100644
--- a/net/websockets/websocket_stream.h
+++ b/net/websockets/websocket_stream.h
@@ -108,6 +108,7 @@
       const GURL& socket_url,
       const std::vector<std::string>& requested_subprotocols,
       const url::Origin& origin,
+      const GURL& first_party_for_cookies,
       const std::string& additional_headers,
       URLRequestContext* url_request_context,
       const BoundNetLog& net_log,
@@ -224,6 +225,7 @@
     const GURL& socket_url,
     std::unique_ptr<WebSocketHandshakeStreamCreateHelper> create_helper,
     const url::Origin& origin,
+    const GURL& first_party_for_cookies,
     const std::string& additional_headers,
     URLRequestContext* url_request_context,
     const BoundNetLog& net_log,
diff --git a/net/websockets/websocket_stream_cookie_test.cc b/net/websockets/websocket_stream_cookie_test.cc
index c3ae3a9a..585e03d1 100644
--- a/net/websockets/websocket_stream_cookie_test.cc
+++ b/net/websockets/websocket_stream_cookie_test.cc
@@ -32,6 +32,7 @@
  public:
   void CreateAndConnect(const GURL& url,
                         const url::Origin& origin,
+                        const GURL& first_party_for_cookies,
                         const std::string& cookie_header,
                         const std::string& response_body) {
     // We assume cookie_header ends with CRLF if not empty, as
@@ -45,7 +46,8 @@
                                             cookie_header, std::string(),
                                             std::string()),
         response_body);
-    CreateAndConnectStream(url.spec(), NoSubProtocols(), origin, "", nullptr);
+    CreateAndConnectStream(url, NoSubProtocols(), origin,
+                           first_party_for_cookies, "", nullptr);
   }
 
   std::string AddCRLFIfNotEmpty(const std::string& s) {
@@ -128,6 +130,7 @@
   const GURL url(GetParam().url);
   const GURL cookie_url(GetParam().cookie_url);
   const url::Origin origin(GURL("http://www.example.com"));
+  const GURL first_party_for_cookies("http://www.example.com/");
   const std::string cookie_line(GetParam().cookie_line);
   const std::string cookie_header(AddCRLFIfNotEmpty(GetParam().cookie_header));
 
@@ -146,7 +149,8 @@
   ASSERT_TRUE(is_called);
   ASSERT_TRUE(set_cookie_result);
 
-  CreateAndConnect(url, origin, cookie_header, WebSocketStandardResponse(""));
+  CreateAndConnect(url, origin, first_party_for_cookies, cookie_header,
+                   WebSocketStandardResponse(""));
   WaitUntilConnectDone();
   EXPECT_FALSE(has_failed());
 }
@@ -158,6 +162,7 @@
   const GURL url(GetParam().url);
   const GURL cookie_url(GetParam().cookie_url);
   const url::Origin origin(GURL("http://www.example.com"));
+  const GURL first_party_for_cookies("http://www.example.com/");
   const std::string cookie_line(GetParam().cookie_line);
   const std::string cookie_header(AddCRLFIfNotEmpty(GetParam().cookie_header));
 
@@ -173,7 +178,7 @@
   CookieStore* store =
       url_request_context_host_.GetURLRequestContext()->cookie_store();
 
-  CreateAndConnect(url, origin, "", response);
+  CreateAndConnect(url, origin, first_party_for_cookies, "", response);
   WaitUntilConnectDone();
   EXPECT_FALSE(has_failed());
 
diff --git a/net/websockets/websocket_stream_create_test_base.cc b/net/websockets/websocket_stream_create_test_base.cc
index 0d68b62..354c5d7 100644
--- a/net/websockets/websocket_stream_create_test_base.cc
+++ b/net/websockets/websocket_stream_create_test_base.cc
@@ -98,9 +98,10 @@
 }
 
 void WebSocketStreamCreateTestBase::CreateAndConnectStream(
-    const std::string& socket_url,
+    const GURL& socket_url,
     const std::vector<std::string>& sub_protocols,
     const url::Origin& origin,
+    const GURL& first_party_for_cookies,
     const std::string& additional_headers,
     std::unique_ptr<base::Timer> timer) {
   for (size_t i = 0; i < ssl_data_.size(); ++i) {
@@ -114,9 +115,9 @@
       new DeterministicKeyWebSocketHandshakeStreamCreateHelper(delegate,
                                                                sub_protocols));
   stream_request_ = CreateAndConnectStreamForTesting(
-      GURL(socket_url), std::move(create_helper), origin, additional_headers,
-      url_request_context_host_.GetURLRequestContext(), BoundNetLog(),
-      std::move(connect_delegate),
+      socket_url, std::move(create_helper), origin, first_party_for_cookies,
+      additional_headers, url_request_context_host_.GetURLRequestContext(),
+      BoundNetLog(), std::move(connect_delegate),
       timer ? std::move(timer)
             : std::unique_ptr<base::Timer>(new base::Timer(false, false)));
 }
diff --git a/net/websockets/websocket_stream_create_test_base.h b/net/websockets/websocket_stream_create_test_base.h
index 1cdc4b40..3d6a7cf 100644
--- a/net/websockets/websocket_stream_create_test_base.h
+++ b/net/websockets/websocket_stream_create_test_base.h
@@ -19,6 +19,8 @@
 #include "net/websockets/websocket_event_interface.h"
 #include "net/websockets/websocket_test_util.h"
 
+class GURL;
+
 namespace net {
 
 class HttpRequestHeaders;
@@ -37,9 +39,10 @@
 
   // A wrapper for CreateAndConnectStreamForTesting that knows about our default
   // parameters.
-  void CreateAndConnectStream(const std::string& socket_url,
+  void CreateAndConnectStream(const GURL& socket_url,
                               const std::vector<std::string>& sub_protocols,
                               const url::Origin& origin,
+                              const GURL& first_party_for_cookies,
                               const std::string& additional_headers,
                               std::unique_ptr<base::Timer> timer);
 
diff --git a/net/websockets/websocket_stream_test.cc b/net/websockets/websocket_stream_test.cc
index a7d25d7..f3938b34 100644
--- a/net/websockets/websocket_stream_test.cc
+++ b/net/websockets/websocket_stream_test.cc
@@ -76,10 +76,18 @@
   return url::Origin(GURL("http://localhost/"));
 }
 
+static GURL LocalhostUrl() {
+  return GURL("http://localhost/foobar");
+}
+
 static url::Origin GoogleOrigin() {
   return url::Origin(GURL("http://google.com/"));
 }
 
+static GURL GoogleUrl() {
+  return GURL("http://google.com/foobar");
+}
+
 class WebSocketStreamCreateTest : public ::testing::Test,
                                   public WebSocketStreamCreateTestBase {
  public:
@@ -96,6 +104,7 @@
       const std::string& socket_path,
       const std::vector<std::string>& sub_protocols,
       const url::Origin& origin,
+      const GURL& first_party_for_cookies,
       const std::string& send_additional_request_headers,
       const std::string& extra_request_headers,
       const std::string& response_body,
@@ -105,7 +114,8 @@
                                  send_additional_request_headers,
                                  extra_request_headers),
         response_body);
-    CreateAndConnectStream(socket_url, sub_protocols, origin,
+    CreateAndConnectStream(GURL(socket_url), sub_protocols, origin,
+                           first_party_for_cookies,
                            send_additional_request_headers, std::move(timer));
   }
 
@@ -117,13 +127,15 @@
       const std::string& socket_path,
       const std::vector<std::string>& sub_protocols,
       const url::Origin& origin,
+      const GURL& first_party_for_cookies,
       const std::string& send_additional_request_headers,
       const std::string& extra_request_headers,
       const std::string& extra_response_headers,
       std::unique_ptr<base::Timer> timer = std::unique_ptr<base::Timer>()) {
     CreateAndConnectCustomResponse(
         socket_url, socket_host, socket_path, sub_protocols, origin,
-        send_additional_request_headers, extra_request_headers,
+        first_party_for_cookies, send_additional_request_headers,
+        extra_request_headers,
         WebSocketStandardResponse(extra_response_headers), std::move(timer));
   }
 
@@ -131,11 +143,13 @@
       const std::string& socket_url,
       const std::vector<std::string>& sub_protocols,
       const url::Origin& origin,
+      const GURL& first_party_for_cookies,
       const std::string& send_additional_request_headers,
       std::unique_ptr<SequencedSocketData> socket_data,
       std::unique_ptr<base::Timer> timer = std::unique_ptr<base::Timer>()) {
     AddRawExpectations(std::move(socket_data));
-    CreateAndConnectStream(socket_url, sub_protocols, origin,
+    CreateAndConnectStream(GURL(socket_url), sub_protocols, origin,
+                           first_party_for_cookies,
                            send_additional_request_headers, std::move(timer));
   }
 
@@ -156,7 +170,7 @@
       const std::string& extensions_header_value) {
     CreateAndConnectStandard(
         "ws://localhost/testing_path", "localhost", "/testing_path",
-        NoSubProtocols(), LocalhostOrigin(), "", "",
+        NoSubProtocols(), LocalhostOrigin(), LocalhostUrl(), "", "",
         "Sec-WebSocket-Extensions: " + extensions_header_value + "\r\n");
     WaitUntilConnectDone();
   }
@@ -234,7 +248,7 @@
     const std::string request =
         base::StringPrintf(request2format, base64_user_pass.c_str());
     CreateAndConnectRawExpectations(
-        url, NoSubProtocols(), LocalhostOrigin(), "",
+        url, NoSubProtocols(), LocalhostOrigin(), LocalhostUrl(), "",
         helper_.BuildSocketData2(request, response2));
   }
 
@@ -312,7 +326,8 @@
 // Confirm that the basic case works as expected.
 TEST_F(WebSocketStreamCreateTest, SimpleSuccess) {
   CreateAndConnectStandard("ws://localhost/", "localhost", "/",
-                           NoSubProtocols(), LocalhostOrigin(), "", "", "");
+                           NoSubProtocols(), LocalhostOrigin(), LocalhostUrl(),
+                           "", "", "");
   EXPECT_FALSE(request_info_);
   EXPECT_FALSE(response_info_);
   WaitUntilConnectDone();
@@ -334,8 +349,8 @@
       "\r\n";
 
   CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/",
-                                 NoSubProtocols(), LocalhostOrigin(), "", "",
-                                 kResponse);
+                                 NoSubProtocols(), LocalhostOrigin(),
+                                 LocalhostUrl(), "", "", kResponse);
   EXPECT_FALSE(request_info_);
   EXPECT_FALSE(response_info_);
   WaitUntilConnectDone();
@@ -391,7 +406,7 @@
       "User-Agent: OveRrIde\r\n"
       "rAnDomHeader: foobar\r\n");
   CreateAndConnectStandard("ws://localhost/", "localhost", "/",
-                           NoSubProtocols(), LocalhostOrigin(),
+                           NoSubProtocols(), LocalhostOrigin(), LocalhostUrl(),
                            additional_headers, additional_headers, "");
   EXPECT_FALSE(request_info_);
   EXPECT_FALSE(response_info_);
@@ -410,7 +425,8 @@
 // Confirm that the stream isn't established until the message loop runs.
 TEST_F(WebSocketStreamCreateTest, NeedsToRunLoop) {
   CreateAndConnectStandard("ws://localhost/", "localhost", "/",
-                           NoSubProtocols(), LocalhostOrigin(), "", "", "");
+                           NoSubProtocols(), LocalhostOrigin(), LocalhostUrl(),
+                           "", "", "");
   EXPECT_FALSE(has_failed());
   EXPECT_FALSE(stream_);
 }
@@ -419,7 +435,7 @@
 TEST_F(WebSocketStreamCreateTest, PathIsUsed) {
   CreateAndConnectStandard("ws://localhost/testing_path", "localhost",
                            "/testing_path", NoSubProtocols(), LocalhostOrigin(),
-                           "", "", "");
+                           LocalhostUrl(), "", "", "");
   WaitUntilConnectDone();
   EXPECT_FALSE(has_failed());
   EXPECT_TRUE(stream_);
@@ -429,7 +445,7 @@
 TEST_F(WebSocketStreamCreateTest, OriginIsUsed) {
   CreateAndConnectStandard("ws://localhost/testing_path", "localhost",
                            "/testing_path", NoSubProtocols(), GoogleOrigin(),
-                           "", "", "");
+                           GoogleUrl(), "", "", "");
   WaitUntilConnectDone();
   EXPECT_FALSE(has_failed());
   EXPECT_TRUE(stream_);
@@ -441,7 +457,8 @@
   sub_protocols.push_back("chatv11.chromium.org");
   sub_protocols.push_back("chatv20.chromium.org");
   CreateAndConnectStandard("ws://localhost/testing_path", "localhost",
-                           "/testing_path", sub_protocols, GoogleOrigin(), "",
+                           "/testing_path", sub_protocols, GoogleOrigin(),
+                           GoogleUrl(), "",
                            "Sec-WebSocket-Protocol: chatv11.chromium.org, "
                            "chatv20.chromium.org\r\n",
                            "Sec-WebSocket-Protocol: chatv20.chromium.org\r\n");
@@ -455,7 +472,7 @@
 TEST_F(WebSocketStreamCreateTest, UnsolicitedSubProtocol) {
   CreateAndConnectStandard("ws://localhost/testing_path", "localhost",
                            "/testing_path", NoSubProtocols(), GoogleOrigin(),
-                           "", "",
+                           GoogleUrl(), "", "",
                            "Sec-WebSocket-Protocol: chatv20.chromium.org\r\n");
   WaitUntilConnectDone();
   EXPECT_FALSE(stream_);
@@ -472,8 +489,8 @@
   sub_protocols.push_back("chat.example.com");
   CreateAndConnectStandard("ws://localhost/testing_path", "localhost",
                            "/testing_path", sub_protocols, LocalhostOrigin(),
-                           "", "Sec-WebSocket-Protocol: chat.example.com\r\n",
-                           "");
+                           LocalhostUrl(), "",
+                           "Sec-WebSocket-Protocol: chat.example.com\r\n", "");
   WaitUntilConnectDone();
   EXPECT_FALSE(stream_);
   EXPECT_TRUE(has_failed());
@@ -489,7 +506,8 @@
   sub_protocols.push_back("chatv11.chromium.org");
   sub_protocols.push_back("chatv20.chromium.org");
   CreateAndConnectStandard("ws://localhost/testing_path", "localhost",
-                           "/testing_path", sub_protocols, GoogleOrigin(), "",
+                           "/testing_path", sub_protocols, GoogleOrigin(),
+                           GoogleUrl(), "",
                            "Sec-WebSocket-Protocol: chatv11.chromium.org, "
                            "chatv20.chromium.org\r\n",
                            "Sec-WebSocket-Protocol: chatv11.chromium.org, "
@@ -509,7 +527,8 @@
   sub_protocols.push_back("chatv11.chromium.org");
   sub_protocols.push_back("chatv20.chromium.org");
   CreateAndConnectStandard("ws://localhost/testing_path", "localhost",
-                           "/testing_path", sub_protocols, GoogleOrigin(), "",
+                           "/testing_path", sub_protocols, GoogleOrigin(),
+                           GoogleUrl(), "",
                            "Sec-WebSocket-Protocol: chatv11.chromium.org, "
                            "chatv20.chromium.org\r\n",
                            "Sec-WebSocket-Protocol: chatv21.chromium.org\r\n");
@@ -544,7 +563,7 @@
 TEST_F(WebSocketStreamCreateExtensionTest, PerMessageDeflateInflates) {
   CreateAndConnectCustomResponse(
       "ws://localhost/testing_path", "localhost", "/testing_path",
-      NoSubProtocols(), LocalhostOrigin(), "", "",
+      NoSubProtocols(), LocalhostOrigin(), LocalhostUrl(), "", "",
       WebSocketStandardResponse(
           "Sec-WebSocket-Extensions: permessage-deflate\r\n") +
           std::string(
@@ -619,7 +638,8 @@
 TEST_F(WebSocketStreamCreateTest, DoubleAccept) {
   CreateAndConnectStandard(
       "ws://localhost/", "localhost", "/", NoSubProtocols(), LocalhostOrigin(),
-      "", "", "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n");
+      LocalhostUrl(), "", "",
+      "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n");
   WaitUntilConnectDone();
   EXPECT_FALSE(stream_);
   EXPECT_TRUE(has_failed());
@@ -637,9 +657,9 @@
       "Connection: Upgrade\r\n"
       "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
       "\r\n";
-  CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/",
-                                 NoSubProtocols(), LocalhostOrigin(), "", "",
-                                 kInvalidStatusCodeResponse);
+  CreateAndConnectCustomResponse(
+      "ws://localhost/", "localhost", "/", NoSubProtocols(), LocalhostOrigin(),
+      LocalhostUrl(), "", "", kInvalidStatusCodeResponse);
   WaitUntilConnectDone();
   EXPECT_TRUE(has_failed());
   EXPECT_EQ("Error during WebSocket handshake: Unexpected response code: 200",
@@ -658,8 +678,8 @@
       "\r\n"
       "<title>Moved</title><h1>Moved</h1>";
   CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/",
-                                 NoSubProtocols(), LocalhostOrigin(), "", "",
-                                 kRedirectResponse);
+                                 NoSubProtocols(), LocalhostOrigin(),
+                                 LocalhostUrl(), "", "", kRedirectResponse);
   WaitUntilConnectDone();
   EXPECT_TRUE(has_failed());
   EXPECT_EQ("Error during WebSocket handshake: Unexpected response code: 302",
@@ -679,8 +699,8 @@
       "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
       "\r\n";
   CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/",
-                                 NoSubProtocols(), LocalhostOrigin(), "", "",
-                                 kMalformedResponse);
+                                 NoSubProtocols(), LocalhostOrigin(),
+                                 LocalhostUrl(), "", "", kMalformedResponse);
   WaitUntilConnectDone();
   EXPECT_TRUE(has_failed());
   EXPECT_EQ("Error during WebSocket handshake: Invalid status line",
@@ -694,9 +714,9 @@
       "Connection: Upgrade\r\n"
       "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
       "\r\n";
-  CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/",
-                                 NoSubProtocols(), LocalhostOrigin(), "", "",
-                                 kMissingUpgradeResponse);
+  CreateAndConnectCustomResponse(
+      "ws://localhost/", "localhost", "/", NoSubProtocols(), LocalhostOrigin(),
+      LocalhostUrl(), "", "", kMissingUpgradeResponse);
   WaitUntilConnectDone();
   EXPECT_TRUE(has_failed());
   EXPECT_EQ("Error during WebSocket handshake: 'Upgrade' header is missing",
@@ -706,8 +726,8 @@
 // There must only be one upgrade header.
 TEST_F(WebSocketStreamCreateTest, DoubleUpgradeHeader) {
   CreateAndConnectStandard("ws://localhost/", "localhost", "/",
-                           NoSubProtocols(), LocalhostOrigin(), "", "",
-                           "Upgrade: HTTP/2.0\r\n");
+                           NoSubProtocols(), LocalhostOrigin(), LocalhostUrl(),
+                           "", "", "Upgrade: HTTP/2.0\r\n");
   WaitUntilConnectDone();
   EXPECT_TRUE(has_failed());
   EXPECT_EQ("Error during WebSocket handshake: "
@@ -723,9 +743,9 @@
       "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
       "Upgrade: hogefuga\r\n"
       "\r\n";
-  CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/",
-                                 NoSubProtocols(), LocalhostOrigin(), "", "",
-                                 kMissingUpgradeResponse);
+  CreateAndConnectCustomResponse(
+      "ws://localhost/", "localhost", "/", NoSubProtocols(), LocalhostOrigin(),
+      LocalhostUrl(), "", "", kMissingUpgradeResponse);
   WaitUntilConnectDone();
   EXPECT_TRUE(has_failed());
   EXPECT_EQ("Error during WebSocket handshake: "
@@ -740,9 +760,9 @@
       "Upgrade: websocket\r\n"
       "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
       "\r\n";
-  CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/",
-                                 NoSubProtocols(), LocalhostOrigin(), "", "",
-                                 kMissingConnectionResponse);
+  CreateAndConnectCustomResponse(
+      "ws://localhost/", "localhost", "/", NoSubProtocols(), LocalhostOrigin(),
+      LocalhostUrl(), "", "", kMissingConnectionResponse);
   WaitUntilConnectDone();
   EXPECT_TRUE(has_failed());
   EXPECT_EQ("Error during WebSocket handshake: "
@@ -758,9 +778,9 @@
       "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
       "Connection: hogefuga\r\n"
       "\r\n";
-  CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/",
-                                 NoSubProtocols(), LocalhostOrigin(), "", "",
-                                 kMissingConnectionResponse);
+  CreateAndConnectCustomResponse(
+      "ws://localhost/", "localhost", "/", NoSubProtocols(), LocalhostOrigin(),
+      LocalhostUrl(), "", "", kMissingConnectionResponse);
   WaitUntilConnectDone();
   EXPECT_TRUE(has_failed());
   EXPECT_EQ("Error during WebSocket handshake: "
@@ -776,9 +796,9 @@
       "Connection: Upgrade, Keep-Alive\r\n"
       "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
       "\r\n";
-  CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/",
-                                 NoSubProtocols(), LocalhostOrigin(), "", "",
-                                 kAdditionalConnectionTokenResponse);
+  CreateAndConnectCustomResponse(
+      "ws://localhost/", "localhost", "/", NoSubProtocols(), LocalhostOrigin(),
+      LocalhostUrl(), "", "", kAdditionalConnectionTokenResponse);
   WaitUntilConnectDone();
   EXPECT_FALSE(has_failed());
   EXPECT_TRUE(stream_);
@@ -791,9 +811,9 @@
       "Upgrade: websocket\r\n"
       "Connection: Upgrade\r\n"
       "\r\n";
-  CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/",
-                                 NoSubProtocols(), LocalhostOrigin(), "", "",
-                                 kMissingAcceptResponse);
+  CreateAndConnectCustomResponse(
+      "ws://localhost/", "localhost", "/", NoSubProtocols(), LocalhostOrigin(),
+      LocalhostUrl(), "", "", kMissingAcceptResponse);
   WaitUntilConnectDone();
   EXPECT_TRUE(has_failed());
   EXPECT_EQ("Error during WebSocket handshake: "
@@ -809,9 +829,9 @@
       "Connection: Upgrade\r\n"
       "Sec-WebSocket-Accept: x/byyPZ2tOFvJCGkkugcKvqhhPk=\r\n"
       "\r\n";
-  CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/",
-                                 NoSubProtocols(), LocalhostOrigin(), "", "",
-                                 kIncorrectAcceptResponse);
+  CreateAndConnectCustomResponse(
+      "ws://localhost/", "localhost", "/", NoSubProtocols(), LocalhostOrigin(),
+      LocalhostUrl(), "", "", kIncorrectAcceptResponse);
   WaitUntilConnectDone();
   EXPECT_TRUE(has_failed());
   EXPECT_EQ("Error during WebSocket handshake: "
@@ -822,7 +842,8 @@
 // Cancellation works.
 TEST_F(WebSocketStreamCreateTest, Cancellation) {
   CreateAndConnectStandard("ws://localhost/", "localhost", "/",
-                           NoSubProtocols(), LocalhostOrigin(), "", "", "");
+                           NoSubProtocols(), LocalhostOrigin(), LocalhostUrl(),
+                           "", "", "");
   stream_request_.reset();
   // WaitUntilConnectDone doesn't work in this case.
   base::RunLoop().RunUntilIdle();
@@ -838,7 +859,7 @@
   socket_data->set_connect_data(
       MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED));
   CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(),
-                                  LocalhostOrigin(), "",
+                                  LocalhostOrigin(), LocalhostUrl(), "",
                                   std::move(socket_data));
   WaitUntilConnectDone();
   EXPECT_TRUE(has_failed());
@@ -854,7 +875,7 @@
   socket_data->set_connect_data(
       MockConnect(ASYNC, ERR_CONNECTION_TIMED_OUT));
   CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(),
-                                  LocalhostOrigin(), "",
+                                  LocalhostOrigin(), LocalhostUrl(), "",
                                   std::move(socket_data));
   WaitUntilConnectDone();
   EXPECT_TRUE(has_failed());
@@ -869,8 +890,8 @@
   std::unique_ptr<MockWeakTimer> timer(new MockWeakTimer(false, false));
   base::WeakPtr<MockWeakTimer> weak_timer = timer->AsWeakPtr();
   CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(),
-                                  LocalhostOrigin(), "", std::move(socket_data),
-                                  std::move(timer));
+                                  LocalhostOrigin(), LocalhostUrl(), "",
+                                  std::move(socket_data), std::move(timer));
   EXPECT_FALSE(has_failed());
   ASSERT_TRUE(weak_timer.get());
   EXPECT_TRUE(weak_timer->IsRunning());
@@ -890,8 +911,8 @@
   base::WeakPtr<MockWeakTimer> weak_timer = timer->AsWeakPtr();
 
   CreateAndConnectStandard("ws://localhost/", "localhost", "/",
-                           NoSubProtocols(), LocalhostOrigin(), "", "", "",
-                           std::move(timer));
+                           NoSubProtocols(), LocalhostOrigin(), LocalhostUrl(),
+                           "", "", "", std::move(timer));
   ASSERT_TRUE(weak_timer);
   EXPECT_TRUE(weak_timer->IsRunning());
 
@@ -910,8 +931,8 @@
   std::unique_ptr<MockWeakTimer> timer(new MockWeakTimer(false, false));
   base::WeakPtr<MockWeakTimer> weak_timer = timer->AsWeakPtr();
   CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(),
-                                  LocalhostOrigin(), "", std::move(socket_data),
-                                  std::move(timer));
+                                  LocalhostOrigin(), LocalhostUrl(), "",
+                                  std::move(socket_data), std::move(timer));
   ASSERT_TRUE(weak_timer.get());
   EXPECT_TRUE(weak_timer->IsRunning());
 
@@ -928,7 +949,7 @@
   std::unique_ptr<SequencedSocketData> socket_data(BuildNullSocketData());
   socket_data->set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
   CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(),
-                                  LocalhostOrigin(), "",
+                                  LocalhostOrigin(), LocalhostUrl(), "",
                                   std::move(socket_data));
   stream_request_.reset();
   // WaitUntilConnectDone doesn't work in this case.
@@ -945,7 +966,7 @@
       new SequencedSocketData(NULL, 0, writes, arraysize(writes)));
   socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK));
   CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(),
-                                  LocalhostOrigin(), "",
+                                  LocalhostOrigin(), LocalhostUrl(), "",
                                   base::WrapUnique(socket_data));
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(socket_data->AllWriteDataConsumed());
@@ -970,7 +991,7 @@
       BuildSocketData(reads, writes));
   SequencedSocketData* socket_data_raw_ptr = socket_data.get();
   CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(),
-                                  LocalhostOrigin(), "",
+                                  LocalhostOrigin(), LocalhostUrl(), "",
                                   std::move(socket_data));
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(socket_data_raw_ptr->AllReadDataConsumed());
@@ -994,8 +1015,8 @@
   }
   ASSERT_GT(set_cookie_headers.size(), 256U * 1024U);
   CreateAndConnectStandard("ws://localhost/", "localhost", "/",
-                           NoSubProtocols(), LocalhostOrigin(), "", "",
-                           set_cookie_headers);
+                           NoSubProtocols(), LocalhostOrigin(), LocalhostUrl(),
+                           "", "", set_cookie_headers);
   WaitUntilConnectDone();
   EXPECT_TRUE(has_failed());
   EXPECT_FALSE(response_info_);
@@ -1013,7 +1034,7 @@
       BuildSocketData(reads, writes));
   SequencedSocketData* socket_data_raw_ptr = socket_data.get();
   CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(),
-                                  LocalhostOrigin(), "",
+                                  LocalhostOrigin(), LocalhostUrl(), "",
                                   std::move(socket_data));
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(socket_data_raw_ptr->AllReadDataConsumed());
@@ -1032,7 +1053,7 @@
   ASSERT_TRUE(ssl_data_[0]->cert.get());
   std::unique_ptr<SequencedSocketData> raw_socket_data(BuildNullSocketData());
   CreateAndConnectRawExpectations("wss://localhost/", NoSubProtocols(),
-                                  LocalhostOrigin(), "",
+                                  LocalhostOrigin(), LocalhostUrl(), "",
                                   std::move(raw_socket_data));
   // WaitUntilConnectDone doesn't work in this case.
   base::RunLoop().RunUntilIdle();
@@ -1055,7 +1076,8 @@
   ssl_data_.push_back(std::move(ssl_data));
   url_request_context_host_.AddRawExpectations(BuildNullSocketData());
   CreateAndConnectStandard("wss://localhost/", "localhost", "/",
-                           NoSubProtocols(), LocalhostOrigin(), "", "", "");
+                           NoSubProtocols(), LocalhostOrigin(), LocalhostUrl(),
+                           "", "", "");
   // WaitUntilConnectDone doesn't work in this case.
   base::RunLoop().RunUntilIdle();
   ASSERT_TRUE(ssl_error_callbacks_);
@@ -1069,8 +1091,8 @@
 // connection should fail cleanly.
 TEST_F(WebSocketStreamCreateBasicAuthTest, FailureNoCredentials) {
   CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/",
-                                 NoSubProtocols(), LocalhostOrigin(), "", "",
-                                 kUnauthorizedResponse);
+                                 NoSubProtocols(), LocalhostOrigin(),
+                                 LocalhostUrl(), "", "", kUnauthorizedResponse);
   WaitUntilConnectDone();
   EXPECT_TRUE(has_failed());
   EXPECT_EQ("HTTP Authentication failed; no valid credentials available",
@@ -1104,7 +1126,8 @@
   AddRawExpectations(helper_.BuildSocketData1(kUnauthorizedResponse));
 
   CreateAndConnectRawExpectations(
-      "ws://FooBar:pass@localhost/", NoSubProtocols(), LocalhostOrigin(), "",
+      "ws://FooBar:pass@localhost/", NoSubProtocols(), LocalhostOrigin(),
+      LocalhostUrl(), "",
       helper_.BuildSocketData2(kAuthorizedRequest,
                                WebSocketStandardResponse(std::string())));
   WaitUntilConnectDone();
@@ -1120,9 +1143,9 @@
 
   {
     StreamCreation creation;
-    creation.CreateAndConnectStandard("ws://localhost/", "localhost", "/",
-                                      creation.NoSubProtocols(),
-                                      LocalhostOrigin(), "", "", "");
+    creation.CreateAndConnectStandard(
+        "ws://localhost/", "localhost", "/", creation.NoSubProtocols(),
+        LocalhostOrigin(), LocalhostUrl(), "", "", "");
   }
 
   std::unique_ptr<base::HistogramSamples> samples(GetSamples(name));
@@ -1141,9 +1164,9 @@
 
   {
     StreamCreation creation;
-    creation.CreateAndConnectStandard("ws://localhost/", "localhost", "/",
-                                      creation.NoSubProtocols(),
-                                      LocalhostOrigin(), "", "", "");
+    creation.CreateAndConnectStandard(
+        "ws://localhost/", "localhost", "/", creation.NoSubProtocols(),
+        LocalhostOrigin(), LocalhostUrl(), "", "", "");
     creation.WaitUntilConnectDone();
   }
 
@@ -1171,7 +1194,7 @@
         "\r\n";
     creation.CreateAndConnectCustomResponse(
         "ws://localhost/", "localhost", "/", creation.NoSubProtocols(),
-        LocalhostOrigin(), "", "", kInvalidStatusCodeResponse);
+        LocalhostOrigin(), LocalhostUrl(), "", "", kInvalidStatusCodeResponse);
     creation.WaitUntilConnectDone();
   }
 
@@ -1204,7 +1227,7 @@
       BuildSocketData(reads, writes));
   socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK));
   CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(),
-                                  LocalhostOrigin(), "",
+                                  LocalhostOrigin(), LocalhostUrl(), "",
                                   std::move(socket_data));
   WaitUntilConnectDone();
   EXPECT_TRUE(has_failed());
@@ -1231,7 +1254,7 @@
       BuildSocketData(reads, writes));
   url_request_context_host_.SetProxyConfig("https=proxy:8000");
   CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(),
-                                  LocalhostOrigin(), "",
+                                  LocalhostOrigin(), LocalhostUrl(), "",
                                   std::move(socket_data));
   WaitUntilConnectDone();
   EXPECT_TRUE(has_failed());
diff --git a/ppapi/ppapi_internal.gyp b/ppapi/ppapi_internal.gyp
index 99b4652d..a1d53b0 100644
--- a/ppapi/ppapi_internal.gyp
+++ b/ppapi/ppapi_internal.gyp
@@ -53,6 +53,7 @@
         '../media/media.gyp:shared_memory_support',
         '../skia/skia.gyp:skia',
         '../third_party/icu/icu.gyp:icuuc',
+        '../ui/gfx/gfx.gyp:gfx_geometry',
         '../ui/surface/surface.gyp:surface',
         '../url/url.gyp:url_lib',
         'ppapi.gyp:ppapi_c',
@@ -87,6 +88,7 @@
             '../gpu/gpu.gyp:command_buffer_traits',
             '../ipc/ipc.gyp:ipc',
             '../skia/skia.gyp:skia',
+            '../ui/gfx/ipc/geometry/gfx_ipc_geometry.gyp:gfx_ipc_geometry',
             'ppapi.gyp:ppapi_c',
             'ppapi_shared',
           ],
@@ -168,6 +170,7 @@
             '../third_party/icu/icu.gyp:icuuc',
             '../third_party/icu/icu.gyp:icui18n',
             '../ui/gfx/gfx.gyp:gfx_geometry',
+            '../ui/gfx/ipc/geometry/gfx_ipc_geometry.gyp:gfx_ipc_geometry',
             '../ui/surface/surface.gyp:surface',
             'ppapi.gyp:ppapi_c',
             'ppapi_shared',
@@ -221,6 +224,7 @@
             '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations_win64',
             '../gpu/gpu.gyp:command_buffer_common_win64',
             '../ipc/ipc.gyp:ipc_win64',
+            '../ui/gfx/gfx.gyp:gfx_geometry_win64',
           ],
           'defines': [
             '<@(nacl_win64_defines)',
@@ -247,6 +251,8 @@
             '../base/base.gyp:base_win64',
             '../ipc/ipc.gyp:ipc_win64',
             '../gpu/gpu.gyp:command_buffer_traits_win64',
+            '../ui/gfx/gfx.gyp:gfx_geometry_win64',
+            '../ui/gfx/ipc/geometry/gfx_ipc_geometry.gyp:gfx_ipc_geometry_win64',
             'ppapi.gyp:ppapi_c',
             'ppapi_shared_win64',
           ],
diff --git a/ppapi/ppapi_proxy_nacl.gyp b/ppapi/ppapi_proxy_nacl.gyp
index 1f194792..dd49bb30 100644
--- a/ppapi/ppapi_proxy_nacl.gyp
+++ b/ppapi/ppapi_proxy_nacl.gyp
@@ -47,6 +47,8 @@
             '../ppapi/ppapi_shared_nacl.gyp:ppapi_shared_nacl',
             '../third_party/WebKit/public/blink_headers.gyp:blink_headers',
             '../third_party/khronos/khronos.gyp:khronos_headers',
+            '../ui/gfx/gfx_nacl.gyp:gfx_geometry_nacl',
+            '../ui/gfx/ipc/geometry/gfx_ipc_geometry_nacl.gyp:gfx_ipc_geometry_nacl',
           ],
         },
       ],
diff --git a/ppapi/ppapi_shared_nacl.gyp b/ppapi/ppapi_shared_nacl.gyp
index 05e4aca..c292a34 100644
--- a/ppapi/ppapi_shared_nacl.gyp
+++ b/ppapi/ppapi_shared_nacl.gyp
@@ -38,6 +38,7 @@
             '../gpu/gpu_nacl.gyp:gles2_implementation_nacl',
             '../media/media_nacl.gyp:shared_memory_support_nacl',
             '../third_party/khronos/khronos.gyp:khronos_headers',
+            '../ui/gfx/gfx_nacl.gyp:gfx_geometry_nacl',
           ],
         },
       ],
diff --git a/ppapi/ppapi_tests.gypi b/ppapi/ppapi_tests.gypi
index 9fdc8025..f6ff8e6 100644
--- a/ppapi/ppapi_tests.gypi
+++ b/ppapi/ppapi_tests.gypi
@@ -209,6 +209,7 @@
         '../skia/skia.gyp:skia',
         '../testing/gmock.gyp:gmock',
         '../testing/gtest.gyp:gtest',
+        '../ui/gfx/gfx.gyp:gfx_geometry',
         '../ui/surface/surface.gyp:surface',
       ],
       'sources': [
diff --git a/ppapi/proxy/BUILD.gn b/ppapi/proxy/BUILD.gn
index fd36af7..b50b61a 100644
--- a/ppapi/proxy/BUILD.gn
+++ b/ppapi/proxy/BUILD.gn
@@ -287,6 +287,8 @@
     "//mojo/edk/system",
     "//ppapi/c",
     "//ppapi/shared_impl",
+    "//ui/gfx/geometry",
+    "//ui/gfx/ipc/geometry",
   ]
 
   if (!is_nacl) {
diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h
index eaf2feb..968fe57 100644
--- a/ppapi/proxy/ppapi_messages.h
+++ b/ppapi/proxy/ppapi_messages.h
@@ -1087,11 +1087,10 @@
 // after this message is sent.
 IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBGraphics3D_TakeFrontBuffer,
                     ppapi::HostResource /* graphics_3d */)
-IPC_MESSAGE_ROUTED4(PpapiHostMsg_PPBGraphics3D_SwapBuffers,
+IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBGraphics3D_SwapBuffers,
                     ppapi::HostResource /* graphics_3d */,
                     gpu::SyncToken /* sync_token */,
-                    int32_t /* width*/,
-                    int32_t /* height*/)
+                    gfx::Size /* size */)
 IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBGraphics3D_EnsureWorkVisible,
                     ppapi::HostResource /* context */)
 
diff --git a/ppapi/proxy/ppb_graphics_3d_proxy.cc b/ppapi/proxy/ppb_graphics_3d_proxy.cc
index ac08224..7725330b 100644
--- a/ppapi/proxy/ppb_graphics_3d_proxy.cc
+++ b/ppapi/proxy/ppb_graphics_3d_proxy.cc
@@ -48,8 +48,8 @@
 
 }  // namespace
 
-Graphics3D::Graphics3D(const HostResource& resource)
-    : PPB_Graphics3D_Shared(resource) {
+Graphics3D::Graphics3D(const HostResource& resource, const gfx::Size& size)
+    : PPB_Graphics3D_Shared(resource, size) {
 }
 
 Graphics3D::~Graphics3D() {
@@ -118,8 +118,7 @@
 }
 
 int32_t Graphics3D::DoSwapBuffers(const gpu::SyncToken& sync_token,
-                                  int32_t width,
-                                  int32_t height) {
+                                  const gfx::Size& size) {
   // A valid sync token would indicate a swap buffer already happened somehow.
   DCHECK(!sync_token.HasData());
 
@@ -137,8 +136,7 @@
   gl->GenSyncTokenCHROMIUM(fence_sync, new_sync_token.GetData());
 
   IPC::Message* msg = new PpapiHostMsg_PPBGraphics3D_SwapBuffers(
-      API_ID_PPB_GRAPHICS_3D, host_resource(), new_sync_token, width,
-      height);
+      API_ID_PPB_GRAPHICS_3D, host_resource(), new_sync_token, size);
   msg->set_unblock(true);
   PluginDispatcher::GetForResource(this)->Send(msg);
 
@@ -215,7 +213,8 @@
   if (result.is_null())
     return 0;
 
-  scoped_refptr<Graphics3D> graphics_3d(new Graphics3D(result));
+  scoped_refptr<Graphics3D> graphics_3d(
+      new Graphics3D(result, attrib_helper.offscreen_framebuffer_size));
   if (!graphics_3d->Init(share_gles2, capabilities, shared_state,
                          command_buffer_id)) {
     return 0;
@@ -361,14 +360,13 @@
 
 void PPB_Graphics3D_Proxy::OnMsgSwapBuffers(const HostResource& context,
                                             const gpu::SyncToken& sync_token,
-                                            int32_t width,
-                                            int32_t height) {
+                                            const gfx::Size& size) {
   EnterHostFromHostResourceForceCallback<PPB_Graphics3D_API> enter(
       context, callback_factory_,
       &PPB_Graphics3D_Proxy::SendSwapBuffersACKToPlugin, context);
   if (enter.succeeded())
     enter.SetResult(enter.object()->SwapBuffersWithSyncToken(
-        enter.callback(), sync_token, width, height));
+        enter.callback(), sync_token, size));
 }
 
 void PPB_Graphics3D_Proxy::OnMsgTakeFrontBuffer(const HostResource& context) {
diff --git a/ppapi/proxy/ppb_graphics_3d_proxy.h b/ppapi/proxy/ppb_graphics_3d_proxy.h
index 2ae06e9..54c4c7a7 100644
--- a/ppapi/proxy/ppb_graphics_3d_proxy.h
+++ b/ppapi/proxy/ppb_graphics_3d_proxy.h
@@ -39,7 +39,7 @@
 
 class PPAPI_PROXY_EXPORT Graphics3D : public PPB_Graphics3D_Shared {
  public:
-  explicit Graphics3D(const HostResource& resource);
+  Graphics3D(const HostResource& resource, const gfx::Size& size);
   ~Graphics3D() override;
 
   bool Init(gpu::gles2::GLES2Implementation* share_gles2,
@@ -65,8 +65,7 @@
   gpu::CommandBuffer* GetCommandBuffer() override;
   gpu::GpuControl* GetGpuControl() override;
   int32_t DoSwapBuffers(const gpu::SyncToken& sync_token,
-                        int32_t width,
-                        int32_t height) override;
+                        const gfx::Size& size) override;
 
   std::unique_ptr<PpapiCommandBufferProxy> command_buffer_;
 
@@ -116,8 +115,7 @@
   void OnMsgDestroyTransferBuffer(const HostResource& context, int32_t id);
   void OnMsgSwapBuffers(const HostResource& context,
                         const gpu::SyncToken& sync_token,
-                        int32_t width,
-                        int32_t height);
+                        const gfx::Size& size);
   void OnMsgTakeFrontBuffer(const HostResource& context);
   void OnMsgEnsureWorkVisible(const HostResource& context);
   // Renderer->plugin message handlers.
diff --git a/ppapi/proxy/video_decoder_resource_unittest.cc b/ppapi/proxy/video_decoder_resource_unittest.cc
index a8e3c4fb..80c28035 100644
--- a/ppapi/proxy/video_decoder_resource_unittest.cc
+++ b/ppapi/proxy/video_decoder_resource_unittest.cc
@@ -109,7 +109,7 @@
     HostResource host_resource;
     host_resource.SetHostResource(pp_instance(), kGraphics3D);
     scoped_refptr<ppapi::proxy::Graphics3D> graphics_3d(
-        new ppapi::proxy::Graphics3D(host_resource));
+        new ppapi::proxy::Graphics3D(host_resource, gfx::Size(640, 480)));
     return graphics_3d->GetReference();
   }
 
diff --git a/ppapi/shared_impl/DEPS b/ppapi/shared_impl/DEPS
index 3947af12..7f786933 100644
--- a/ppapi/shared_impl/DEPS
+++ b/ppapi/shared_impl/DEPS
@@ -4,6 +4,7 @@
   "+media/audio",
   "+media/base",
   "+skia",
+  "+ui/gfx/geometry",
 
   "-ppapi/cpp",
   "-ppapi/proxy",
diff --git a/ppapi/shared_impl/file_ref_util.cc b/ppapi/shared_impl/file_ref_util.cc
index d111f69..a517b3f 100644
--- a/ppapi/shared_impl/file_ref_util.cc
+++ b/ppapi/shared_impl/file_ref_util.cc
@@ -52,7 +52,7 @@
 }
 
 void NormalizeInternalPath(std::string* path) {
-  if (path->size() > 1 && path->at(path->size() - 1) == '/')
+  if (path->size() > 1 && path->back() == '/')
     path->erase(path->size() - 1, 1);
 }
 
diff --git a/ppapi/shared_impl/ppb_graphics_3d_shared.cc b/ppapi/shared_impl/ppb_graphics_3d_shared.cc
index 0c40b4cb..4d3a4b06 100644
--- a/ppapi/shared_impl/ppb_graphics_3d_shared.cc
+++ b/ppapi/shared_impl/ppb_graphics_3d_shared.cc
@@ -17,8 +17,9 @@
 PPB_Graphics3D_Shared::PPB_Graphics3D_Shared(PP_Instance instance)
     : Resource(OBJECT_IS_IMPL, instance) {}
 
-PPB_Graphics3D_Shared::PPB_Graphics3D_Shared(const HostResource& host_resource)
-    : Resource(OBJECT_IS_PROXY, host_resource) {}
+PPB_Graphics3D_Shared::PPB_Graphics3D_Shared(const HostResource& host_resource,
+                                             const gfx::Size& size)
+    : Resource(OBJECT_IS_PROXY, host_resource), size_(size) {}
 
 PPB_Graphics3D_Shared::~PPB_Graphics3D_Shared() {
   // Make sure that GLES2 implementation has already been destroyed.
@@ -51,22 +52,20 @@
     return PP_ERROR_BADARGUMENT;
 
   gles2_impl()->ResizeCHROMIUM(width, height, 1.f, true);
-  width_ = width;
-  height_ = height;
+  size_ = gfx::Size(width, height);
   // TODO(alokp): Check if resize succeeded and return appropriate error code.
   return PP_OK;
 }
 
 int32_t PPB_Graphics3D_Shared::SwapBuffers(
     scoped_refptr<TrackedCallback> callback) {
-  return SwapBuffersWithSyncToken(callback, gpu::SyncToken(), width_, height_);
+  return SwapBuffersWithSyncToken(callback, gpu::SyncToken(), size_);
 }
 
 int32_t PPB_Graphics3D_Shared::SwapBuffersWithSyncToken(
     scoped_refptr<TrackedCallback> callback,
     const gpu::SyncToken& sync_token,
-    int32_t width,
-    int32_t height) {
+    const gfx::Size& size) {
   if (HasPendingSwap()) {
     Log(PP_LOGLEVEL_ERROR,
         "PPB_Graphics3D.SwapBuffers: Plugin attempted swap "
@@ -76,7 +75,7 @@
   }
 
   swap_callback_ = callback;
-  return DoSwapBuffers(sync_token, width, height);
+  return DoSwapBuffers(sync_token, size);
 }
 
 int32_t PPB_Graphics3D_Shared::GetAttribMaxValue(int32_t attribute,
diff --git a/ppapi/shared_impl/ppb_graphics_3d_shared.h b/ppapi/shared_impl/ppb_graphics_3d_shared.h
index 4c8a1ab6..84bad21d 100644
--- a/ppapi/shared_impl/ppb_graphics_3d_shared.h
+++ b/ppapi/shared_impl/ppb_graphics_3d_shared.h
@@ -15,6 +15,7 @@
 #include "ppapi/shared_impl/resource.h"
 #include "ppapi/shared_impl/tracked_callback.h"
 #include "ppapi/thunk/ppb_graphics_3d_api.h"
+#include "ui/gfx/geometry/size.h"
 
 namespace gpu {
 class CommandBuffer;
@@ -44,8 +45,7 @@
   int32_t SwapBuffers(scoped_refptr<TrackedCallback> callback) override;
   int32_t SwapBuffersWithSyncToken(scoped_refptr<TrackedCallback> callback,
                                    const gpu::SyncToken& sync_token,
-                                   int32_t width,
-                                   int32_t height) override;
+                                   const gfx::Size& size) override;
   int32_t GetAttribMaxValue(int32_t attribute, int32_t* value) override;
 
   void* MapTexSubImage2DCHROMIUM(GLenum target,
@@ -67,14 +67,14 @@
 
  protected:
   PPB_Graphics3D_Shared(PP_Instance instance);
-  PPB_Graphics3D_Shared(const HostResource& host_resource);
+  PPB_Graphics3D_Shared(const HostResource& host_resource,
+                        const gfx::Size& size);
   ~PPB_Graphics3D_Shared() override;
 
   virtual gpu::CommandBuffer* GetCommandBuffer() = 0;
   virtual gpu::GpuControl* GetGpuControl() = 0;
   virtual int32_t DoSwapBuffers(const gpu::SyncToken& sync_token,
-                                int32_t width,
-                                int32_t height) = 0;
+                                const gfx::Size& size) = 0;
 
   bool HasPendingSwap() const;
   bool CreateGLES2Impl(int32_t command_buffer_size,
@@ -87,9 +87,9 @@
   std::unique_ptr<gpu::TransferBuffer> transfer_buffer_;
   std::unique_ptr<gpu::gles2::GLES2Implementation> gles2_impl_;
 
-  // A local cache of the size of the viewport.
-  int32_t width_ = -1;
-  int32_t height_ = -1;
+  // A local cache of the size of the viewport. This is only valid in plugin
+  // resources.
+  gfx::Size size_;
 
   // Callback that needs to be executed when swap-buffers is completed.
   scoped_refptr<TrackedCallback> swap_callback_;
diff --git a/ppapi/thunk/ppb_graphics_3d_api.h b/ppapi/thunk/ppb_graphics_3d_api.h
index 9c2e312..8d590ec9 100644
--- a/ppapi/thunk/ppb_graphics_3d_api.h
+++ b/ppapi/thunk/ppb_graphics_3d_api.h
@@ -13,6 +13,10 @@
 #include "ppapi/c/ppb_graphics_3d.h"
 #include "ppapi/thunk/ppapi_thunk_export.h"
 
+namespace gfx {
+class Size;
+}
+
 namespace gpu {
 struct SyncToken;
 }
@@ -36,8 +40,7 @@
   virtual int32_t SwapBuffersWithSyncToken(
       scoped_refptr<TrackedCallback> callback,
       const gpu::SyncToken& sync_token,
-      int32_t width,
-      int32_t height) = 0;
+      const gfx::Size& size) = 0;
   virtual int32_t GetAttribMaxValue(int32_t attribute, int32_t* value) = 0;
 
   // Graphics3DTrusted API.
diff --git a/remoting/android/java/src/org/chromium/chromoting/AbstractDesktopView.java b/remoting/android/java/src/org/chromium/chromoting/AbstractDesktopView.java
index 63202bc..06f51a4 100644
--- a/remoting/android/java/src/org/chromium/chromoting/AbstractDesktopView.java
+++ b/remoting/android/java/src/org/chromium/chromoting/AbstractDesktopView.java
@@ -8,8 +8,6 @@
 import android.graphics.Point;
 import android.view.SurfaceView;
 
-import org.chromium.chromoting.jni.Client;
-
 /**
  * Callback interface to allow the TouchInputHandler to request actions on the DesktopView.
  */
@@ -18,12 +16,6 @@
         super(context);
     }
 
-    /**
-     * Initializes the instance. Implementations can assume this function will be called exactly
-     * once after constructor but before other functions.
-     */
-    public abstract void init(Desktop desktop, Client client);
-
     /** Triggers a brief animation to indicate the existence and location of an input event. */
     public abstract void showInputFeedback(DesktopView.InputFeedbackType feedbackToShow, Point pos);
 
diff --git a/remoting/android/java/src/org/chromium/chromoting/Desktop.java b/remoting/android/java/src/org/chromium/chromoting/Desktop.java
index d328a030..81e454b 100644
--- a/remoting/android/java/src/org/chromium/chromoting/Desktop.java
+++ b/remoting/android/java/src/org/chromium/chromoting/Desktop.java
@@ -105,11 +105,10 @@
         mToolbar = (Toolbar) findViewById(R.id.toolbar);
         setSupportActionBar(mToolbar);
 
-        AbstractDesktopView remoteHostDesktop = mClient.createDesktopView(this);
+        AbstractDesktopView remoteHostDesktop = mClient.createDesktopView(this, mClient);
         remoteHostDesktop.setLayoutParams(new ViewGroup.LayoutParams(
                 ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
         ((ViewGroup) findViewById(R.id.desktop_view_placeholder)).addView(remoteHostDesktop);
-        remoteHostDesktop.init(this, mClient);
         mSwitchToCardboardDesktopActivity = false;
 
         getSupportActionBar().setDisplayShowTitleEnabled(false);
diff --git a/remoting/android/java/src/org/chromium/chromoting/DesktopView.java b/remoting/android/java/src/org/chromium/chromoting/DesktopView.java
index 56e3a8b..57b8a7c 100644
--- a/remoting/android/java/src/org/chromium/chromoting/DesktopView.java
+++ b/remoting/android/java/src/org/chromium/chromoting/DesktopView.java
@@ -39,12 +39,9 @@
     private final TouchInputHandler mInputHandler;
 
     /** The parent Desktop activity. */
-    private Desktop mDesktop;
+    private final Desktop mDesktop;
 
-    /** The Client connection, used to inject input and fetch the video frames. */
-    private Client mClient;
-
-    private Display mDisplay;
+    private final Display mDisplay;
 
 
     // Flag to prevent multiple repaint requests from being backed up. Requests for repainting will
@@ -72,17 +69,20 @@
     /** Whether the TouchInputHandler has requested animation to be performed. */
     private boolean mInputAnimationRunning = false;
 
-    public DesktopView(Context context, Display display) {
-        super(context);
-
+    public DesktopView(Display display, Desktop desktop, Client client) {
+        super(desktop);
         Preconditions.notNull(display);
+        Preconditions.notNull(desktop);
+        Preconditions.notNull(client);
         mDisplay = display;
+        mDesktop = desktop;
 
         // Give this view keyboard focus, allowing us to customize the soft keyboard's settings.
         setFocusableInTouchMode(true);
 
         mRenderData = new RenderData();
-        mInputHandler = new TouchInputHandler(this, context, mRenderData);
+        mInputHandler = new TouchInputHandler(this, desktop, mRenderData);
+        mInputHandler.init(desktop, new InputEventSender(client));
 
         mRepaintPending = false;
 
@@ -91,17 +91,6 @@
         attachRedrawCallback();
     }
 
-    @Override
-    public void init(Desktop desktop, Client client) {
-        Preconditions.isNull(mDesktop);
-        Preconditions.isNull(mClient);
-        Preconditions.notNull(desktop);
-        Preconditions.notNull(client);
-        mDesktop = desktop;
-        mClient = client;
-        mInputHandler.init(desktop, new InputEventSender(client));
-    }
-
     public Event<PaintEventParameter> onPaint() {
         return mOnPaint;
     }
diff --git a/remoting/android/java/src/org/chromium/chromoting/DesktopViewFactory.java b/remoting/android/java/src/org/chromium/chromoting/DesktopViewFactory.java
index 3cb55ba..fd51d5d5 100644
--- a/remoting/android/java/src/org/chromium/chromoting/DesktopViewFactory.java
+++ b/remoting/android/java/src/org/chromium/chromoting/DesktopViewFactory.java
@@ -4,7 +4,7 @@
 
 package org.chromium.chromoting;
 
-import android.content.Context;
+import org.chromium.chromoting.jni.Client;
 
 /**
  * Interface for creating a implementation specific desktop view.
@@ -14,5 +14,5 @@
      * Creates an uninitialized implementation specific desktop view. Initializing and adding the
      * view should done separately.
      */
-    AbstractDesktopView createDesktopView(Context context);
+    AbstractDesktopView createDesktopView(Desktop desktop, Client client);
 }
diff --git a/remoting/android/java/src/org/chromium/chromoting/jni/Client.java b/remoting/android/java/src/org/chromium/chromoting/jni/Client.java
index 3a8114d..3373c07 100644
--- a/remoting/android/java/src/org/chromium/chromoting/jni/Client.java
+++ b/remoting/android/java/src/org/chromium/chromoting/jni/Client.java
@@ -11,6 +11,7 @@
 import org.chromium.base.annotations.SuppressFBWarnings;
 import org.chromium.chromoting.AbstractDesktopView;
 import org.chromium.chromoting.CapabilityManager;
+import org.chromium.chromoting.Desktop;
 import org.chromium.chromoting.DesktopViewFactory;
 import org.chromium.chromoting.InputStub;
 import org.chromium.chromoting.Preconditions;
@@ -45,20 +46,20 @@
     }
 
     /**
-     * Sets the desktop view factory. Called by the native code when the connection starts.
+     * Sets the desktop view factory to be used by {@link Client#createDesktopView(Context)}.
      * @param factory The factory to create implementation-dependent desktop view.
      */
-    @CalledByNative
-    private void setDesktopViewFactory(DesktopViewFactory factory) {
+    public void setDesktopViewFactory(DesktopViewFactory factory) {
         mDesktopViewFactory = factory;
     }
 
     /**
-     * Creates an implementation specific desktop view.
+     * Creates an implementation specific {@link AbstractDesktopView} using the
+     * {@link DesktopViewFactory} set by {@link Client#setDesktopViewFactory(DesktopViewFactory)}.
      */
-    public AbstractDesktopView createDesktopView(Context context) {
+    public AbstractDesktopView createDesktopView(Desktop desktop, Client client) {
         Preconditions.notNull(mDesktopViewFactory);
-        return mDesktopViewFactory.createDesktopView(context);
+        return mDesktopViewFactory.createDesktopView(desktop, client);
     }
 
     // Suppress FindBugs warning, since |sClient| is only used on the UI thread.
diff --git a/remoting/android/java/src/org/chromium/chromoting/jni/Display.java b/remoting/android/java/src/org/chromium/chromoting/jni/Display.java
index f7c7a10..926eb4f 100644
--- a/remoting/android/java/src/org/chromium/chromoting/jni/Display.java
+++ b/remoting/android/java/src/org/chromium/chromoting/jni/Display.java
@@ -4,7 +4,6 @@
 
 package org.chromium.chromoting.jni;
 
-import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Point;
 import android.os.Looper;
@@ -13,6 +12,7 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.chromoting.AbstractDesktopView;
+import org.chromium.chromoting.Desktop;
 import org.chromium.chromoting.DesktopView;
 import org.chromium.chromoting.DesktopViewFactory;
 
@@ -170,13 +170,13 @@
     }
 
     @CalledByNative
-    private DesktopViewFactory createDesktopViewFactory() {
-        return new DesktopViewFactory() {
+    private void initializeClient(Client client) {
+        client.setDesktopViewFactory(new DesktopViewFactory() {
             @Override
-            public AbstractDesktopView createDesktopView(Context context) {
-                return new DesktopView(context, Display.this);
+            public AbstractDesktopView createDesktopView(Desktop desktop, Client client) {
+                return new DesktopView(Display.this, desktop, client);
             }
-        };
+        });
     }
 
     @CalledByNative
diff --git a/remoting/android/java/src/org/chromium/chromoting/jni/GlDisplay.java b/remoting/android/java/src/org/chromium/chromoting/jni/GlDisplay.java
index 2c99bd2..0a32059 100644
--- a/remoting/android/java/src/org/chromium/chromoting/jni/GlDisplay.java
+++ b/remoting/android/java/src/org/chromium/chromoting/jni/GlDisplay.java
@@ -4,12 +4,12 @@
 
 package org.chromium.chromoting.jni;
 
-import android.content.Context;
 import android.view.Surface;
 
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.chromoting.AbstractDesktopView;
+import org.chromium.chromoting.Desktop;
 import org.chromium.chromoting.DesktopViewFactory;
 import org.chromium.chromoting.Event;
 import org.chromium.chromoting.SizeChangedEventParameter;
@@ -159,14 +159,14 @@
     }
 
     @CalledByNative
-    private DesktopViewFactory createDesktopViewFactory() {
-        return new DesktopViewFactory() {
+    private void initializeClient(Client client) {
+        client.setDesktopViewFactory(new DesktopViewFactory() {
             @Override
-            public AbstractDesktopView createDesktopView(Context context) {
+            public AbstractDesktopView createDesktopView(Desktop desktop, Client client) {
                 // UNIMPLEMENTED.
                 return null;
             }
-        };
+        });
     }
 
     @CalledByNative
diff --git a/remoting/client/jni/chromoting_jni_instance.cc b/remoting/client/jni/chromoting_jni_instance.cc
index de73b4f..97f6693f 100644
--- a/remoting/client/jni/chromoting_jni_instance.cc
+++ b/remoting/client/jni/chromoting_jni_instance.cc
@@ -74,6 +74,7 @@
       capabilities_(capabilities),
       weak_factory_(this) {
   DCHECK(jni_runtime_->ui_task_runner()->BelongsToCurrentThread());
+  weak_ptr_ = weak_factory_.GetWeakPtr();
 
   // Initialize XMPP config.
   xmpp_config_.host = kXmppServer;
@@ -369,7 +370,7 @@
 }
 
 base::WeakPtr<ChromotingJniInstance> ChromotingJniInstance::GetWeakPtr() {
-  return weak_factory_.GetWeakPtr();
+  return weak_ptr_;
 }
 
 void ChromotingJniInstance::ConnectToHostOnNetworkThread() {
diff --git a/remoting/client/jni/chromoting_jni_instance.h b/remoting/client/jni/chromoting_jni_instance.h
index beeaa91..b4cc64f 100644
--- a/remoting/client/jni/chromoting_jni_instance.h
+++ b/remoting/client/jni/chromoting_jni_instance.h
@@ -200,6 +200,7 @@
   // thread.
   bool connected_ = false;
 
+  base::WeakPtr<ChromotingJniInstance> weak_ptr_;
   base::WeakPtrFactory<ChromotingJniInstance> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ChromotingJniInstance);
diff --git a/remoting/client/jni/jni_client.cc b/remoting/client/jni/jni_client.cc
index 90db7a9..b3c7114a 100644
--- a/remoting/client/jni/jni_client.cc
+++ b/remoting/client/jni/jni_client.cc
@@ -26,7 +26,9 @@
                      base::android::ScopedJavaGlobalRef<jobject> java_client)
     : runtime_(runtime),
       java_client_(java_client),
-      weak_factory_(this) {}
+      weak_factory_(this) {
+  weak_ptr_ = weak_factory_.GetWeakPtr();
+}
 
 JniClient::~JniClient() {
   DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
@@ -166,9 +168,7 @@
 #else
   JniDisplayHandler* raw_display_handler = new JniDisplayHandler(runtime_);
 #endif  // defined(REMOTING_ANDROID_ENABLE_OPENGL_RENDERER)
-  Java_Client_setDesktopViewFactory(
-      env, java_client_.obj(),
-      raw_display_handler->CreateDesktopViewFactory().obj());
+  raw_display_handler->InitializeClient(java_client_);
   display_handler_.reset(raw_display_handler);
   ConnectToHost(raw_display_handler,
                 ConvertJavaStringToUTF8(env, username),
@@ -295,7 +295,7 @@
 }
 
 base::WeakPtr<JniClient> JniClient::GetWeakPtr() {
-  return weak_factory_.GetWeakPtr();
+  return weak_ptr_;
 }
 
 static jlong Init(JNIEnv* env, const JavaParamRef<jobject>& caller) {
diff --git a/remoting/client/jni/jni_client.h b/remoting/client/jni/jni_client.h
index 697f82a..75e5c539 100644
--- a/remoting/client/jni/jni_client.h
+++ b/remoting/client/jni/jni_client.h
@@ -166,6 +166,7 @@
   std::unique_ptr<ChromotingJniInstance> session_;
 
   // Holds pointer for the UI thread.
+  base::WeakPtr<JniClient> weak_ptr_;
   base::WeakPtrFactory<JniClient> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(JniClient);
diff --git a/remoting/client/jni/jni_display_handler.cc b/remoting/client/jni/jni_display_handler.cc
index 185a972..e139e7b 100644
--- a/remoting/client/jni/jni_display_handler.cc
+++ b/remoting/client/jni/jni_display_handler.cc
@@ -55,6 +55,7 @@
 JniDisplayHandler::JniDisplayHandler(ChromotingJniRuntime* runtime)
     : runtime_(runtime),
       weak_factory_(this) {
+  weak_ptr_ = weak_factory_.GetWeakPtr();
   JNIEnv* env = base::android::AttachCurrentThread();
   java_display_.Reset(Java_Display_createJavaDisplayObject(
       env, reinterpret_cast<intptr_t>(this)));
@@ -66,10 +67,10 @@
                           java_display_.obj());
 }
 
-base::android::ScopedJavaLocalRef<jobject>
-JniDisplayHandler::CreateDesktopViewFactory() {
-  return Java_Display_createDesktopViewFactory(
-      base::android::AttachCurrentThread(), java_display_.obj());
+void JniDisplayHandler::InitializeClient(
+    const base::android::JavaRef<jobject>& java_client) {
+  return Java_Display_initializeClient(base::android::AttachCurrentThread(),
+                                       java_display_.obj(), java_client.obj());
 }
 
 void JniDisplayHandler::UpdateCursorShape(
@@ -95,14 +96,13 @@
 std::unique_ptr<protocol::CursorShapeStub>
 JniDisplayHandler::CreateCursorShapeStub() {
   return base::WrapUnique(
-      new DisplayCursorShapeStub(weak_factory_.GetWeakPtr(),
-                                 runtime_->display_task_runner()));
+      new DisplayCursorShapeStub(weak_ptr_, runtime_->display_task_runner()));
 }
 
 std::unique_ptr<protocol::VideoRenderer>
 JniDisplayHandler::CreateVideoRenderer() {
   return base::WrapUnique(
-      new JniVideoRenderer(runtime_, weak_factory_.GetWeakPtr()));
+      new JniVideoRenderer(runtime_, weak_ptr_));
 }
 
 // static
@@ -137,8 +137,7 @@
     JNIEnv* env,
     const base::android::JavaParamRef<jobject>& caller) {
   runtime_->display_task_runner()->PostTask(
-      FROM_HERE, base::Bind(&JniDisplayHandler::RedrawCanvas,
-                            weak_factory_.GetWeakPtr()));
+      FROM_HERE, base::Bind(&JniDisplayHandler::RedrawCanvas, weak_ptr_));
 }
 
 }  // namespace remoting
diff --git a/remoting/client/jni/jni_display_handler.h b/remoting/client/jni/jni_display_handler.h
index e62d354..2f804885 100644
--- a/remoting/client/jni/jni_display_handler.h
+++ b/remoting/client/jni/jni_display_handler.h
@@ -30,7 +30,9 @@
   // Must be deleted on the display thread.
   ~JniDisplayHandler() override;
 
-  base::android::ScopedJavaLocalRef<jobject> CreateDesktopViewFactory();
+  // Sets the DesktopViewFactory for the Java client.
+  void InitializeClient(
+      const base::android::JavaRef<jobject>& java_client);
 
   void UpdateCursorShape(const protocol::CursorShapeInfo& cursor_shape);
 
@@ -60,6 +62,7 @@
   ChromotingJniRuntime* runtime_;
 
   base::android::ScopedJavaGlobalRef<jobject> java_display_;
+  base::WeakPtr<JniDisplayHandler> weak_ptr_;
   base::WeakPtrFactory<JniDisplayHandler> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(JniDisplayHandler);
diff --git a/remoting/client/jni/jni_gl_display_handler.cc b/remoting/client/jni/jni_gl_display_handler.cc
index 20e24e9..4e86735f 100644
--- a/remoting/client/jni/jni_gl_display_handler.cc
+++ b/remoting/client/jni/jni_gl_display_handler.cc
@@ -23,10 +23,11 @@
                             java_display_.obj());
 }
 
-base::android::ScopedJavaLocalRef<jobject>
-JniGlDisplayHandler::CreateDesktopViewFactory() {
-  return Java_GlDisplay_createDesktopViewFactory(
-      base::android::AttachCurrentThread(), java_display_.obj());
+void JniGlDisplayHandler::InitializeClient(
+    const base::android::JavaRef<jobject>& java_client) {
+  return Java_GlDisplay_initializeClient(base::android::AttachCurrentThread(),
+                                         java_display_.obj(),
+                                         java_client.obj());
 }
 
 std::unique_ptr<protocol::CursorShapeStub>
diff --git a/remoting/client/jni/jni_gl_display_handler.h b/remoting/client/jni/jni_gl_display_handler.h
index 45ec72fc..7ddfaaa 100644
--- a/remoting/client/jni/jni_gl_display_handler.h
+++ b/remoting/client/jni/jni_gl_display_handler.h
@@ -26,8 +26,9 @@
   JniGlDisplayHandler(ChromotingJniRuntime* runtime);
   ~JniGlDisplayHandler() override;
 
-  base::android::ScopedJavaLocalRef<jobject> CreateDesktopViewFactory();
-
+  // Sets the DesktopViewFactory for the Java client.
+  void InitializeClient(
+      const base::android::JavaRef<jobject>& java_client);
   // DisplayUpdaterFactory overrides.
   std::unique_ptr<protocol::CursorShapeStub> CreateCursorShapeStub() override;
   std::unique_ptr<protocol::VideoRenderer> CreateVideoRenderer() override;
diff --git a/remoting/client/jni/jni_pairing_secret_fetcher.cc b/remoting/client/jni/jni_pairing_secret_fetcher.cc
index f659327..39a3652 100644
--- a/remoting/client/jni/jni_pairing_secret_fetcher.cc
+++ b/remoting/client/jni/jni_pairing_secret_fetcher.cc
@@ -16,7 +16,9 @@
     jni_runtime_(runtime),
     jni_client_(client),
     host_id_(host_id),
-    weak_factory_(this) {}
+    weak_factory_(this) {
+  weak_ptr_ = weak_factory_.GetWeakPtr();
+}
 
 JniPairingSecretFetcher::~JniPairingSecretFetcher() {
   DCHECK(jni_runtime_->network_task_runner()->BelongsToCurrentThread());
@@ -42,7 +44,7 @@
 }
 
 base::WeakPtr<JniPairingSecretFetcher> JniPairingSecretFetcher::GetWeakPtr() {
-  return weak_factory_.GetWeakPtr();
+  return weak_ptr_;
 }
 
 // static
diff --git a/remoting/client/jni/jni_pairing_secret_fetcher.h b/remoting/client/jni/jni_pairing_secret_fetcher.h
index 39f448d..db329e33 100644
--- a/remoting/client/jni/jni_pairing_secret_fetcher.h
+++ b/remoting/client/jni/jni_pairing_secret_fetcher.h
@@ -51,6 +51,7 @@
   // the UI thread, but must be posted to the network thread to call it.
   protocol::SecretFetchedCallback callback_;
 
+  base::WeakPtr<JniPairingSecretFetcher> weak_ptr_;
   base::WeakPtrFactory<JniPairingSecretFetcher> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(JniPairingSecretFetcher);
diff --git a/remoting/host/BUILD.gn b/remoting/host/BUILD.gn
index e85af02..0100db9 100644
--- a/remoting/host/BUILD.gn
+++ b/remoting/host/BUILD.gn
@@ -987,6 +987,7 @@
         ":credits",
         ":remoting_me2me_host_static",
         "//build/config/sanitizers:deps",
+        "//remoting/base:breakpad",
         "//remoting/resources",
       ]
       if (is_mac) {
@@ -1233,44 +1234,45 @@
               root_build_dir)
       _extra_files = []
 
-      args = [
-               rebase_path("$root_gen_dir/installation", root_build_dir),
-               rebase_path(_output, root_build_dir),
-               "--source-file-roots",
-               rebase_path("//remoting/host/installer/win"),
-               "--source-files",
-               rebase_path("//remoting/host/installer/win/chromoting.wxs"),
-               rebase_path("//remoting/host/installer/win/parameters.json"),
+      args =
+          [
+            rebase_path("$root_gen_dir/remoting_installation", root_build_dir),
+            rebase_path(_output, root_build_dir),
+            "--source-file-roots",
+            rebase_path("//remoting/host/installer/win"),
+            "--source-files",
+            rebase_path("//remoting/host/installer/win/chromoting.wxs"),
+            rebase_path("//remoting/host/installer/win/parameters.json"),
 
-               # Input files
-               "--generated-files",
-             ] + _generated_files +
-             [
-               rebase_path("//remoting/resources/chromoting.ico"),
+            # Input files
+            "--generated-files",
+          ] + _generated_files +
+          [
+            rebase_path("//remoting/resources/chromoting.ico"),
 
-               # Position of files in zip file
-               "--generated-files-dst",
-               "files/remote_assistance_host.exe",
-               "files/remote_security_key.exe",
-               "files/remoting_core.dll",
-               "files/remoting_desktop.exe",
-               "files/remoting_host.exe",
-               "files/remoting_native_messaging_host.exe",
-               "files/remoting_start_host.exe",
-               "files/CREDITS.txt",
-               "files/com.google.chrome.remote_assistance.json",
-               "files/com.google.chrome.remote_desktop.json",
-               "files/chromoting.ico",
-               "files/icudtl.dat",
-             ] + _extra_files +  # Defs
-             [
-               "--defs",
-               "BRANDING=$_branding",
-               "DAEMON_CONTROLLER_CLSID={$daemon_controller_clsid}",
-               "RDP_DESKTOP_SESSION_CLSID={$rdp_desktop_session_clsid}",
-               "VERSION=$chrome_version_full",
-               "OFFICIAL_BUILD=$_official_build",
-             ]
+            # Position of files in zip file
+            "--generated-files-dst",
+            "files/remote_assistance_host.exe",
+            "files/remote_security_key.exe",
+            "files/remoting_core.dll",
+            "files/remoting_desktop.exe",
+            "files/remoting_host.exe",
+            "files/remoting_native_messaging_host.exe",
+            "files/remoting_start_host.exe",
+            "files/CREDITS.txt",
+            "files/com.google.chrome.remote_assistance.json",
+            "files/com.google.chrome.remote_desktop.json",
+            "files/chromoting.ico",
+            "files/icudtl.dat",
+          ] + _extra_files +  # Defs
+          [
+            "--defs",
+            "BRANDING=$_branding",
+            "DAEMON_CONTROLLER_CLSID={$daemon_controller_clsid}",
+            "RDP_DESKTOP_SESSION_CLSID={$rdp_desktop_session_clsid}",
+            "VERSION=$chrome_version_full",
+            "OFFICIAL_BUILD=$_official_build",
+          ]
     }
   } else if (is_mac) {
     import("//build/config/zip.gni")
@@ -1311,7 +1313,8 @@
       host_uninstaller_name_nospace = host_uninstaller_name
 
       args = [
-               rebase_path(target_gen_dir, root_build_dir),
+               rebase_path("$target_gen_dir/remoting_installation",
+                           root_build_dir),
                rebase_path(zip_path, root_build_dir),
                "--source-file-roots",
                rebase_path("installer/mac/", root_build_dir),
@@ -1545,7 +1548,7 @@
           "--wix_path",
           rebase_path("//third_party/wix"),
           "--intermediate_dir",
-          rebase_path("$root_gen_dir/installation", root_build_dir),
+          rebase_path("$root_gen_dir/remoting_installation", root_build_dir),
           "--target_arch",
           msi_script_arch,
           rebase_path("$root_out_dir/remoting-me2me-host-$current_os.zip",
diff --git a/services/ui/public/interfaces/BUILD.gn b/services/ui/public/interfaces/BUILD.gn
index 33a07da..66bce555 100644
--- a/services/ui/public/interfaces/BUILD.gn
+++ b/services/ui/public/interfaces/BUILD.gn
@@ -7,6 +7,7 @@
 mojom("interfaces") {
   sources = [
     "accelerator_registrar.mojom",
+    "accessibility_manager.mojom",
     "animations.mojom",
     "channel_handle.mojom",
     "clipboard.mojom",
diff --git a/services/ui/public/interfaces/accessibility_manager.mojom b/services/ui/public/interfaces/accessibility_manager.mojom
new file mode 100644
index 0000000..a63873d
--- /dev/null
+++ b/services/ui/public/interfaces/accessibility_manager.mojom
@@ -0,0 +1,13 @@
+// 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 ui.mojom;
+
+// Allows controlling accessibility in the UI service. Only one client at a time
+// can connect to AccessibilityManager per user. If a new client connects to it,
+// then any previously connected client for that user is disconnected.
+interface AccessibilityManager {
+  // Enables (or disables) high contrast mode.
+  SetHighContrastMode(bool enabled);
+};
diff --git a/services/ui/service.cc b/services/ui/service.cc
index e229e59..b11c4cf 100644
--- a/services/ui/service.cc
+++ b/services/ui/service.cc
@@ -23,6 +23,7 @@
 #include "services/ui/gles2/gpu_impl.h"
 #include "services/ui/gpu/gpu_service_impl.h"
 #include "services/ui/gpu/gpu_service_mus.h"
+#include "services/ui/ws/accessibility_manager.h"
 #include "services/ui/ws/display.h"
 #include "services/ui/ws/display_binding.h"
 #include "services/ui/ws/display_manager.h"
@@ -75,6 +76,7 @@
 
 struct Service::UserState {
   std::unique_ptr<clipboard::ClipboardImpl> clipboard;
+  std::unique_ptr<ws::AccessibilityManager> accessibility;
   std::unique_ptr<ws::WindowTreeHostFactory> window_tree_host_factory;
 };
 
@@ -224,6 +226,7 @@
 }
 
 bool Service::OnConnect(Connection* connection) {
+  connection->AddInterface<mojom::AccessibilityManager>(this);
   connection->AddInterface<mojom::Clipboard>(this);
   connection->AddInterface<mojom::DisplayManager>(this);
   connection->AddInterface<mojom::UserAccessManager>(this);
@@ -281,6 +284,17 @@
 }
 
 void Service::Create(shell::Connection* connection,
+                     mojom::AccessibilityManagerRequest request) {
+  UserState* user_state = GetUserState(connection);
+  if (!user_state->accessibility) {
+    const ws::UserId& user_id = connection->GetRemoteIdentity().user_id();
+    user_state->accessibility.reset(
+        new ws::AccessibilityManager(window_server_.get(), user_id));
+  }
+  user_state->accessibility->Bind(std::move(request));
+}
+
+void Service::Create(shell::Connection* connection,
                      mojom::ClipboardRequest request) {
   UserState* user_state = GetUserState(connection);
   if (!user_state->clipboard)
diff --git a/services/ui/service.h b/services/ui/service.h
index 5251e9b..a9103ce 100644
--- a/services/ui/service.h
+++ b/services/ui/service.h
@@ -19,6 +19,7 @@
 #include "services/shell/public/cpp/service.h"
 #include "services/tracing/public/cpp/tracing_impl.h"
 #include "services/ui/input_devices/input_device_server.h"
+#include "services/ui/public/interfaces/accessibility_manager.mojom.h"
 #include "services/ui/public/interfaces/clipboard.mojom.h"
 #include "services/ui/public/interfaces/display.mojom.h"
 #include "services/ui/public/interfaces/gpu.mojom.h"
@@ -64,6 +65,7 @@
 class Service
     : public shell::Service,
       public ws::WindowServerDelegate,
+      public shell::InterfaceFactory<mojom::AccessibilityManager>,
       public shell::InterfaceFactory<mojom::Clipboard>,
       public shell::InterfaceFactory<mojom::DisplayManager>,
       public shell::InterfaceFactory<mojom::Gpu>,
@@ -108,6 +110,10 @@
   bool IsTestConfig() const override;
   void CreateDefaultDisplays() override;
 
+  // shell::InterfaceFactory<mojom::AccessibilityManager> implementation.
+  void Create(shell::Connection* connection,
+              mojom::AccessibilityManagerRequest request) override;
+
   // shell::InterfaceFactory<mojom::Clipboard> implementation.
   void Create(shell::Connection* connection,
               mojom::ClipboardRequest request) override;
diff --git a/services/ui/surfaces/display_compositor.cc b/services/ui/surfaces/display_compositor.cc
index bdf1424..c5eb071 100644
--- a/services/ui/surfaces/display_compositor.cc
+++ b/services/ui/surfaces/display_compositor.cc
@@ -30,10 +30,10 @@
     : task_runner_(task_runner),
       surfaces_state_(surfaces_state),
       factory_(surfaces_state->manager(), this),
-      allocator_(surfaces_state->next_id_namespace()) {
-  allocator_.RegisterSurfaceIdNamespace(surfaces_state_->manager());
+      allocator_(surfaces_state->next_client_id()) {
+  allocator_.RegisterSurfaceClientId(surfaces_state_->manager());
   surfaces_state_->manager()->RegisterSurfaceFactoryClient(
-      allocator_.id_namespace(), this);
+      allocator_.client_id(), this);
 
   scoped_refptr<SurfacesContextProvider> surfaces_context_provider(
       new SurfacesContextProvider(widget, gpu_state));
@@ -69,7 +69,7 @@
   display_.reset(new cc::Display(
       surfaces_state_->manager(), nullptr /* bitmap_manager */,
       nullptr /* gpu_memory_buffer_manager */, cc::RendererSettings(),
-      allocator_.id_namespace(), std::move(synthetic_begin_frame_source),
+      allocator_.client_id(), std::move(synthetic_begin_frame_source),
       std::move(display_output_surface), std::move(scheduler),
       base::MakeUnique<cc::TextureMailboxDeleter>(task_runner_.get())));
   display_->Initialize(this);
@@ -77,7 +77,7 @@
 
 DisplayCompositor::~DisplayCompositor() {
   surfaces_state_->manager()->UnregisterSurfaceFactoryClient(
-      allocator_.id_namespace());
+      allocator_.client_id());
 }
 
 void DisplayCompositor::SubmitCompositorFrame(
diff --git a/services/ui/surfaces/surfaces_state.cc b/services/ui/surfaces/surfaces_state.cc
index 38ebeef..edb1e8e 100644
--- a/services/ui/surfaces/surfaces_state.cc
+++ b/services/ui/surfaces/surfaces_state.cc
@@ -6,7 +6,7 @@
 
 namespace ui {
 
-SurfacesState::SurfacesState() : next_id_namespace_(1u) {}
+SurfacesState::SurfacesState() : next_client_id_(1u) {}
 
 SurfacesState::~SurfacesState() {}
 
diff --git a/services/ui/surfaces/surfaces_state.h b/services/ui/surfaces/surfaces_state.h
index c55fb08..c35f900 100644
--- a/services/ui/surfaces/surfaces_state.h
+++ b/services/ui/surfaces/surfaces_state.h
@@ -27,7 +27,7 @@
  public:
   SurfacesState();
 
-  uint32_t next_id_namespace() { return next_id_namespace_++; }
+  uint32_t next_client_id() { return next_client_id_++; }
 
   cc::SurfaceManager* manager() { return &manager_; }
 
@@ -38,7 +38,7 @@
   // A Surface ID is an unsigned 64-bit int where the high 32-bits are generated
   // by the Surfaces service, and the low 32-bits are generated by the process
   // that requested the Surface.
-  uint32_t next_id_namespace_;
+  uint32_t next_client_id_;
   cc::SurfaceManager manager_;
 
   DISALLOW_COPY_AND_ASSIGN(SurfacesState);
diff --git a/services/ui/ws/BUILD.gn b/services/ui/ws/BUILD.gn
index 456a5d8..c61fba8 100644
--- a/services/ui/ws/BUILD.gn
+++ b/services/ui/ws/BUILD.gn
@@ -13,6 +13,8 @@
     "accelerator.h",
     "access_policy.h",
     "access_policy_delegate.h",
+    "accessibility_manager.cc",
+    "accessibility_manager.h",
     "animation_runner.cc",
     "animation_runner.h",
     "animation_runner_observer.h",
diff --git a/services/ui/ws/accessibility_manager.cc b/services/ui/ws/accessibility_manager.cc
new file mode 100644
index 0000000..3b934bb
--- /dev/null
+++ b/services/ui/ws/accessibility_manager.cc
@@ -0,0 +1,30 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/ui/ws/accessibility_manager.h"
+
+#include "services/ui/ws/window_server.h"
+
+namespace ui {
+namespace ws {
+
+AccessibilityManager::AccessibilityManager(WindowServer* window_server,
+                                           const UserId& user)
+    : window_server_(window_server), user_(user), binding_(this) {
+  DCHECK(window_server_);
+}
+
+AccessibilityManager::~AccessibilityManager() {}
+
+void AccessibilityManager::Bind(mojom::AccessibilityManagerRequest request) {
+  binding_.Close();
+  binding_.Bind(std::move(request));
+}
+
+void AccessibilityManager::SetHighContrastMode(bool enabled) {
+  window_server_->SetHighContrastMode(user_, enabled);
+}
+
+}  // namespace ws
+}  // namespace ui
diff --git a/services/ui/ws/accessibility_manager.h b/services/ui/ws/accessibility_manager.h
new file mode 100644
index 0000000..aaf8992
--- /dev/null
+++ b/services/ui/ws/accessibility_manager.h
@@ -0,0 +1,38 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_UI_WS_ACCESSIBILITY_MANAGER_H_
+#define SERVICES_UI_WS_ACCESSIBILITY_MANAGER_H_
+
+#include "mojo/public/cpp/bindings/binding.h"
+#include "services/ui/public/interfaces/accessibility_manager.mojom.h"
+#include "services/ui/ws/user_id.h"
+
+namespace ui {
+namespace ws {
+
+class WindowServer;
+
+class AccessibilityManager : public mojom::AccessibilityManager {
+ public:
+  AccessibilityManager(WindowServer* window_server, const UserId& user);
+  ~AccessibilityManager() override;
+
+  void Bind(mojom::AccessibilityManagerRequest request);
+
+ private:
+  // mojom::AccessibilityManager:
+  void SetHighContrastMode(bool enabled) override;
+
+  WindowServer* window_server_;
+  const UserId user_;
+  mojo::Binding<mojom::AccessibilityManager> binding_;
+
+  DISALLOW_COPY_AND_ASSIGN(AccessibilityManager);
+};
+
+}  // namespace ws
+}  // namespace ui
+
+#endif  // SERVICES_UI_WS_ACCESSIBILITY_MANAGER_H_
diff --git a/services/ui/ws/display.cc b/services/ui/ws/display.cc
index c1b75eb..f733e83 100644
--- a/services/ui/ws/display.cc
+++ b/services/ui/ws/display.cc
@@ -275,6 +275,10 @@
   return root_.get();
 }
 
+bool Display::IsInHighContrastMode() {
+  return window_server_->IsActiveUserInHighContrastMode();
+}
+
 void Display::OnEvent(const ui::Event& event) {
   WindowManagerDisplayRoot* display_root = GetActiveWindowManagerDisplayRoot();
   if (display_root)
diff --git a/services/ui/ws/display.h b/services/ui/ws/display.h
index 2d8d6dd..aaca1cf 100644
--- a/services/ui/ws/display.h
+++ b/services/ui/ws/display.h
@@ -168,6 +168,7 @@
 
   // PlatformDisplayDelegate:
   ServerWindow* GetRootWindow() override;
+  bool IsInHighContrastMode() override;
   void OnEvent(const ui::Event& event) override;
   void OnNativeCaptureLost() override;
   void OnDisplayClosed() override;
diff --git a/services/ui/ws/frame_generator.cc b/services/ui/ws/frame_generator.cc
index d09b0d7..b361bf3 100644
--- a/services/ui/ws/frame_generator.cc
+++ b/services/ui/ws/frame_generator.cc
@@ -7,6 +7,7 @@
 #include "base/containers/adapters.h"
 #include "cc/output/compositor_frame.h"
 #include "cc/quads/render_pass.h"
+#include "cc/quads/render_pass_draw_quad.h"
 #include "cc/quads/shared_quad_state.h"
 #include "cc/quads/surface_draw_quad.h"
 #include "services/ui/surfaces/display_compositor.h"
@@ -26,7 +27,9 @@
       gpu_state_(gpu_state),
       surfaces_state_(surfaces_state),
       draw_timer_(false, false),
-      weak_factory_(this) {}
+      weak_factory_(this) {
+  DCHECK(delegate_);
+}
 
 FrameGenerator::~FrameGenerator() {
   // Invalidate WeakPtrs now to avoid callbacks back into the
@@ -90,8 +93,11 @@
 cc::CompositorFrame FrameGenerator::GenerateCompositorFrame() {
   const ViewportMetrics& metrics = delegate_->GetViewportMetrics();
   std::unique_ptr<cc::RenderPass> render_pass = cc::RenderPass::Create();
-  render_pass->damage_rect = dirty_rect_;
-  render_pass->output_rect = gfx::Rect(metrics.size_in_pixels);
+  gfx::Rect output_rect(metrics.size_in_pixels);
+  dirty_rect_.Intersect(output_rect);
+  const cc::RenderPassId render_pass_id(1, 1);
+  render_pass->SetNew(render_pass_id, output_rect, dirty_rect_,
+                      gfx::Transform());
 
   DrawWindowTree(render_pass.get(), delegate_->GetRootWindow(), gfx::Vector2d(),
                  1.0f);
@@ -99,6 +105,24 @@
   std::unique_ptr<cc::DelegatedFrameData> frame_data(
       new cc::DelegatedFrameData);
   frame_data->render_pass_list.push_back(std::move(render_pass));
+  if (delegate_->IsInHighContrastMode()) {
+    std::unique_ptr<cc::RenderPass> invert_pass = cc::RenderPass::Create();
+    invert_pass->SetNew(cc::RenderPassId(2, 0), output_rect, dirty_rect_,
+                        gfx::Transform());
+    cc::SharedQuadState* shared_state =
+        invert_pass->CreateAndAppendSharedQuadState();
+    shared_state->SetAll(gfx::Transform(), output_rect.size(), output_rect,
+                         output_rect, false, 1.f, SkXfermode::kSrcOver_Mode, 0);
+    auto* quad = invert_pass->CreateAndAppendDrawQuad<cc::RenderPassDrawQuad>();
+    cc::FilterOperations filters;
+    filters.Append(cc::FilterOperation::CreateInvertFilter(1.f));
+    quad->SetNew(shared_state, output_rect, output_rect, render_pass_id,
+                 0 /* mask_resource_id */, gfx::Vector2dF() /* mask_uv_scale */,
+                 gfx::Size() /* mask_texture_size */, filters,
+                 gfx::Vector2dF() /* filters_scale */,
+                 cc::FilterOperations() /* background_filters */);
+    frame_data->render_pass_list.push_back(std::move(invert_pass));
+  }
 
   cc::CompositorFrame frame;
   frame.delegated_frame_data = std::move(frame_data);
diff --git a/services/ui/ws/frame_generator_delegate.h b/services/ui/ws/frame_generator_delegate.h
index 456bab2e..fa82a8f9 100644
--- a/services/ui/ws/frame_generator_delegate.h
+++ b/services/ui/ws/frame_generator_delegate.h
@@ -25,6 +25,8 @@
   // Called when a compositor frame is finished drawing.
   virtual void OnCompositorFrameDrawn() = 0;
 
+  virtual bool IsInHighContrastMode() = 0;
+
   virtual const ViewportMetrics& GetViewportMetrics() = 0;
 
  protected:
diff --git a/services/ui/ws/platform_display.cc b/services/ui/ws/platform_display.cc
index 801a8a4c..93d4e08 100644
--- a/services/ui/ws/platform_display.cc
+++ b/services/ui/ws/platform_display.cc
@@ -271,6 +271,10 @@
     delegate_->OnCompositorFrameDrawn();
 }
 
+bool DefaultPlatformDisplay::IsInHighContrastMode() {
+  return delegate_ ? delegate_->IsInHighContrastMode() : false;
+}
+
 const ViewportMetrics& DefaultPlatformDisplay::GetViewportMetrics() {
   return metrics_;
 }
diff --git a/services/ui/ws/platform_display.h b/services/ui/ws/platform_display.h
index 5da5f5c2..209daeb 100644
--- a/services/ui/ws/platform_display.h
+++ b/services/ui/ws/platform_display.h
@@ -142,6 +142,7 @@
   // FrameGeneratorDelegate:
   ServerWindow* GetRootWindow() override;
   void OnCompositorFrameDrawn() override;
+  bool IsInHighContrastMode() override;
   const ViewportMetrics& GetViewportMetrics() override;
 
   int64_t display_id_;
diff --git a/services/ui/ws/platform_display_delegate.h b/services/ui/ws/platform_display_delegate.h
index 0371eb2..9c92f58 100644
--- a/services/ui/ws/platform_display_delegate.h
+++ b/services/ui/ws/platform_display_delegate.h
@@ -26,6 +26,8 @@
   // Returns the root window of this display.
   virtual ServerWindow* GetRootWindow() = 0;
 
+  virtual bool IsInHighContrastMode() = 0;
+
   // Called when the window managed by the PlatformDisplay is closed.
   virtual void OnDisplayClosed() = 0;
 
diff --git a/services/ui/ws/server_window_surface.cc b/services/ui/ws/server_window_surface.cc
index 92dd57b6..154667fe 100644
--- a/services/ui/ws/server_window_surface.cc
+++ b/services/ui/ws/server_window_surface.cc
@@ -44,7 +44,7 @@
 
   if (registered_surface_factory_client_) {
     cc::SurfaceManager* surface_manager = manager_->GetSurfaceManager();
-    surface_manager->UnregisterSurfaceFactoryClient(manager_->id_namespace());
+    surface_manager->UnregisterSurfaceFactoryClient(manager_->client_id());
   }
 }
 
@@ -87,7 +87,7 @@
   DCHECK(!registered_surface_factory_client_);
   registered_surface_factory_client_ = true;
   cc::SurfaceManager* surface_manager = manager_->GetSurfaceManager();
-  surface_manager->RegisterSurfaceFactoryClient(manager_->id_namespace(), this);
+  surface_manager->RegisterSurfaceFactoryClient(manager_->client_id(), this);
 }
 
 ServerWindow* ServerWindowSurface::window() {
diff --git a/services/ui/ws/server_window_surface_manager.cc b/services/ui/ws/server_window_surface_manager.cc
index 13a3ff5..9f82135 100644
--- a/services/ui/ws/server_window_surface_manager.cc
+++ b/services/ui/ws/server_window_surface_manager.cc
@@ -15,11 +15,11 @@
 ServerWindowSurfaceManager::ServerWindowSurfaceManager(ServerWindow* window)
     : window_(window),
       surface_id_allocator_(
-          window->delegate()->GetSurfacesState()->next_id_namespace()),
+          window->delegate()->GetSurfacesState()->next_client_id()),
       waiting_for_initial_frames_(
           window_->properties().count(ui::mojom::kWaitForUnderlay_Property) >
           0) {
-  surface_id_allocator_.RegisterSurfaceIdNamespace(GetSurfaceManager());
+  surface_id_allocator_.RegisterSurfaceClientId(GetSurfaceManager());
 }
 
 ServerWindowSurfaceManager::~ServerWindowSurfaceManager() {
diff --git a/services/ui/ws/server_window_surface_manager.h b/services/ui/ws/server_window_surface_manager.h
index b3ce36a..41f1d84b 100644
--- a/services/ui/ws/server_window_surface_manager.h
+++ b/services/ui/ws/server_window_surface_manager.h
@@ -46,7 +46,7 @@
   bool HasSurfaceOfType(mojom::SurfaceType type) const;
   bool HasAnySurface() const;
 
-  uint32_t id_namespace() const { return surface_id_allocator_.id_namespace(); }
+  uint32_t client_id() const { return surface_id_allocator_.client_id(); }
   cc::SurfaceManager* GetSurfaceManager();
 
  private:
diff --git a/services/ui/ws/test_utils.cc b/services/ui/ws/test_utils.cc
index f870d0a7..40debd5 100644
--- a/services/ui/ws/test_utils.cc
+++ b/services/ui/ws/test_utils.cc
@@ -120,6 +120,10 @@
   return root_.get();
 }
 
+bool TestFrameGeneratorDelegate::IsInHighContrastMode() {
+  return false;
+}
+
 const ViewportMetrics& TestFrameGeneratorDelegate::GetViewportMetrics() {
   return metrics_;
 }
diff --git a/services/ui/ws/test_utils.h b/services/ui/ws/test_utils.h
index e701b55..2040c01d 100644
--- a/services/ui/ws/test_utils.h
+++ b/services/ui/ws/test_utils.h
@@ -256,6 +256,7 @@
   // FrameGeneratorDelegate:
   ServerWindow* GetRootWindow() override;
   void OnCompositorFrameDrawn() override {}
+  bool IsInHighContrastMode() override;
   const ViewportMetrics& GetViewportMetrics() override;
 
  private:
diff --git a/services/ui/ws/window_server.cc b/services/ui/ws/window_server.cc
index 1510881..92aa4ae 100644
--- a/services/ui/ws/window_server.cc
+++ b/services/ui/ws/window_server.cc
@@ -282,6 +282,22 @@
   return nullptr;
 }
 
+bool WindowServer::IsActiveUserInHighContrastMode() const {
+  return IsUserInHighContrastMode(user_id_tracker_.active_id());
+}
+
+void WindowServer::SetHighContrastMode(const UserId& user, bool enabled) {
+  if (IsUserInHighContrastMode(user) == enabled)
+    return;
+  high_contrast_mode_[user] = enabled;
+  if (user_id_tracker_.active_id() != user)
+    return;
+  for (Display* display : display_manager_->displays()) {
+    display->SchedulePaint(display->root_window(),
+                           gfx::Rect(display->root_window()->bounds().size()));
+  }
+}
+
 uint32_t WindowServer::GenerateWindowManagerChangeId(
     WindowTree* source,
     uint32_t client_change_id) {
@@ -515,6 +531,11 @@
     display_root->display()->UpdateNativeCursor(cursor_id);
 }
 
+bool WindowServer::IsUserInHighContrastMode(const UserId& user) const {
+  const auto iter = high_contrast_mode_.find(user);
+  return (iter == high_contrast_mode_.end()) ? false : iter->second;
+}
+
 ui::SurfacesState* WindowServer::GetSurfacesState() {
   return surfaces_state_.get();
 }
@@ -736,7 +757,15 @@
 }
 
 void WindowServer::OnActiveUserIdChanged(const UserId& previously_active_id,
-                                         const UserId& active_id) {}
+                                         const UserId& active_id) {
+  if (IsUserInHighContrastMode(previously_active_id) ==
+      IsUserInHighContrastMode(active_id))
+    return;
+  for (Display* display : display_manager_->displays()) {
+    display->SchedulePaint(display->root_window(),
+                           gfx::Rect(display->root_window()->bounds().size()));
+  }
+}
 
 void WindowServer::OnUserIdAdded(const UserId& id) {
   activity_monitor_map_[id] = base::MakeUnique<UserActivityMonitor>(nullptr);
diff --git a/services/ui/ws/window_server.h b/services/ui/ws/window_server.h
index 64e42116..8978098 100644
--- a/services/ui/ws/window_server.h
+++ b/services/ui/ws/window_server.h
@@ -143,6 +143,9 @@
   bool SetFocusedWindow(ServerWindow* window);
   ServerWindow* GetFocusedWindow();
 
+  bool IsActiveUserInHighContrastMode() const;
+  void SetHighContrastMode(const UserId& user, bool enabled);
+
   // Returns a change id for the window manager that is associated with
   // |source| and |client_change_id|. When the window manager replies
   // WindowManagerChangeCompleted() is called to obtain the original source
@@ -252,6 +255,8 @@
   // |window|.
   void UpdateNativeCursorIfOver(ServerWindow* window);
 
+  bool IsUserInHighContrastMode(const UserId& user) const;
+
   // Overridden from ServerWindowDelegate:
   ui::SurfacesState* GetSurfacesState() override;
   void OnScheduleWindowPaint(ServerWindow* window) override;
@@ -333,6 +338,7 @@
   Operation* current_operation_;
 
   bool in_destructor_;
+  std::map<UserId, bool> high_contrast_mode_;
 
   // Maps from window manager change id to the client that initiated the
   // request.
diff --git a/sql/statement.cc b/sql/statement.cc
index 1502b09..5778fd0d 100644
--- a/sql/statement.cc
+++ b/sql/statement.cc
@@ -294,7 +294,7 @@
   return sqlite3_column_blob(ref_->stmt(), col);
 }
 
-bool Statement::ColumnBlobAsString(int col, std::string* blob) {
+bool Statement::ColumnBlobAsString(int col, std::string* blob) const {
   if (!CheckValid())
     return false;
 
diff --git a/sql/statement.h b/sql/statement.h
index 83a5a2d..3bc99ed 100644
--- a/sql/statement.h
+++ b/sql/statement.h
@@ -139,7 +139,7 @@
   // vector. Danger! ColumnBlob may return NULL if there is no data!
   int ColumnByteLength(int col) const;
   const void* ColumnBlob(int col) const;
-  bool ColumnBlobAsString(int col, std::string* blob);
+  bool ColumnBlobAsString(int col, std::string* blob) const;
   bool ColumnBlobAsString16(int col, base::string16* val) const;
   bool ColumnBlobAsVector(int col, std::vector<char>* val) const;
   bool ColumnBlobAsVector(int col, std::vector<unsigned char>* val) const;
diff --git a/sync/internal_api/sync_manager_impl.cc b/sync/internal_api/sync_manager_impl.cc
index 3f5c370..cc59e645 100644
--- a/sync/internal_api/sync_manager_impl.cc
+++ b/sync/internal_api/sync_manager_impl.cc
@@ -74,10 +74,11 @@
       return GetUpdatesCallerInfo::NEW_CLIENT;
     case CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE:
     case CONFIGURE_REASON_CRYPTO:
+    case CONFIGURE_REASON_CATCH_UP:
       return GetUpdatesCallerInfo::NEWLY_SUPPORTED_DATATYPE;
     case CONFIGURE_REASON_PROGRAMMATIC:
       return GetUpdatesCallerInfo::PROGRAMMATIC;
-    default:
+    case CONFIGURE_REASON_UNKNOWN:
       NOTREACHED();
   }
   return GetUpdatesCallerInfo::UNKNOWN;
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json
index c6c1e341..798e73c 100644
--- a/testing/buildbot/chromium.gpu.fyi.json
+++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -4640,6 +4640,33 @@
           "--show-stdout",
           "--browser=release",
           "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--webgl-conformance-version=2.0.0",
+          "--webgl2-only=true",
+          "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "webgl2_conformance_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:0412",
+              "os": "Linux"
+            }
+          ],
+          "shards": 12
+        }
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=release",
+          "-v",
           "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/Ahem.woff b/testing/libfuzzer/fuzzers/woff2_corpus/Ahem.woff
deleted file mode 100644
index 0bc8093..0000000
--- a/testing/libfuzzer/fuzzers/woff2_corpus/Ahem.woff
+++ /dev/null
Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/Ahem.woff2 b/testing/libfuzzer/fuzzers/woff2_corpus/Ahem.woff2
new file mode 100644
index 0000000..7729324
--- /dev/null
+++ b/testing/libfuzzer/fuzzers/woff2_corpus/Ahem.woff2
Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/AhemSpaceLigature.woff b/testing/libfuzzer/fuzzers/woff2_corpus/AhemSpaceLigature.woff
deleted file mode 100644
index 2f576b9a..0000000
--- a/testing/libfuzzer/fuzzers/woff2_corpus/AhemSpaceLigature.woff
+++ /dev/null
Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/AhemSpaceLigature.woff2 b/testing/libfuzzer/fuzzers/woff2_corpus/AhemSpaceLigature.woff2
new file mode 100644
index 0000000..dc15e79d
--- /dev/null
+++ b/testing/libfuzzer/fuzzers/woff2_corpus/AhemSpaceLigature.woff2
Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/DejaVuSerif-webfont.woff b/testing/libfuzzer/fuzzers/woff2_corpus/DejaVuSerif-webfont.woff
deleted file mode 100644
index 4583cc6..0000000
--- a/testing/libfuzzer/fuzzers/woff2_corpus/DejaVuSerif-webfont.woff
+++ /dev/null
Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/DejaVuSerif-webfont.woff2 b/testing/libfuzzer/fuzzers/woff2_corpus/DejaVuSerif-webfont.woff2
new file mode 100644
index 0000000..953010a
--- /dev/null
+++ b/testing/libfuzzer/fuzzers/woff2_corpus/DejaVuSerif-webfont.woff2
Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/DejaVuSerif.woff2 b/testing/libfuzzer/fuzzers/woff2_corpus/DejaVuSerif.woff2
new file mode 100644
index 0000000..b972c08
--- /dev/null
+++ b/testing/libfuzzer/fuzzers/woff2_corpus/DejaVuSerif.woff2
Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/EzraSIL.woff2 b/testing/libfuzzer/fuzzers/woff2_corpus/EzraSIL.woff2
new file mode 100644
index 0000000..e987c38
--- /dev/null
+++ b/testing/libfuzzer/fuzzers/woff2_corpus/EzraSIL.woff2
Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/LinLibertineO.woff2 b/testing/libfuzzer/fuzzers/woff2_corpus/LinLibertineO.woff2
new file mode 100644
index 0000000..e843c8c
--- /dev/null
+++ b/testing/libfuzzer/fuzzers/woff2_corpus/LinLibertineO.woff2
Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/LinLibertine_R.woff b/testing/libfuzzer/fuzzers/woff2_corpus/LinLibertine_R.woff
deleted file mode 100644
index 0357ad4..0000000
--- a/testing/libfuzzer/fuzzers/woff2_corpus/LinLibertine_R.woff
+++ /dev/null
Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/MEgalopolisExtra.woff b/testing/libfuzzer/fuzzers/woff2_corpus/MEgalopolisExtra.woff
deleted file mode 100644
index ee37efff..0000000
--- a/testing/libfuzzer/fuzzers/woff2_corpus/MEgalopolisExtra.woff
+++ /dev/null
Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/MEgalopolisExtra.woff2 b/testing/libfuzzer/fuzzers/woff2_corpus/MEgalopolisExtra.woff2
new file mode 100644
index 0000000..2d0def4
--- /dev/null
+++ b/testing/libfuzzer/fuzzers/woff2_corpus/MEgalopolisExtra.woff2
Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/OpenSans-Regular.woff b/testing/libfuzzer/fuzzers/woff2_corpus/OpenSans-Regular.woff
deleted file mode 100644
index 55b25f8..0000000
--- a/testing/libfuzzer/fuzzers/woff2_corpus/OpenSans-Regular.woff
+++ /dev/null
Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/OpenSans.woff2 b/testing/libfuzzer/fuzzers/woff2_corpus/OpenSans.woff2
new file mode 100644
index 0000000..f898c34
--- /dev/null
+++ b/testing/libfuzzer/fuzzers/woff2_corpus/OpenSans.woff2
Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/mplus-1p-regular.woff b/testing/libfuzzer/fuzzers/woff2_corpus/mplus-1p-regular.woff
deleted file mode 100644
index 42cfff6..0000000
--- a/testing/libfuzzer/fuzzers/woff2_corpus/mplus-1p-regular.woff
+++ /dev/null
Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/mplus-1p-regular.woff2 b/testing/libfuzzer/fuzzers/woff2_corpus/mplus-1p-regular.woff2
new file mode 100644
index 0000000..171e366
--- /dev/null
+++ b/testing/libfuzzer/fuzzers/woff2_corpus/mplus-1p-regular.woff2
Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/open_sans.woff b/testing/libfuzzer/fuzzers/woff2_corpus/open_sans.woff
deleted file mode 100644
index 55b25f8..0000000
--- a/testing/libfuzzer/fuzzers/woff2_corpus/open_sans.woff
+++ /dev/null
Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/sileot-webfont.woff b/testing/libfuzzer/fuzzers/woff2_corpus/sileot-webfont.woff
deleted file mode 100644
index 81547578..0000000
--- a/testing/libfuzzer/fuzzers/woff2_corpus/sileot-webfont.woff
+++ /dev/null
Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/tcu-font.woff b/testing/libfuzzer/fuzzers/woff2_corpus/tcu-font.woff
deleted file mode 100644
index c880aaab..0000000
--- a/testing/libfuzzer/fuzzers/woff2_corpus/tcu-font.woff
+++ /dev/null
Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/tcu-font.woff2 b/testing/libfuzzer/fuzzers/woff2_corpus/tcu-font.woff2
new file mode 100644
index 0000000..df15e4cd
--- /dev/null
+++ b/testing/libfuzzer/fuzzers/woff2_corpus/tcu-font.woff2
Binary files differ
diff --git a/testing/variations/fieldtrial_testing_config_android.json b/testing/variations/fieldtrial_testing_config_android.json
index 39241df..944d72e4 100644
--- a/testing/variations/fieldtrial_testing_config_android.json
+++ b/testing/variations/fieldtrial_testing_config_android.json
@@ -115,6 +115,14 @@
             "group_name": "Enabled"
         }
     ],
+    "ExpectCTReporting": [
+        {
+            "enable_features": [
+                "ExpectCTReporting"
+            ],
+            "group_name": "ExpectCTReportingEnabled"
+        }
+    ],
     "ImeThread": [
         {
             "enable_features": [
diff --git a/testing/variations/fieldtrial_testing_config_chromeos.json b/testing/variations/fieldtrial_testing_config_chromeos.json
index 56fde3f..313979f 100644
--- a/testing/variations/fieldtrial_testing_config_chromeos.json
+++ b/testing/variations/fieldtrial_testing_config_chromeos.json
@@ -64,6 +64,14 @@
             "group_name": "Enabled"
         }
     ],
+    "ExpectCTReporting": [
+        {
+            "enable_features": [
+                "ExpectCTReporting"
+            ],
+            "group_name": "ExpectCTReportingEnabled"
+        }
+    ],
     "ExtensionActionRedesign": [
         {
             "group_name": "Enabled"
diff --git a/testing/variations/fieldtrial_testing_config_ios.json b/testing/variations/fieldtrial_testing_config_ios.json
index bb8cfc3d..95c1922 100644
--- a/testing/variations/fieldtrial_testing_config_ios.json
+++ b/testing/variations/fieldtrial_testing_config_ios.json
@@ -28,6 +28,14 @@
             "group_name": "Enabled"
         }
     ],
+    "ExpectCTReporting": [
+        {
+            "enable_features": [
+                "ExpectCTReporting"
+            ],
+            "group_name": "ExpectCTReportingEnabled"
+        }
+    ],
     "NetworkTimeQueries": [
         {
             "enable_features": [
diff --git a/testing/variations/fieldtrial_testing_config_linux.json b/testing/variations/fieldtrial_testing_config_linux.json
index 9a910c46..8b524112 100644
--- a/testing/variations/fieldtrial_testing_config_linux.json
+++ b/testing/variations/fieldtrial_testing_config_linux.json
@@ -74,6 +74,14 @@
             "group_name": "Enabled"
         }
     ],
+    "ExpectCTReporting": [
+        {
+            "enable_features": [
+                "ExpectCTReporting"
+            ],
+            "group_name": "ExpectCTReportingEnabled"
+        }
+    ],
     "ExtensionActionRedesign": [
         {
             "group_name": "Enabled"
diff --git a/testing/variations/fieldtrial_testing_config_mac.json b/testing/variations/fieldtrial_testing_config_mac.json
index d2d5faa..55c7809 100644
--- a/testing/variations/fieldtrial_testing_config_mac.json
+++ b/testing/variations/fieldtrial_testing_config_mac.json
@@ -83,6 +83,14 @@
             "group_name": "Enabled"
         }
     ],
+    "ExpectCTReporting": [
+        {
+            "enable_features": [
+                "ExpectCTReporting"
+            ],
+            "group_name": "ExpectCTReportingEnabled"
+        }
+    ],
     "ExtensionActionRedesign": [
         {
             "group_name": "Enabled"
diff --git a/testing/variations/fieldtrial_testing_config_win.json b/testing/variations/fieldtrial_testing_config_win.json
index ffafb44..59e24f6 100644
--- a/testing/variations/fieldtrial_testing_config_win.json
+++ b/testing/variations/fieldtrial_testing_config_win.json
@@ -95,6 +95,14 @@
             "group_name": "Enabled"
         }
     ],
+    "ExpectCTReporting": [
+        {
+            "enable_features": [
+                "ExpectCTReporting"
+            ],
+            "group_name": "ExpectCTReportingEnabled"
+        }
+    ],
     "ExtensionActionRedesign": [
         {
             "group_name": "Enabled"
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
index 9d84010..b6988e8a 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
@@ -249,7 +249,6 @@
 compositing/images/direct-image-dynamic-border-draws-content.html [ Failure ]
 compositing/images/direct-image-dynamic-clip-path.html [ Failure ]
 compositing/img-layer-grow.html [ Failure ]
-compositing/img-layer-object-fit.html [ Failure ]
 compositing/layer-creation/animation-overlap-with-children.html [ Failure ]
 compositing/layer-creation/assumed-overlap-for-inline-transform.html [ Failure ]
 compositing/layer-creation/compositing-reason-removed.html [ Failure ]
@@ -667,21 +666,9 @@
 fast/css/margin-top-bottom-dynamic.html [ Failure ]
 fast/css/nested-rounded-corners.html [ Failure ]
 fast/css/number-parsing-crash.html [ Crash ]
-fast/css/object-fit-embed.html [ Failure ]
-fast/css/object-fit-grow-landscape.html [ Failure ]
-fast/css/object-fit-grow-portrait.html [ Failure ]
 fast/css/object-fit-img-svg.html [ Failure ]
 fast/css/object-fit-img-svg2.html [ Failure ]
-fast/css/object-fit-img.html [ Failure ]
-fast/css/object-fit-input-image.html [ Failure ]
-fast/css/object-fit-object.html [ Failure ]
-fast/css/object-fit-shrink.html [ Failure ]
-fast/css/object-fit-video-poster.html [ Failure ]
 fast/css/object-position-svg.html [ Failure ]
-fast/css/object-position-with-fit-contain.html [ Failure ]
-fast/css/object-position-with-fit-cover.html [ Failure ]
-fast/css/object-position-with-fit-none.html [ Failure ]
-fast/css/object-position.html [ Failure ]
 fast/css/only-child-pseudo-class.html [ Failure ]
 fast/css/only-of-type-pseudo-class.html [ Failure ]
 fast/css/outline-auto-empty-rects.html [ Failure ]
@@ -1060,7 +1047,6 @@
 fast/images/color-profile-reflection.html [ Crash ]
 fast/images/color-profile-svg-fill-text.html [ Failure ]
 fast/images/color-profile-svg-foreign-object.html [ Failure ]
-fast/images/content-url-broken-image-with-alt-text.html [ Failure ]
 fast/images/content-url-image-with-alt-text.html [ Crash Failure ]
 fast/images/fixed-img-src-change-after-scroll.html [ Failure ]
 fast/images/mask-box-image-crash.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 8e76b1d9..82398e6 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -195,35 +195,6 @@
 # TODO(oshima): Mac Android are currently not supported.
 crbug.com/567837 [ Mac Android ] virtual/scalefactor200withzoom/fast/hidpi/static [ Skip ]
 
-crbug.com/613414 [ Win ] fast/hidpi/broken-image-icon-hidpi.html [ NeedsRebaseline ]
-crbug.com/613414 [ Win ] svg/custom/masking-clipping-hidpi.svg [ NeedsRebaseline ]
-crbug.com/613414 [ Win ] css3/filters/effect-reference-hidpi.html [ NeedsRebaseline ]
-crbug.com/613414 [ Win ] fast/hidpi/device-scale-factor-paint.html [ NeedsRebaseline ]
-crbug.com/613414 [ Win ] virtual/display_list_2d_canvas/fast/canvas/canvas-hidpi-blurry.html [ NeedsRebaseline ]
-crbug.com/613414 [ Win ] fast/hidpi/focus-rings.html [ NeedsRebaseline ]
-crbug.com/613414 [ Win ] css3/filters/effect-reference-hidpi-hw.html [ NeedsRebaseline ]
-crbug.com/613414 [ Win ] fast/hidpi/resize-corner-hidpi.html [ NeedsRebaseline ]
-crbug.com/613414 [ Win ] fast/hidpi/broken-image-with-size-hidpi.html [ NeedsRebaseline ]
-crbug.com/613414 [ Win ] virtual/gpu/fast/canvas/canvas-hidpi-blurry.html [ NeedsRebaseline ]
-crbug.com/613414 [ Win ] fast/sub-pixel/shadows-hidpi.html [ NeedsRebaseline ]
-crbug.com/613414 [ Win ] compositing/tiled-layers-hidpi.html [ NeedsRebaseline ]
-crbug.com/613414 [ Win ] svg/as-image/image-respects-deviceScaleFactor.html [ NeedsRebaseline ]
-crbug.com/613414 [ Win ] fast/hidpi/clip-text-in-hidpi.html [ NeedsRebaseline ]
-crbug.com/613414 [ Win ] fast/canvas/canvas-hidpi-blurry.html [ NeedsRebaseline ]
-crbug.com/613414 [ Win ] fast/backgrounds/gradient-background-leakage-hidpi.html [ NeedsRebaseline ]
-crbug.com/613414 [ Win ] fast/hidpi/gradient-with-scaled-ancestor.html [ NeedsRebaseline ]
-crbug.com/613414 [ Win ] editing/spelling/grammar-markers-hidpi.html [ NeedsRebaseline ]
-crbug.com/613414 [ Win ] editing/spelling/inline-spelling-markers-hidpi.html [ NeedsRebaseline ]
-crbug.com/613414 [ Win ] editing/spelling/inline-spelling-markers-hidpi-composited.html [ NeedsRebaseline ]
-crbug.com/613414 [ Win ] fast/hidpi/image-srcset-intrinsic-size-zero.html [ NeedsRebaseline ]
-crbug.com/613414 [ Win ] virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance.html [ NeedsRebaseline ]
-crbug.com/613414 [ Win ] virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance.html [ NeedsRebaseline ]
-crbug.com/613414 [ Win ] virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance.html [ NeedsRebaseline ]
-crbug.com/613414 [ Win ] virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance.html [ NeedsRebaseline ]
-crbug.com/613414 [ Win ] svg/filters/filter-source-position.svg [ NeedsRebaseline ]
-crbug.com/613414 [ Win ] virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance.html [ NeedsRebaseline ]
-crbug.com/613414 [ Win ] virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance.html [ NeedsRebaseline ]
-
 # Mac does not support fractional scale factor.
 crbug.com/567837 [ Mac ] virtual/scalefactor150/fast/hidpi/static [ Skip ]
 
@@ -475,6 +446,8 @@
 crbug.com/490511 imported/wpt/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-fallback.html [ Failure ]
 crbug.com/490511 imported/wpt/html/semantics/document-metadata/styling/LinkStyle.html [ Failure Pass ]
 crbug.com/490511 imported/wpt/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/src.html [ Failure ]
+crbug.com/627706 imported/wpt/html/semantics/embedded-content/the-img-element/invalid-src.html [ Skip ]
+crbug.com/490511 imported/wpt/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html [ NeedsRebaseline ]
 crbug.com/525889 imported/wpt/html/webappapis/scripting/processing-model-2/compile-error-in-setInterval.html [ Failure ]
 crbug.com/525889 imported/wpt/html/webappapis/scripting/processing-model-2/compile-error-in-setTimeout.html [ Failure ]
 crbug.com/525889 imported/wpt/html/webappapis/scripting/processing-model-2/runtime-error-in-setInterval.html [ Failure ]
@@ -517,9 +490,6 @@
 
 # Web Components related tests (Shadow DOM, Custom Elements) failures.
 crbug.com/505364 imported/wpt/shadow-dom/untriaged/styles/test-003.html [ Failure ]
-crbug.com/505364 imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-002.html [ Failure ]
-crbug.com/505364 imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-003.html [ Failure ]
-crbug.com/505364 imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-004.html [ Failure ]
 crbug.com/505364 imported/wpt/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-event-interface/event-path-001.html [ Failure ]
 crbug.com/505364 imported/wpt/custom-elements/v0/instantiating/extensions-to-document-interface/create-element-interface-type-is-a-type-extension.html [ Failure ]
 crbug.com/505364 imported/csswg-test/css-scoping-1/css-scoping-shadow-slot-display-override.html [ Failure ]
@@ -789,7 +759,6 @@
 crbug.com/564403 http/tests/inspector/service-workers/service-worker-manager.html [ Failure Pass ]
 
 crbug.com/613728 fast/table/border-collapsing/cached-cell-append.html [ Failure ]
-crbug.com/613728 fast/table/border-collapsing/cached-change-tbody-border-width.html [ Failure ]
 crbug.com/613728 fast/table/border-collapsing/cached-change-col-border-width.html [ Failure ]
 crbug.com/613728 fast/table/border-collapsing/cached-cell-remove.html [ Failure ]
 crbug.com/613728 fast/table/border-collapsing/cached-69296.html [ Failure ]
@@ -811,7 +780,6 @@
 
 # We only want to run one of the web-animations-api tests in stable mode.
 crbug.com/441553 virtual/stable/web-animations-api [ Skip ]
-crbug.com/368946 virtual/stable/web-animations-api/eased-keyframes.html [ Pass ]
 # These tests *only* run in stable, to verify that these features are unsupported and throw exceptions.
 crbug.com/441559 virtual/stable/web-animations-api/partial-keyframes-unsupported.html [ Pass ]
 crbug.com/437696 virtual/stable/web-animations-api/additive-animations-unsupported.html [ Pass ]
@@ -956,10 +924,10 @@
 crbug.com/619060 imported/wpt/pointerevents/pointerevent_pointerleave_after_pointercancel_touch-manual.html  [ Skip ]
 crbug.com/619060 imported/wpt/pointerevents/pointerevent_pointerleave_after_pointerup_nohover-manual.html  [ Skip ]
 crbug.com/619060 imported/wpt/pointerevents/pointerevent_pointerleave_touch-manual.html  [ Skip ]
-crbug.com/620236 imported/wpt/pointerevents/pointerevent_properties_mouse-manual.html [ Skip ]
 crbug.com/620236 imported/wpt/pointerevents/pointerevent_releasepointercapture_onpointercancel_touch-manual.html  [ Skip ]
+crbug.com/620236 imported/wpt/pointerevents/pointerevent_suppress_compat_events_on_click.html [ Skip ]
+crbug.com/620236 imported/wpt/pointerevents/pointerevent_suppress_compat_events_on_drag_mouse.html [ Skip ]
 crbug.com/620236 imported/wpt/pointerevents/pointerevent_touch-action-auto-css_touch-manual.html  [ Skip ]
-crbug.com/620236 imported/wpt/pointerevents/pointerevent_touch-action-button-test_touch-manual.html  [ Skip ]
 crbug.com/620236 imported/wpt/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch-manual.html  [ Skip ]
 crbug.com/620236 imported/wpt/pointerevents/pointerevent_touch-action-inherit_child-none_touch-manual.html  [ Skip ]
 crbug.com/620236 imported/wpt/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual.html  [ Skip ]
@@ -978,6 +946,7 @@
 
 crbug.com/583413 imported/wpt/pointerevents/pointerevent_pointerleave_pen-manual.html  [ Failure ]
 
+crbug.com/627716 imported/wpt/pointerevents/pointerevent_touch-action-button-test_touch-manual.html [ Skip ]
 
 # These testcases are incorrect, mark them as failing until they're fixed in the testsuite.
 # https://lists.w3.org/Archives/Public/www-style/2016Jan/0275.html
@@ -1333,8 +1302,6 @@
 crbug.com/624019 [ Mac ] bluetooth/notifications/stop-twice.html [ Skip ]
 crbug.com/624019 [ Mac ] bluetooth/notifications/stop-without-starting.html [ Skip ]
 
-crbug.com/626992 paint/invalidation/outline-containing-image-in-non-standard-mode.html [ NeedsRebaseline ]
-
 crbug.com/487344 compositing/video/video-controls-layer-creation.html [ Failure ]
 crbug.com/487344 fast/hidpi/video-controls-in-hidpi.html [ Failure ]
 crbug.com/487344 fast/layers/video-layer.html [ Failure ]
@@ -1390,3 +1357,7 @@
 crbug.com/625020 [ Debug ] compositing/repaint/page-scale-repaint.html [ Timeout ]
 
 crbug.com/620432 accessibility/aria-activedescendant.html [ Failure ]
+
+crbug.com/627754 [ Precise Debug ] virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance.html [ Failure ]
+crbug.com/627754 [ Precise Debug ] virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance.html [ Failure ]
+
diff --git a/third_party/WebKit/LayoutTests/W3CImportExpectations b/third_party/WebKit/LayoutTests/W3CImportExpectations
index 0db0697..cda5870 100644
--- a/third_party/WebKit/LayoutTests/W3CImportExpectations
+++ b/third_party/WebKit/LayoutTests/W3CImportExpectations
@@ -196,6 +196,7 @@
 imported/wpt/XMLHttpRequest [ Skip ]
 imported/wpt/ambient-light [ Skip ]
 imported/wpt/animation-timing [ Skip ]
+imported/wpt/annotation-model [ Skip ]
 imported/wpt/app-uri [ Skip ]
 imported/wpt/battery-status [ Skip ]
 ## Owners: none; No tests in the directory.
diff --git a/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-width-interpolation.html b/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-width-interpolation.html
index 311fc51..c561683 100644
--- a/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-width-interpolation.html
+++ b/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-width-interpolation.html
@@ -89,6 +89,78 @@
   {at: 1, is: '20rem'},
   {at: 1.4, is: '0'}
 ]);
+assertAttributeInterpolation({
+  property: 'width',
+  from: '1vw',
+  to: '6vw'
+}, [
+  {at: -0.4, is: '0vw'},
+  {at: 0, is: '1vw'},
+  {at: 0.2, is: '2vw'},
+  {at: 0.6, is: '4vw'},
+  {at: 1, is: '6vw'},
+  {at: 1.4, is: '8vw'}
+]);
+assertAttributeInterpolation({
+  property: 'width',
+  from: '1vh',
+  to: '6vh'
+}, [
+  {at: -0.4, is: '0vh'},
+  {at: 0, is: '1vh'},
+  {at: 0.2, is: '2vh'},
+  {at: 0.6, is: '4vh'},
+  {at: 1, is: '6vh'},
+  {at: 1.4, is: '8vh'}
+]);
+assertAttributeInterpolation({
+  property: 'width',
+  from: '1vmin',
+  to: '6vmin'
+}, [
+  {at: -0.4, is: '0vmin'},
+  {at: 0, is: '1vmin'},
+  {at: 0.2, is: '2vmin'},
+  {at: 0.6, is: '4vmin'},
+  {at: 1, is: '6vmin'},
+  {at: 1.4, is: '8vmin'}
+]);
+assertAttributeInterpolation({
+  property: 'width',
+  from: '1vmax',
+  to: '6vmax'
+}, [
+  {at: -0.4, is: '0vmax'},
+  {at: 0, is: '1vmax'},
+  {at: 0.2, is: '2vmax'},
+  {at: 0.6, is: '4vmax'},
+  {at: 1, is: '6vmax'},
+  {at: 1.4, is: '8vmax'}
+]);
+assertAttributeInterpolation({
+  property: 'width',
+  from: '10vh',
+  to: '20vw'
+}, [
+  {at: -0.4, is: '20'},
+  {at: 0, is: '10vh'},
+  {at: 0.2, is: '80'},
+  {at: 0.6, is: '120'},
+  {at: 1, is: '20vw'},
+  {at: 1.4, is: '200'}
+]);
+assertAttributeInterpolation({
+  property: 'width',
+  from: '10vmin',
+  to: '20vmax'
+}, [
+  {at: -0.4, is: '20'},
+  {at: 0, is: '10vmin'},
+  {at: 0.2, is: '80'},
+  {at: 0.6, is: '120'},
+  {at: 1, is: '20vmax'},
+  {at: 1.4, is: '200'}
+]);
 </script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/compositing/img-layer-object-fit-expected.html b/third_party/WebKit/LayoutTests/compositing/img-layer-object-fit-expected.html
deleted file mode 100644
index b1beeecd8..0000000
--- a/third_party/WebKit/LayoutTests/compositing/img-layer-object-fit-expected.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<style>
-  img {
-    width: 100px;
-    height: 30px;
-  }
-</style>
-<img src="resources/simple_image.png" style="object-fit: contain"/><br/>
-<img src="resources/simple_image.png" style="object-fit: cover"/><br/>
-<img src="resources/simple_image.png" style="object-fit: none"/><br/>
-<img src="resources/simple_image.png" style="object-fit: scale-down"/><br/>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/compositing/img-layer-object-fit-expected.png b/third_party/WebKit/LayoutTests/compositing/img-layer-object-fit-expected.png
new file mode 100644
index 0000000..9c9cc0c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/compositing/img-layer-object-fit-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/csspaint/paint2d-zoom-expected.png b/third_party/WebKit/LayoutTests/csspaint/paint2d-zoom-expected.png
new file mode 100644
index 0000000..2385f47
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/csspaint/paint2d-zoom-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/csspaint/paint2d-zoom-expected.txt b/third_party/WebKit/LayoutTests/csspaint/paint2d-zoom-expected.txt
new file mode 100644
index 0000000..61418eaf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/csspaint/paint2d-zoom-expected.txt
@@ -0,0 +1,8 @@
+CONSOLE MESSAGE: line 31: The worklet should log: 'width: 100, height: 100'
+CONSOLE MESSAGE: line 8: width: 100, height: 100
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x348
+  LayoutBlockFlow {HTML} at (0,0) size 800x348
+    LayoutBlockFlow {BODY} at (24,24) size 752x300
+      LayoutBlockFlow {DIV} at (0,0) size 300x300
diff --git a/third_party/WebKit/LayoutTests/csspaint/paint2d-zoom.html b/third_party/WebKit/LayoutTests/csspaint/paint2d-zoom.html
new file mode 100644
index 0000000..ba22299
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/csspaint/paint2d-zoom.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../resources/run-after-layout-and-paint.js"></script>
+<script src="resources/test-runner-paint-worklet.js"></script>
+<style>
+    #output {
+        width: 100px;
+        height: 100px;
+        background-image: paint(worklet);
+    }
+</style>
+</head>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('worklet', class {
+    paint(ctx, geom) {
+         ctx.rotate(10 * Math.PI / 180);
+         ctx.strokeStyle = 'blue';
+         ctx.lineWidth = 4;
+         ctx.strokeRect(30, 10, 30, 30);
+         console.log('width: ' + geom.width + ', height: ' + geom.height);
+    }
+});
+</script>
+
+<script>
+    document.body.style.zoom = "300%";
+    console.log('The worklet should log: \'width: 100, height: 100\'');
+    importPaintWorkletAndTerminateTestAfterAsyncPaint(document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-item-with-percent-height-replaced-element.html b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-item-with-percent-height-replaced-element.html
new file mode 100644
index 0000000..93f1700
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-item-with-percent-height-replaced-element.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+
+<link href="resources/grid.css" rel="stylesheet">
+<link href="resources/grid-alignment.css" rel="stylesheet">
+<link href="../css-intrinsic-dimensions/resources/width-keyword-classes.css" rel="stylesheet">
+
+<style>
+    .grid {
+        grid: 200px / 200px;
+        width: 200px;
+    }
+
+    .red {
+        background-color: red;
+    }
+
+    img {
+        height: 100%;
+        display: block;
+    }
+</style>
+
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../../resources/check-layout-th.js"></script>
+
+<body onload="checkLayout('.grid')">
+<div id="log"></div>
+
+<p>This test checks that percentage heights are properly resolved for grid items that are replaced elements.
+You shouldn't see any red if the test is working as expected.</p>
+
+<p>1) 100% height on the image (grid item) should be resolved against the height of the grid area (200px).
+Actually we don't need the 100% height in this case as the grid items are stretched by default.</p>
+
+<div class="grid red">
+    <img src="../css/resources/greenbox-100px.png"
+         data-expected-width="200" data-expected-height="200">
+</div>
+
+<p>2) 100% height on the image (grid item's child) should be resolved against the height of the grid item,
+which is stretched by default to the height of the grid area (200px).</p>
+
+
+<div class="grid red">
+    <div data-expected-width="200" data-expected-height="200">
+        <img src="../css/resources/greenbox-100px.png"
+             data-expected-width="200" data-expected-height="200">
+    </div>
+</div>
+
+<p>3) 100% height on the image (grid item) should be resolved against the height of the grid area (200px).
+The grid item is not stretched in this case but the height percentage can be resolved anyway.</p>
+
+<div class="grid red alignItemsStart">
+    <img src="../css/resources/greenbox-100px.png"
+         data-expected-width="200" data-expected-height="200">
+</div>
+
+<p>4) 100% height on the image (grid item's child) should be resolved against the height of the grid item,
+as it's not stretched the grid item's height is indefinite, so the percentage cannot be resolved.</p>
+
+<div class="grid alignItemsStart justifyItemsStart">
+    <div class="firstRowFirstColumn red" style="width: 100px; height: 100px;"
+        data-expected-width="100" data-expected-height="100">
+    </div>
+    <div class="firstRowFirstColumn">
+        <img src="../css/resources/greenbox-100px.png"
+            data-expected-width="100" data-expected-height="100">
+    </div>
+</div>
+
+</body>
diff --git a/third_party/WebKit/LayoutTests/fast/css/object-fit-grow-landscape-expected.html b/third_party/WebKit/LayoutTests/fast/css/object-fit-grow-landscape-expected.html
deleted file mode 100644
index 76c1e9e3..0000000
--- a/third_party/WebKit/LayoutTests/fast/css/object-fit-grow-landscape-expected.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!DOCTYPE html>
-
-<html>
-  <head>
-    <title>object-fit, landscape images smaller than content box</title>
-    <style type="text/css">
-      .group > div {
-        display: inline-block;
-        overflow: hidden;
-        width: 144px;
-        height: 144px;
-        margin: 10px;
-        border: 1px solid black;
-        background-color: gray;
-      }
-
-      .group > * > * { display: block; }
-      .group.landscape > *:nth-child(1) > * { width:100%; height:100%; }
-      .group.landscape > *:nth-child(2) > * { width:100%; margin-top:25%; }
-      .group.landscape > *:nth-child(3) > * { height:100%; margin-left:-50%; }
-      .group.landscape > *:nth-child(4) > * { margin-left: 36px; margin-top:54px; }
-      .group.landscape > *:nth-child(5) > * { margin-left: 36px; margin-top:54px; }
-    </style>
-  </head>
-  <body>
-
-    <!-- Small images, should be scaled up when allowed. -->
-    <div class="group landscape">
-      <div><img src="resources/circles-landscape-small.png"></div>
-      <div><img src="resources/circles-landscape-small.png"></div>
-      <div><img src="resources/circles-landscape-small.png"></div>
-      <div><img src="resources/circles-landscape-small.png"></div>
-      <div><img src="resources/circles-landscape-small.png"></div>
-    </div>
-  </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/fast/css/object-fit-grow-portrait-expected.html b/third_party/WebKit/LayoutTests/fast/css/object-fit-grow-portrait-expected.html
deleted file mode 100644
index b11997c8..0000000
--- a/third_party/WebKit/LayoutTests/fast/css/object-fit-grow-portrait-expected.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!DOCTYPE html>
-
-<html>
-  <head>
-    <title>object-fit, portrait images smaller than content box</title>
-    <style type="text/css">
-      .group > div {
-        display: inline-block;
-        overflow: hidden;
-        height: 144px;
-        width: 144px;
-        margin: 10px;
-        border: 1px solid black;
-        background-color: gray;
-      }
-      div > * > * { display:block; }
-      .group.portrait > *:nth-child(1) > * { width:100%; height:100%; }
-      .group.portrait > *:nth-child(2) > * { height:100%; margin-left:25%; }
-      .group.portrait > *:nth-child(3) > * { width:100%; margin-top:-50%; }
-      .group.portrait > *:nth-child(4) > * { margin-top:36px; margin-left:54px; }
-      .group.portrait > *:nth-child(5) > * { margin-top:36px; margin-left:54px; }
-    </style>
-  </head>
-  <body>
-
-    <!-- Small images, should be scaled up when allowed. -->
-    <div class="group portrait">
-      <div><img src="resources/circles-portrait-small.png"></div>
-      <div><img src="resources/circles-portrait-small.png"></div>
-      <div><img src="resources/circles-portrait-small.png"></div>
-      <div><img src="resources/circles-portrait-small.png"></div>
-      <div><img src="resources/circles-portrait-small.png"></div>
-    </div>
-  </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/HTMLTemplateElement/no-form-association2.html b/third_party/WebKit/LayoutTests/fast/dom/HTMLTemplateElement/no-form-association2.html
new file mode 100644
index 0000000..e819b2d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/dom/HTMLTemplateElement/no-form-association2.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<body>
+<!-- based on WebKit test: https://trac.webkit.org/changeset/160182 -->
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script>
+function stripSpaces(str) {
+  return str.replace(/[\s\n]/gm, '');
+}
+</script>
+<form>
+  <template id="templateWithFormInsideForm">
+    <form>
+      <input>
+    </form>
+  </template>
+</form>
+<script>
+test(function() {
+  var templateWithFormInsideForm = document.getElementById('templateWithFormInsideForm');
+  assert_equals(stripSpaces(templateWithFormInsideForm.innerHTML), '<form><input></form>');
+  var formInsideTemplate = templateWithFormInsideForm.content.firstElementChild;
+  assert_equals(formInsideTemplate.localName, 'form');
+  var inputInsideTemplate = templateWithFormInsideForm.content.querySelector('input');
+  assert_equals(inputInsideTemplate.form, formInsideTemplate);
+  assert_equals(formInsideTemplate.firstElementChild, inputInsideTemplate);
+}, 'Form control elements inside templates should not be associated with forms outside the template.');
+</script>
+<template id="templateWithNestedForms">
+  <form>
+    <form></form>
+  </form>
+</template>
+<script>
+test(function() {
+  var templateWithNestedForms = document.getElementById('templateWithNestedForms');
+  assert_equals(stripSpaces(templateWithNestedForms.innerHTML), '<form><form></form></form>');
+}, '(Nested) form elements inside templates should be parsed correctly.');
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/events/event-creation-expected.txt b/third_party/WebKit/LayoutTests/fast/events/event-creation-expected.txt
index fa2b75d..fe9ab579 100644
--- a/third_party/WebKit/LayoutTests/fast/events/event-creation-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/events/event-creation-expected.txt
@@ -1,4 +1,3 @@
-CONSOLE WARNING: line 1: 'SVGZoomEvent' is deprecated and will be removed in M52, around July 2016. See https://www.chromestatus.com/features/5760883808534528 for more details.
 This tests that document.createEvent is hooked up for all Event interfaces (and alternatives) and creates the right instance.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
@@ -111,12 +110,6 @@
 PASS document.createEvent('StorageEvent').constructor === window.StorageEvent is true
 PASS document.createEvent('SVGEvents') instanceof window.Event is true
 PASS document.createEvent('SVGEvents').constructor === window.Event is true
-PASS document.createEvent('SVGZoomEvent') instanceof window.SVGZoomEvent is true
-PASS document.createEvent('SVGZoomEvent') instanceof window.Event is true
-PASS document.createEvent('SVGZoomEvent').constructor === window.SVGZoomEvent is true
-PASS document.createEvent('SVGZoomEvents') instanceof window.SVGZoomEvent is true
-PASS document.createEvent('SVGZoomEvents') instanceof window.Event is true
-PASS document.createEvent('SVGZoomEvents').constructor === window.SVGZoomEvent is true
 PASS document.createEvent('CloseEvent') instanceof window.CloseEvent is true
 PASS document.createEvent('CloseEvent') instanceof window.Event is true
 PASS document.createEvent('CloseEvent').constructor === window.CloseEvent is true
diff --git a/third_party/WebKit/LayoutTests/fast/events/event-creation.html b/third_party/WebKit/LayoutTests/fast/events/event-creation.html
index e08d06b..7b43650 100644
--- a/third_party/WebKit/LayoutTests/fast/events/event-creation.html
+++ b/third_party/WebKit/LayoutTests/fast/events/event-creation.html
@@ -166,16 +166,6 @@
     shouldBeTrue("document.createEvent('SVGEvents') instanceof window.Event");
     shouldBeTrue("document.createEvent('SVGEvents').constructor === window.Event");
 
-    // SVGZoomEvent
-    shouldBeTrue("document.createEvent('SVGZoomEvent') instanceof window.SVGZoomEvent");
-    shouldBeTrue("document.createEvent('SVGZoomEvent') instanceof window.Event");
-    shouldBeTrue("document.createEvent('SVGZoomEvent').constructor === window.SVGZoomEvent");
-
-    // SVGZoomEvents (SVGZoomEvent alternative)
-    shouldBeTrue("document.createEvent('SVGZoomEvents') instanceof window.SVGZoomEvent");
-    shouldBeTrue("document.createEvent('SVGZoomEvents') instanceof window.Event");
-    shouldBeTrue("document.createEvent('SVGZoomEvents').constructor === window.SVGZoomEvent");
-
     // CloseEvent
     shouldBeTrue("document.createEvent('CloseEvent') instanceof window.CloseEvent");
     shouldBeTrue("document.createEvent('CloseEvent') instanceof window.Event");
diff --git a/third_party/WebKit/LayoutTests/fast/events/mouse-cursor-change-after-image-load.html b/third_party/WebKit/LayoutTests/fast/events/mouse-cursor-change-after-image-load.html
new file mode 100644
index 0000000..031e576
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/events/mouse-cursor-change-after-image-load.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Cursor: should update after image loaded even when stationary</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<style>
+#target {
+  height: 500px;
+  width: 500px;
+}
+</style>
+</head>
+<body>
+<div id="target"></div>
+<script>
+var cursorTest = async_test('Test cursor update after image loaded');
+cursorTest.step(function() {
+    assert_not_equals(window.eventSender, undefined, 'This test requires eventSender.');
+
+    assert_equals(internals.getCurrentCursorInfo(), "type=Pointer hotSpot=0,0");
+
+    var target = document.getElementById('target');
+    var rect = target.getBoundingClientRect();
+    eventSender.mouseMoveTo(rect.left + 3, rect.top + 3);
+
+    // Wait for condition until timeout.
+    function waitForCondition(condition, completion) {
+        if (condition()) {
+            completion();
+        } else {
+            requestAnimationFrame(() => waitForCondition(condition, completion));
+        }
+    }
+
+    function testSetCursorImage(url, expectedCursorInfo, complete) {
+        const currentCursorInfo = internals.getCurrentCursorInfo();
+        target.style.cursor = `url(${url}),auto`;
+        waitForCondition(() => internals.getCurrentCursorInfo() != currentCursorInfo, cursorTest.step_func(() => {
+            assert_equals(internals.getCurrentCursorInfo(), expectedCursorInfo);
+            complete();
+        }));
+    }
+
+    testSetCursorImage('resources/greenbox.png', 'type=Custom hotSpot=0,0 image=25x25', () => {
+        testSetCursorImage('resources/abe.png', 'type=Custom hotSpot=0,0 image=76x103', () => {
+            cursorTest.done();
+        })
+    });
+});
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/select/menulist-appearance-none.html b/third_party/WebKit/LayoutTests/fast/forms/select/menulist-appearance-none.html
new file mode 100644
index 0000000..85e0f63
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/forms/select/menulist-appearance-none.html
@@ -0,0 +1,7 @@
+<p>
+    Rendering test for <i><a href="https://bugs.chromium.org/p/chromium/issues/detail?id=626278">https://bugs.chromium.org/p/chromium/issues/detail?id=626278</a>
+    Regression: HTML Select's text appears chopped if appearance is set to none</i>.
+</p>
+<select style="-webkit-appearance: none; line-height: 40px;">
+    <option>Test</option>
+</select>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/text/text-dir-auto-with-placeholder.html b/third_party/WebKit/LayoutTests/fast/forms/text/text-dir-auto-with-placeholder.html
new file mode 100644
index 0000000..24be51f6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/forms/text/text-dir-auto-with-placeholder.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<body>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<input dir="auto" placeholder="LTR placeholder string" value="&#x05E2;">
+<script>
+test(() => {
+    assert_equals(getComputedStyle(document.querySelector('input'), '').direction, 'rtl');
+}, 'Placeholder\'s direction shouldn\'t affect INPUT direction.');
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-dir-auto-with-placeholder.html b/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-dir-auto-with-placeholder.html
new file mode 100644
index 0000000..a97f68d1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-dir-auto-with-placeholder.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<body>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<textarea dir="auto" placeholder="LTR placeholder string">&#x05E2;</textarea>
+<script>
+test(() => {
+    assert_equals(getComputedStyle(document.querySelector('textarea'), '').direction, 'rtl');
+}, 'Placeholder\'s direction shouldn\'t affect TEXTAREA direction.');
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/fast/table/border-collapsing/cached-change-tbody-border-width-expected.txt b/third_party/WebKit/LayoutTests/fast/table/border-collapsing/cached-change-tbody-border-width-expected.txt
index 2514bae..e9d80df 100644
--- a/third_party/WebKit/LayoutTests/fast/table/border-collapsing/cached-change-tbody-border-width-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/table/border-collapsing/cached-change-tbody-border-width-expected.txt
@@ -1,53 +1,55 @@
 {
+  "name": "Content Root Layer",
   "bounds": [800, 600],
   "children": [
     {
+      "name": "LayoutView #document",
       "bounds": [800, 600],
       "contentsOpaque": true,
       "drawsContent": true,
       "paintInvalidations": [
         {
           "object": "LayoutTable TABLE",
-          "rect": [8, 159, 111, 2],
+          "rect": [8, 159, 114, 2],
           "reason": "incremental"
         },
         {
           "object": "LayoutTable TABLE",
-          "rect": [8, 160, 111, 1],
+          "rect": [8, 160, 114, 1],
           "reason": "incremental"
         },
         {
           "object": "LayoutTableSection TBODY id='tbody'",
-          "rect": [10, 10, 107, 100],
+          "rect": [10, 10, 110, 100],
           "reason": "style change"
         },
         {
+          "object": "LayoutTableRow TR",
+          "rect": [10, 110, 110, 50],
+          "reason": "bounds change"
+        },
+        {
+          "object": "LayoutTableSection TBODY",
+          "rect": [10, 110, 110, 50],
+          "reason": "bounds change"
+        },
+        {
+          "object": "LayoutTableRow TR",
+          "rect": [10, 60, 110, 50],
+          "reason": "bounds change"
+        },
+        {
+          "object": "LayoutTableRow TR",
+          "rect": [10, 10, 110, 50],
+          "reason": "bounds change"
+        },
+        {
           "object": "LayoutTableSection TBODY id='tbody'",
           "rect": [9, 9, 107, 100],
           "reason": "style change"
         },
         {
           "object": "LayoutTableRow TR",
-          "rect": [10, 110, 107, 50],
-          "reason": "bounds change"
-        },
-        {
-          "object": "LayoutTableSection TBODY",
-          "rect": [10, 110, 107, 50],
-          "reason": "bounds change"
-        },
-        {
-          "object": "LayoutTableRow TR",
-          "rect": [10, 60, 107, 50],
-          "reason": "bounds change"
-        },
-        {
-          "object": "LayoutTableRow TR",
-          "rect": [10, 10, 107, 50],
-          "reason": "bounds change"
-        },
-        {
-          "object": "LayoutTableRow TR",
           "rect": [9, 109, 107, 50],
           "reason": "bounds change"
         },
@@ -68,27 +70,32 @@
         },
         {
           "object": "LayoutTableCell TD",
-          "rect": [62, 8, 57, 53],
-          "reason": "location change"
-        },
-        {
-          "object": "LayoutTableCell TD",
-          "rect": [63, 108, 56, 53],
+          "rect": [64, 8, 58, 53],
           "reason": "bounds change"
         },
         {
           "object": "LayoutTableCell TD",
-          "rect": [8, 59, 56, 53],
+          "rect": [8, 59, 58, 53],
           "reason": "bounds change"
         },
         {
           "object": "LayoutTableCell TD",
-          "rect": [8, 8, 56, 53],
+          "rect": [8, 8, 58, 53],
           "reason": "location change"
         },
         {
           "object": "LayoutTableCell TD",
-          "rect": [63, 60, 56, 52],
+          "rect": [65, 108, 57, 53],
+          "reason": "bounds change"
+        },
+        {
+          "object": "LayoutTableCell TD",
+          "rect": [8, 108, 57, 53],
+          "reason": "bounds change"
+        },
+        {
+          "object": "LayoutTableCell TD",
+          "rect": [65, 60, 57, 52],
           "reason": "bounds change"
         },
         {
@@ -98,7 +105,12 @@
         },
         {
           "object": "LayoutTableCell TD",
-          "rect": [8, 108, 55, 53],
+          "rect": [62, 8, 55, 52],
+          "reason": "bounds change"
+        },
+        {
+          "object": "LayoutTableCell TD",
+          "rect": [63, 109, 54, 51],
           "reason": "bounds change"
         },
         {
@@ -108,40 +120,90 @@
         },
         {
           "object": "LayoutTable TABLE",
-          "rect": [115, 8, 4, 153],
+          "rect": [115, 8, 7, 153],
           "reason": "incremental"
         },
         {
           "object": "LayoutTable TABLE",
-          "rect": [117, 8, 2, 153],
+          "rect": [117, 8, 5, 153],
           "reason": "incremental"
-        },
-        {
-          "object": "LayoutTableCell TD",
-          "reason": "full"
-        },
-        {
-          "object": "LayoutTableCell TD",
-          "reason": "full"
-        },
-        {
-          "object": "LayoutTableCell TD",
-          "reason": "full"
-        },
-        {
-          "object": "LayoutTableCell TD",
-          "reason": "full"
-        },
-        {
-          "object": "LayoutTableCell TD",
-          "reason": "full"
-        },
-        {
-          "object": "LayoutTableCell TD",
-          "reason": "full"
         }
       ]
     }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutTableCell TD",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutTableCell TD",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutTableCell TD",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutTableCell TD",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutTableCell TD",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutTableCell TD",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutTable TABLE",
+      "reason": "incremental"
+    },
+    {
+      "object": "LayoutTableSection TBODY id='tbody'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutTableRow TR",
+      "reason": "bounds change"
+    },
+    {
+      "object": "LayoutTableCell TD",
+      "reason": "location change"
+    },
+    {
+      "object": "LayoutTableCell TD",
+      "reason": "bounds change"
+    },
+    {
+      "object": "LayoutTableRow TR",
+      "reason": "bounds change"
+    },
+    {
+      "object": "LayoutTableCell TD",
+      "reason": "bounds change"
+    },
+    {
+      "object": "LayoutTableCell TD",
+      "reason": "bounds change"
+    },
+    {
+      "object": "LayoutTableSection TBODY",
+      "reason": "bounds change"
+    },
+    {
+      "object": "LayoutTableRow TR",
+      "reason": "bounds change"
+    },
+    {
+      "object": "LayoutTableCell TD",
+      "reason": "bounds change"
+    },
+    {
+      "object": "LayoutTableCell TD",
+      "reason": "bounds change"
+    }
   ]
 }
 
diff --git a/third_party/WebKit/LayoutTests/fast/table/change-tbody-border-width-expected.txt b/third_party/WebKit/LayoutTests/fast/table/change-tbody-border-width-expected.txt
new file mode 100644
index 0000000..d93f49f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/table/change-tbody-border-width-expected.txt
@@ -0,0 +1,9 @@
+Changing a collapsed border's width should change the width of the table and the width of a shrink-to-fit containing block.
+
+There should be a square with a 4px inner blue border and a 1px outer black border.
+
+Firefox 50.0a1 (nightly 2016-07-07) fails this, so it should probably be upstreamed, except it uses chrome-specific `runAfterLayoutAndPaint`.
+
+The table cell has rowspan=2 because we almost didn't cover the case where a cell's rowspan exceeded the declared rows.
+
+PASS
diff --git a/third_party/WebKit/LayoutTests/fast/table/change-tbody-border-width.html b/third_party/WebKit/LayoutTests/fast/table/change-tbody-border-width.html
new file mode 100644
index 0000000..6760bc58
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/table/change-tbody-border-width.html
@@ -0,0 +1,30 @@
+<!doctype html>
+<style>
+    td {
+        width: 50px;
+        height: 50px;
+        padding: 0px;
+    }
+</style>
+<script src="../../resources/check-layout.js"></script>
+<script src="../../resources/run-after-layout-and-paint.js"></script>
+<script type="text/javascript">
+    function shrinkSectionBorder() {
+        document.getElementById("section").style.borderWidth = "4px";
+        checkLayout("div");
+    }
+    runAfterLayoutAndPaint(shrinkSectionBorder, true);
+</script>
+<p>Changing a collapsed border's width should change the width of the table and the width of a shrink-to-fit containing block.</p>
+<p>There should be a square with a 4px inner blue border and a 1px outer black border.</p>
+<p>Firefox 50.0a1 (nightly 2016-07-07) fails this, so it should probably be upstreamed, except it uses chrome-specific `runAfterLayoutAndPaint`.</p>
+<p>The table cell has rowspan=2 because we almost didn't cover the case where a cell's rowspan exceeded the declared rows.</p>
+<div style="float:left; border: 1px solid black" data-expected-width=60>
+    <table style="border-collapse:collapse" data-expected-width=58 data-expected-height=58>
+        <tbody style="border:18px solid lightblue" id="section">
+            <tr>
+                <td rowspan=2></td>
+            </tr>
+        </tbody>
+    </table>
+</div>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/console-show-all-messages.html b/third_party/WebKit/LayoutTests/http/tests/inspector/console-show-all-messages.html
index 54be7f8..fbb08c2 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/console-show-all-messages.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/console-show-all-messages.html
@@ -30,6 +30,7 @@
 
             function testPageOnlyMessages(next)
             {
+                InspectorTest.changeExecutionContext("top");
                 checkbox.click();
                 dumpVisibleConsoleMessageText();
                 next();
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js
index 1f346e4d..5768313 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js
@@ -305,9 +305,7 @@
 
     function runtimeCallFramePosition()
     {
-        var lineNumber = this.lineNumber ? this.lineNumber - 1 : 0;
-        var columnNumber = this.columnNumber ? this.columnNumber - 1 : 0;
-        return new WebInspector.DebuggerModel.Location(debuggerModel, this.scriptId, lineNumber, columnNumber);
+        return new WebInspector.DebuggerModel.Location(debuggerModel, this.scriptId, this.lineNumber, this.columnNumber);
     }
 
     results.push("Call stack:");
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-document-initiator-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-document-initiator-expected.txt
index 0963b31..9fc76a7 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-document-initiator-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-document-initiator-expected.txt
@@ -2,5 +2,5 @@
 
 Page reloaded.
 http://127.0.0.1:8000/inspector/network/network-document-initiator.html?foo: script
-    navigateFromScript http://127.0.0.1:8000/inspector/network/network-document-initiator.html 9
+    navigateFromScript http://127.0.0.1:8000/inspector/network/network-document-initiator.html 8
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-initiator-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-initiator-expected.txt
index 5074d5c..8936c55 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-initiator-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-initiator-expected.txt
@@ -7,7 +7,7 @@
 http://127.0.0.1:8000/inspector/network/resources/resource.php?type=image&random=1&size=100: parser
     http://127.0.0.1:8000/inspector/network/resources/network-initiator-frame.html 5
 http://127.0.0.1:8000/inspector/network/resources/resource.php?type=image&random=1&size=400: script
-    loadData http://127.0.0.1:8000/inspector/network/resources/network-initiator-frame.html 14
+    loadData http://127.0.0.1:8000/inspector/network/resources/network-initiator-frame.html 13
 http://127.0.0.1:8000/inspector/network/resources/style.css: parser
     http://127.0.0.1:8000/inspector/network/resources/network-initiator-frame.html 8
 http://127.0.0.1:8000/inspector/network/resources/empty.html: parser
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/sources/debugger/async-callstack-network-initiator-image-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/sources/debugger/async-callstack-network-initiator-image-expected.txt
index 0f3e069..2509230 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/sources/debugger/async-callstack-network-initiator-image-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/sources/debugger/async-callstack-network-initiator-image-expected.txt
@@ -1,5 +1,5 @@
 Tests asynchronous network initiator for image loaded from JS.
 
 
-async-callstack-network-initiator-image.html:12
+async-callstack-network-initiator-image.html:11
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/stacktraces/csp-inline-warning-contains-stacktrace-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/stacktraces/csp-inline-warning-contains-stacktrace-expected.txt
index 5f6dfc7..1137f966 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/stacktraces/csp-inline-warning-contains-stacktrace-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/stacktraces/csp-inline-warning-contains-stacktrace-expected.txt
@@ -8,5 +8,5 @@
 
     url: http://127.0.0.1:8000/inspector/stacktraces/resources/csp-inline-test.js
     function: thisTest
-    line: 4
+    line: 3
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/stacktraces/csp-setInterval-warning-contains-stacktrace-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/stacktraces/csp-setInterval-warning-contains-stacktrace-expected.txt
index 90ce322..aef89db2 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/stacktraces/csp-setInterval-warning-contains-stacktrace-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/stacktraces/csp-setInterval-warning-contains-stacktrace-expected.txt
@@ -8,5 +8,5 @@
 
     url: http://127.0.0.1:8000/inspector/stacktraces/csp-setInterval-warning-contains-stacktrace.html
     function: thisTest
-    line: 11
+    line: 10
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/stacktraces/csp-setTimeout-warning-contains-stacktrace-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/stacktraces/csp-setTimeout-warning-contains-stacktrace-expected.txt
index 01d3338c7..f4fc3ce4 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/stacktraces/csp-setTimeout-warning-contains-stacktrace-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/stacktraces/csp-setTimeout-warning-contains-stacktrace-expected.txt
@@ -8,5 +8,5 @@
 
     url: http://127.0.0.1:8000/inspector/stacktraces/csp-setTimeout-warning-contains-stacktrace.html
     function: thisTest
-    line: 11
+    line: 10
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/workspace-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/workspace-test.js
index 58c70a5..8007349 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/workspace-test.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/workspace-test.js
@@ -43,11 +43,11 @@
         WebInspector.Target.call(this, InspectorTest.testTargetManager, name, type, connection, null, callback);
         this.consoleModel = new WebInspector.ConsoleModel(this);
         this.networkManager = new WebInspector.NetworkManager(this);
+        this.runtimeModel = new WebInspector.RuntimeModel(this);
         this.resourceTreeModel = new WebInspector.ResourceTreeModel(this);
         this.resourceTreeModel._inspectedPageURL = InspectorTest.resourceTreeModel._inspectedPageURL;
         this.resourceTreeModel._cachedResourcesProcessed = true;
         this.resourceTreeModel._frameAttached("42", 0);
-        this.runtimeModel = new WebInspector.RuntimeModel(this);
         this.debuggerModel = debuggerModelConstructor ? new debuggerModelConstructor(this) : new WebInspector.DebuggerModel(this);
         this._modelByConstructor.set(WebInspector.DebuggerModel, this.debuggerModel);
         this.domModel = new WebInspector.DOMModel(this);
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/first-party-cookie-accepted.html b/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/first-party-cookie-accepted.html
new file mode 100644
index 0000000..d060b65
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/first-party-cookie-accepted.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/websocket/resources/get-request-header.js"></script>
+<script src="/websocket/resources/cookie-test-util.js"></script>
+<script>
+if (window.testRunner) {
+  // Block third-party cookies.
+  testRunner.setBlockThirdPartyCookies(true);
+}
+
+const origin = WS_ORIGIN;
+
+promise_test(() => {
+  return setCookie(origin).then(
+    () => {
+      return connectAndGetRequestHeadersFrom(origin);
+    }
+  ).then(
+    headers => {
+      const cookie = headers['cookie'];
+      assert_not_equals(cookie, undefined,
+                        'headers should contain a cookie header.');
+      assert_equals(
+          normalizeCookie(cookie),
+          'same-site-lax=1; same-site-strict=1; ws-domain-local-ip=1; ' +
+              'ws-path-root=1; ws=1');
+      return clear(origin);
+    }
+  );
+}, "Test that first-party cookies not blocked for WebSockets.");
+</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/resources/set-cookie.html b/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/resources/set-cookie.html
new file mode 100644
index 0000000..a0a59c11
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/resources/set-cookie.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<script src="/websocket/resources/get-request-header.js"></script>
+<script src="/websocket/resources/cookie-test-util.js"></script>
+<script>
+function notifySuccess(value) {
+  window.parent.postMessage('DONE: ' + value, '*');
+}
+
+function notifyFailure(reason) {
+  window.parent.postMessage('FAIL: ' + reason, '*');
+}
+
+let origin = WS_ORIGIN;
+if (location.search == '?remote') {
+  origin = WS_REMOTE_ORIGIN;
+}
+
+setCookie(origin).then(
+  () => connectAndGetRequestHeadersFrom(origin),
+  notifyFailure
+).then(
+  headers => {
+    const cookie = headers['cookie'];
+    return clear(origin).then(() => {
+      notifySuccess(JSON.stringify(cookie));
+    });
+  }
+).catch(
+  notifyFailure
+);
+</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/third-party-cookie-accepted.html b/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/third-party-cookie-accepted.html
new file mode 100644
index 0000000..0c1f45c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/third-party-cookie-accepted.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/websocket/resources/get-request-header.js"></script>
+<script src="/websocket/resources/cookie-test-util.js"></script>
+<script>
+if (window.testRunner) {
+  // Don't block third-party cookies.
+  testRunner.setBlockThirdPartyCookies(false);
+}
+
+const origin = WS_REMOTE_ORIGIN;
+
+promise_test(t => {
+  return setCookie(origin).then(
+    () => {
+      return connectAndGetRequestHeadersFrom(origin);
+    }
+  ).then(
+    headers => {
+      const cookie = headers['cookie'];
+      assert_not_equals(cookie, undefined,
+                        'headers should contain a cookie header.');
+      // Same-site cookies are not included.
+      assert_equals(normalizeCookie(cookie), 'ws-path-root=1; ws=1');
+      return clear(origin);
+    }
+  );
+}, "Test that third-party cookies are accepted for WebSockets when blocking " +
+    "is disabled.");
+</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/third-party-cookie-blocked-on-cross-origin-websocket.html b/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/third-party-cookie-blocked-on-cross-origin-websocket.html
new file mode 100644
index 0000000..17ee16c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/third-party-cookie-blocked-on-cross-origin-websocket.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+if (window.testRunner) {
+  // Block third-party cookies.
+  testRunner.setBlockThirdPartyCookies(true);
+}
+
+async_test(t => {
+  window.addEventListener(
+      'message',
+      t.step_func_done(event => {
+        assert_equals(event.data, 'DONE: undefined');
+      }),
+      false);
+}, "Test that first-party cookies are blocked for WebSockets conforming the " +
+    "requirements of the SameSite attribute.");
+</script>
+<!--
+  The iframe is a remote origin. It uses the same origin as this test case file
+  for the WebSocket.
+-->
+<iframe src="http://localhost:8000/security/cookies/websocket/resources/set-cookie.html"></iframe>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/third-party-cookie-blocked-on-same-origin-websocket.html b/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/third-party-cookie-blocked-on-same-origin-websocket.html
new file mode 100644
index 0000000..c93d819
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/third-party-cookie-blocked-on-same-origin-websocket.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+if (window.testRunner) {
+  // Block third-party cookies.
+  testRunner.setBlockThirdPartyCookies(true);
+}
+
+async_test(t => {
+  window.addEventListener(
+      'message',
+      t.step_func_done(event => {
+        assert_equals(event.data, 'DONE: undefined');
+      }),
+      false);
+}, "Test that third-party cookies are blocked for WebSockets even when the " +
+    "WebSocket's URL's domain is an exact match for the domain of its " +
+    "initiator.");
+</script>
+<!--
+  The iframe is a remote origin. It uses a remote origin for the WebSocket.
+-->
+<iframe src="http://localhost:8000/security/cookies/websocket/resources/set-cookie.html?remote"></iframe>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/third-party-cookie-blocked.html b/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/third-party-cookie-blocked.html
new file mode 100644
index 0000000..78fca21
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/third-party-cookie-blocked.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/websocket/resources/get-request-header.js"></script>
+<script src="/websocket/resources/cookie-test-util.js"></script>
+<script>
+if (window.testRunner) {
+  // Block third-party cookies.
+  testRunner.setBlockThirdPartyCookies(true);
+}
+
+const origin = WS_REMOTE_ORIGIN;
+
+promise_test(t => {
+  return setCookie(origin).then(
+    () => {
+      return connectAndGetRequestHeadersFrom(origin);
+    }
+  ).then(
+    headers => {
+      const cookie = headers['cookie'];
+      assert_equals(cookie, undefined,
+                    'headers should not contain any cookie header.');
+      return clear(origin);
+    }
+  );
+}, "Test third-party cookie blocking for WebSockets");
+</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/websocket/cookie-ws-to-ws-expected.txt b/third_party/WebKit/LayoutTests/http/tests/websocket/cookie-ws-to-ws-expected.txt
index 33fb8c1..c08104b 100644
--- a/third_party/WebKit/LayoutTests/http/tests/websocket/cookie-ws-to-ws-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/websocket/cookie-ws-to-ws-expected.txt
@@ -3,7 +3,7 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS cookie is "ws-domain-local-ip=1; ws-path-root=1; ws=1"
+PASS cookie is "same-site-lax=1; same-site-strict=1; ws-domain-local-ip=1; ws-path-root=1; ws=1"
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/http/tests/websocket/cookie-ws-to-ws.html b/third_party/WebKit/LayoutTests/http/tests/websocket/cookie-ws-to-ws.html
index 74cd330..095712b 100644
--- a/third_party/WebKit/LayoutTests/http/tests/websocket/cookie-ws-to-ws.html
+++ b/third_party/WebKit/LayoutTests/http/tests/websocket/cookie-ws-to-ws.html
@@ -22,7 +22,7 @@
 ws_set_cookie.onclose = function (e) {
     connectAndGetRequestHeader('cookie').then(function(value) {
         cookie = normalizeCookie(value);
-        shouldBeEqualToString('cookie', 'ws-domain-local-ip=1; ws-path-root=1; ws=1');
+        shouldBeEqualToString('cookie', 'same-site-lax=1; same-site-strict=1; ws-domain-local-ip=1; ws-path-root=1; ws=1');
         clear();
     }, finishAsFailed);
 };
diff --git a/third_party/WebKit/LayoutTests/http/tests/websocket/extensions.html b/third_party/WebKit/LayoutTests/http/tests/websocket/extensions.html
index 91549f8..c25f97c6 100644
--- a/third_party/WebKit/LayoutTests/http/tests/websocket/extensions.html
+++ b/third_party/WebKit/LayoutTests/http/tests/websocket/extensions.html
@@ -6,7 +6,7 @@
 
 window.jsTestIsAsync = true;
 
-var ws = new WebSocket(ECHO_REQUEST_HEADERS_WS_URL);
+var ws = new WebSocket(WS_ECHO_REQUEST_HEADERS_URL);
 debug("Check the value before opening the connection:");
 shouldBeEqualToString("ws.extensions", "");
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/websocket/resources/cookie-test-util.js b/third_party/WebKit/LayoutTests/http/tests/websocket/resources/cookie-test-util.js
new file mode 100644
index 0000000..9d5492e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/websocket/resources/cookie-test-util.js
@@ -0,0 +1,25 @@
+// Normalize a cookie string
+function normalizeCookie(cookie) {
+  // Split the cookie string, sort it and then put it back together.
+  return cookie.split('; ').sort().join('; ');
+}
+
+function clear(server) {
+  return new Promise(resolve => {
+    const ws = new WebSocket(server + '/set-cookie?clear=1');
+    ws.onopen = () => {
+      ws.close();
+    };
+    ws.onclose = resolve;
+  });
+}
+
+function setCookie(server) {
+  return new Promise(resolve => {
+    const ws = new WebSocket(server + '/set-cookie');
+    ws.onopen = () => {
+      ws.close();
+    };
+    ws.onclose = resolve;
+  });
+}
diff --git a/third_party/WebKit/LayoutTests/http/tests/websocket/resources/get-request-header.js b/third_party/WebKit/LayoutTests/http/tests/websocket/resources/get-request-header.js
index da429bd2e..23791e3 100644
--- a/third_party/WebKit/LayoutTests/http/tests/websocket/resources/get-request-header.js
+++ b/third_party/WebKit/LayoutTests/http/tests/websocket/resources/get-request-header.js
@@ -1,22 +1,27 @@
-var ECHO_REQUEST_HEADERS_WS_URL = 'ws://127.0.0.1:8880/echo-request-headers';
+var WS_ORIGIN = 'ws://127.0.0.1:8880';
+var WS_REMOTE_ORIGIN = 'ws://localhost:8880';
+var WS_ECHO_REQUEST_HEADERS_URL = WS_ORIGIN + '/echo-request-headers';
 
 // Returns a Promise which will create a new WebSocket, and resolve to the value
 // of the specified header in the request, or reject with an error message if
 // something goes wrong. The header must be specified in lower-case.
 function connectAndGetRequestHeader(request_header)
 {
-    return connectAndGetRequestHeaders().then(function(headers)
-    {
-        return headers[request_header];
-    });
+    return connectAndGetRequestHeaders(WS_ORIGIN).then(
+        headers => headers[request_header]);
+}
+
+function connectAndGetRequestHeaders()
+{
+    return connectAndGetRequestHeadersFrom(WS_ORIGIN);
 }
 
 // Returns a Promise which will create a new WebSocket, and return all the
 // request headers as an object, with the header names as keys in lower-case.
-function connectAndGetRequestHeaders()
+function connectAndGetRequestHeadersFrom(server)
 {
     return new Promise(function(resolve, reject) {
-        var header_ws = new WebSocket(ECHO_REQUEST_HEADERS_WS_URL);
+        var header_ws = new WebSocket(server + '/echo-request-headers');
         header_ws.onmessage = function (evt) {
             try {
                 var headers = JSON.parse(evt.data);
diff --git a/third_party/WebKit/LayoutTests/http/tests/websocket/set-cookie_wsh.py b/third_party/WebKit/LayoutTests/http/tests/websocket/set-cookie_wsh.py
index 1c8bf05..15db410 100644
--- a/third_party/WebKit/LayoutTests/http/tests/websocket/set-cookie_wsh.py
+++ b/third_party/WebKit/LayoutTests/http/tests/websocket/set-cookie_wsh.py
@@ -41,6 +41,8 @@
         'ws-path-root=1; Path=/' + max_age,
         'ws-path-foobar=1; Path=/foo/bar' + max_age,
         'ws=1' + max_age,
+        'same-site-strict=1; SameSite=Strict' + max_age,
+        'same-site-lax=1; SameSite=Lax' + max_age
     ]
     for value in cookie_values:
         request.extra_headers.append(('Set-Cookie', value))
diff --git a/third_party/WebKit/LayoutTests/http/tests/websocket/workers/resources/cookie-ws-to-ws.js b/third_party/WebKit/LayoutTests/http/tests/websocket/workers/resources/cookie-ws-to-ws.js
index 1039663a..050eac8 100644
--- a/third_party/WebKit/LayoutTests/http/tests/websocket/workers/resources/cookie-ws-to-ws.js
+++ b/third_party/WebKit/LayoutTests/http/tests/websocket/workers/resources/cookie-ws-to-ws.js
@@ -48,8 +48,8 @@
         .then(echoCookie)
         .then(
         function (cookie) {
-            if (cookie != 'ws-domain-local-ip=1; ws-path-root=1; ws=1')
-                return Promise.reject('Echoed cookie is incorrect');
+            if (cookie != 'ws-domain-local-ip=1; ws-path-root=1; ws=1; same-site-strict=1; same-site-lax=1')
+                return Promise.reject('Echoed cookie is incorrect: ' + cookie);
 
             postMessage("DONE");
         }
diff --git a/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt b/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt
index 48596722..36222a1 100644
--- a/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt
@@ -109,6 +109,9 @@
 CONSOLE MESSAGE: line 137:     getter y
 CONSOLE MESSAGE: line 137:     getter z
 CONSOLE MESSAGE: line 137:     method constructor
+CONSOLE MESSAGE: line 137: interface CSSVariableReferenceValue
+CONSOLE MESSAGE: line 137:     getter variable
+CONSOLE MESSAGE: line 137:     method constructor
 CONSOLE MESSAGE: line 137: interface CountQueuingStrategy
 CONSOLE MESSAGE: line 137:     method constructor
 CONSOLE MESSAGE: line 137:     method size
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/FileAPI/idlharness-expected.txt b/third_party/WebKit/LayoutTests/imported/wpt/FileAPI/idlharness-expected.txt
index cfaa630..4c03728c 100644
--- a/third_party/WebKit/LayoutTests/imported/wpt/FileAPI/idlharness-expected.txt
+++ b/third_party/WebKit/LayoutTests/imported/wpt/FileAPI/idlharness-expected.txt
@@ -95,5 +95,6 @@
 PASS FileReader interface: new FileReader() must inherit property "onabort" with the proper type (13) 
 PASS FileReader interface: new FileReader() must inherit property "onerror" with the proper type (14) 
 PASS FileReader interface: new FileReader() must inherit property "onloadend" with the proper type (15) 
+PASS FileReaderSync interface: existence and properties of interface object 
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/FileAPI/idlharness.idl b/third_party/WebKit/LayoutTests/imported/wpt/FileAPI/idlharness.idl
index ae83a9cb..62e6c5d 100644
--- a/third_party/WebKit/LayoutTests/imported/wpt/FileAPI/idlharness.idl
+++ b/third_party/WebKit/LayoutTests/imported/wpt/FileAPI/idlharness.idl
@@ -79,3 +79,13 @@
   static void revokeObjectURL(DOMString url);
 
 };
+
+[Constructor, Exposed=Worker]
+interface FileReaderSync {
+
+  // Synchronously return strings
+
+  ArrayBuffer readAsArrayBuffer(Blob blob);
+  DOMString readAsText(Blob blob, optional DOMString label);
+  DOMString readAsDataURL(Blob blob);
+};
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/FileAPI/idlharness.worker.js b/third_party/WebKit/LayoutTests/imported/wpt/FileAPI/idlharness.worker.js
index 40ba816..3243e34 100644
--- a/third_party/WebKit/LayoutTests/imported/wpt/FileAPI/idlharness.worker.js
+++ b/third_party/WebKit/LayoutTests/imported/wpt/FileAPI/idlharness.worker.js
@@ -18,20 +18,7 @@
     idl_array.add_untested_idls("[TreatNonCallableAsNull] callback EventHandlerNonNull = any (Event event);");
     idl_array.add_untested_idls("typedef EventHandlerNonNull? EventHandler;");
 
-
-    var worker_idls =
-            '[Constructor, Exposed=Worker]\n' +
-            'interface FileReaderSync {\n' +
-            '\n' +
-            '  // Synchronously return strings\n' +
-            '\n' +
-            '  ArrayBuffer readAsArrayBuffer(Blob blob);\n' +
-            '  DOMString readAsText(Blob blob, optional DOMString label);\n' +
-            '  DOMString readAsDataURL(Blob blob);\n' +
-            '};';
-
     idl_array.add_idls(idls);
-    idl_array.add_idls(worker_idls);
 
     idl_array.add_objects({
         Blob: ['new Blob(["TEST"])'],
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/common/entities.json b/third_party/WebKit/LayoutTests/imported/wpt/common/entities.json
new file mode 100644
index 0000000..8a1f590
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/common/entities.json
@@ -0,0 +1,2233 @@
+{
+  "&Aacute;": { "codepoints": [193], "characters": "\u00C1" },
+  "&Aacute": { "codepoints": [193], "characters": "\u00C1" },
+  "&aacute;": { "codepoints": [225], "characters": "\u00E1" },
+  "&aacute": { "codepoints": [225], "characters": "\u00E1" },
+  "&Abreve;": { "codepoints": [258], "characters": "\u0102" },
+  "&abreve;": { "codepoints": [259], "characters": "\u0103" },
+  "&ac;": { "codepoints": [8766], "characters": "\u223E" },
+  "&acd;": { "codepoints": [8767], "characters": "\u223F" },
+  "&acE;": { "codepoints": [8766, 819], "characters": "\u223E\u0333" },
+  "&Acirc;": { "codepoints": [194], "characters": "\u00C2" },
+  "&Acirc": { "codepoints": [194], "characters": "\u00C2" },
+  "&acirc;": { "codepoints": [226], "characters": "\u00E2" },
+  "&acirc": { "codepoints": [226], "characters": "\u00E2" },
+  "&acute;": { "codepoints": [180], "characters": "\u00B4" },
+  "&acute": { "codepoints": [180], "characters": "\u00B4" },
+  "&Acy;": { "codepoints": [1040], "characters": "\u0410" },
+  "&acy;": { "codepoints": [1072], "characters": "\u0430" },
+  "&AElig;": { "codepoints": [198], "characters": "\u00C6" },
+  "&AElig": { "codepoints": [198], "characters": "\u00C6" },
+  "&aelig;": { "codepoints": [230], "characters": "\u00E6" },
+  "&aelig": { "codepoints": [230], "characters": "\u00E6" },
+  "&af;": { "codepoints": [8289], "characters": "\u2061" },
+  "&Afr;": { "codepoints": [120068], "characters": "\uD835\uDD04" },
+  "&afr;": { "codepoints": [120094], "characters": "\uD835\uDD1E" },
+  "&Agrave;": { "codepoints": [192], "characters": "\u00C0" },
+  "&Agrave": { "codepoints": [192], "characters": "\u00C0" },
+  "&agrave;": { "codepoints": [224], "characters": "\u00E0" },
+  "&agrave": { "codepoints": [224], "characters": "\u00E0" },
+  "&alefsym;": { "codepoints": [8501], "characters": "\u2135" },
+  "&aleph;": { "codepoints": [8501], "characters": "\u2135" },
+  "&Alpha;": { "codepoints": [913], "characters": "\u0391" },
+  "&alpha;": { "codepoints": [945], "characters": "\u03B1" },
+  "&Amacr;": { "codepoints": [256], "characters": "\u0100" },
+  "&amacr;": { "codepoints": [257], "characters": "\u0101" },
+  "&amalg;": { "codepoints": [10815], "characters": "\u2A3F" },
+  "&amp;": { "codepoints": [38], "characters": "\u0026" },
+  "&amp": { "codepoints": [38], "characters": "\u0026" },
+  "&AMP;": { "codepoints": [38], "characters": "\u0026" },
+  "&AMP": { "codepoints": [38], "characters": "\u0026" },
+  "&andand;": { "codepoints": [10837], "characters": "\u2A55" },
+  "&And;": { "codepoints": [10835], "characters": "\u2A53" },
+  "&and;": { "codepoints": [8743], "characters": "\u2227" },
+  "&andd;": { "codepoints": [10844], "characters": "\u2A5C" },
+  "&andslope;": { "codepoints": [10840], "characters": "\u2A58" },
+  "&andv;": { "codepoints": [10842], "characters": "\u2A5A" },
+  "&ang;": { "codepoints": [8736], "characters": "\u2220" },
+  "&ange;": { "codepoints": [10660], "characters": "\u29A4" },
+  "&angle;": { "codepoints": [8736], "characters": "\u2220" },
+  "&angmsdaa;": { "codepoints": [10664], "characters": "\u29A8" },
+  "&angmsdab;": { "codepoints": [10665], "characters": "\u29A9" },
+  "&angmsdac;": { "codepoints": [10666], "characters": "\u29AA" },
+  "&angmsdad;": { "codepoints": [10667], "characters": "\u29AB" },
+  "&angmsdae;": { "codepoints": [10668], "characters": "\u29AC" },
+  "&angmsdaf;": { "codepoints": [10669], "characters": "\u29AD" },
+  "&angmsdag;": { "codepoints": [10670], "characters": "\u29AE" },
+  "&angmsdah;": { "codepoints": [10671], "characters": "\u29AF" },
+  "&angmsd;": { "codepoints": [8737], "characters": "\u2221" },
+  "&angrt;": { "codepoints": [8735], "characters": "\u221F" },
+  "&angrtvb;": { "codepoints": [8894], "characters": "\u22BE" },
+  "&angrtvbd;": { "codepoints": [10653], "characters": "\u299D" },
+  "&angsph;": { "codepoints": [8738], "characters": "\u2222" },
+  "&angst;": { "codepoints": [197], "characters": "\u00C5" },
+  "&angzarr;": { "codepoints": [9084], "characters": "\u237C" },
+  "&Aogon;": { "codepoints": [260], "characters": "\u0104" },
+  "&aogon;": { "codepoints": [261], "characters": "\u0105" },
+  "&Aopf;": { "codepoints": [120120], "characters": "\uD835\uDD38" },
+  "&aopf;": { "codepoints": [120146], "characters": "\uD835\uDD52" },
+  "&apacir;": { "codepoints": [10863], "characters": "\u2A6F" },
+  "&ap;": { "codepoints": [8776], "characters": "\u2248" },
+  "&apE;": { "codepoints": [10864], "characters": "\u2A70" },
+  "&ape;": { "codepoints": [8778], "characters": "\u224A" },
+  "&apid;": { "codepoints": [8779], "characters": "\u224B" },
+  "&apos;": { "codepoints": [39], "characters": "\u0027" },
+  "&ApplyFunction;": { "codepoints": [8289], "characters": "\u2061" },
+  "&approx;": { "codepoints": [8776], "characters": "\u2248" },
+  "&approxeq;": { "codepoints": [8778], "characters": "\u224A" },
+  "&Aring;": { "codepoints": [197], "characters": "\u00C5" },
+  "&Aring": { "codepoints": [197], "characters": "\u00C5" },
+  "&aring;": { "codepoints": [229], "characters": "\u00E5" },
+  "&aring": { "codepoints": [229], "characters": "\u00E5" },
+  "&Ascr;": { "codepoints": [119964], "characters": "\uD835\uDC9C" },
+  "&ascr;": { "codepoints": [119990], "characters": "\uD835\uDCB6" },
+  "&Assign;": { "codepoints": [8788], "characters": "\u2254" },
+  "&ast;": { "codepoints": [42], "characters": "\u002A" },
+  "&asymp;": { "codepoints": [8776], "characters": "\u2248" },
+  "&asympeq;": { "codepoints": [8781], "characters": "\u224D" },
+  "&Atilde;": { "codepoints": [195], "characters": "\u00C3" },
+  "&Atilde": { "codepoints": [195], "characters": "\u00C3" },
+  "&atilde;": { "codepoints": [227], "characters": "\u00E3" },
+  "&atilde": { "codepoints": [227], "characters": "\u00E3" },
+  "&Auml;": { "codepoints": [196], "characters": "\u00C4" },
+  "&Auml": { "codepoints": [196], "characters": "\u00C4" },
+  "&auml;": { "codepoints": [228], "characters": "\u00E4" },
+  "&auml": { "codepoints": [228], "characters": "\u00E4" },
+  "&awconint;": { "codepoints": [8755], "characters": "\u2233" },
+  "&awint;": { "codepoints": [10769], "characters": "\u2A11" },
+  "&backcong;": { "codepoints": [8780], "characters": "\u224C" },
+  "&backepsilon;": { "codepoints": [1014], "characters": "\u03F6" },
+  "&backprime;": { "codepoints": [8245], "characters": "\u2035" },
+  "&backsim;": { "codepoints": [8765], "characters": "\u223D" },
+  "&backsimeq;": { "codepoints": [8909], "characters": "\u22CD" },
+  "&Backslash;": { "codepoints": [8726], "characters": "\u2216" },
+  "&Barv;": { "codepoints": [10983], "characters": "\u2AE7" },
+  "&barvee;": { "codepoints": [8893], "characters": "\u22BD" },
+  "&barwed;": { "codepoints": [8965], "characters": "\u2305" },
+  "&Barwed;": { "codepoints": [8966], "characters": "\u2306" },
+  "&barwedge;": { "codepoints": [8965], "characters": "\u2305" },
+  "&bbrk;": { "codepoints": [9141], "characters": "\u23B5" },
+  "&bbrktbrk;": { "codepoints": [9142], "characters": "\u23B6" },
+  "&bcong;": { "codepoints": [8780], "characters": "\u224C" },
+  "&Bcy;": { "codepoints": [1041], "characters": "\u0411" },
+  "&bcy;": { "codepoints": [1073], "characters": "\u0431" },
+  "&bdquo;": { "codepoints": [8222], "characters": "\u201E" },
+  "&becaus;": { "codepoints": [8757], "characters": "\u2235" },
+  "&because;": { "codepoints": [8757], "characters": "\u2235" },
+  "&Because;": { "codepoints": [8757], "characters": "\u2235" },
+  "&bemptyv;": { "codepoints": [10672], "characters": "\u29B0" },
+  "&bepsi;": { "codepoints": [1014], "characters": "\u03F6" },
+  "&bernou;": { "codepoints": [8492], "characters": "\u212C" },
+  "&Bernoullis;": { "codepoints": [8492], "characters": "\u212C" },
+  "&Beta;": { "codepoints": [914], "characters": "\u0392" },
+  "&beta;": { "codepoints": [946], "characters": "\u03B2" },
+  "&beth;": { "codepoints": [8502], "characters": "\u2136" },
+  "&between;": { "codepoints": [8812], "characters": "\u226C" },
+  "&Bfr;": { "codepoints": [120069], "characters": "\uD835\uDD05" },
+  "&bfr;": { "codepoints": [120095], "characters": "\uD835\uDD1F" },
+  "&bigcap;": { "codepoints": [8898], "characters": "\u22C2" },
+  "&bigcirc;": { "codepoints": [9711], "characters": "\u25EF" },
+  "&bigcup;": { "codepoints": [8899], "characters": "\u22C3" },
+  "&bigodot;": { "codepoints": [10752], "characters": "\u2A00" },
+  "&bigoplus;": { "codepoints": [10753], "characters": "\u2A01" },
+  "&bigotimes;": { "codepoints": [10754], "characters": "\u2A02" },
+  "&bigsqcup;": { "codepoints": [10758], "characters": "\u2A06" },
+  "&bigstar;": { "codepoints": [9733], "characters": "\u2605" },
+  "&bigtriangledown;": { "codepoints": [9661], "characters": "\u25BD" },
+  "&bigtriangleup;": { "codepoints": [9651], "characters": "\u25B3" },
+  "&biguplus;": { "codepoints": [10756], "characters": "\u2A04" },
+  "&bigvee;": { "codepoints": [8897], "characters": "\u22C1" },
+  "&bigwedge;": { "codepoints": [8896], "characters": "\u22C0" },
+  "&bkarow;": { "codepoints": [10509], "characters": "\u290D" },
+  "&blacklozenge;": { "codepoints": [10731], "characters": "\u29EB" },
+  "&blacksquare;": { "codepoints": [9642], "characters": "\u25AA" },
+  "&blacktriangle;": { "codepoints": [9652], "characters": "\u25B4" },
+  "&blacktriangledown;": { "codepoints": [9662], "characters": "\u25BE" },
+  "&blacktriangleleft;": { "codepoints": [9666], "characters": "\u25C2" },
+  "&blacktriangleright;": { "codepoints": [9656], "characters": "\u25B8" },
+  "&blank;": { "codepoints": [9251], "characters": "\u2423" },
+  "&blk12;": { "codepoints": [9618], "characters": "\u2592" },
+  "&blk14;": { "codepoints": [9617], "characters": "\u2591" },
+  "&blk34;": { "codepoints": [9619], "characters": "\u2593" },
+  "&block;": { "codepoints": [9608], "characters": "\u2588" },
+  "&bne;": { "codepoints": [61, 8421], "characters": "\u003D\u20E5" },
+  "&bnequiv;": { "codepoints": [8801, 8421], "characters": "\u2261\u20E5" },
+  "&bNot;": { "codepoints": [10989], "characters": "\u2AED" },
+  "&bnot;": { "codepoints": [8976], "characters": "\u2310" },
+  "&Bopf;": { "codepoints": [120121], "characters": "\uD835\uDD39" },
+  "&bopf;": { "codepoints": [120147], "characters": "\uD835\uDD53" },
+  "&bot;": { "codepoints": [8869], "characters": "\u22A5" },
+  "&bottom;": { "codepoints": [8869], "characters": "\u22A5" },
+  "&bowtie;": { "codepoints": [8904], "characters": "\u22C8" },
+  "&boxbox;": { "codepoints": [10697], "characters": "\u29C9" },
+  "&boxdl;": { "codepoints": [9488], "characters": "\u2510" },
+  "&boxdL;": { "codepoints": [9557], "characters": "\u2555" },
+  "&boxDl;": { "codepoints": [9558], "characters": "\u2556" },
+  "&boxDL;": { "codepoints": [9559], "characters": "\u2557" },
+  "&boxdr;": { "codepoints": [9484], "characters": "\u250C" },
+  "&boxdR;": { "codepoints": [9554], "characters": "\u2552" },
+  "&boxDr;": { "codepoints": [9555], "characters": "\u2553" },
+  "&boxDR;": { "codepoints": [9556], "characters": "\u2554" },
+  "&boxh;": { "codepoints": [9472], "characters": "\u2500" },
+  "&boxH;": { "codepoints": [9552], "characters": "\u2550" },
+  "&boxhd;": { "codepoints": [9516], "characters": "\u252C" },
+  "&boxHd;": { "codepoints": [9572], "characters": "\u2564" },
+  "&boxhD;": { "codepoints": [9573], "characters": "\u2565" },
+  "&boxHD;": { "codepoints": [9574], "characters": "\u2566" },
+  "&boxhu;": { "codepoints": [9524], "characters": "\u2534" },
+  "&boxHu;": { "codepoints": [9575], "characters": "\u2567" },
+  "&boxhU;": { "codepoints": [9576], "characters": "\u2568" },
+  "&boxHU;": { "codepoints": [9577], "characters": "\u2569" },
+  "&boxminus;": { "codepoints": [8863], "characters": "\u229F" },
+  "&boxplus;": { "codepoints": [8862], "characters": "\u229E" },
+  "&boxtimes;": { "codepoints": [8864], "characters": "\u22A0" },
+  "&boxul;": { "codepoints": [9496], "characters": "\u2518" },
+  "&boxuL;": { "codepoints": [9563], "characters": "\u255B" },
+  "&boxUl;": { "codepoints": [9564], "characters": "\u255C" },
+  "&boxUL;": { "codepoints": [9565], "characters": "\u255D" },
+  "&boxur;": { "codepoints": [9492], "characters": "\u2514" },
+  "&boxuR;": { "codepoints": [9560], "characters": "\u2558" },
+  "&boxUr;": { "codepoints": [9561], "characters": "\u2559" },
+  "&boxUR;": { "codepoints": [9562], "characters": "\u255A" },
+  "&boxv;": { "codepoints": [9474], "characters": "\u2502" },
+  "&boxV;": { "codepoints": [9553], "characters": "\u2551" },
+  "&boxvh;": { "codepoints": [9532], "characters": "\u253C" },
+  "&boxvH;": { "codepoints": [9578], "characters": "\u256A" },
+  "&boxVh;": { "codepoints": [9579], "characters": "\u256B" },
+  "&boxVH;": { "codepoints": [9580], "characters": "\u256C" },
+  "&boxvl;": { "codepoints": [9508], "characters": "\u2524" },
+  "&boxvL;": { "codepoints": [9569], "characters": "\u2561" },
+  "&boxVl;": { "codepoints": [9570], "characters": "\u2562" },
+  "&boxVL;": { "codepoints": [9571], "characters": "\u2563" },
+  "&boxvr;": { "codepoints": [9500], "characters": "\u251C" },
+  "&boxvR;": { "codepoints": [9566], "characters": "\u255E" },
+  "&boxVr;": { "codepoints": [9567], "characters": "\u255F" },
+  "&boxVR;": { "codepoints": [9568], "characters": "\u2560" },
+  "&bprime;": { "codepoints": [8245], "characters": "\u2035" },
+  "&breve;": { "codepoints": [728], "characters": "\u02D8" },
+  "&Breve;": { "codepoints": [728], "characters": "\u02D8" },
+  "&brvbar;": { "codepoints": [166], "characters": "\u00A6" },
+  "&brvbar": { "codepoints": [166], "characters": "\u00A6" },
+  "&bscr;": { "codepoints": [119991], "characters": "\uD835\uDCB7" },
+  "&Bscr;": { "codepoints": [8492], "characters": "\u212C" },
+  "&bsemi;": { "codepoints": [8271], "characters": "\u204F" },
+  "&bsim;": { "codepoints": [8765], "characters": "\u223D" },
+  "&bsime;": { "codepoints": [8909], "characters": "\u22CD" },
+  "&bsolb;": { "codepoints": [10693], "characters": "\u29C5" },
+  "&bsol;": { "codepoints": [92], "characters": "\u005C" },
+  "&bsolhsub;": { "codepoints": [10184], "characters": "\u27C8" },
+  "&bull;": { "codepoints": [8226], "characters": "\u2022" },
+  "&bullet;": { "codepoints": [8226], "characters": "\u2022" },
+  "&bump;": { "codepoints": [8782], "characters": "\u224E" },
+  "&bumpE;": { "codepoints": [10926], "characters": "\u2AAE" },
+  "&bumpe;": { "codepoints": [8783], "characters": "\u224F" },
+  "&Bumpeq;": { "codepoints": [8782], "characters": "\u224E" },
+  "&bumpeq;": { "codepoints": [8783], "characters": "\u224F" },
+  "&Cacute;": { "codepoints": [262], "characters": "\u0106" },
+  "&cacute;": { "codepoints": [263], "characters": "\u0107" },
+  "&capand;": { "codepoints": [10820], "characters": "\u2A44" },
+  "&capbrcup;": { "codepoints": [10825], "characters": "\u2A49" },
+  "&capcap;": { "codepoints": [10827], "characters": "\u2A4B" },
+  "&cap;": { "codepoints": [8745], "characters": "\u2229" },
+  "&Cap;": { "codepoints": [8914], "characters": "\u22D2" },
+  "&capcup;": { "codepoints": [10823], "characters": "\u2A47" },
+  "&capdot;": { "codepoints": [10816], "characters": "\u2A40" },
+  "&CapitalDifferentialD;": { "codepoints": [8517], "characters": "\u2145" },
+  "&caps;": { "codepoints": [8745, 65024], "characters": "\u2229\uFE00" },
+  "&caret;": { "codepoints": [8257], "characters": "\u2041" },
+  "&caron;": { "codepoints": [711], "characters": "\u02C7" },
+  "&Cayleys;": { "codepoints": [8493], "characters": "\u212D" },
+  "&ccaps;": { "codepoints": [10829], "characters": "\u2A4D" },
+  "&Ccaron;": { "codepoints": [268], "characters": "\u010C" },
+  "&ccaron;": { "codepoints": [269], "characters": "\u010D" },
+  "&Ccedil;": { "codepoints": [199], "characters": "\u00C7" },
+  "&Ccedil": { "codepoints": [199], "characters": "\u00C7" },
+  "&ccedil;": { "codepoints": [231], "characters": "\u00E7" },
+  "&ccedil": { "codepoints": [231], "characters": "\u00E7" },
+  "&Ccirc;": { "codepoints": [264], "characters": "\u0108" },
+  "&ccirc;": { "codepoints": [265], "characters": "\u0109" },
+  "&Cconint;": { "codepoints": [8752], "characters": "\u2230" },
+  "&ccups;": { "codepoints": [10828], "characters": "\u2A4C" },
+  "&ccupssm;": { "codepoints": [10832], "characters": "\u2A50" },
+  "&Cdot;": { "codepoints": [266], "characters": "\u010A" },
+  "&cdot;": { "codepoints": [267], "characters": "\u010B" },
+  "&cedil;": { "codepoints": [184], "characters": "\u00B8" },
+  "&cedil": { "codepoints": [184], "characters": "\u00B8" },
+  "&Cedilla;": { "codepoints": [184], "characters": "\u00B8" },
+  "&cemptyv;": { "codepoints": [10674], "characters": "\u29B2" },
+  "&cent;": { "codepoints": [162], "characters": "\u00A2" },
+  "&cent": { "codepoints": [162], "characters": "\u00A2" },
+  "&centerdot;": { "codepoints": [183], "characters": "\u00B7" },
+  "&CenterDot;": { "codepoints": [183], "characters": "\u00B7" },
+  "&cfr;": { "codepoints": [120096], "characters": "\uD835\uDD20" },
+  "&Cfr;": { "codepoints": [8493], "characters": "\u212D" },
+  "&CHcy;": { "codepoints": [1063], "characters": "\u0427" },
+  "&chcy;": { "codepoints": [1095], "characters": "\u0447" },
+  "&check;": { "codepoints": [10003], "characters": "\u2713" },
+  "&checkmark;": { "codepoints": [10003], "characters": "\u2713" },
+  "&Chi;": { "codepoints": [935], "characters": "\u03A7" },
+  "&chi;": { "codepoints": [967], "characters": "\u03C7" },
+  "&circ;": { "codepoints": [710], "characters": "\u02C6" },
+  "&circeq;": { "codepoints": [8791], "characters": "\u2257" },
+  "&circlearrowleft;": { "codepoints": [8634], "characters": "\u21BA" },
+  "&circlearrowright;": { "codepoints": [8635], "characters": "\u21BB" },
+  "&circledast;": { "codepoints": [8859], "characters": "\u229B" },
+  "&circledcirc;": { "codepoints": [8858], "characters": "\u229A" },
+  "&circleddash;": { "codepoints": [8861], "characters": "\u229D" },
+  "&CircleDot;": { "codepoints": [8857], "characters": "\u2299" },
+  "&circledR;": { "codepoints": [174], "characters": "\u00AE" },
+  "&circledS;": { "codepoints": [9416], "characters": "\u24C8" },
+  "&CircleMinus;": { "codepoints": [8854], "characters": "\u2296" },
+  "&CirclePlus;": { "codepoints": [8853], "characters": "\u2295" },
+  "&CircleTimes;": { "codepoints": [8855], "characters": "\u2297" },
+  "&cir;": { "codepoints": [9675], "characters": "\u25CB" },
+  "&cirE;": { "codepoints": [10691], "characters": "\u29C3" },
+  "&cire;": { "codepoints": [8791], "characters": "\u2257" },
+  "&cirfnint;": { "codepoints": [10768], "characters": "\u2A10" },
+  "&cirmid;": { "codepoints": [10991], "characters": "\u2AEF" },
+  "&cirscir;": { "codepoints": [10690], "characters": "\u29C2" },
+  "&ClockwiseContourIntegral;": { "codepoints": [8754], "characters": "\u2232" },
+  "&CloseCurlyDoubleQuote;": { "codepoints": [8221], "characters": "\u201D" },
+  "&CloseCurlyQuote;": { "codepoints": [8217], "characters": "\u2019" },
+  "&clubs;": { "codepoints": [9827], "characters": "\u2663" },
+  "&clubsuit;": { "codepoints": [9827], "characters": "\u2663" },
+  "&colon;": { "codepoints": [58], "characters": "\u003A" },
+  "&Colon;": { "codepoints": [8759], "characters": "\u2237" },
+  "&Colone;": { "codepoints": [10868], "characters": "\u2A74" },
+  "&colone;": { "codepoints": [8788], "characters": "\u2254" },
+  "&coloneq;": { "codepoints": [8788], "characters": "\u2254" },
+  "&comma;": { "codepoints": [44], "characters": "\u002C" },
+  "&commat;": { "codepoints": [64], "characters": "\u0040" },
+  "&comp;": { "codepoints": [8705], "characters": "\u2201" },
+  "&compfn;": { "codepoints": [8728], "characters": "\u2218" },
+  "&complement;": { "codepoints": [8705], "characters": "\u2201" },
+  "&complexes;": { "codepoints": [8450], "characters": "\u2102" },
+  "&cong;": { "codepoints": [8773], "characters": "\u2245" },
+  "&congdot;": { "codepoints": [10861], "characters": "\u2A6D" },
+  "&Congruent;": { "codepoints": [8801], "characters": "\u2261" },
+  "&conint;": { "codepoints": [8750], "characters": "\u222E" },
+  "&Conint;": { "codepoints": [8751], "characters": "\u222F" },
+  "&ContourIntegral;": { "codepoints": [8750], "characters": "\u222E" },
+  "&copf;": { "codepoints": [120148], "characters": "\uD835\uDD54" },
+  "&Copf;": { "codepoints": [8450], "characters": "\u2102" },
+  "&coprod;": { "codepoints": [8720], "characters": "\u2210" },
+  "&Coproduct;": { "codepoints": [8720], "characters": "\u2210" },
+  "&copy;": { "codepoints": [169], "characters": "\u00A9" },
+  "&copy": { "codepoints": [169], "characters": "\u00A9" },
+  "&COPY;": { "codepoints": [169], "characters": "\u00A9" },
+  "&COPY": { "codepoints": [169], "characters": "\u00A9" },
+  "&copysr;": { "codepoints": [8471], "characters": "\u2117" },
+  "&CounterClockwiseContourIntegral;": { "codepoints": [8755], "characters": "\u2233" },
+  "&crarr;": { "codepoints": [8629], "characters": "\u21B5" },
+  "&cross;": { "codepoints": [10007], "characters": "\u2717" },
+  "&Cross;": { "codepoints": [10799], "characters": "\u2A2F" },
+  "&Cscr;": { "codepoints": [119966], "characters": "\uD835\uDC9E" },
+  "&cscr;": { "codepoints": [119992], "characters": "\uD835\uDCB8" },
+  "&csub;": { "codepoints": [10959], "characters": "\u2ACF" },
+  "&csube;": { "codepoints": [10961], "characters": "\u2AD1" },
+  "&csup;": { "codepoints": [10960], "characters": "\u2AD0" },
+  "&csupe;": { "codepoints": [10962], "characters": "\u2AD2" },
+  "&ctdot;": { "codepoints": [8943], "characters": "\u22EF" },
+  "&cudarrl;": { "codepoints": [10552], "characters": "\u2938" },
+  "&cudarrr;": { "codepoints": [10549], "characters": "\u2935" },
+  "&cuepr;": { "codepoints": [8926], "characters": "\u22DE" },
+  "&cuesc;": { "codepoints": [8927], "characters": "\u22DF" },
+  "&cularr;": { "codepoints": [8630], "characters": "\u21B6" },
+  "&cularrp;": { "codepoints": [10557], "characters": "\u293D" },
+  "&cupbrcap;": { "codepoints": [10824], "characters": "\u2A48" },
+  "&cupcap;": { "codepoints": [10822], "characters": "\u2A46" },
+  "&CupCap;": { "codepoints": [8781], "characters": "\u224D" },
+  "&cup;": { "codepoints": [8746], "characters": "\u222A" },
+  "&Cup;": { "codepoints": [8915], "characters": "\u22D3" },
+  "&cupcup;": { "codepoints": [10826], "characters": "\u2A4A" },
+  "&cupdot;": { "codepoints": [8845], "characters": "\u228D" },
+  "&cupor;": { "codepoints": [10821], "characters": "\u2A45" },
+  "&cups;": { "codepoints": [8746, 65024], "characters": "\u222A\uFE00" },
+  "&curarr;": { "codepoints": [8631], "characters": "\u21B7" },
+  "&curarrm;": { "codepoints": [10556], "characters": "\u293C" },
+  "&curlyeqprec;": { "codepoints": [8926], "characters": "\u22DE" },
+  "&curlyeqsucc;": { "codepoints": [8927], "characters": "\u22DF" },
+  "&curlyvee;": { "codepoints": [8910], "characters": "\u22CE" },
+  "&curlywedge;": { "codepoints": [8911], "characters": "\u22CF" },
+  "&curren;": { "codepoints": [164], "characters": "\u00A4" },
+  "&curren": { "codepoints": [164], "characters": "\u00A4" },
+  "&curvearrowleft;": { "codepoints": [8630], "characters": "\u21B6" },
+  "&curvearrowright;": { "codepoints": [8631], "characters": "\u21B7" },
+  "&cuvee;": { "codepoints": [8910], "characters": "\u22CE" },
+  "&cuwed;": { "codepoints": [8911], "characters": "\u22CF" },
+  "&cwconint;": { "codepoints": [8754], "characters": "\u2232" },
+  "&cwint;": { "codepoints": [8753], "characters": "\u2231" },
+  "&cylcty;": { "codepoints": [9005], "characters": "\u232D" },
+  "&dagger;": { "codepoints": [8224], "characters": "\u2020" },
+  "&Dagger;": { "codepoints": [8225], "characters": "\u2021" },
+  "&daleth;": { "codepoints": [8504], "characters": "\u2138" },
+  "&darr;": { "codepoints": [8595], "characters": "\u2193" },
+  "&Darr;": { "codepoints": [8609], "characters": "\u21A1" },
+  "&dArr;": { "codepoints": [8659], "characters": "\u21D3" },
+  "&dash;": { "codepoints": [8208], "characters": "\u2010" },
+  "&Dashv;": { "codepoints": [10980], "characters": "\u2AE4" },
+  "&dashv;": { "codepoints": [8867], "characters": "\u22A3" },
+  "&dbkarow;": { "codepoints": [10511], "characters": "\u290F" },
+  "&dblac;": { "codepoints": [733], "characters": "\u02DD" },
+  "&Dcaron;": { "codepoints": [270], "characters": "\u010E" },
+  "&dcaron;": { "codepoints": [271], "characters": "\u010F" },
+  "&Dcy;": { "codepoints": [1044], "characters": "\u0414" },
+  "&dcy;": { "codepoints": [1076], "characters": "\u0434" },
+  "&ddagger;": { "codepoints": [8225], "characters": "\u2021" },
+  "&ddarr;": { "codepoints": [8650], "characters": "\u21CA" },
+  "&DD;": { "codepoints": [8517], "characters": "\u2145" },
+  "&dd;": { "codepoints": [8518], "characters": "\u2146" },
+  "&DDotrahd;": { "codepoints": [10513], "characters": "\u2911" },
+  "&ddotseq;": { "codepoints": [10871], "characters": "\u2A77" },
+  "&deg;": { "codepoints": [176], "characters": "\u00B0" },
+  "&deg": { "codepoints": [176], "characters": "\u00B0" },
+  "&Del;": { "codepoints": [8711], "characters": "\u2207" },
+  "&Delta;": { "codepoints": [916], "characters": "\u0394" },
+  "&delta;": { "codepoints": [948], "characters": "\u03B4" },
+  "&demptyv;": { "codepoints": [10673], "characters": "\u29B1" },
+  "&dfisht;": { "codepoints": [10623], "characters": "\u297F" },
+  "&Dfr;": { "codepoints": [120071], "characters": "\uD835\uDD07" },
+  "&dfr;": { "codepoints": [120097], "characters": "\uD835\uDD21" },
+  "&dHar;": { "codepoints": [10597], "characters": "\u2965" },
+  "&dharl;": { "codepoints": [8643], "characters": "\u21C3" },
+  "&dharr;": { "codepoints": [8642], "characters": "\u21C2" },
+  "&DiacriticalAcute;": { "codepoints": [180], "characters": "\u00B4" },
+  "&DiacriticalDot;": { "codepoints": [729], "characters": "\u02D9" },
+  "&DiacriticalDoubleAcute;": { "codepoints": [733], "characters": "\u02DD" },
+  "&DiacriticalGrave;": { "codepoints": [96], "characters": "\u0060" },
+  "&DiacriticalTilde;": { "codepoints": [732], "characters": "\u02DC" },
+  "&diam;": { "codepoints": [8900], "characters": "\u22C4" },
+  "&diamond;": { "codepoints": [8900], "characters": "\u22C4" },
+  "&Diamond;": { "codepoints": [8900], "characters": "\u22C4" },
+  "&diamondsuit;": { "codepoints": [9830], "characters": "\u2666" },
+  "&diams;": { "codepoints": [9830], "characters": "\u2666" },
+  "&die;": { "codepoints": [168], "characters": "\u00A8" },
+  "&DifferentialD;": { "codepoints": [8518], "characters": "\u2146" },
+  "&digamma;": { "codepoints": [989], "characters": "\u03DD" },
+  "&disin;": { "codepoints": [8946], "characters": "\u22F2" },
+  "&div;": { "codepoints": [247], "characters": "\u00F7" },
+  "&divide;": { "codepoints": [247], "characters": "\u00F7" },
+  "&divide": { "codepoints": [247], "characters": "\u00F7" },
+  "&divideontimes;": { "codepoints": [8903], "characters": "\u22C7" },
+  "&divonx;": { "codepoints": [8903], "characters": "\u22C7" },
+  "&DJcy;": { "codepoints": [1026], "characters": "\u0402" },
+  "&djcy;": { "codepoints": [1106], "characters": "\u0452" },
+  "&dlcorn;": { "codepoints": [8990], "characters": "\u231E" },
+  "&dlcrop;": { "codepoints": [8973], "characters": "\u230D" },
+  "&dollar;": { "codepoints": [36], "characters": "\u0024" },
+  "&Dopf;": { "codepoints": [120123], "characters": "\uD835\uDD3B" },
+  "&dopf;": { "codepoints": [120149], "characters": "\uD835\uDD55" },
+  "&Dot;": { "codepoints": [168], "characters": "\u00A8" },
+  "&dot;": { "codepoints": [729], "characters": "\u02D9" },
+  "&DotDot;": { "codepoints": [8412], "characters": "\u20DC" },
+  "&doteq;": { "codepoints": [8784], "characters": "\u2250" },
+  "&doteqdot;": { "codepoints": [8785], "characters": "\u2251" },
+  "&DotEqual;": { "codepoints": [8784], "characters": "\u2250" },
+  "&dotminus;": { "codepoints": [8760], "characters": "\u2238" },
+  "&dotplus;": { "codepoints": [8724], "characters": "\u2214" },
+  "&dotsquare;": { "codepoints": [8865], "characters": "\u22A1" },
+  "&doublebarwedge;": { "codepoints": [8966], "characters": "\u2306" },
+  "&DoubleContourIntegral;": { "codepoints": [8751], "characters": "\u222F" },
+  "&DoubleDot;": { "codepoints": [168], "characters": "\u00A8" },
+  "&DoubleDownArrow;": { "codepoints": [8659], "characters": "\u21D3" },
+  "&DoubleLeftArrow;": { "codepoints": [8656], "characters": "\u21D0" },
+  "&DoubleLeftRightArrow;": { "codepoints": [8660], "characters": "\u21D4" },
+  "&DoubleLeftTee;": { "codepoints": [10980], "characters": "\u2AE4" },
+  "&DoubleLongLeftArrow;": { "codepoints": [10232], "characters": "\u27F8" },
+  "&DoubleLongLeftRightArrow;": { "codepoints": [10234], "characters": "\u27FA" },
+  "&DoubleLongRightArrow;": { "codepoints": [10233], "characters": "\u27F9" },
+  "&DoubleRightArrow;": { "codepoints": [8658], "characters": "\u21D2" },
+  "&DoubleRightTee;": { "codepoints": [8872], "characters": "\u22A8" },
+  "&DoubleUpArrow;": { "codepoints": [8657], "characters": "\u21D1" },
+  "&DoubleUpDownArrow;": { "codepoints": [8661], "characters": "\u21D5" },
+  "&DoubleVerticalBar;": { "codepoints": [8741], "characters": "\u2225" },
+  "&DownArrowBar;": { "codepoints": [10515], "characters": "\u2913" },
+  "&downarrow;": { "codepoints": [8595], "characters": "\u2193" },
+  "&DownArrow;": { "codepoints": [8595], "characters": "\u2193" },
+  "&Downarrow;": { "codepoints": [8659], "characters": "\u21D3" },
+  "&DownArrowUpArrow;": { "codepoints": [8693], "characters": "\u21F5" },
+  "&DownBreve;": { "codepoints": [785], "characters": "\u0311" },
+  "&downdownarrows;": { "codepoints": [8650], "characters": "\u21CA" },
+  "&downharpoonleft;": { "codepoints": [8643], "characters": "\u21C3" },
+  "&downharpoonright;": { "codepoints": [8642], "characters": "\u21C2" },
+  "&DownLeftRightVector;": { "codepoints": [10576], "characters": "\u2950" },
+  "&DownLeftTeeVector;": { "codepoints": [10590], "characters": "\u295E" },
+  "&DownLeftVectorBar;": { "codepoints": [10582], "characters": "\u2956" },
+  "&DownLeftVector;": { "codepoints": [8637], "characters": "\u21BD" },
+  "&DownRightTeeVector;": { "codepoints": [10591], "characters": "\u295F" },
+  "&DownRightVectorBar;": { "codepoints": [10583], "characters": "\u2957" },
+  "&DownRightVector;": { "codepoints": [8641], "characters": "\u21C1" },
+  "&DownTeeArrow;": { "codepoints": [8615], "characters": "\u21A7" },
+  "&DownTee;": { "codepoints": [8868], "characters": "\u22A4" },
+  "&drbkarow;": { "codepoints": [10512], "characters": "\u2910" },
+  "&drcorn;": { "codepoints": [8991], "characters": "\u231F" },
+  "&drcrop;": { "codepoints": [8972], "characters": "\u230C" },
+  "&Dscr;": { "codepoints": [119967], "characters": "\uD835\uDC9F" },
+  "&dscr;": { "codepoints": [119993], "characters": "\uD835\uDCB9" },
+  "&DScy;": { "codepoints": [1029], "characters": "\u0405" },
+  "&dscy;": { "codepoints": [1109], "characters": "\u0455" },
+  "&dsol;": { "codepoints": [10742], "characters": "\u29F6" },
+  "&Dstrok;": { "codepoints": [272], "characters": "\u0110" },
+  "&dstrok;": { "codepoints": [273], "characters": "\u0111" },
+  "&dtdot;": { "codepoints": [8945], "characters": "\u22F1" },
+  "&dtri;": { "codepoints": [9663], "characters": "\u25BF" },
+  "&dtrif;": { "codepoints": [9662], "characters": "\u25BE" },
+  "&duarr;": { "codepoints": [8693], "characters": "\u21F5" },
+  "&duhar;": { "codepoints": [10607], "characters": "\u296F" },
+  "&dwangle;": { "codepoints": [10662], "characters": "\u29A6" },
+  "&DZcy;": { "codepoints": [1039], "characters": "\u040F" },
+  "&dzcy;": { "codepoints": [1119], "characters": "\u045F" },
+  "&dzigrarr;": { "codepoints": [10239], "characters": "\u27FF" },
+  "&Eacute;": { "codepoints": [201], "characters": "\u00C9" },
+  "&Eacute": { "codepoints": [201], "characters": "\u00C9" },
+  "&eacute;": { "codepoints": [233], "characters": "\u00E9" },
+  "&eacute": { "codepoints": [233], "characters": "\u00E9" },
+  "&easter;": { "codepoints": [10862], "characters": "\u2A6E" },
+  "&Ecaron;": { "codepoints": [282], "characters": "\u011A" },
+  "&ecaron;": { "codepoints": [283], "characters": "\u011B" },
+  "&Ecirc;": { "codepoints": [202], "characters": "\u00CA" },
+  "&Ecirc": { "codepoints": [202], "characters": "\u00CA" },
+  "&ecirc;": { "codepoints": [234], "characters": "\u00EA" },
+  "&ecirc": { "codepoints": [234], "characters": "\u00EA" },
+  "&ecir;": { "codepoints": [8790], "characters": "\u2256" },
+  "&ecolon;": { "codepoints": [8789], "characters": "\u2255" },
+  "&Ecy;": { "codepoints": [1069], "characters": "\u042D" },
+  "&ecy;": { "codepoints": [1101], "characters": "\u044D" },
+  "&eDDot;": { "codepoints": [10871], "characters": "\u2A77" },
+  "&Edot;": { "codepoints": [278], "characters": "\u0116" },
+  "&edot;": { "codepoints": [279], "characters": "\u0117" },
+  "&eDot;": { "codepoints": [8785], "characters": "\u2251" },
+  "&ee;": { "codepoints": [8519], "characters": "\u2147" },
+  "&efDot;": { "codepoints": [8786], "characters": "\u2252" },
+  "&Efr;": { "codepoints": [120072], "characters": "\uD835\uDD08" },
+  "&efr;": { "codepoints": [120098], "characters": "\uD835\uDD22" },
+  "&eg;": { "codepoints": [10906], "characters": "\u2A9A" },
+  "&Egrave;": { "codepoints": [200], "characters": "\u00C8" },
+  "&Egrave": { "codepoints": [200], "characters": "\u00C8" },
+  "&egrave;": { "codepoints": [232], "characters": "\u00E8" },
+  "&egrave": { "codepoints": [232], "characters": "\u00E8" },
+  "&egs;": { "codepoints": [10902], "characters": "\u2A96" },
+  "&egsdot;": { "codepoints": [10904], "characters": "\u2A98" },
+  "&el;": { "codepoints": [10905], "characters": "\u2A99" },
+  "&Element;": { "codepoints": [8712], "characters": "\u2208" },
+  "&elinters;": { "codepoints": [9191], "characters": "\u23E7" },
+  "&ell;": { "codepoints": [8467], "characters": "\u2113" },
+  "&els;": { "codepoints": [10901], "characters": "\u2A95" },
+  "&elsdot;": { "codepoints": [10903], "characters": "\u2A97" },
+  "&Emacr;": { "codepoints": [274], "characters": "\u0112" },
+  "&emacr;": { "codepoints": [275], "characters": "\u0113" },
+  "&empty;": { "codepoints": [8709], "characters": "\u2205" },
+  "&emptyset;": { "codepoints": [8709], "characters": "\u2205" },
+  "&EmptySmallSquare;": { "codepoints": [9723], "characters": "\u25FB" },
+  "&emptyv;": { "codepoints": [8709], "characters": "\u2205" },
+  "&EmptyVerySmallSquare;": { "codepoints": [9643], "characters": "\u25AB" },
+  "&emsp13;": { "codepoints": [8196], "characters": "\u2004" },
+  "&emsp14;": { "codepoints": [8197], "characters": "\u2005" },
+  "&emsp;": { "codepoints": [8195], "characters": "\u2003" },
+  "&ENG;": { "codepoints": [330], "characters": "\u014A" },
+  "&eng;": { "codepoints": [331], "characters": "\u014B" },
+  "&ensp;": { "codepoints": [8194], "characters": "\u2002" },
+  "&Eogon;": { "codepoints": [280], "characters": "\u0118" },
+  "&eogon;": { "codepoints": [281], "characters": "\u0119" },
+  "&Eopf;": { "codepoints": [120124], "characters": "\uD835\uDD3C" },
+  "&eopf;": { "codepoints": [120150], "characters": "\uD835\uDD56" },
+  "&epar;": { "codepoints": [8917], "characters": "\u22D5" },
+  "&eparsl;": { "codepoints": [10723], "characters": "\u29E3" },
+  "&eplus;": { "codepoints": [10865], "characters": "\u2A71" },
+  "&epsi;": { "codepoints": [949], "characters": "\u03B5" },
+  "&Epsilon;": { "codepoints": [917], "characters": "\u0395" },
+  "&epsilon;": { "codepoints": [949], "characters": "\u03B5" },
+  "&epsiv;": { "codepoints": [1013], "characters": "\u03F5" },
+  "&eqcirc;": { "codepoints": [8790], "characters": "\u2256" },
+  "&eqcolon;": { "codepoints": [8789], "characters": "\u2255" },
+  "&eqsim;": { "codepoints": [8770], "characters": "\u2242" },
+  "&eqslantgtr;": { "codepoints": [10902], "characters": "\u2A96" },
+  "&eqslantless;": { "codepoints": [10901], "characters": "\u2A95" },
+  "&Equal;": { "codepoints": [10869], "characters": "\u2A75" },
+  "&equals;": { "codepoints": [61], "characters": "\u003D" },
+  "&EqualTilde;": { "codepoints": [8770], "characters": "\u2242" },
+  "&equest;": { "codepoints": [8799], "characters": "\u225F" },
+  "&Equilibrium;": { "codepoints": [8652], "characters": "\u21CC" },
+  "&equiv;": { "codepoints": [8801], "characters": "\u2261" },
+  "&equivDD;": { "codepoints": [10872], "characters": "\u2A78" },
+  "&eqvparsl;": { "codepoints": [10725], "characters": "\u29E5" },
+  "&erarr;": { "codepoints": [10609], "characters": "\u2971" },
+  "&erDot;": { "codepoints": [8787], "characters": "\u2253" },
+  "&escr;": { "codepoints": [8495], "characters": "\u212F" },
+  "&Escr;": { "codepoints": [8496], "characters": "\u2130" },
+  "&esdot;": { "codepoints": [8784], "characters": "\u2250" },
+  "&Esim;": { "codepoints": [10867], "characters": "\u2A73" },
+  "&esim;": { "codepoints": [8770], "characters": "\u2242" },
+  "&Eta;": { "codepoints": [919], "characters": "\u0397" },
+  "&eta;": { "codepoints": [951], "characters": "\u03B7" },
+  "&ETH;": { "codepoints": [208], "characters": "\u00D0" },
+  "&ETH": { "codepoints": [208], "characters": "\u00D0" },
+  "&eth;": { "codepoints": [240], "characters": "\u00F0" },
+  "&eth": { "codepoints": [240], "characters": "\u00F0" },
+  "&Euml;": { "codepoints": [203], "characters": "\u00CB" },
+  "&Euml": { "codepoints": [203], "characters": "\u00CB" },
+  "&euml;": { "codepoints": [235], "characters": "\u00EB" },
+  "&euml": { "codepoints": [235], "characters": "\u00EB" },
+  "&euro;": { "codepoints": [8364], "characters": "\u20AC" },
+  "&excl;": { "codepoints": [33], "characters": "\u0021" },
+  "&exist;": { "codepoints": [8707], "characters": "\u2203" },
+  "&Exists;": { "codepoints": [8707], "characters": "\u2203" },
+  "&expectation;": { "codepoints": [8496], "characters": "\u2130" },
+  "&exponentiale;": { "codepoints": [8519], "characters": "\u2147" },
+  "&ExponentialE;": { "codepoints": [8519], "characters": "\u2147" },
+  "&fallingdotseq;": { "codepoints": [8786], "characters": "\u2252" },
+  "&Fcy;": { "codepoints": [1060], "characters": "\u0424" },
+  "&fcy;": { "codepoints": [1092], "characters": "\u0444" },
+  "&female;": { "codepoints": [9792], "characters": "\u2640" },
+  "&ffilig;": { "codepoints": [64259], "characters": "\uFB03" },
+  "&fflig;": { "codepoints": [64256], "characters": "\uFB00" },
+  "&ffllig;": { "codepoints": [64260], "characters": "\uFB04" },
+  "&Ffr;": { "codepoints": [120073], "characters": "\uD835\uDD09" },
+  "&ffr;": { "codepoints": [120099], "characters": "\uD835\uDD23" },
+  "&filig;": { "codepoints": [64257], "characters": "\uFB01" },
+  "&FilledSmallSquare;": { "codepoints": [9724], "characters": "\u25FC" },
+  "&FilledVerySmallSquare;": { "codepoints": [9642], "characters": "\u25AA" },
+  "&fjlig;": { "codepoints": [102, 106], "characters": "\u0066\u006A" },
+  "&flat;": { "codepoints": [9837], "characters": "\u266D" },
+  "&fllig;": { "codepoints": [64258], "characters": "\uFB02" },
+  "&fltns;": { "codepoints": [9649], "characters": "\u25B1" },
+  "&fnof;": { "codepoints": [402], "characters": "\u0192" },
+  "&Fopf;": { "codepoints": [120125], "characters": "\uD835\uDD3D" },
+  "&fopf;": { "codepoints": [120151], "characters": "\uD835\uDD57" },
+  "&forall;": { "codepoints": [8704], "characters": "\u2200" },
+  "&ForAll;": { "codepoints": [8704], "characters": "\u2200" },
+  "&fork;": { "codepoints": [8916], "characters": "\u22D4" },
+  "&forkv;": { "codepoints": [10969], "characters": "\u2AD9" },
+  "&Fouriertrf;": { "codepoints": [8497], "characters": "\u2131" },
+  "&fpartint;": { "codepoints": [10765], "characters": "\u2A0D" },
+  "&frac12;": { "codepoints": [189], "characters": "\u00BD" },
+  "&frac12": { "codepoints": [189], "characters": "\u00BD" },
+  "&frac13;": { "codepoints": [8531], "characters": "\u2153" },
+  "&frac14;": { "codepoints": [188], "characters": "\u00BC" },
+  "&frac14": { "codepoints": [188], "characters": "\u00BC" },
+  "&frac15;": { "codepoints": [8533], "characters": "\u2155" },
+  "&frac16;": { "codepoints": [8537], "characters": "\u2159" },
+  "&frac18;": { "codepoints": [8539], "characters": "\u215B" },
+  "&frac23;": { "codepoints": [8532], "characters": "\u2154" },
+  "&frac25;": { "codepoints": [8534], "characters": "\u2156" },
+  "&frac34;": { "codepoints": [190], "characters": "\u00BE" },
+  "&frac34": { "codepoints": [190], "characters": "\u00BE" },
+  "&frac35;": { "codepoints": [8535], "characters": "\u2157" },
+  "&frac38;": { "codepoints": [8540], "characters": "\u215C" },
+  "&frac45;": { "codepoints": [8536], "characters": "\u2158" },
+  "&frac56;": { "codepoints": [8538], "characters": "\u215A" },
+  "&frac58;": { "codepoints": [8541], "characters": "\u215D" },
+  "&frac78;": { "codepoints": [8542], "characters": "\u215E" },
+  "&frasl;": { "codepoints": [8260], "characters": "\u2044" },
+  "&frown;": { "codepoints": [8994], "characters": "\u2322" },
+  "&fscr;": { "codepoints": [119995], "characters": "\uD835\uDCBB" },
+  "&Fscr;": { "codepoints": [8497], "characters": "\u2131" },
+  "&gacute;": { "codepoints": [501], "characters": "\u01F5" },
+  "&Gamma;": { "codepoints": [915], "characters": "\u0393" },
+  "&gamma;": { "codepoints": [947], "characters": "\u03B3" },
+  "&Gammad;": { "codepoints": [988], "characters": "\u03DC" },
+  "&gammad;": { "codepoints": [989], "characters": "\u03DD" },
+  "&gap;": { "codepoints": [10886], "characters": "\u2A86" },
+  "&Gbreve;": { "codepoints": [286], "characters": "\u011E" },
+  "&gbreve;": { "codepoints": [287], "characters": "\u011F" },
+  "&Gcedil;": { "codepoints": [290], "characters": "\u0122" },
+  "&Gcirc;": { "codepoints": [284], "characters": "\u011C" },
+  "&gcirc;": { "codepoints": [285], "characters": "\u011D" },
+  "&Gcy;": { "codepoints": [1043], "characters": "\u0413" },
+  "&gcy;": { "codepoints": [1075], "characters": "\u0433" },
+  "&Gdot;": { "codepoints": [288], "characters": "\u0120" },
+  "&gdot;": { "codepoints": [289], "characters": "\u0121" },
+  "&ge;": { "codepoints": [8805], "characters": "\u2265" },
+  "&gE;": { "codepoints": [8807], "characters": "\u2267" },
+  "&gEl;": { "codepoints": [10892], "characters": "\u2A8C" },
+  "&gel;": { "codepoints": [8923], "characters": "\u22DB" },
+  "&geq;": { "codepoints": [8805], "characters": "\u2265" },
+  "&geqq;": { "codepoints": [8807], "characters": "\u2267" },
+  "&geqslant;": { "codepoints": [10878], "characters": "\u2A7E" },
+  "&gescc;": { "codepoints": [10921], "characters": "\u2AA9" },
+  "&ges;": { "codepoints": [10878], "characters": "\u2A7E" },
+  "&gesdot;": { "codepoints": [10880], "characters": "\u2A80" },
+  "&gesdoto;": { "codepoints": [10882], "characters": "\u2A82" },
+  "&gesdotol;": { "codepoints": [10884], "characters": "\u2A84" },
+  "&gesl;": { "codepoints": [8923, 65024], "characters": "\u22DB\uFE00" },
+  "&gesles;": { "codepoints": [10900], "characters": "\u2A94" },
+  "&Gfr;": { "codepoints": [120074], "characters": "\uD835\uDD0A" },
+  "&gfr;": { "codepoints": [120100], "characters": "\uD835\uDD24" },
+  "&gg;": { "codepoints": [8811], "characters": "\u226B" },
+  "&Gg;": { "codepoints": [8921], "characters": "\u22D9" },
+  "&ggg;": { "codepoints": [8921], "characters": "\u22D9" },
+  "&gimel;": { "codepoints": [8503], "characters": "\u2137" },
+  "&GJcy;": { "codepoints": [1027], "characters": "\u0403" },
+  "&gjcy;": { "codepoints": [1107], "characters": "\u0453" },
+  "&gla;": { "codepoints": [10917], "characters": "\u2AA5" },
+  "&gl;": { "codepoints": [8823], "characters": "\u2277" },
+  "&glE;": { "codepoints": [10898], "characters": "\u2A92" },
+  "&glj;": { "codepoints": [10916], "characters": "\u2AA4" },
+  "&gnap;": { "codepoints": [10890], "characters": "\u2A8A" },
+  "&gnapprox;": { "codepoints": [10890], "characters": "\u2A8A" },
+  "&gne;": { "codepoints": [10888], "characters": "\u2A88" },
+  "&gnE;": { "codepoints": [8809], "characters": "\u2269" },
+  "&gneq;": { "codepoints": [10888], "characters": "\u2A88" },
+  "&gneqq;": { "codepoints": [8809], "characters": "\u2269" },
+  "&gnsim;": { "codepoints": [8935], "characters": "\u22E7" },
+  "&Gopf;": { "codepoints": [120126], "characters": "\uD835\uDD3E" },
+  "&gopf;": { "codepoints": [120152], "characters": "\uD835\uDD58" },
+  "&grave;": { "codepoints": [96], "characters": "\u0060" },
+  "&GreaterEqual;": { "codepoints": [8805], "characters": "\u2265" },
+  "&GreaterEqualLess;": { "codepoints": [8923], "characters": "\u22DB" },
+  "&GreaterFullEqual;": { "codepoints": [8807], "characters": "\u2267" },
+  "&GreaterGreater;": { "codepoints": [10914], "characters": "\u2AA2" },
+  "&GreaterLess;": { "codepoints": [8823], "characters": "\u2277" },
+  "&GreaterSlantEqual;": { "codepoints": [10878], "characters": "\u2A7E" },
+  "&GreaterTilde;": { "codepoints": [8819], "characters": "\u2273" },
+  "&Gscr;": { "codepoints": [119970], "characters": "\uD835\uDCA2" },
+  "&gscr;": { "codepoints": [8458], "characters": "\u210A" },
+  "&gsim;": { "codepoints": [8819], "characters": "\u2273" },
+  "&gsime;": { "codepoints": [10894], "characters": "\u2A8E" },
+  "&gsiml;": { "codepoints": [10896], "characters": "\u2A90" },
+  "&gtcc;": { "codepoints": [10919], "characters": "\u2AA7" },
+  "&gtcir;": { "codepoints": [10874], "characters": "\u2A7A" },
+  "&gt;": { "codepoints": [62], "characters": "\u003E" },
+  "&gt": { "codepoints": [62], "characters": "\u003E" },
+  "&GT;": { "codepoints": [62], "characters": "\u003E" },
+  "&GT": { "codepoints": [62], "characters": "\u003E" },
+  "&Gt;": { "codepoints": [8811], "characters": "\u226B" },
+  "&gtdot;": { "codepoints": [8919], "characters": "\u22D7" },
+  "&gtlPar;": { "codepoints": [10645], "characters": "\u2995" },
+  "&gtquest;": { "codepoints": [10876], "characters": "\u2A7C" },
+  "&gtrapprox;": { "codepoints": [10886], "characters": "\u2A86" },
+  "&gtrarr;": { "codepoints": [10616], "characters": "\u2978" },
+  "&gtrdot;": { "codepoints": [8919], "characters": "\u22D7" },
+  "&gtreqless;": { "codepoints": [8923], "characters": "\u22DB" },
+  "&gtreqqless;": { "codepoints": [10892], "characters": "\u2A8C" },
+  "&gtrless;": { "codepoints": [8823], "characters": "\u2277" },
+  "&gtrsim;": { "codepoints": [8819], "characters": "\u2273" },
+  "&gvertneqq;": { "codepoints": [8809, 65024], "characters": "\u2269\uFE00" },
+  "&gvnE;": { "codepoints": [8809, 65024], "characters": "\u2269\uFE00" },
+  "&Hacek;": { "codepoints": [711], "characters": "\u02C7" },
+  "&hairsp;": { "codepoints": [8202], "characters": "\u200A" },
+  "&half;": { "codepoints": [189], "characters": "\u00BD" },
+  "&hamilt;": { "codepoints": [8459], "characters": "\u210B" },
+  "&HARDcy;": { "codepoints": [1066], "characters": "\u042A" },
+  "&hardcy;": { "codepoints": [1098], "characters": "\u044A" },
+  "&harrcir;": { "codepoints": [10568], "characters": "\u2948" },
+  "&harr;": { "codepoints": [8596], "characters": "\u2194" },
+  "&hArr;": { "codepoints": [8660], "characters": "\u21D4" },
+  "&harrw;": { "codepoints": [8621], "characters": "\u21AD" },
+  "&Hat;": { "codepoints": [94], "characters": "\u005E" },
+  "&hbar;": { "codepoints": [8463], "characters": "\u210F" },
+  "&Hcirc;": { "codepoints": [292], "characters": "\u0124" },
+  "&hcirc;": { "codepoints": [293], "characters": "\u0125" },
+  "&hearts;": { "codepoints": [9829], "characters": "\u2665" },
+  "&heartsuit;": { "codepoints": [9829], "characters": "\u2665" },
+  "&hellip;": { "codepoints": [8230], "characters": "\u2026" },
+  "&hercon;": { "codepoints": [8889], "characters": "\u22B9" },
+  "&hfr;": { "codepoints": [120101], "characters": "\uD835\uDD25" },
+  "&Hfr;": { "codepoints": [8460], "characters": "\u210C" },
+  "&HilbertSpace;": { "codepoints": [8459], "characters": "\u210B" },
+  "&hksearow;": { "codepoints": [10533], "characters": "\u2925" },
+  "&hkswarow;": { "codepoints": [10534], "characters": "\u2926" },
+  "&hoarr;": { "codepoints": [8703], "characters": "\u21FF" },
+  "&homtht;": { "codepoints": [8763], "characters": "\u223B" },
+  "&hookleftarrow;": { "codepoints": [8617], "characters": "\u21A9" },
+  "&hookrightarrow;": { "codepoints": [8618], "characters": "\u21AA" },
+  "&hopf;": { "codepoints": [120153], "characters": "\uD835\uDD59" },
+  "&Hopf;": { "codepoints": [8461], "characters": "\u210D" },
+  "&horbar;": { "codepoints": [8213], "characters": "\u2015" },
+  "&HorizontalLine;": { "codepoints": [9472], "characters": "\u2500" },
+  "&hscr;": { "codepoints": [119997], "characters": "\uD835\uDCBD" },
+  "&Hscr;": { "codepoints": [8459], "characters": "\u210B" },
+  "&hslash;": { "codepoints": [8463], "characters": "\u210F" },
+  "&Hstrok;": { "codepoints": [294], "characters": "\u0126" },
+  "&hstrok;": { "codepoints": [295], "characters": "\u0127" },
+  "&HumpDownHump;": { "codepoints": [8782], "characters": "\u224E" },
+  "&HumpEqual;": { "codepoints": [8783], "characters": "\u224F" },
+  "&hybull;": { "codepoints": [8259], "characters": "\u2043" },
+  "&hyphen;": { "codepoints": [8208], "characters": "\u2010" },
+  "&Iacute;": { "codepoints": [205], "characters": "\u00CD" },
+  "&Iacute": { "codepoints": [205], "characters": "\u00CD" },
+  "&iacute;": { "codepoints": [237], "characters": "\u00ED" },
+  "&iacute": { "codepoints": [237], "characters": "\u00ED" },
+  "&ic;": { "codepoints": [8291], "characters": "\u2063" },
+  "&Icirc;": { "codepoints": [206], "characters": "\u00CE" },
+  "&Icirc": { "codepoints": [206], "characters": "\u00CE" },
+  "&icirc;": { "codepoints": [238], "characters": "\u00EE" },
+  "&icirc": { "codepoints": [238], "characters": "\u00EE" },
+  "&Icy;": { "codepoints": [1048], "characters": "\u0418" },
+  "&icy;": { "codepoints": [1080], "characters": "\u0438" },
+  "&Idot;": { "codepoints": [304], "characters": "\u0130" },
+  "&IEcy;": { "codepoints": [1045], "characters": "\u0415" },
+  "&iecy;": { "codepoints": [1077], "characters": "\u0435" },
+  "&iexcl;": { "codepoints": [161], "characters": "\u00A1" },
+  "&iexcl": { "codepoints": [161], "characters": "\u00A1" },
+  "&iff;": { "codepoints": [8660], "characters": "\u21D4" },
+  "&ifr;": { "codepoints": [120102], "characters": "\uD835\uDD26" },
+  "&Ifr;": { "codepoints": [8465], "characters": "\u2111" },
+  "&Igrave;": { "codepoints": [204], "characters": "\u00CC" },
+  "&Igrave": { "codepoints": [204], "characters": "\u00CC" },
+  "&igrave;": { "codepoints": [236], "characters": "\u00EC" },
+  "&igrave": { "codepoints": [236], "characters": "\u00EC" },
+  "&ii;": { "codepoints": [8520], "characters": "\u2148" },
+  "&iiiint;": { "codepoints": [10764], "characters": "\u2A0C" },
+  "&iiint;": { "codepoints": [8749], "characters": "\u222D" },
+  "&iinfin;": { "codepoints": [10716], "characters": "\u29DC" },
+  "&iiota;": { "codepoints": [8489], "characters": "\u2129" },
+  "&IJlig;": { "codepoints": [306], "characters": "\u0132" },
+  "&ijlig;": { "codepoints": [307], "characters": "\u0133" },
+  "&Imacr;": { "codepoints": [298], "characters": "\u012A" },
+  "&imacr;": { "codepoints": [299], "characters": "\u012B" },
+  "&image;": { "codepoints": [8465], "characters": "\u2111" },
+  "&ImaginaryI;": { "codepoints": [8520], "characters": "\u2148" },
+  "&imagline;": { "codepoints": [8464], "characters": "\u2110" },
+  "&imagpart;": { "codepoints": [8465], "characters": "\u2111" },
+  "&imath;": { "codepoints": [305], "characters": "\u0131" },
+  "&Im;": { "codepoints": [8465], "characters": "\u2111" },
+  "&imof;": { "codepoints": [8887], "characters": "\u22B7" },
+  "&imped;": { "codepoints": [437], "characters": "\u01B5" },
+  "&Implies;": { "codepoints": [8658], "characters": "\u21D2" },
+  "&incare;": { "codepoints": [8453], "characters": "\u2105" },
+  "&in;": { "codepoints": [8712], "characters": "\u2208" },
+  "&infin;": { "codepoints": [8734], "characters": "\u221E" },
+  "&infintie;": { "codepoints": [10717], "characters": "\u29DD" },
+  "&inodot;": { "codepoints": [305], "characters": "\u0131" },
+  "&intcal;": { "codepoints": [8890], "characters": "\u22BA" },
+  "&int;": { "codepoints": [8747], "characters": "\u222B" },
+  "&Int;": { "codepoints": [8748], "characters": "\u222C" },
+  "&integers;": { "codepoints": [8484], "characters": "\u2124" },
+  "&Integral;": { "codepoints": [8747], "characters": "\u222B" },
+  "&intercal;": { "codepoints": [8890], "characters": "\u22BA" },
+  "&Intersection;": { "codepoints": [8898], "characters": "\u22C2" },
+  "&intlarhk;": { "codepoints": [10775], "characters": "\u2A17" },
+  "&intprod;": { "codepoints": [10812], "characters": "\u2A3C" },
+  "&InvisibleComma;": { "codepoints": [8291], "characters": "\u2063" },
+  "&InvisibleTimes;": { "codepoints": [8290], "characters": "\u2062" },
+  "&IOcy;": { "codepoints": [1025], "characters": "\u0401" },
+  "&iocy;": { "codepoints": [1105], "characters": "\u0451" },
+  "&Iogon;": { "codepoints": [302], "characters": "\u012E" },
+  "&iogon;": { "codepoints": [303], "characters": "\u012F" },
+  "&Iopf;": { "codepoints": [120128], "characters": "\uD835\uDD40" },
+  "&iopf;": { "codepoints": [120154], "characters": "\uD835\uDD5A" },
+  "&Iota;": { "codepoints": [921], "characters": "\u0399" },
+  "&iota;": { "codepoints": [953], "characters": "\u03B9" },
+  "&iprod;": { "codepoints": [10812], "characters": "\u2A3C" },
+  "&iquest;": { "codepoints": [191], "characters": "\u00BF" },
+  "&iquest": { "codepoints": [191], "characters": "\u00BF" },
+  "&iscr;": { "codepoints": [119998], "characters": "\uD835\uDCBE" },
+  "&Iscr;": { "codepoints": [8464], "characters": "\u2110" },
+  "&isin;": { "codepoints": [8712], "characters": "\u2208" },
+  "&isindot;": { "codepoints": [8949], "characters": "\u22F5" },
+  "&isinE;": { "codepoints": [8953], "characters": "\u22F9" },
+  "&isins;": { "codepoints": [8948], "characters": "\u22F4" },
+  "&isinsv;": { "codepoints": [8947], "characters": "\u22F3" },
+  "&isinv;": { "codepoints": [8712], "characters": "\u2208" },
+  "&it;": { "codepoints": [8290], "characters": "\u2062" },
+  "&Itilde;": { "codepoints": [296], "characters": "\u0128" },
+  "&itilde;": { "codepoints": [297], "characters": "\u0129" },
+  "&Iukcy;": { "codepoints": [1030], "characters": "\u0406" },
+  "&iukcy;": { "codepoints": [1110], "characters": "\u0456" },
+  "&Iuml;": { "codepoints": [207], "characters": "\u00CF" },
+  "&Iuml": { "codepoints": [207], "characters": "\u00CF" },
+  "&iuml;": { "codepoints": [239], "characters": "\u00EF" },
+  "&iuml": { "codepoints": [239], "characters": "\u00EF" },
+  "&Jcirc;": { "codepoints": [308], "characters": "\u0134" },
+  "&jcirc;": { "codepoints": [309], "characters": "\u0135" },
+  "&Jcy;": { "codepoints": [1049], "characters": "\u0419" },
+  "&jcy;": { "codepoints": [1081], "characters": "\u0439" },
+  "&Jfr;": { "codepoints": [120077], "characters": "\uD835\uDD0D" },
+  "&jfr;": { "codepoints": [120103], "characters": "\uD835\uDD27" },
+  "&jmath;": { "codepoints": [567], "characters": "\u0237" },
+  "&Jopf;": { "codepoints": [120129], "characters": "\uD835\uDD41" },
+  "&jopf;": { "codepoints": [120155], "characters": "\uD835\uDD5B" },
+  "&Jscr;": { "codepoints": [119973], "characters": "\uD835\uDCA5" },
+  "&jscr;": { "codepoints": [119999], "characters": "\uD835\uDCBF" },
+  "&Jsercy;": { "codepoints": [1032], "characters": "\u0408" },
+  "&jsercy;": { "codepoints": [1112], "characters": "\u0458" },
+  "&Jukcy;": { "codepoints": [1028], "characters": "\u0404" },
+  "&jukcy;": { "codepoints": [1108], "characters": "\u0454" },
+  "&Kappa;": { "codepoints": [922], "characters": "\u039A" },
+  "&kappa;": { "codepoints": [954], "characters": "\u03BA" },
+  "&kappav;": { "codepoints": [1008], "characters": "\u03F0" },
+  "&Kcedil;": { "codepoints": [310], "characters": "\u0136" },
+  "&kcedil;": { "codepoints": [311], "characters": "\u0137" },
+  "&Kcy;": { "codepoints": [1050], "characters": "\u041A" },
+  "&kcy;": { "codepoints": [1082], "characters": "\u043A" },
+  "&Kfr;": { "codepoints": [120078], "characters": "\uD835\uDD0E" },
+  "&kfr;": { "codepoints": [120104], "characters": "\uD835\uDD28" },
+  "&kgreen;": { "codepoints": [312], "characters": "\u0138" },
+  "&KHcy;": { "codepoints": [1061], "characters": "\u0425" },
+  "&khcy;": { "codepoints": [1093], "characters": "\u0445" },
+  "&KJcy;": { "codepoints": [1036], "characters": "\u040C" },
+  "&kjcy;": { "codepoints": [1116], "characters": "\u045C" },
+  "&Kopf;": { "codepoints": [120130], "characters": "\uD835\uDD42" },
+  "&kopf;": { "codepoints": [120156], "characters": "\uD835\uDD5C" },
+  "&Kscr;": { "codepoints": [119974], "characters": "\uD835\uDCA6" },
+  "&kscr;": { "codepoints": [120000], "characters": "\uD835\uDCC0" },
+  "&lAarr;": { "codepoints": [8666], "characters": "\u21DA" },
+  "&Lacute;": { "codepoints": [313], "characters": "\u0139" },
+  "&lacute;": { "codepoints": [314], "characters": "\u013A" },
+  "&laemptyv;": { "codepoints": [10676], "characters": "\u29B4" },
+  "&lagran;": { "codepoints": [8466], "characters": "\u2112" },
+  "&Lambda;": { "codepoints": [923], "characters": "\u039B" },
+  "&lambda;": { "codepoints": [955], "characters": "\u03BB" },
+  "&lang;": { "codepoints": [10216], "characters": "\u27E8" },
+  "&Lang;": { "codepoints": [10218], "characters": "\u27EA" },
+  "&langd;": { "codepoints": [10641], "characters": "\u2991" },
+  "&langle;": { "codepoints": [10216], "characters": "\u27E8" },
+  "&lap;": { "codepoints": [10885], "characters": "\u2A85" },
+  "&Laplacetrf;": { "codepoints": [8466], "characters": "\u2112" },
+  "&laquo;": { "codepoints": [171], "characters": "\u00AB" },
+  "&laquo": { "codepoints": [171], "characters": "\u00AB" },
+  "&larrb;": { "codepoints": [8676], "characters": "\u21E4" },
+  "&larrbfs;": { "codepoints": [10527], "characters": "\u291F" },
+  "&larr;": { "codepoints": [8592], "characters": "\u2190" },
+  "&Larr;": { "codepoints": [8606], "characters": "\u219E" },
+  "&lArr;": { "codepoints": [8656], "characters": "\u21D0" },
+  "&larrfs;": { "codepoints": [10525], "characters": "\u291D" },
+  "&larrhk;": { "codepoints": [8617], "characters": "\u21A9" },
+  "&larrlp;": { "codepoints": [8619], "characters": "\u21AB" },
+  "&larrpl;": { "codepoints": [10553], "characters": "\u2939" },
+  "&larrsim;": { "codepoints": [10611], "characters": "\u2973" },
+  "&larrtl;": { "codepoints": [8610], "characters": "\u21A2" },
+  "&latail;": { "codepoints": [10521], "characters": "\u2919" },
+  "&lAtail;": { "codepoints": [10523], "characters": "\u291B" },
+  "&lat;": { "codepoints": [10923], "characters": "\u2AAB" },
+  "&late;": { "codepoints": [10925], "characters": "\u2AAD" },
+  "&lates;": { "codepoints": [10925, 65024], "characters": "\u2AAD\uFE00" },
+  "&lbarr;": { "codepoints": [10508], "characters": "\u290C" },
+  "&lBarr;": { "codepoints": [10510], "characters": "\u290E" },
+  "&lbbrk;": { "codepoints": [10098], "characters": "\u2772" },
+  "&lbrace;": { "codepoints": [123], "characters": "\u007B" },
+  "&lbrack;": { "codepoints": [91], "characters": "\u005B" },
+  "&lbrke;": { "codepoints": [10635], "characters": "\u298B" },
+  "&lbrksld;": { "codepoints": [10639], "characters": "\u298F" },
+  "&lbrkslu;": { "codepoints": [10637], "characters": "\u298D" },
+  "&Lcaron;": { "codepoints": [317], "characters": "\u013D" },
+  "&lcaron;": { "codepoints": [318], "characters": "\u013E" },
+  "&Lcedil;": { "codepoints": [315], "characters": "\u013B" },
+  "&lcedil;": { "codepoints": [316], "characters": "\u013C" },
+  "&lceil;": { "codepoints": [8968], "characters": "\u2308" },
+  "&lcub;": { "codepoints": [123], "characters": "\u007B" },
+  "&Lcy;": { "codepoints": [1051], "characters": "\u041B" },
+  "&lcy;": { "codepoints": [1083], "characters": "\u043B" },
+  "&ldca;": { "codepoints": [10550], "characters": "\u2936" },
+  "&ldquo;": { "codepoints": [8220], "characters": "\u201C" },
+  "&ldquor;": { "codepoints": [8222], "characters": "\u201E" },
+  "&ldrdhar;": { "codepoints": [10599], "characters": "\u2967" },
+  "&ldrushar;": { "codepoints": [10571], "characters": "\u294B" },
+  "&ldsh;": { "codepoints": [8626], "characters": "\u21B2" },
+  "&le;": { "codepoints": [8804], "characters": "\u2264" },
+  "&lE;": { "codepoints": [8806], "characters": "\u2266" },
+  "&LeftAngleBracket;": { "codepoints": [10216], "characters": "\u27E8" },
+  "&LeftArrowBar;": { "codepoints": [8676], "characters": "\u21E4" },
+  "&leftarrow;": { "codepoints": [8592], "characters": "\u2190" },
+  "&LeftArrow;": { "codepoints": [8592], "characters": "\u2190" },
+  "&Leftarrow;": { "codepoints": [8656], "characters": "\u21D0" },
+  "&LeftArrowRightArrow;": { "codepoints": [8646], "characters": "\u21C6" },
+  "&leftarrowtail;": { "codepoints": [8610], "characters": "\u21A2" },
+  "&LeftCeiling;": { "codepoints": [8968], "characters": "\u2308" },
+  "&LeftDoubleBracket;": { "codepoints": [10214], "characters": "\u27E6" },
+  "&LeftDownTeeVector;": { "codepoints": [10593], "characters": "\u2961" },
+  "&LeftDownVectorBar;": { "codepoints": [10585], "characters": "\u2959" },
+  "&LeftDownVector;": { "codepoints": [8643], "characters": "\u21C3" },
+  "&LeftFloor;": { "codepoints": [8970], "characters": "\u230A" },
+  "&leftharpoondown;": { "codepoints": [8637], "characters": "\u21BD" },
+  "&leftharpoonup;": { "codepoints": [8636], "characters": "\u21BC" },
+  "&leftleftarrows;": { "codepoints": [8647], "characters": "\u21C7" },
+  "&leftrightarrow;": { "codepoints": [8596], "characters": "\u2194" },
+  "&LeftRightArrow;": { "codepoints": [8596], "characters": "\u2194" },
+  "&Leftrightarrow;": { "codepoints": [8660], "characters": "\u21D4" },
+  "&leftrightarrows;": { "codepoints": [8646], "characters": "\u21C6" },
+  "&leftrightharpoons;": { "codepoints": [8651], "characters": "\u21CB" },
+  "&leftrightsquigarrow;": { "codepoints": [8621], "characters": "\u21AD" },
+  "&LeftRightVector;": { "codepoints": [10574], "characters": "\u294E" },
+  "&LeftTeeArrow;": { "codepoints": [8612], "characters": "\u21A4" },
+  "&LeftTee;": { "codepoints": [8867], "characters": "\u22A3" },
+  "&LeftTeeVector;": { "codepoints": [10586], "characters": "\u295A" },
+  "&leftthreetimes;": { "codepoints": [8907], "characters": "\u22CB" },
+  "&LeftTriangleBar;": { "codepoints": [10703], "characters": "\u29CF" },
+  "&LeftTriangle;": { "codepoints": [8882], "characters": "\u22B2" },
+  "&LeftTriangleEqual;": { "codepoints": [8884], "characters": "\u22B4" },
+  "&LeftUpDownVector;": { "codepoints": [10577], "characters": "\u2951" },
+  "&LeftUpTeeVector;": { "codepoints": [10592], "characters": "\u2960" },
+  "&LeftUpVectorBar;": { "codepoints": [10584], "characters": "\u2958" },
+  "&LeftUpVector;": { "codepoints": [8639], "characters": "\u21BF" },
+  "&LeftVectorBar;": { "codepoints": [10578], "characters": "\u2952" },
+  "&LeftVector;": { "codepoints": [8636], "characters": "\u21BC" },
+  "&lEg;": { "codepoints": [10891], "characters": "\u2A8B" },
+  "&leg;": { "codepoints": [8922], "characters": "\u22DA" },
+  "&leq;": { "codepoints": [8804], "characters": "\u2264" },
+  "&leqq;": { "codepoints": [8806], "characters": "\u2266" },
+  "&leqslant;": { "codepoints": [10877], "characters": "\u2A7D" },
+  "&lescc;": { "codepoints": [10920], "characters": "\u2AA8" },
+  "&les;": { "codepoints": [10877], "characters": "\u2A7D" },
+  "&lesdot;": { "codepoints": [10879], "characters": "\u2A7F" },
+  "&lesdoto;": { "codepoints": [10881], "characters": "\u2A81" },
+  "&lesdotor;": { "codepoints": [10883], "characters": "\u2A83" },
+  "&lesg;": { "codepoints": [8922, 65024], "characters": "\u22DA\uFE00" },
+  "&lesges;": { "codepoints": [10899], "characters": "\u2A93" },
+  "&lessapprox;": { "codepoints": [10885], "characters": "\u2A85" },
+  "&lessdot;": { "codepoints": [8918], "characters": "\u22D6" },
+  "&lesseqgtr;": { "codepoints": [8922], "characters": "\u22DA" },
+  "&lesseqqgtr;": { "codepoints": [10891], "characters": "\u2A8B" },
+  "&LessEqualGreater;": { "codepoints": [8922], "characters": "\u22DA" },
+  "&LessFullEqual;": { "codepoints": [8806], "characters": "\u2266" },
+  "&LessGreater;": { "codepoints": [8822], "characters": "\u2276" },
+  "&lessgtr;": { "codepoints": [8822], "characters": "\u2276" },
+  "&LessLess;": { "codepoints": [10913], "characters": "\u2AA1" },
+  "&lesssim;": { "codepoints": [8818], "characters": "\u2272" },
+  "&LessSlantEqual;": { "codepoints": [10877], "characters": "\u2A7D" },
+  "&LessTilde;": { "codepoints": [8818], "characters": "\u2272" },
+  "&lfisht;": { "codepoints": [10620], "characters": "\u297C" },
+  "&lfloor;": { "codepoints": [8970], "characters": "\u230A" },
+  "&Lfr;": { "codepoints": [120079], "characters": "\uD835\uDD0F" },
+  "&lfr;": { "codepoints": [120105], "characters": "\uD835\uDD29" },
+  "&lg;": { "codepoints": [8822], "characters": "\u2276" },
+  "&lgE;": { "codepoints": [10897], "characters": "\u2A91" },
+  "&lHar;": { "codepoints": [10594], "characters": "\u2962" },
+  "&lhard;": { "codepoints": [8637], "characters": "\u21BD" },
+  "&lharu;": { "codepoints": [8636], "characters": "\u21BC" },
+  "&lharul;": { "codepoints": [10602], "characters": "\u296A" },
+  "&lhblk;": { "codepoints": [9604], "characters": "\u2584" },
+  "&LJcy;": { "codepoints": [1033], "characters": "\u0409" },
+  "&ljcy;": { "codepoints": [1113], "characters": "\u0459" },
+  "&llarr;": { "codepoints": [8647], "characters": "\u21C7" },
+  "&ll;": { "codepoints": [8810], "characters": "\u226A" },
+  "&Ll;": { "codepoints": [8920], "characters": "\u22D8" },
+  "&llcorner;": { "codepoints": [8990], "characters": "\u231E" },
+  "&Lleftarrow;": { "codepoints": [8666], "characters": "\u21DA" },
+  "&llhard;": { "codepoints": [10603], "characters": "\u296B" },
+  "&lltri;": { "codepoints": [9722], "characters": "\u25FA" },
+  "&Lmidot;": { "codepoints": [319], "characters": "\u013F" },
+  "&lmidot;": { "codepoints": [320], "characters": "\u0140" },
+  "&lmoustache;": { "codepoints": [9136], "characters": "\u23B0" },
+  "&lmoust;": { "codepoints": [9136], "characters": "\u23B0" },
+  "&lnap;": { "codepoints": [10889], "characters": "\u2A89" },
+  "&lnapprox;": { "codepoints": [10889], "characters": "\u2A89" },
+  "&lne;": { "codepoints": [10887], "characters": "\u2A87" },
+  "&lnE;": { "codepoints": [8808], "characters": "\u2268" },
+  "&lneq;": { "codepoints": [10887], "characters": "\u2A87" },
+  "&lneqq;": { "codepoints": [8808], "characters": "\u2268" },
+  "&lnsim;": { "codepoints": [8934], "characters": "\u22E6" },
+  "&loang;": { "codepoints": [10220], "characters": "\u27EC" },
+  "&loarr;": { "codepoints": [8701], "characters": "\u21FD" },
+  "&lobrk;": { "codepoints": [10214], "characters": "\u27E6" },
+  "&longleftarrow;": { "codepoints": [10229], "characters": "\u27F5" },
+  "&LongLeftArrow;": { "codepoints": [10229], "characters": "\u27F5" },
+  "&Longleftarrow;": { "codepoints": [10232], "characters": "\u27F8" },
+  "&longleftrightarrow;": { "codepoints": [10231], "characters": "\u27F7" },
+  "&LongLeftRightArrow;": { "codepoints": [10231], "characters": "\u27F7" },
+  "&Longleftrightarrow;": { "codepoints": [10234], "characters": "\u27FA" },
+  "&longmapsto;": { "codepoints": [10236], "characters": "\u27FC" },
+  "&longrightarrow;": { "codepoints": [10230], "characters": "\u27F6" },
+  "&LongRightArrow;": { "codepoints": [10230], "characters": "\u27F6" },
+  "&Longrightarrow;": { "codepoints": [10233], "characters": "\u27F9" },
+  "&looparrowleft;": { "codepoints": [8619], "characters": "\u21AB" },
+  "&looparrowright;": { "codepoints": [8620], "characters": "\u21AC" },
+  "&lopar;": { "codepoints": [10629], "characters": "\u2985" },
+  "&Lopf;": { "codepoints": [120131], "characters": "\uD835\uDD43" },
+  "&lopf;": { "codepoints": [120157], "characters": "\uD835\uDD5D" },
+  "&loplus;": { "codepoints": [10797], "characters": "\u2A2D" },
+  "&lotimes;": { "codepoints": [10804], "characters": "\u2A34" },
+  "&lowast;": { "codepoints": [8727], "characters": "\u2217" },
+  "&lowbar;": { "codepoints": [95], "characters": "\u005F" },
+  "&LowerLeftArrow;": { "codepoints": [8601], "characters": "\u2199" },
+  "&LowerRightArrow;": { "codepoints": [8600], "characters": "\u2198" },
+  "&loz;": { "codepoints": [9674], "characters": "\u25CA" },
+  "&lozenge;": { "codepoints": [9674], "characters": "\u25CA" },
+  "&lozf;": { "codepoints": [10731], "characters": "\u29EB" },
+  "&lpar;": { "codepoints": [40], "characters": "\u0028" },
+  "&lparlt;": { "codepoints": [10643], "characters": "\u2993" },
+  "&lrarr;": { "codepoints": [8646], "characters": "\u21C6" },
+  "&lrcorner;": { "codepoints": [8991], "characters": "\u231F" },
+  "&lrhar;": { "codepoints": [8651], "characters": "\u21CB" },
+  "&lrhard;": { "codepoints": [10605], "characters": "\u296D" },
+  "&lrm;": { "codepoints": [8206], "characters": "\u200E" },
+  "&lrtri;": { "codepoints": [8895], "characters": "\u22BF" },
+  "&lsaquo;": { "codepoints": [8249], "characters": "\u2039" },
+  "&lscr;": { "codepoints": [120001], "characters": "\uD835\uDCC1" },
+  "&Lscr;": { "codepoints": [8466], "characters": "\u2112" },
+  "&lsh;": { "codepoints": [8624], "characters": "\u21B0" },
+  "&Lsh;": { "codepoints": [8624], "characters": "\u21B0" },
+  "&lsim;": { "codepoints": [8818], "characters": "\u2272" },
+  "&lsime;": { "codepoints": [10893], "characters": "\u2A8D" },
+  "&lsimg;": { "codepoints": [10895], "characters": "\u2A8F" },
+  "&lsqb;": { "codepoints": [91], "characters": "\u005B" },
+  "&lsquo;": { "codepoints": [8216], "characters": "\u2018" },
+  "&lsquor;": { "codepoints": [8218], "characters": "\u201A" },
+  "&Lstrok;": { "codepoints": [321], "characters": "\u0141" },
+  "&lstrok;": { "codepoints": [322], "characters": "\u0142" },
+  "&ltcc;": { "codepoints": [10918], "characters": "\u2AA6" },
+  "&ltcir;": { "codepoints": [10873], "characters": "\u2A79" },
+  "&lt;": { "codepoints": [60], "characters": "\u003C" },
+  "&lt": { "codepoints": [60], "characters": "\u003C" },
+  "&LT;": { "codepoints": [60], "characters": "\u003C" },
+  "&LT": { "codepoints": [60], "characters": "\u003C" },
+  "&Lt;": { "codepoints": [8810], "characters": "\u226A" },
+  "&ltdot;": { "codepoints": [8918], "characters": "\u22D6" },
+  "&lthree;": { "codepoints": [8907], "characters": "\u22CB" },
+  "&ltimes;": { "codepoints": [8905], "characters": "\u22C9" },
+  "&ltlarr;": { "codepoints": [10614], "characters": "\u2976" },
+  "&ltquest;": { "codepoints": [10875], "characters": "\u2A7B" },
+  "&ltri;": { "codepoints": [9667], "characters": "\u25C3" },
+  "&ltrie;": { "codepoints": [8884], "characters": "\u22B4" },
+  "&ltrif;": { "codepoints": [9666], "characters": "\u25C2" },
+  "&ltrPar;": { "codepoints": [10646], "characters": "\u2996" },
+  "&lurdshar;": { "codepoints": [10570], "characters": "\u294A" },
+  "&luruhar;": { "codepoints": [10598], "characters": "\u2966" },
+  "&lvertneqq;": { "codepoints": [8808, 65024], "characters": "\u2268\uFE00" },
+  "&lvnE;": { "codepoints": [8808, 65024], "characters": "\u2268\uFE00" },
+  "&macr;": { "codepoints": [175], "characters": "\u00AF" },
+  "&macr": { "codepoints": [175], "characters": "\u00AF" },
+  "&male;": { "codepoints": [9794], "characters": "\u2642" },
+  "&malt;": { "codepoints": [10016], "characters": "\u2720" },
+  "&maltese;": { "codepoints": [10016], "characters": "\u2720" },
+  "&Map;": { "codepoints": [10501], "characters": "\u2905" },
+  "&map;": { "codepoints": [8614], "characters": "\u21A6" },
+  "&mapsto;": { "codepoints": [8614], "characters": "\u21A6" },
+  "&mapstodown;": { "codepoints": [8615], "characters": "\u21A7" },
+  "&mapstoleft;": { "codepoints": [8612], "characters": "\u21A4" },
+  "&mapstoup;": { "codepoints": [8613], "characters": "\u21A5" },
+  "&marker;": { "codepoints": [9646], "characters": "\u25AE" },
+  "&mcomma;": { "codepoints": [10793], "characters": "\u2A29" },
+  "&Mcy;": { "codepoints": [1052], "characters": "\u041C" },
+  "&mcy;": { "codepoints": [1084], "characters": "\u043C" },
+  "&mdash;": { "codepoints": [8212], "characters": "\u2014" },
+  "&mDDot;": { "codepoints": [8762], "characters": "\u223A" },
+  "&measuredangle;": { "codepoints": [8737], "characters": "\u2221" },
+  "&MediumSpace;": { "codepoints": [8287], "characters": "\u205F" },
+  "&Mellintrf;": { "codepoints": [8499], "characters": "\u2133" },
+  "&Mfr;": { "codepoints": [120080], "characters": "\uD835\uDD10" },
+  "&mfr;": { "codepoints": [120106], "characters": "\uD835\uDD2A" },
+  "&mho;": { "codepoints": [8487], "characters": "\u2127" },
+  "&micro;": { "codepoints": [181], "characters": "\u00B5" },
+  "&micro": { "codepoints": [181], "characters": "\u00B5" },
+  "&midast;": { "codepoints": [42], "characters": "\u002A" },
+  "&midcir;": { "codepoints": [10992], "characters": "\u2AF0" },
+  "&mid;": { "codepoints": [8739], "characters": "\u2223" },
+  "&middot;": { "codepoints": [183], "characters": "\u00B7" },
+  "&middot": { "codepoints": [183], "characters": "\u00B7" },
+  "&minusb;": { "codepoints": [8863], "characters": "\u229F" },
+  "&minus;": { "codepoints": [8722], "characters": "\u2212" },
+  "&minusd;": { "codepoints": [8760], "characters": "\u2238" },
+  "&minusdu;": { "codepoints": [10794], "characters": "\u2A2A" },
+  "&MinusPlus;": { "codepoints": [8723], "characters": "\u2213" },
+  "&mlcp;": { "codepoints": [10971], "characters": "\u2ADB" },
+  "&mldr;": { "codepoints": [8230], "characters": "\u2026" },
+  "&mnplus;": { "codepoints": [8723], "characters": "\u2213" },
+  "&models;": { "codepoints": [8871], "characters": "\u22A7" },
+  "&Mopf;": { "codepoints": [120132], "characters": "\uD835\uDD44" },
+  "&mopf;": { "codepoints": [120158], "characters": "\uD835\uDD5E" },
+  "&mp;": { "codepoints": [8723], "characters": "\u2213" },
+  "&mscr;": { "codepoints": [120002], "characters": "\uD835\uDCC2" },
+  "&Mscr;": { "codepoints": [8499], "characters": "\u2133" },
+  "&mstpos;": { "codepoints": [8766], "characters": "\u223E" },
+  "&Mu;": { "codepoints": [924], "characters": "\u039C" },
+  "&mu;": { "codepoints": [956], "characters": "\u03BC" },
+  "&multimap;": { "codepoints": [8888], "characters": "\u22B8" },
+  "&mumap;": { "codepoints": [8888], "characters": "\u22B8" },
+  "&nabla;": { "codepoints": [8711], "characters": "\u2207" },
+  "&Nacute;": { "codepoints": [323], "characters": "\u0143" },
+  "&nacute;": { "codepoints": [324], "characters": "\u0144" },
+  "&nang;": { "codepoints": [8736, 8402], "characters": "\u2220\u20D2" },
+  "&nap;": { "codepoints": [8777], "characters": "\u2249" },
+  "&napE;": { "codepoints": [10864, 824], "characters": "\u2A70\u0338" },
+  "&napid;": { "codepoints": [8779, 824], "characters": "\u224B\u0338" },
+  "&napos;": { "codepoints": [329], "characters": "\u0149" },
+  "&napprox;": { "codepoints": [8777], "characters": "\u2249" },
+  "&natural;": { "codepoints": [9838], "characters": "\u266E" },
+  "&naturals;": { "codepoints": [8469], "characters": "\u2115" },
+  "&natur;": { "codepoints": [9838], "characters": "\u266E" },
+  "&nbsp;": { "codepoints": [160], "characters": "\u00A0" },
+  "&nbsp": { "codepoints": [160], "characters": "\u00A0" },
+  "&nbump;": { "codepoints": [8782, 824], "characters": "\u224E\u0338" },
+  "&nbumpe;": { "codepoints": [8783, 824], "characters": "\u224F\u0338" },
+  "&ncap;": { "codepoints": [10819], "characters": "\u2A43" },
+  "&Ncaron;": { "codepoints": [327], "characters": "\u0147" },
+  "&ncaron;": { "codepoints": [328], "characters": "\u0148" },
+  "&Ncedil;": { "codepoints": [325], "characters": "\u0145" },
+  "&ncedil;": { "codepoints": [326], "characters": "\u0146" },
+  "&ncong;": { "codepoints": [8775], "characters": "\u2247" },
+  "&ncongdot;": { "codepoints": [10861, 824], "characters": "\u2A6D\u0338" },
+  "&ncup;": { "codepoints": [10818], "characters": "\u2A42" },
+  "&Ncy;": { "codepoints": [1053], "characters": "\u041D" },
+  "&ncy;": { "codepoints": [1085], "characters": "\u043D" },
+  "&ndash;": { "codepoints": [8211], "characters": "\u2013" },
+  "&nearhk;": { "codepoints": [10532], "characters": "\u2924" },
+  "&nearr;": { "codepoints": [8599], "characters": "\u2197" },
+  "&neArr;": { "codepoints": [8663], "characters": "\u21D7" },
+  "&nearrow;": { "codepoints": [8599], "characters": "\u2197" },
+  "&ne;": { "codepoints": [8800], "characters": "\u2260" },
+  "&nedot;": { "codepoints": [8784, 824], "characters": "\u2250\u0338" },
+  "&NegativeMediumSpace;": { "codepoints": [8203], "characters": "\u200B" },
+  "&NegativeThickSpace;": { "codepoints": [8203], "characters": "\u200B" },
+  "&NegativeThinSpace;": { "codepoints": [8203], "characters": "\u200B" },
+  "&NegativeVeryThinSpace;": { "codepoints": [8203], "characters": "\u200B" },
+  "&nequiv;": { "codepoints": [8802], "characters": "\u2262" },
+  "&nesear;": { "codepoints": [10536], "characters": "\u2928" },
+  "&nesim;": { "codepoints": [8770, 824], "characters": "\u2242\u0338" },
+  "&NestedGreaterGreater;": { "codepoints": [8811], "characters": "\u226B" },
+  "&NestedLessLess;": { "codepoints": [8810], "characters": "\u226A" },
+  "&NewLine;": { "codepoints": [10], "characters": "\u000A" },
+  "&nexist;": { "codepoints": [8708], "characters": "\u2204" },
+  "&nexists;": { "codepoints": [8708], "characters": "\u2204" },
+  "&Nfr;": { "codepoints": [120081], "characters": "\uD835\uDD11" },
+  "&nfr;": { "codepoints": [120107], "characters": "\uD835\uDD2B" },
+  "&ngE;": { "codepoints": [8807, 824], "characters": "\u2267\u0338" },
+  "&nge;": { "codepoints": [8817], "characters": "\u2271" },
+  "&ngeq;": { "codepoints": [8817], "characters": "\u2271" },
+  "&ngeqq;": { "codepoints": [8807, 824], "characters": "\u2267\u0338" },
+  "&ngeqslant;": { "codepoints": [10878, 824], "characters": "\u2A7E\u0338" },
+  "&nges;": { "codepoints": [10878, 824], "characters": "\u2A7E\u0338" },
+  "&nGg;": { "codepoints": [8921, 824], "characters": "\u22D9\u0338" },
+  "&ngsim;": { "codepoints": [8821], "characters": "\u2275" },
+  "&nGt;": { "codepoints": [8811, 8402], "characters": "\u226B\u20D2" },
+  "&ngt;": { "codepoints": [8815], "characters": "\u226F" },
+  "&ngtr;": { "codepoints": [8815], "characters": "\u226F" },
+  "&nGtv;": { "codepoints": [8811, 824], "characters": "\u226B\u0338" },
+  "&nharr;": { "codepoints": [8622], "characters": "\u21AE" },
+  "&nhArr;": { "codepoints": [8654], "characters": "\u21CE" },
+  "&nhpar;": { "codepoints": [10994], "characters": "\u2AF2" },
+  "&ni;": { "codepoints": [8715], "characters": "\u220B" },
+  "&nis;": { "codepoints": [8956], "characters": "\u22FC" },
+  "&nisd;": { "codepoints": [8954], "characters": "\u22FA" },
+  "&niv;": { "codepoints": [8715], "characters": "\u220B" },
+  "&NJcy;": { "codepoints": [1034], "characters": "\u040A" },
+  "&njcy;": { "codepoints": [1114], "characters": "\u045A" },
+  "&nlarr;": { "codepoints": [8602], "characters": "\u219A" },
+  "&nlArr;": { "codepoints": [8653], "characters": "\u21CD" },
+  "&nldr;": { "codepoints": [8229], "characters": "\u2025" },
+  "&nlE;": { "codepoints": [8806, 824], "characters": "\u2266\u0338" },
+  "&nle;": { "codepoints": [8816], "characters": "\u2270" },
+  "&nleftarrow;": { "codepoints": [8602], "characters": "\u219A" },
+  "&nLeftarrow;": { "codepoints": [8653], "characters": "\u21CD" },
+  "&nleftrightarrow;": { "codepoints": [8622], "characters": "\u21AE" },
+  "&nLeftrightarrow;": { "codepoints": [8654], "characters": "\u21CE" },
+  "&nleq;": { "codepoints": [8816], "characters": "\u2270" },
+  "&nleqq;": { "codepoints": [8806, 824], "characters": "\u2266\u0338" },
+  "&nleqslant;": { "codepoints": [10877, 824], "characters": "\u2A7D\u0338" },
+  "&nles;": { "codepoints": [10877, 824], "characters": "\u2A7D\u0338" },
+  "&nless;": { "codepoints": [8814], "characters": "\u226E" },
+  "&nLl;": { "codepoints": [8920, 824], "characters": "\u22D8\u0338" },
+  "&nlsim;": { "codepoints": [8820], "characters": "\u2274" },
+  "&nLt;": { "codepoints": [8810, 8402], "characters": "\u226A\u20D2" },
+  "&nlt;": { "codepoints": [8814], "characters": "\u226E" },
+  "&nltri;": { "codepoints": [8938], "characters": "\u22EA" },
+  "&nltrie;": { "codepoints": [8940], "characters": "\u22EC" },
+  "&nLtv;": { "codepoints": [8810, 824], "characters": "\u226A\u0338" },
+  "&nmid;": { "codepoints": [8740], "characters": "\u2224" },
+  "&NoBreak;": { "codepoints": [8288], "characters": "\u2060" },
+  "&NonBreakingSpace;": { "codepoints": [160], "characters": "\u00A0" },
+  "&nopf;": { "codepoints": [120159], "characters": "\uD835\uDD5F" },
+  "&Nopf;": { "codepoints": [8469], "characters": "\u2115" },
+  "&Not;": { "codepoints": [10988], "characters": "\u2AEC" },
+  "&not;": { "codepoints": [172], "characters": "\u00AC" },
+  "&not": { "codepoints": [172], "characters": "\u00AC" },
+  "&NotCongruent;": { "codepoints": [8802], "characters": "\u2262" },
+  "&NotCupCap;": { "codepoints": [8813], "characters": "\u226D" },
+  "&NotDoubleVerticalBar;": { "codepoints": [8742], "characters": "\u2226" },
+  "&NotElement;": { "codepoints": [8713], "characters": "\u2209" },
+  "&NotEqual;": { "codepoints": [8800], "characters": "\u2260" },
+  "&NotEqualTilde;": { "codepoints": [8770, 824], "characters": "\u2242\u0338" },
+  "&NotExists;": { "codepoints": [8708], "characters": "\u2204" },
+  "&NotGreater;": { "codepoints": [8815], "characters": "\u226F" },
+  "&NotGreaterEqual;": { "codepoints": [8817], "characters": "\u2271" },
+  "&NotGreaterFullEqual;": { "codepoints": [8807, 824], "characters": "\u2267\u0338" },
+  "&NotGreaterGreater;": { "codepoints": [8811, 824], "characters": "\u226B\u0338" },
+  "&NotGreaterLess;": { "codepoints": [8825], "characters": "\u2279" },
+  "&NotGreaterSlantEqual;": { "codepoints": [10878, 824], "characters": "\u2A7E\u0338" },
+  "&NotGreaterTilde;": { "codepoints": [8821], "characters": "\u2275" },
+  "&NotHumpDownHump;": { "codepoints": [8782, 824], "characters": "\u224E\u0338" },
+  "&NotHumpEqual;": { "codepoints": [8783, 824], "characters": "\u224F\u0338" },
+  "&notin;": { "codepoints": [8713], "characters": "\u2209" },
+  "&notindot;": { "codepoints": [8949, 824], "characters": "\u22F5\u0338" },
+  "&notinE;": { "codepoints": [8953, 824], "characters": "\u22F9\u0338" },
+  "&notinva;": { "codepoints": [8713], "characters": "\u2209" },
+  "&notinvb;": { "codepoints": [8951], "characters": "\u22F7" },
+  "&notinvc;": { "codepoints": [8950], "characters": "\u22F6" },
+  "&NotLeftTriangleBar;": { "codepoints": [10703, 824], "characters": "\u29CF\u0338" },
+  "&NotLeftTriangle;": { "codepoints": [8938], "characters": "\u22EA" },
+  "&NotLeftTriangleEqual;": { "codepoints": [8940], "characters": "\u22EC" },
+  "&NotLess;": { "codepoints": [8814], "characters": "\u226E" },
+  "&NotLessEqual;": { "codepoints": [8816], "characters": "\u2270" },
+  "&NotLessGreater;": { "codepoints": [8824], "characters": "\u2278" },
+  "&NotLessLess;": { "codepoints": [8810, 824], "characters": "\u226A\u0338" },
+  "&NotLessSlantEqual;": { "codepoints": [10877, 824], "characters": "\u2A7D\u0338" },
+  "&NotLessTilde;": { "codepoints": [8820], "characters": "\u2274" },
+  "&NotNestedGreaterGreater;": { "codepoints": [10914, 824], "characters": "\u2AA2\u0338" },
+  "&NotNestedLessLess;": { "codepoints": [10913, 824], "characters": "\u2AA1\u0338" },
+  "&notni;": { "codepoints": [8716], "characters": "\u220C" },
+  "&notniva;": { "codepoints": [8716], "characters": "\u220C" },
+  "&notnivb;": { "codepoints": [8958], "characters": "\u22FE" },
+  "&notnivc;": { "codepoints": [8957], "characters": "\u22FD" },
+  "&NotPrecedes;": { "codepoints": [8832], "characters": "\u2280" },
+  "&NotPrecedesEqual;": { "codepoints": [10927, 824], "characters": "\u2AAF\u0338" },
+  "&NotPrecedesSlantEqual;": { "codepoints": [8928], "characters": "\u22E0" },
+  "&NotReverseElement;": { "codepoints": [8716], "characters": "\u220C" },
+  "&NotRightTriangleBar;": { "codepoints": [10704, 824], "characters": "\u29D0\u0338" },
+  "&NotRightTriangle;": { "codepoints": [8939], "characters": "\u22EB" },
+  "&NotRightTriangleEqual;": { "codepoints": [8941], "characters": "\u22ED" },
+  "&NotSquareSubset;": { "codepoints": [8847, 824], "characters": "\u228F\u0338" },
+  "&NotSquareSubsetEqual;": { "codepoints": [8930], "characters": "\u22E2" },
+  "&NotSquareSuperset;": { "codepoints": [8848, 824], "characters": "\u2290\u0338" },
+  "&NotSquareSupersetEqual;": { "codepoints": [8931], "characters": "\u22E3" },
+  "&NotSubset;": { "codepoints": [8834, 8402], "characters": "\u2282\u20D2" },
+  "&NotSubsetEqual;": { "codepoints": [8840], "characters": "\u2288" },
+  "&NotSucceeds;": { "codepoints": [8833], "characters": "\u2281" },
+  "&NotSucceedsEqual;": { "codepoints": [10928, 824], "characters": "\u2AB0\u0338" },
+  "&NotSucceedsSlantEqual;": { "codepoints": [8929], "characters": "\u22E1" },
+  "&NotSucceedsTilde;": { "codepoints": [8831, 824], "characters": "\u227F\u0338" },
+  "&NotSuperset;": { "codepoints": [8835, 8402], "characters": "\u2283\u20D2" },
+  "&NotSupersetEqual;": { "codepoints": [8841], "characters": "\u2289" },
+  "&NotTilde;": { "codepoints": [8769], "characters": "\u2241" },
+  "&NotTildeEqual;": { "codepoints": [8772], "characters": "\u2244" },
+  "&NotTildeFullEqual;": { "codepoints": [8775], "characters": "\u2247" },
+  "&NotTildeTilde;": { "codepoints": [8777], "characters": "\u2249" },
+  "&NotVerticalBar;": { "codepoints": [8740], "characters": "\u2224" },
+  "&nparallel;": { "codepoints": [8742], "characters": "\u2226" },
+  "&npar;": { "codepoints": [8742], "characters": "\u2226" },
+  "&nparsl;": { "codepoints": [11005, 8421], "characters": "\u2AFD\u20E5" },
+  "&npart;": { "codepoints": [8706, 824], "characters": "\u2202\u0338" },
+  "&npolint;": { "codepoints": [10772], "characters": "\u2A14" },
+  "&npr;": { "codepoints": [8832], "characters": "\u2280" },
+  "&nprcue;": { "codepoints": [8928], "characters": "\u22E0" },
+  "&nprec;": { "codepoints": [8832], "characters": "\u2280" },
+  "&npreceq;": { "codepoints": [10927, 824], "characters": "\u2AAF\u0338" },
+  "&npre;": { "codepoints": [10927, 824], "characters": "\u2AAF\u0338" },
+  "&nrarrc;": { "codepoints": [10547, 824], "characters": "\u2933\u0338" },
+  "&nrarr;": { "codepoints": [8603], "characters": "\u219B" },
+  "&nrArr;": { "codepoints": [8655], "characters": "\u21CF" },
+  "&nrarrw;": { "codepoints": [8605, 824], "characters": "\u219D\u0338" },
+  "&nrightarrow;": { "codepoints": [8603], "characters": "\u219B" },
+  "&nRightarrow;": { "codepoints": [8655], "characters": "\u21CF" },
+  "&nrtri;": { "codepoints": [8939], "characters": "\u22EB" },
+  "&nrtrie;": { "codepoints": [8941], "characters": "\u22ED" },
+  "&nsc;": { "codepoints": [8833], "characters": "\u2281" },
+  "&nsccue;": { "codepoints": [8929], "characters": "\u22E1" },
+  "&nsce;": { "codepoints": [10928, 824], "characters": "\u2AB0\u0338" },
+  "&Nscr;": { "codepoints": [119977], "characters": "\uD835\uDCA9" },
+  "&nscr;": { "codepoints": [120003], "characters": "\uD835\uDCC3" },
+  "&nshortmid;": { "codepoints": [8740], "characters": "\u2224" },
+  "&nshortparallel;": { "codepoints": [8742], "characters": "\u2226" },
+  "&nsim;": { "codepoints": [8769], "characters": "\u2241" },
+  "&nsime;": { "codepoints": [8772], "characters": "\u2244" },
+  "&nsimeq;": { "codepoints": [8772], "characters": "\u2244" },
+  "&nsmid;": { "codepoints": [8740], "characters": "\u2224" },
+  "&nspar;": { "codepoints": [8742], "characters": "\u2226" },
+  "&nsqsube;": { "codepoints": [8930], "characters": "\u22E2" },
+  "&nsqsupe;": { "codepoints": [8931], "characters": "\u22E3" },
+  "&nsub;": { "codepoints": [8836], "characters": "\u2284" },
+  "&nsubE;": { "codepoints": [10949, 824], "characters": "\u2AC5\u0338" },
+  "&nsube;": { "codepoints": [8840], "characters": "\u2288" },
+  "&nsubset;": { "codepoints": [8834, 8402], "characters": "\u2282\u20D2" },
+  "&nsubseteq;": { "codepoints": [8840], "characters": "\u2288" },
+  "&nsubseteqq;": { "codepoints": [10949, 824], "characters": "\u2AC5\u0338" },
+  "&nsucc;": { "codepoints": [8833], "characters": "\u2281" },
+  "&nsucceq;": { "codepoints": [10928, 824], "characters": "\u2AB0\u0338" },
+  "&nsup;": { "codepoints": [8837], "characters": "\u2285" },
+  "&nsupE;": { "codepoints": [10950, 824], "characters": "\u2AC6\u0338" },
+  "&nsupe;": { "codepoints": [8841], "characters": "\u2289" },
+  "&nsupset;": { "codepoints": [8835, 8402], "characters": "\u2283\u20D2" },
+  "&nsupseteq;": { "codepoints": [8841], "characters": "\u2289" },
+  "&nsupseteqq;": { "codepoints": [10950, 824], "characters": "\u2AC6\u0338" },
+  "&ntgl;": { "codepoints": [8825], "characters": "\u2279" },
+  "&Ntilde;": { "codepoints": [209], "characters": "\u00D1" },
+  "&Ntilde": { "codepoints": [209], "characters": "\u00D1" },
+  "&ntilde;": { "codepoints": [241], "characters": "\u00F1" },
+  "&ntilde": { "codepoints": [241], "characters": "\u00F1" },
+  "&ntlg;": { "codepoints": [8824], "characters": "\u2278" },
+  "&ntriangleleft;": { "codepoints": [8938], "characters": "\u22EA" },
+  "&ntrianglelefteq;": { "codepoints": [8940], "characters": "\u22EC" },
+  "&ntriangleright;": { "codepoints": [8939], "characters": "\u22EB" },
+  "&ntrianglerighteq;": { "codepoints": [8941], "characters": "\u22ED" },
+  "&Nu;": { "codepoints": [925], "characters": "\u039D" },
+  "&nu;": { "codepoints": [957], "characters": "\u03BD" },
+  "&num;": { "codepoints": [35], "characters": "\u0023" },
+  "&numero;": { "codepoints": [8470], "characters": "\u2116" },
+  "&numsp;": { "codepoints": [8199], "characters": "\u2007" },
+  "&nvap;": { "codepoints": [8781, 8402], "characters": "\u224D\u20D2" },
+  "&nvdash;": { "codepoints": [8876], "characters": "\u22AC" },
+  "&nvDash;": { "codepoints": [8877], "characters": "\u22AD" },
+  "&nVdash;": { "codepoints": [8878], "characters": "\u22AE" },
+  "&nVDash;": { "codepoints": [8879], "characters": "\u22AF" },
+  "&nvge;": { "codepoints": [8805, 8402], "characters": "\u2265\u20D2" },
+  "&nvgt;": { "codepoints": [62, 8402], "characters": "\u003E\u20D2" },
+  "&nvHarr;": { "codepoints": [10500], "characters": "\u2904" },
+  "&nvinfin;": { "codepoints": [10718], "characters": "\u29DE" },
+  "&nvlArr;": { "codepoints": [10498], "characters": "\u2902" },
+  "&nvle;": { "codepoints": [8804, 8402], "characters": "\u2264\u20D2" },
+  "&nvlt;": { "codepoints": [60, 8402], "characters": "\u003C\u20D2" },
+  "&nvltrie;": { "codepoints": [8884, 8402], "characters": "\u22B4\u20D2" },
+  "&nvrArr;": { "codepoints": [10499], "characters": "\u2903" },
+  "&nvrtrie;": { "codepoints": [8885, 8402], "characters": "\u22B5\u20D2" },
+  "&nvsim;": { "codepoints": [8764, 8402], "characters": "\u223C\u20D2" },
+  "&nwarhk;": { "codepoints": [10531], "characters": "\u2923" },
+  "&nwarr;": { "codepoints": [8598], "characters": "\u2196" },
+  "&nwArr;": { "codepoints": [8662], "characters": "\u21D6" },
+  "&nwarrow;": { "codepoints": [8598], "characters": "\u2196" },
+  "&nwnear;": { "codepoints": [10535], "characters": "\u2927" },
+  "&Oacute;": { "codepoints": [211], "characters": "\u00D3" },
+  "&Oacute": { "codepoints": [211], "characters": "\u00D3" },
+  "&oacute;": { "codepoints": [243], "characters": "\u00F3" },
+  "&oacute": { "codepoints": [243], "characters": "\u00F3" },
+  "&oast;": { "codepoints": [8859], "characters": "\u229B" },
+  "&Ocirc;": { "codepoints": [212], "characters": "\u00D4" },
+  "&Ocirc": { "codepoints": [212], "characters": "\u00D4" },
+  "&ocirc;": { "codepoints": [244], "characters": "\u00F4" },
+  "&ocirc": { "codepoints": [244], "characters": "\u00F4" },
+  "&ocir;": { "codepoints": [8858], "characters": "\u229A" },
+  "&Ocy;": { "codepoints": [1054], "characters": "\u041E" },
+  "&ocy;": { "codepoints": [1086], "characters": "\u043E" },
+  "&odash;": { "codepoints": [8861], "characters": "\u229D" },
+  "&Odblac;": { "codepoints": [336], "characters": "\u0150" },
+  "&odblac;": { "codepoints": [337], "characters": "\u0151" },
+  "&odiv;": { "codepoints": [10808], "characters": "\u2A38" },
+  "&odot;": { "codepoints": [8857], "characters": "\u2299" },
+  "&odsold;": { "codepoints": [10684], "characters": "\u29BC" },
+  "&OElig;": { "codepoints": [338], "characters": "\u0152" },
+  "&oelig;": { "codepoints": [339], "characters": "\u0153" },
+  "&ofcir;": { "codepoints": [10687], "characters": "\u29BF" },
+  "&Ofr;": { "codepoints": [120082], "characters": "\uD835\uDD12" },
+  "&ofr;": { "codepoints": [120108], "characters": "\uD835\uDD2C" },
+  "&ogon;": { "codepoints": [731], "characters": "\u02DB" },
+  "&Ograve;": { "codepoints": [210], "characters": "\u00D2" },
+  "&Ograve": { "codepoints": [210], "characters": "\u00D2" },
+  "&ograve;": { "codepoints": [242], "characters": "\u00F2" },
+  "&ograve": { "codepoints": [242], "characters": "\u00F2" },
+  "&ogt;": { "codepoints": [10689], "characters": "\u29C1" },
+  "&ohbar;": { "codepoints": [10677], "characters": "\u29B5" },
+  "&ohm;": { "codepoints": [937], "characters": "\u03A9" },
+  "&oint;": { "codepoints": [8750], "characters": "\u222E" },
+  "&olarr;": { "codepoints": [8634], "characters": "\u21BA" },
+  "&olcir;": { "codepoints": [10686], "characters": "\u29BE" },
+  "&olcross;": { "codepoints": [10683], "characters": "\u29BB" },
+  "&oline;": { "codepoints": [8254], "characters": "\u203E" },
+  "&olt;": { "codepoints": [10688], "characters": "\u29C0" },
+  "&Omacr;": { "codepoints": [332], "characters": "\u014C" },
+  "&omacr;": { "codepoints": [333], "characters": "\u014D" },
+  "&Omega;": { "codepoints": [937], "characters": "\u03A9" },
+  "&omega;": { "codepoints": [969], "characters": "\u03C9" },
+  "&Omicron;": { "codepoints": [927], "characters": "\u039F" },
+  "&omicron;": { "codepoints": [959], "characters": "\u03BF" },
+  "&omid;": { "codepoints": [10678], "characters": "\u29B6" },
+  "&ominus;": { "codepoints": [8854], "characters": "\u2296" },
+  "&Oopf;": { "codepoints": [120134], "characters": "\uD835\uDD46" },
+  "&oopf;": { "codepoints": [120160], "characters": "\uD835\uDD60" },
+  "&opar;": { "codepoints": [10679], "characters": "\u29B7" },
+  "&OpenCurlyDoubleQuote;": { "codepoints": [8220], "characters": "\u201C" },
+  "&OpenCurlyQuote;": { "codepoints": [8216], "characters": "\u2018" },
+  "&operp;": { "codepoints": [10681], "characters": "\u29B9" },
+  "&oplus;": { "codepoints": [8853], "characters": "\u2295" },
+  "&orarr;": { "codepoints": [8635], "characters": "\u21BB" },
+  "&Or;": { "codepoints": [10836], "characters": "\u2A54" },
+  "&or;": { "codepoints": [8744], "characters": "\u2228" },
+  "&ord;": { "codepoints": [10845], "characters": "\u2A5D" },
+  "&order;": { "codepoints": [8500], "characters": "\u2134" },
+  "&orderof;": { "codepoints": [8500], "characters": "\u2134" },
+  "&ordf;": { "codepoints": [170], "characters": "\u00AA" },
+  "&ordf": { "codepoints": [170], "characters": "\u00AA" },
+  "&ordm;": { "codepoints": [186], "characters": "\u00BA" },
+  "&ordm": { "codepoints": [186], "characters": "\u00BA" },
+  "&origof;": { "codepoints": [8886], "characters": "\u22B6" },
+  "&oror;": { "codepoints": [10838], "characters": "\u2A56" },
+  "&orslope;": { "codepoints": [10839], "characters": "\u2A57" },
+  "&orv;": { "codepoints": [10843], "characters": "\u2A5B" },
+  "&oS;": { "codepoints": [9416], "characters": "\u24C8" },
+  "&Oscr;": { "codepoints": [119978], "characters": "\uD835\uDCAA" },
+  "&oscr;": { "codepoints": [8500], "characters": "\u2134" },
+  "&Oslash;": { "codepoints": [216], "characters": "\u00D8" },
+  "&Oslash": { "codepoints": [216], "characters": "\u00D8" },
+  "&oslash;": { "codepoints": [248], "characters": "\u00F8" },
+  "&oslash": { "codepoints": [248], "characters": "\u00F8" },
+  "&osol;": { "codepoints": [8856], "characters": "\u2298" },
+  "&Otilde;": { "codepoints": [213], "characters": "\u00D5" },
+  "&Otilde": { "codepoints": [213], "characters": "\u00D5" },
+  "&otilde;": { "codepoints": [245], "characters": "\u00F5" },
+  "&otilde": { "codepoints": [245], "characters": "\u00F5" },
+  "&otimesas;": { "codepoints": [10806], "characters": "\u2A36" },
+  "&Otimes;": { "codepoints": [10807], "characters": "\u2A37" },
+  "&otimes;": { "codepoints": [8855], "characters": "\u2297" },
+  "&Ouml;": { "codepoints": [214], "characters": "\u00D6" },
+  "&Ouml": { "codepoints": [214], "characters": "\u00D6" },
+  "&ouml;": { "codepoints": [246], "characters": "\u00F6" },
+  "&ouml": { "codepoints": [246], "characters": "\u00F6" },
+  "&ovbar;": { "codepoints": [9021], "characters": "\u233D" },
+  "&OverBar;": { "codepoints": [8254], "characters": "\u203E" },
+  "&OverBrace;": { "codepoints": [9182], "characters": "\u23DE" },
+  "&OverBracket;": { "codepoints": [9140], "characters": "\u23B4" },
+  "&OverParenthesis;": { "codepoints": [9180], "characters": "\u23DC" },
+  "&para;": { "codepoints": [182], "characters": "\u00B6" },
+  "&para": { "codepoints": [182], "characters": "\u00B6" },
+  "&parallel;": { "codepoints": [8741], "characters": "\u2225" },
+  "&par;": { "codepoints": [8741], "characters": "\u2225" },
+  "&parsim;": { "codepoints": [10995], "characters": "\u2AF3" },
+  "&parsl;": { "codepoints": [11005], "characters": "\u2AFD" },
+  "&part;": { "codepoints": [8706], "characters": "\u2202" },
+  "&PartialD;": { "codepoints": [8706], "characters": "\u2202" },
+  "&Pcy;": { "codepoints": [1055], "characters": "\u041F" },
+  "&pcy;": { "codepoints": [1087], "characters": "\u043F" },
+  "&percnt;": { "codepoints": [37], "characters": "\u0025" },
+  "&period;": { "codepoints": [46], "characters": "\u002E" },
+  "&permil;": { "codepoints": [8240], "characters": "\u2030" },
+  "&perp;": { "codepoints": [8869], "characters": "\u22A5" },
+  "&pertenk;": { "codepoints": [8241], "characters": "\u2031" },
+  "&Pfr;": { "codepoints": [120083], "characters": "\uD835\uDD13" },
+  "&pfr;": { "codepoints": [120109], "characters": "\uD835\uDD2D" },
+  "&Phi;": { "codepoints": [934], "characters": "\u03A6" },
+  "&phi;": { "codepoints": [966], "characters": "\u03C6" },
+  "&phiv;": { "codepoints": [981], "characters": "\u03D5" },
+  "&phmmat;": { "codepoints": [8499], "characters": "\u2133" },
+  "&phone;": { "codepoints": [9742], "characters": "\u260E" },
+  "&Pi;": { "codepoints": [928], "characters": "\u03A0" },
+  "&pi;": { "codepoints": [960], "characters": "\u03C0" },
+  "&pitchfork;": { "codepoints": [8916], "characters": "\u22D4" },
+  "&piv;": { "codepoints": [982], "characters": "\u03D6" },
+  "&planck;": { "codepoints": [8463], "characters": "\u210F" },
+  "&planckh;": { "codepoints": [8462], "characters": "\u210E" },
+  "&plankv;": { "codepoints": [8463], "characters": "\u210F" },
+  "&plusacir;": { "codepoints": [10787], "characters": "\u2A23" },
+  "&plusb;": { "codepoints": [8862], "characters": "\u229E" },
+  "&pluscir;": { "codepoints": [10786], "characters": "\u2A22" },
+  "&plus;": { "codepoints": [43], "characters": "\u002B" },
+  "&plusdo;": { "codepoints": [8724], "characters": "\u2214" },
+  "&plusdu;": { "codepoints": [10789], "characters": "\u2A25" },
+  "&pluse;": { "codepoints": [10866], "characters": "\u2A72" },
+  "&PlusMinus;": { "codepoints": [177], "characters": "\u00B1" },
+  "&plusmn;": { "codepoints": [177], "characters": "\u00B1" },
+  "&plusmn": { "codepoints": [177], "characters": "\u00B1" },
+  "&plussim;": { "codepoints": [10790], "characters": "\u2A26" },
+  "&plustwo;": { "codepoints": [10791], "characters": "\u2A27" },
+  "&pm;": { "codepoints": [177], "characters": "\u00B1" },
+  "&Poincareplane;": { "codepoints": [8460], "characters": "\u210C" },
+  "&pointint;": { "codepoints": [10773], "characters": "\u2A15" },
+  "&popf;": { "codepoints": [120161], "characters": "\uD835\uDD61" },
+  "&Popf;": { "codepoints": [8473], "characters": "\u2119" },
+  "&pound;": { "codepoints": [163], "characters": "\u00A3" },
+  "&pound": { "codepoints": [163], "characters": "\u00A3" },
+  "&prap;": { "codepoints": [10935], "characters": "\u2AB7" },
+  "&Pr;": { "codepoints": [10939], "characters": "\u2ABB" },
+  "&pr;": { "codepoints": [8826], "characters": "\u227A" },
+  "&prcue;": { "codepoints": [8828], "characters": "\u227C" },
+  "&precapprox;": { "codepoints": [10935], "characters": "\u2AB7" },
+  "&prec;": { "codepoints": [8826], "characters": "\u227A" },
+  "&preccurlyeq;": { "codepoints": [8828], "characters": "\u227C" },
+  "&Precedes;": { "codepoints": [8826], "characters": "\u227A" },
+  "&PrecedesEqual;": { "codepoints": [10927], "characters": "\u2AAF" },
+  "&PrecedesSlantEqual;": { "codepoints": [8828], "characters": "\u227C" },
+  "&PrecedesTilde;": { "codepoints": [8830], "characters": "\u227E" },
+  "&preceq;": { "codepoints": [10927], "characters": "\u2AAF" },
+  "&precnapprox;": { "codepoints": [10937], "characters": "\u2AB9" },
+  "&precneqq;": { "codepoints": [10933], "characters": "\u2AB5" },
+  "&precnsim;": { "codepoints": [8936], "characters": "\u22E8" },
+  "&pre;": { "codepoints": [10927], "characters": "\u2AAF" },
+  "&prE;": { "codepoints": [10931], "characters": "\u2AB3" },
+  "&precsim;": { "codepoints": [8830], "characters": "\u227E" },
+  "&prime;": { "codepoints": [8242], "characters": "\u2032" },
+  "&Prime;": { "codepoints": [8243], "characters": "\u2033" },
+  "&primes;": { "codepoints": [8473], "characters": "\u2119" },
+  "&prnap;": { "codepoints": [10937], "characters": "\u2AB9" },
+  "&prnE;": { "codepoints": [10933], "characters": "\u2AB5" },
+  "&prnsim;": { "codepoints": [8936], "characters": "\u22E8" },
+  "&prod;": { "codepoints": [8719], "characters": "\u220F" },
+  "&Product;": { "codepoints": [8719], "characters": "\u220F" },
+  "&profalar;": { "codepoints": [9006], "characters": "\u232E" },
+  "&profline;": { "codepoints": [8978], "characters": "\u2312" },
+  "&profsurf;": { "codepoints": [8979], "characters": "\u2313" },
+  "&prop;": { "codepoints": [8733], "characters": "\u221D" },
+  "&Proportional;": { "codepoints": [8733], "characters": "\u221D" },
+  "&Proportion;": { "codepoints": [8759], "characters": "\u2237" },
+  "&propto;": { "codepoints": [8733], "characters": "\u221D" },
+  "&prsim;": { "codepoints": [8830], "characters": "\u227E" },
+  "&prurel;": { "codepoints": [8880], "characters": "\u22B0" },
+  "&Pscr;": { "codepoints": [119979], "characters": "\uD835\uDCAB" },
+  "&pscr;": { "codepoints": [120005], "characters": "\uD835\uDCC5" },
+  "&Psi;": { "codepoints": [936], "characters": "\u03A8" },
+  "&psi;": { "codepoints": [968], "characters": "\u03C8" },
+  "&puncsp;": { "codepoints": [8200], "characters": "\u2008" },
+  "&Qfr;": { "codepoints": [120084], "characters": "\uD835\uDD14" },
+  "&qfr;": { "codepoints": [120110], "characters": "\uD835\uDD2E" },
+  "&qint;": { "codepoints": [10764], "characters": "\u2A0C" },
+  "&qopf;": { "codepoints": [120162], "characters": "\uD835\uDD62" },
+  "&Qopf;": { "codepoints": [8474], "characters": "\u211A" },
+  "&qprime;": { "codepoints": [8279], "characters": "\u2057" },
+  "&Qscr;": { "codepoints": [119980], "characters": "\uD835\uDCAC" },
+  "&qscr;": { "codepoints": [120006], "characters": "\uD835\uDCC6" },
+  "&quaternions;": { "codepoints": [8461], "characters": "\u210D" },
+  "&quatint;": { "codepoints": [10774], "characters": "\u2A16" },
+  "&quest;": { "codepoints": [63], "characters": "\u003F" },
+  "&questeq;": { "codepoints": [8799], "characters": "\u225F" },
+  "&quot;": { "codepoints": [34], "characters": "\u0022" },
+  "&quot": { "codepoints": [34], "characters": "\u0022" },
+  "&QUOT;": { "codepoints": [34], "characters": "\u0022" },
+  "&QUOT": { "codepoints": [34], "characters": "\u0022" },
+  "&rAarr;": { "codepoints": [8667], "characters": "\u21DB" },
+  "&race;": { "codepoints": [8765, 817], "characters": "\u223D\u0331" },
+  "&Racute;": { "codepoints": [340], "characters": "\u0154" },
+  "&racute;": { "codepoints": [341], "characters": "\u0155" },
+  "&radic;": { "codepoints": [8730], "characters": "\u221A" },
+  "&raemptyv;": { "codepoints": [10675], "characters": "\u29B3" },
+  "&rang;": { "codepoints": [10217], "characters": "\u27E9" },
+  "&Rang;": { "codepoints": [10219], "characters": "\u27EB" },
+  "&rangd;": { "codepoints": [10642], "characters": "\u2992" },
+  "&range;": { "codepoints": [10661], "characters": "\u29A5" },
+  "&rangle;": { "codepoints": [10217], "characters": "\u27E9" },
+  "&raquo;": { "codepoints": [187], "characters": "\u00BB" },
+  "&raquo": { "codepoints": [187], "characters": "\u00BB" },
+  "&rarrap;": { "codepoints": [10613], "characters": "\u2975" },
+  "&rarrb;": { "codepoints": [8677], "characters": "\u21E5" },
+  "&rarrbfs;": { "codepoints": [10528], "characters": "\u2920" },
+  "&rarrc;": { "codepoints": [10547], "characters": "\u2933" },
+  "&rarr;": { "codepoints": [8594], "characters": "\u2192" },
+  "&Rarr;": { "codepoints": [8608], "characters": "\u21A0" },
+  "&rArr;": { "codepoints": [8658], "characters": "\u21D2" },
+  "&rarrfs;": { "codepoints": [10526], "characters": "\u291E" },
+  "&rarrhk;": { "codepoints": [8618], "characters": "\u21AA" },
+  "&rarrlp;": { "codepoints": [8620], "characters": "\u21AC" },
+  "&rarrpl;": { "codepoints": [10565], "characters": "\u2945" },
+  "&rarrsim;": { "codepoints": [10612], "characters": "\u2974" },
+  "&Rarrtl;": { "codepoints": [10518], "characters": "\u2916" },
+  "&rarrtl;": { "codepoints": [8611], "characters": "\u21A3" },
+  "&rarrw;": { "codepoints": [8605], "characters": "\u219D" },
+  "&ratail;": { "codepoints": [10522], "characters": "\u291A" },
+  "&rAtail;": { "codepoints": [10524], "characters": "\u291C" },
+  "&ratio;": { "codepoints": [8758], "characters": "\u2236" },
+  "&rationals;": { "codepoints": [8474], "characters": "\u211A" },
+  "&rbarr;": { "codepoints": [10509], "characters": "\u290D" },
+  "&rBarr;": { "codepoints": [10511], "characters": "\u290F" },
+  "&RBarr;": { "codepoints": [10512], "characters": "\u2910" },
+  "&rbbrk;": { "codepoints": [10099], "characters": "\u2773" },
+  "&rbrace;": { "codepoints": [125], "characters": "\u007D" },
+  "&rbrack;": { "codepoints": [93], "characters": "\u005D" },
+  "&rbrke;": { "codepoints": [10636], "characters": "\u298C" },
+  "&rbrksld;": { "codepoints": [10638], "characters": "\u298E" },
+  "&rbrkslu;": { "codepoints": [10640], "characters": "\u2990" },
+  "&Rcaron;": { "codepoints": [344], "characters": "\u0158" },
+  "&rcaron;": { "codepoints": [345], "characters": "\u0159" },
+  "&Rcedil;": { "codepoints": [342], "characters": "\u0156" },
+  "&rcedil;": { "codepoints": [343], "characters": "\u0157" },
+  "&rceil;": { "codepoints": [8969], "characters": "\u2309" },
+  "&rcub;": { "codepoints": [125], "characters": "\u007D" },
+  "&Rcy;": { "codepoints": [1056], "characters": "\u0420" },
+  "&rcy;": { "codepoints": [1088], "characters": "\u0440" },
+  "&rdca;": { "codepoints": [10551], "characters": "\u2937" },
+  "&rdldhar;": { "codepoints": [10601], "characters": "\u2969" },
+  "&rdquo;": { "codepoints": [8221], "characters": "\u201D" },
+  "&rdquor;": { "codepoints": [8221], "characters": "\u201D" },
+  "&rdsh;": { "codepoints": [8627], "characters": "\u21B3" },
+  "&real;": { "codepoints": [8476], "characters": "\u211C" },
+  "&realine;": { "codepoints": [8475], "characters": "\u211B" },
+  "&realpart;": { "codepoints": [8476], "characters": "\u211C" },
+  "&reals;": { "codepoints": [8477], "characters": "\u211D" },
+  "&Re;": { "codepoints": [8476], "characters": "\u211C" },
+  "&rect;": { "codepoints": [9645], "characters": "\u25AD" },
+  "&reg;": { "codepoints": [174], "characters": "\u00AE" },
+  "&reg": { "codepoints": [174], "characters": "\u00AE" },
+  "&REG;": { "codepoints": [174], "characters": "\u00AE" },
+  "&REG": { "codepoints": [174], "characters": "\u00AE" },
+  "&ReverseElement;": { "codepoints": [8715], "characters": "\u220B" },
+  "&ReverseEquilibrium;": { "codepoints": [8651], "characters": "\u21CB" },
+  "&ReverseUpEquilibrium;": { "codepoints": [10607], "characters": "\u296F" },
+  "&rfisht;": { "codepoints": [10621], "characters": "\u297D" },
+  "&rfloor;": { "codepoints": [8971], "characters": "\u230B" },
+  "&rfr;": { "codepoints": [120111], "characters": "\uD835\uDD2F" },
+  "&Rfr;": { "codepoints": [8476], "characters": "\u211C" },
+  "&rHar;": { "codepoints": [10596], "characters": "\u2964" },
+  "&rhard;": { "codepoints": [8641], "characters": "\u21C1" },
+  "&rharu;": { "codepoints": [8640], "characters": "\u21C0" },
+  "&rharul;": { "codepoints": [10604], "characters": "\u296C" },
+  "&Rho;": { "codepoints": [929], "characters": "\u03A1" },
+  "&rho;": { "codepoints": [961], "characters": "\u03C1" },
+  "&rhov;": { "codepoints": [1009], "characters": "\u03F1" },
+  "&RightAngleBracket;": { "codepoints": [10217], "characters": "\u27E9" },
+  "&RightArrowBar;": { "codepoints": [8677], "characters": "\u21E5" },
+  "&rightarrow;": { "codepoints": [8594], "characters": "\u2192" },
+  "&RightArrow;": { "codepoints": [8594], "characters": "\u2192" },
+  "&Rightarrow;": { "codepoints": [8658], "characters": "\u21D2" },
+  "&RightArrowLeftArrow;": { "codepoints": [8644], "characters": "\u21C4" },
+  "&rightarrowtail;": { "codepoints": [8611], "characters": "\u21A3" },
+  "&RightCeiling;": { "codepoints": [8969], "characters": "\u2309" },
+  "&RightDoubleBracket;": { "codepoints": [10215], "characters": "\u27E7" },
+  "&RightDownTeeVector;": { "codepoints": [10589], "characters": "\u295D" },
+  "&RightDownVectorBar;": { "codepoints": [10581], "characters": "\u2955" },
+  "&RightDownVector;": { "codepoints": [8642], "characters": "\u21C2" },
+  "&RightFloor;": { "codepoints": [8971], "characters": "\u230B" },
+  "&rightharpoondown;": { "codepoints": [8641], "characters": "\u21C1" },
+  "&rightharpoonup;": { "codepoints": [8640], "characters": "\u21C0" },
+  "&rightleftarrows;": { "codepoints": [8644], "characters": "\u21C4" },
+  "&rightleftharpoons;": { "codepoints": [8652], "characters": "\u21CC" },
+  "&rightrightarrows;": { "codepoints": [8649], "characters": "\u21C9" },
+  "&rightsquigarrow;": { "codepoints": [8605], "characters": "\u219D" },
+  "&RightTeeArrow;": { "codepoints": [8614], "characters": "\u21A6" },
+  "&RightTee;": { "codepoints": [8866], "characters": "\u22A2" },
+  "&RightTeeVector;": { "codepoints": [10587], "characters": "\u295B" },
+  "&rightthreetimes;": { "codepoints": [8908], "characters": "\u22CC" },
+  "&RightTriangleBar;": { "codepoints": [10704], "characters": "\u29D0" },
+  "&RightTriangle;": { "codepoints": [8883], "characters": "\u22B3" },
+  "&RightTriangleEqual;": { "codepoints": [8885], "characters": "\u22B5" },
+  "&RightUpDownVector;": { "codepoints": [10575], "characters": "\u294F" },
+  "&RightUpTeeVector;": { "codepoints": [10588], "characters": "\u295C" },
+  "&RightUpVectorBar;": { "codepoints": [10580], "characters": "\u2954" },
+  "&RightUpVector;": { "codepoints": [8638], "characters": "\u21BE" },
+  "&RightVectorBar;": { "codepoints": [10579], "characters": "\u2953" },
+  "&RightVector;": { "codepoints": [8640], "characters": "\u21C0" },
+  "&ring;": { "codepoints": [730], "characters": "\u02DA" },
+  "&risingdotseq;": { "codepoints": [8787], "characters": "\u2253" },
+  "&rlarr;": { "codepoints": [8644], "characters": "\u21C4" },
+  "&rlhar;": { "codepoints": [8652], "characters": "\u21CC" },
+  "&rlm;": { "codepoints": [8207], "characters": "\u200F" },
+  "&rmoustache;": { "codepoints": [9137], "characters": "\u23B1" },
+  "&rmoust;": { "codepoints": [9137], "characters": "\u23B1" },
+  "&rnmid;": { "codepoints": [10990], "characters": "\u2AEE" },
+  "&roang;": { "codepoints": [10221], "characters": "\u27ED" },
+  "&roarr;": { "codepoints": [8702], "characters": "\u21FE" },
+  "&robrk;": { "codepoints": [10215], "characters": "\u27E7" },
+  "&ropar;": { "codepoints": [10630], "characters": "\u2986" },
+  "&ropf;": { "codepoints": [120163], "characters": "\uD835\uDD63" },
+  "&Ropf;": { "codepoints": [8477], "characters": "\u211D" },
+  "&roplus;": { "codepoints": [10798], "characters": "\u2A2E" },
+  "&rotimes;": { "codepoints": [10805], "characters": "\u2A35" },
+  "&RoundImplies;": { "codepoints": [10608], "characters": "\u2970" },
+  "&rpar;": { "codepoints": [41], "characters": "\u0029" },
+  "&rpargt;": { "codepoints": [10644], "characters": "\u2994" },
+  "&rppolint;": { "codepoints": [10770], "characters": "\u2A12" },
+  "&rrarr;": { "codepoints": [8649], "characters": "\u21C9" },
+  "&Rrightarrow;": { "codepoints": [8667], "characters": "\u21DB" },
+  "&rsaquo;": { "codepoints": [8250], "characters": "\u203A" },
+  "&rscr;": { "codepoints": [120007], "characters": "\uD835\uDCC7" },
+  "&Rscr;": { "codepoints": [8475], "characters": "\u211B" },
+  "&rsh;": { "codepoints": [8625], "characters": "\u21B1" },
+  "&Rsh;": { "codepoints": [8625], "characters": "\u21B1" },
+  "&rsqb;": { "codepoints": [93], "characters": "\u005D" },
+  "&rsquo;": { "codepoints": [8217], "characters": "\u2019" },
+  "&rsquor;": { "codepoints": [8217], "characters": "\u2019" },
+  "&rthree;": { "codepoints": [8908], "characters": "\u22CC" },
+  "&rtimes;": { "codepoints": [8906], "characters": "\u22CA" },
+  "&rtri;": { "codepoints": [9657], "characters": "\u25B9" },
+  "&rtrie;": { "codepoints": [8885], "characters": "\u22B5" },
+  "&rtrif;": { "codepoints": [9656], "characters": "\u25B8" },
+  "&rtriltri;": { "codepoints": [10702], "characters": "\u29CE" },
+  "&RuleDelayed;": { "codepoints": [10740], "characters": "\u29F4" },
+  "&ruluhar;": { "codepoints": [10600], "characters": "\u2968" },
+  "&rx;": { "codepoints": [8478], "characters": "\u211E" },
+  "&Sacute;": { "codepoints": [346], "characters": "\u015A" },
+  "&sacute;": { "codepoints": [347], "characters": "\u015B" },
+  "&sbquo;": { "codepoints": [8218], "characters": "\u201A" },
+  "&scap;": { "codepoints": [10936], "characters": "\u2AB8" },
+  "&Scaron;": { "codepoints": [352], "characters": "\u0160" },
+  "&scaron;": { "codepoints": [353], "characters": "\u0161" },
+  "&Sc;": { "codepoints": [10940], "characters": "\u2ABC" },
+  "&sc;": { "codepoints": [8827], "characters": "\u227B" },
+  "&sccue;": { "codepoints": [8829], "characters": "\u227D" },
+  "&sce;": { "codepoints": [10928], "characters": "\u2AB0" },
+  "&scE;": { "codepoints": [10932], "characters": "\u2AB4" },
+  "&Scedil;": { "codepoints": [350], "characters": "\u015E" },
+  "&scedil;": { "codepoints": [351], "characters": "\u015F" },
+  "&Scirc;": { "codepoints": [348], "characters": "\u015C" },
+  "&scirc;": { "codepoints": [349], "characters": "\u015D" },
+  "&scnap;": { "codepoints": [10938], "characters": "\u2ABA" },
+  "&scnE;": { "codepoints": [10934], "characters": "\u2AB6" },
+  "&scnsim;": { "codepoints": [8937], "characters": "\u22E9" },
+  "&scpolint;": { "codepoints": [10771], "characters": "\u2A13" },
+  "&scsim;": { "codepoints": [8831], "characters": "\u227F" },
+  "&Scy;": { "codepoints": [1057], "characters": "\u0421" },
+  "&scy;": { "codepoints": [1089], "characters": "\u0441" },
+  "&sdotb;": { "codepoints": [8865], "characters": "\u22A1" },
+  "&sdot;": { "codepoints": [8901], "characters": "\u22C5" },
+  "&sdote;": { "codepoints": [10854], "characters": "\u2A66" },
+  "&searhk;": { "codepoints": [10533], "characters": "\u2925" },
+  "&searr;": { "codepoints": [8600], "characters": "\u2198" },
+  "&seArr;": { "codepoints": [8664], "characters": "\u21D8" },
+  "&searrow;": { "codepoints": [8600], "characters": "\u2198" },
+  "&sect;": { "codepoints": [167], "characters": "\u00A7" },
+  "&sect": { "codepoints": [167], "characters": "\u00A7" },
+  "&semi;": { "codepoints": [59], "characters": "\u003B" },
+  "&seswar;": { "codepoints": [10537], "characters": "\u2929" },
+  "&setminus;": { "codepoints": [8726], "characters": "\u2216" },
+  "&setmn;": { "codepoints": [8726], "characters": "\u2216" },
+  "&sext;": { "codepoints": [10038], "characters": "\u2736" },
+  "&Sfr;": { "codepoints": [120086], "characters": "\uD835\uDD16" },
+  "&sfr;": { "codepoints": [120112], "characters": "\uD835\uDD30" },
+  "&sfrown;": { "codepoints": [8994], "characters": "\u2322" },
+  "&sharp;": { "codepoints": [9839], "characters": "\u266F" },
+  "&SHCHcy;": { "codepoints": [1065], "characters": "\u0429" },
+  "&shchcy;": { "codepoints": [1097], "characters": "\u0449" },
+  "&SHcy;": { "codepoints": [1064], "characters": "\u0428" },
+  "&shcy;": { "codepoints": [1096], "characters": "\u0448" },
+  "&ShortDownArrow;": { "codepoints": [8595], "characters": "\u2193" },
+  "&ShortLeftArrow;": { "codepoints": [8592], "characters": "\u2190" },
+  "&shortmid;": { "codepoints": [8739], "characters": "\u2223" },
+  "&shortparallel;": { "codepoints": [8741], "characters": "\u2225" },
+  "&ShortRightArrow;": { "codepoints": [8594], "characters": "\u2192" },
+  "&ShortUpArrow;": { "codepoints": [8593], "characters": "\u2191" },
+  "&shy;": { "codepoints": [173], "characters": "\u00AD" },
+  "&shy": { "codepoints": [173], "characters": "\u00AD" },
+  "&Sigma;": { "codepoints": [931], "characters": "\u03A3" },
+  "&sigma;": { "codepoints": [963], "characters": "\u03C3" },
+  "&sigmaf;": { "codepoints": [962], "characters": "\u03C2" },
+  "&sigmav;": { "codepoints": [962], "characters": "\u03C2" },
+  "&sim;": { "codepoints": [8764], "characters": "\u223C" },
+  "&simdot;": { "codepoints": [10858], "characters": "\u2A6A" },
+  "&sime;": { "codepoints": [8771], "characters": "\u2243" },
+  "&simeq;": { "codepoints": [8771], "characters": "\u2243" },
+  "&simg;": { "codepoints": [10910], "characters": "\u2A9E" },
+  "&simgE;": { "codepoints": [10912], "characters": "\u2AA0" },
+  "&siml;": { "codepoints": [10909], "characters": "\u2A9D" },
+  "&simlE;": { "codepoints": [10911], "characters": "\u2A9F" },
+  "&simne;": { "codepoints": [8774], "characters": "\u2246" },
+  "&simplus;": { "codepoints": [10788], "characters": "\u2A24" },
+  "&simrarr;": { "codepoints": [10610], "characters": "\u2972" },
+  "&slarr;": { "codepoints": [8592], "characters": "\u2190" },
+  "&SmallCircle;": { "codepoints": [8728], "characters": "\u2218" },
+  "&smallsetminus;": { "codepoints": [8726], "characters": "\u2216" },
+  "&smashp;": { "codepoints": [10803], "characters": "\u2A33" },
+  "&smeparsl;": { "codepoints": [10724], "characters": "\u29E4" },
+  "&smid;": { "codepoints": [8739], "characters": "\u2223" },
+  "&smile;": { "codepoints": [8995], "characters": "\u2323" },
+  "&smt;": { "codepoints": [10922], "characters": "\u2AAA" },
+  "&smte;": { "codepoints": [10924], "characters": "\u2AAC" },
+  "&smtes;": { "codepoints": [10924, 65024], "characters": "\u2AAC\uFE00" },
+  "&SOFTcy;": { "codepoints": [1068], "characters": "\u042C" },
+  "&softcy;": { "codepoints": [1100], "characters": "\u044C" },
+  "&solbar;": { "codepoints": [9023], "characters": "\u233F" },
+  "&solb;": { "codepoints": [10692], "characters": "\u29C4" },
+  "&sol;": { "codepoints": [47], "characters": "\u002F" },
+  "&Sopf;": { "codepoints": [120138], "characters": "\uD835\uDD4A" },
+  "&sopf;": { "codepoints": [120164], "characters": "\uD835\uDD64" },
+  "&spades;": { "codepoints": [9824], "characters": "\u2660" },
+  "&spadesuit;": { "codepoints": [9824], "characters": "\u2660" },
+  "&spar;": { "codepoints": [8741], "characters": "\u2225" },
+  "&sqcap;": { "codepoints": [8851], "characters": "\u2293" },
+  "&sqcaps;": { "codepoints": [8851, 65024], "characters": "\u2293\uFE00" },
+  "&sqcup;": { "codepoints": [8852], "characters": "\u2294" },
+  "&sqcups;": { "codepoints": [8852, 65024], "characters": "\u2294\uFE00" },
+  "&Sqrt;": { "codepoints": [8730], "characters": "\u221A" },
+  "&sqsub;": { "codepoints": [8847], "characters": "\u228F" },
+  "&sqsube;": { "codepoints": [8849], "characters": "\u2291" },
+  "&sqsubset;": { "codepoints": [8847], "characters": "\u228F" },
+  "&sqsubseteq;": { "codepoints": [8849], "characters": "\u2291" },
+  "&sqsup;": { "codepoints": [8848], "characters": "\u2290" },
+  "&sqsupe;": { "codepoints": [8850], "characters": "\u2292" },
+  "&sqsupset;": { "codepoints": [8848], "characters": "\u2290" },
+  "&sqsupseteq;": { "codepoints": [8850], "characters": "\u2292" },
+  "&square;": { "codepoints": [9633], "characters": "\u25A1" },
+  "&Square;": { "codepoints": [9633], "characters": "\u25A1" },
+  "&SquareIntersection;": { "codepoints": [8851], "characters": "\u2293" },
+  "&SquareSubset;": { "codepoints": [8847], "characters": "\u228F" },
+  "&SquareSubsetEqual;": { "codepoints": [8849], "characters": "\u2291" },
+  "&SquareSuperset;": { "codepoints": [8848], "characters": "\u2290" },
+  "&SquareSupersetEqual;": { "codepoints": [8850], "characters": "\u2292" },
+  "&SquareUnion;": { "codepoints": [8852], "characters": "\u2294" },
+  "&squarf;": { "codepoints": [9642], "characters": "\u25AA" },
+  "&squ;": { "codepoints": [9633], "characters": "\u25A1" },
+  "&squf;": { "codepoints": [9642], "characters": "\u25AA" },
+  "&srarr;": { "codepoints": [8594], "characters": "\u2192" },
+  "&Sscr;": { "codepoints": [119982], "characters": "\uD835\uDCAE" },
+  "&sscr;": { "codepoints": [120008], "characters": "\uD835\uDCC8" },
+  "&ssetmn;": { "codepoints": [8726], "characters": "\u2216" },
+  "&ssmile;": { "codepoints": [8995], "characters": "\u2323" },
+  "&sstarf;": { "codepoints": [8902], "characters": "\u22C6" },
+  "&Star;": { "codepoints": [8902], "characters": "\u22C6" },
+  "&star;": { "codepoints": [9734], "characters": "\u2606" },
+  "&starf;": { "codepoints": [9733], "characters": "\u2605" },
+  "&straightepsilon;": { "codepoints": [1013], "characters": "\u03F5" },
+  "&straightphi;": { "codepoints": [981], "characters": "\u03D5" },
+  "&strns;": { "codepoints": [175], "characters": "\u00AF" },
+  "&sub;": { "codepoints": [8834], "characters": "\u2282" },
+  "&Sub;": { "codepoints": [8912], "characters": "\u22D0" },
+  "&subdot;": { "codepoints": [10941], "characters": "\u2ABD" },
+  "&subE;": { "codepoints": [10949], "characters": "\u2AC5" },
+  "&sube;": { "codepoints": [8838], "characters": "\u2286" },
+  "&subedot;": { "codepoints": [10947], "characters": "\u2AC3" },
+  "&submult;": { "codepoints": [10945], "characters": "\u2AC1" },
+  "&subnE;": { "codepoints": [10955], "characters": "\u2ACB" },
+  "&subne;": { "codepoints": [8842], "characters": "\u228A" },
+  "&subplus;": { "codepoints": [10943], "characters": "\u2ABF" },
+  "&subrarr;": { "codepoints": [10617], "characters": "\u2979" },
+  "&subset;": { "codepoints": [8834], "characters": "\u2282" },
+  "&Subset;": { "codepoints": [8912], "characters": "\u22D0" },
+  "&subseteq;": { "codepoints": [8838], "characters": "\u2286" },
+  "&subseteqq;": { "codepoints": [10949], "characters": "\u2AC5" },
+  "&SubsetEqual;": { "codepoints": [8838], "characters": "\u2286" },
+  "&subsetneq;": { "codepoints": [8842], "characters": "\u228A" },
+  "&subsetneqq;": { "codepoints": [10955], "characters": "\u2ACB" },
+  "&subsim;": { "codepoints": [10951], "characters": "\u2AC7" },
+  "&subsub;": { "codepoints": [10965], "characters": "\u2AD5" },
+  "&subsup;": { "codepoints": [10963], "characters": "\u2AD3" },
+  "&succapprox;": { "codepoints": [10936], "characters": "\u2AB8" },
+  "&succ;": { "codepoints": [8827], "characters": "\u227B" },
+  "&succcurlyeq;": { "codepoints": [8829], "characters": "\u227D" },
+  "&Succeeds;": { "codepoints": [8827], "characters": "\u227B" },
+  "&SucceedsEqual;": { "codepoints": [10928], "characters": "\u2AB0" },
+  "&SucceedsSlantEqual;": { "codepoints": [8829], "characters": "\u227D" },
+  "&SucceedsTilde;": { "codepoints": [8831], "characters": "\u227F" },
+  "&succeq;": { "codepoints": [10928], "characters": "\u2AB0" },
+  "&succnapprox;": { "codepoints": [10938], "characters": "\u2ABA" },
+  "&succneqq;": { "codepoints": [10934], "characters": "\u2AB6" },
+  "&succnsim;": { "codepoints": [8937], "characters": "\u22E9" },
+  "&succsim;": { "codepoints": [8831], "characters": "\u227F" },
+  "&SuchThat;": { "codepoints": [8715], "characters": "\u220B" },
+  "&sum;": { "codepoints": [8721], "characters": "\u2211" },
+  "&Sum;": { "codepoints": [8721], "characters": "\u2211" },
+  "&sung;": { "codepoints": [9834], "characters": "\u266A" },
+  "&sup1;": { "codepoints": [185], "characters": "\u00B9" },
+  "&sup1": { "codepoints": [185], "characters": "\u00B9" },
+  "&sup2;": { "codepoints": [178], "characters": "\u00B2" },
+  "&sup2": { "codepoints": [178], "characters": "\u00B2" },
+  "&sup3;": { "codepoints": [179], "characters": "\u00B3" },
+  "&sup3": { "codepoints": [179], "characters": "\u00B3" },
+  "&sup;": { "codepoints": [8835], "characters": "\u2283" },
+  "&Sup;": { "codepoints": [8913], "characters": "\u22D1" },
+  "&supdot;": { "codepoints": [10942], "characters": "\u2ABE" },
+  "&supdsub;": { "codepoints": [10968], "characters": "\u2AD8" },
+  "&supE;": { "codepoints": [10950], "characters": "\u2AC6" },
+  "&supe;": { "codepoints": [8839], "characters": "\u2287" },
+  "&supedot;": { "codepoints": [10948], "characters": "\u2AC4" },
+  "&Superset;": { "codepoints": [8835], "characters": "\u2283" },
+  "&SupersetEqual;": { "codepoints": [8839], "characters": "\u2287" },
+  "&suphsol;": { "codepoints": [10185], "characters": "\u27C9" },
+  "&suphsub;": { "codepoints": [10967], "characters": "\u2AD7" },
+  "&suplarr;": { "codepoints": [10619], "characters": "\u297B" },
+  "&supmult;": { "codepoints": [10946], "characters": "\u2AC2" },
+  "&supnE;": { "codepoints": [10956], "characters": "\u2ACC" },
+  "&supne;": { "codepoints": [8843], "characters": "\u228B" },
+  "&supplus;": { "codepoints": [10944], "characters": "\u2AC0" },
+  "&supset;": { "codepoints": [8835], "characters": "\u2283" },
+  "&Supset;": { "codepoints": [8913], "characters": "\u22D1" },
+  "&supseteq;": { "codepoints": [8839], "characters": "\u2287" },
+  "&supseteqq;": { "codepoints": [10950], "characters": "\u2AC6" },
+  "&supsetneq;": { "codepoints": [8843], "characters": "\u228B" },
+  "&supsetneqq;": { "codepoints": [10956], "characters": "\u2ACC" },
+  "&supsim;": { "codepoints": [10952], "characters": "\u2AC8" },
+  "&supsub;": { "codepoints": [10964], "characters": "\u2AD4" },
+  "&supsup;": { "codepoints": [10966], "characters": "\u2AD6" },
+  "&swarhk;": { "codepoints": [10534], "characters": "\u2926" },
+  "&swarr;": { "codepoints": [8601], "characters": "\u2199" },
+  "&swArr;": { "codepoints": [8665], "characters": "\u21D9" },
+  "&swarrow;": { "codepoints": [8601], "characters": "\u2199" },
+  "&swnwar;": { "codepoints": [10538], "characters": "\u292A" },
+  "&szlig;": { "codepoints": [223], "characters": "\u00DF" },
+  "&szlig": { "codepoints": [223], "characters": "\u00DF" },
+  "&Tab;": { "codepoints": [9], "characters": "\u0009" },
+  "&target;": { "codepoints": [8982], "characters": "\u2316" },
+  "&Tau;": { "codepoints": [932], "characters": "\u03A4" },
+  "&tau;": { "codepoints": [964], "characters": "\u03C4" },
+  "&tbrk;": { "codepoints": [9140], "characters": "\u23B4" },
+  "&Tcaron;": { "codepoints": [356], "characters": "\u0164" },
+  "&tcaron;": { "codepoints": [357], "characters": "\u0165" },
+  "&Tcedil;": { "codepoints": [354], "characters": "\u0162" },
+  "&tcedil;": { "codepoints": [355], "characters": "\u0163" },
+  "&Tcy;": { "codepoints": [1058], "characters": "\u0422" },
+  "&tcy;": { "codepoints": [1090], "characters": "\u0442" },
+  "&tdot;": { "codepoints": [8411], "characters": "\u20DB" },
+  "&telrec;": { "codepoints": [8981], "characters": "\u2315" },
+  "&Tfr;": { "codepoints": [120087], "characters": "\uD835\uDD17" },
+  "&tfr;": { "codepoints": [120113], "characters": "\uD835\uDD31" },
+  "&there4;": { "codepoints": [8756], "characters": "\u2234" },
+  "&therefore;": { "codepoints": [8756], "characters": "\u2234" },
+  "&Therefore;": { "codepoints": [8756], "characters": "\u2234" },
+  "&Theta;": { "codepoints": [920], "characters": "\u0398" },
+  "&theta;": { "codepoints": [952], "characters": "\u03B8" },
+  "&thetasym;": { "codepoints": [977], "characters": "\u03D1" },
+  "&thetav;": { "codepoints": [977], "characters": "\u03D1" },
+  "&thickapprox;": { "codepoints": [8776], "characters": "\u2248" },
+  "&thicksim;": { "codepoints": [8764], "characters": "\u223C" },
+  "&ThickSpace;": { "codepoints": [8287, 8202], "characters": "\u205F\u200A" },
+  "&ThinSpace;": { "codepoints": [8201], "characters": "\u2009" },
+  "&thinsp;": { "codepoints": [8201], "characters": "\u2009" },
+  "&thkap;": { "codepoints": [8776], "characters": "\u2248" },
+  "&thksim;": { "codepoints": [8764], "characters": "\u223C" },
+  "&THORN;": { "codepoints": [222], "characters": "\u00DE" },
+  "&THORN": { "codepoints": [222], "characters": "\u00DE" },
+  "&thorn;": { "codepoints": [254], "characters": "\u00FE" },
+  "&thorn": { "codepoints": [254], "characters": "\u00FE" },
+  "&tilde;": { "codepoints": [732], "characters": "\u02DC" },
+  "&Tilde;": { "codepoints": [8764], "characters": "\u223C" },
+  "&TildeEqual;": { "codepoints": [8771], "characters": "\u2243" },
+  "&TildeFullEqual;": { "codepoints": [8773], "characters": "\u2245" },
+  "&TildeTilde;": { "codepoints": [8776], "characters": "\u2248" },
+  "&timesbar;": { "codepoints": [10801], "characters": "\u2A31" },
+  "&timesb;": { "codepoints": [8864], "characters": "\u22A0" },
+  "&times;": { "codepoints": [215], "characters": "\u00D7" },
+  "&times": { "codepoints": [215], "characters": "\u00D7" },
+  "&timesd;": { "codepoints": [10800], "characters": "\u2A30" },
+  "&tint;": { "codepoints": [8749], "characters": "\u222D" },
+  "&toea;": { "codepoints": [10536], "characters": "\u2928" },
+  "&topbot;": { "codepoints": [9014], "characters": "\u2336" },
+  "&topcir;": { "codepoints": [10993], "characters": "\u2AF1" },
+  "&top;": { "codepoints": [8868], "characters": "\u22A4" },
+  "&Topf;": { "codepoints": [120139], "characters": "\uD835\uDD4B" },
+  "&topf;": { "codepoints": [120165], "characters": "\uD835\uDD65" },
+  "&topfork;": { "codepoints": [10970], "characters": "\u2ADA" },
+  "&tosa;": { "codepoints": [10537], "characters": "\u2929" },
+  "&tprime;": { "codepoints": [8244], "characters": "\u2034" },
+  "&trade;": { "codepoints": [8482], "characters": "\u2122" },
+  "&TRADE;": { "codepoints": [8482], "characters": "\u2122" },
+  "&triangle;": { "codepoints": [9653], "characters": "\u25B5" },
+  "&triangledown;": { "codepoints": [9663], "characters": "\u25BF" },
+  "&triangleleft;": { "codepoints": [9667], "characters": "\u25C3" },
+  "&trianglelefteq;": { "codepoints": [8884], "characters": "\u22B4" },
+  "&triangleq;": { "codepoints": [8796], "characters": "\u225C" },
+  "&triangleright;": { "codepoints": [9657], "characters": "\u25B9" },
+  "&trianglerighteq;": { "codepoints": [8885], "characters": "\u22B5" },
+  "&tridot;": { "codepoints": [9708], "characters": "\u25EC" },
+  "&trie;": { "codepoints": [8796], "characters": "\u225C" },
+  "&triminus;": { "codepoints": [10810], "characters": "\u2A3A" },
+  "&TripleDot;": { "codepoints": [8411], "characters": "\u20DB" },
+  "&triplus;": { "codepoints": [10809], "characters": "\u2A39" },
+  "&trisb;": { "codepoints": [10701], "characters": "\u29CD" },
+  "&tritime;": { "codepoints": [10811], "characters": "\u2A3B" },
+  "&trpezium;": { "codepoints": [9186], "characters": "\u23E2" },
+  "&Tscr;": { "codepoints": [119983], "characters": "\uD835\uDCAF" },
+  "&tscr;": { "codepoints": [120009], "characters": "\uD835\uDCC9" },
+  "&TScy;": { "codepoints": [1062], "characters": "\u0426" },
+  "&tscy;": { "codepoints": [1094], "characters": "\u0446" },
+  "&TSHcy;": { "codepoints": [1035], "characters": "\u040B" },
+  "&tshcy;": { "codepoints": [1115], "characters": "\u045B" },
+  "&Tstrok;": { "codepoints": [358], "characters": "\u0166" },
+  "&tstrok;": { "codepoints": [359], "characters": "\u0167" },
+  "&twixt;": { "codepoints": [8812], "characters": "\u226C" },
+  "&twoheadleftarrow;": { "codepoints": [8606], "characters": "\u219E" },
+  "&twoheadrightarrow;": { "codepoints": [8608], "characters": "\u21A0" },
+  "&Uacute;": { "codepoints": [218], "characters": "\u00DA" },
+  "&Uacute": { "codepoints": [218], "characters": "\u00DA" },
+  "&uacute;": { "codepoints": [250], "characters": "\u00FA" },
+  "&uacute": { "codepoints": [250], "characters": "\u00FA" },
+  "&uarr;": { "codepoints": [8593], "characters": "\u2191" },
+  "&Uarr;": { "codepoints": [8607], "characters": "\u219F" },
+  "&uArr;": { "codepoints": [8657], "characters": "\u21D1" },
+  "&Uarrocir;": { "codepoints": [10569], "characters": "\u2949" },
+  "&Ubrcy;": { "codepoints": [1038], "characters": "\u040E" },
+  "&ubrcy;": { "codepoints": [1118], "characters": "\u045E" },
+  "&Ubreve;": { "codepoints": [364], "characters": "\u016C" },
+  "&ubreve;": { "codepoints": [365], "characters": "\u016D" },
+  "&Ucirc;": { "codepoints": [219], "characters": "\u00DB" },
+  "&Ucirc": { "codepoints": [219], "characters": "\u00DB" },
+  "&ucirc;": { "codepoints": [251], "characters": "\u00FB" },
+  "&ucirc": { "codepoints": [251], "characters": "\u00FB" },
+  "&Ucy;": { "codepoints": [1059], "characters": "\u0423" },
+  "&ucy;": { "codepoints": [1091], "characters": "\u0443" },
+  "&udarr;": { "codepoints": [8645], "characters": "\u21C5" },
+  "&Udblac;": { "codepoints": [368], "characters": "\u0170" },
+  "&udblac;": { "codepoints": [369], "characters": "\u0171" },
+  "&udhar;": { "codepoints": [10606], "characters": "\u296E" },
+  "&ufisht;": { "codepoints": [10622], "characters": "\u297E" },
+  "&Ufr;": { "codepoints": [120088], "characters": "\uD835\uDD18" },
+  "&ufr;": { "codepoints": [120114], "characters": "\uD835\uDD32" },
+  "&Ugrave;": { "codepoints": [217], "characters": "\u00D9" },
+  "&Ugrave": { "codepoints": [217], "characters": "\u00D9" },
+  "&ugrave;": { "codepoints": [249], "characters": "\u00F9" },
+  "&ugrave": { "codepoints": [249], "characters": "\u00F9" },
+  "&uHar;": { "codepoints": [10595], "characters": "\u2963" },
+  "&uharl;": { "codepoints": [8639], "characters": "\u21BF" },
+  "&uharr;": { "codepoints": [8638], "characters": "\u21BE" },
+  "&uhblk;": { "codepoints": [9600], "characters": "\u2580" },
+  "&ulcorn;": { "codepoints": [8988], "characters": "\u231C" },
+  "&ulcorner;": { "codepoints": [8988], "characters": "\u231C" },
+  "&ulcrop;": { "codepoints": [8975], "characters": "\u230F" },
+  "&ultri;": { "codepoints": [9720], "characters": "\u25F8" },
+  "&Umacr;": { "codepoints": [362], "characters": "\u016A" },
+  "&umacr;": { "codepoints": [363], "characters": "\u016B" },
+  "&uml;": { "codepoints": [168], "characters": "\u00A8" },
+  "&uml": { "codepoints": [168], "characters": "\u00A8" },
+  "&UnderBar;": { "codepoints": [95], "characters": "\u005F" },
+  "&UnderBrace;": { "codepoints": [9183], "characters": "\u23DF" },
+  "&UnderBracket;": { "codepoints": [9141], "characters": "\u23B5" },
+  "&UnderParenthesis;": { "codepoints": [9181], "characters": "\u23DD" },
+  "&Union;": { "codepoints": [8899], "characters": "\u22C3" },
+  "&UnionPlus;": { "codepoints": [8846], "characters": "\u228E" },
+  "&Uogon;": { "codepoints": [370], "characters": "\u0172" },
+  "&uogon;": { "codepoints": [371], "characters": "\u0173" },
+  "&Uopf;": { "codepoints": [120140], "characters": "\uD835\uDD4C" },
+  "&uopf;": { "codepoints": [120166], "characters": "\uD835\uDD66" },
+  "&UpArrowBar;": { "codepoints": [10514], "characters": "\u2912" },
+  "&uparrow;": { "codepoints": [8593], "characters": "\u2191" },
+  "&UpArrow;": { "codepoints": [8593], "characters": "\u2191" },
+  "&Uparrow;": { "codepoints": [8657], "characters": "\u21D1" },
+  "&UpArrowDownArrow;": { "codepoints": [8645], "characters": "\u21C5" },
+  "&updownarrow;": { "codepoints": [8597], "characters": "\u2195" },
+  "&UpDownArrow;": { "codepoints": [8597], "characters": "\u2195" },
+  "&Updownarrow;": { "codepoints": [8661], "characters": "\u21D5" },
+  "&UpEquilibrium;": { "codepoints": [10606], "characters": "\u296E" },
+  "&upharpoonleft;": { "codepoints": [8639], "characters": "\u21BF" },
+  "&upharpoonright;": { "codepoints": [8638], "characters": "\u21BE" },
+  "&uplus;": { "codepoints": [8846], "characters": "\u228E" },
+  "&UpperLeftArrow;": { "codepoints": [8598], "characters": "\u2196" },
+  "&UpperRightArrow;": { "codepoints": [8599], "characters": "\u2197" },
+  "&upsi;": { "codepoints": [965], "characters": "\u03C5" },
+  "&Upsi;": { "codepoints": [978], "characters": "\u03D2" },
+  "&upsih;": { "codepoints": [978], "characters": "\u03D2" },
+  "&Upsilon;": { "codepoints": [933], "characters": "\u03A5" },
+  "&upsilon;": { "codepoints": [965], "characters": "\u03C5" },
+  "&UpTeeArrow;": { "codepoints": [8613], "characters": "\u21A5" },
+  "&UpTee;": { "codepoints": [8869], "characters": "\u22A5" },
+  "&upuparrows;": { "codepoints": [8648], "characters": "\u21C8" },
+  "&urcorn;": { "codepoints": [8989], "characters": "\u231D" },
+  "&urcorner;": { "codepoints": [8989], "characters": "\u231D" },
+  "&urcrop;": { "codepoints": [8974], "characters": "\u230E" },
+  "&Uring;": { "codepoints": [366], "characters": "\u016E" },
+  "&uring;": { "codepoints": [367], "characters": "\u016F" },
+  "&urtri;": { "codepoints": [9721], "characters": "\u25F9" },
+  "&Uscr;": { "codepoints": [119984], "characters": "\uD835\uDCB0" },
+  "&uscr;": { "codepoints": [120010], "characters": "\uD835\uDCCA" },
+  "&utdot;": { "codepoints": [8944], "characters": "\u22F0" },
+  "&Utilde;": { "codepoints": [360], "characters": "\u0168" },
+  "&utilde;": { "codepoints": [361], "characters": "\u0169" },
+  "&utri;": { "codepoints": [9653], "characters": "\u25B5" },
+  "&utrif;": { "codepoints": [9652], "characters": "\u25B4" },
+  "&uuarr;": { "codepoints": [8648], "characters": "\u21C8" },
+  "&Uuml;": { "codepoints": [220], "characters": "\u00DC" },
+  "&Uuml": { "codepoints": [220], "characters": "\u00DC" },
+  "&uuml;": { "codepoints": [252], "characters": "\u00FC" },
+  "&uuml": { "codepoints": [252], "characters": "\u00FC" },
+  "&uwangle;": { "codepoints": [10663], "characters": "\u29A7" },
+  "&vangrt;": { "codepoints": [10652], "characters": "\u299C" },
+  "&varepsilon;": { "codepoints": [1013], "characters": "\u03F5" },
+  "&varkappa;": { "codepoints": [1008], "characters": "\u03F0" },
+  "&varnothing;": { "codepoints": [8709], "characters": "\u2205" },
+  "&varphi;": { "codepoints": [981], "characters": "\u03D5" },
+  "&varpi;": { "codepoints": [982], "characters": "\u03D6" },
+  "&varpropto;": { "codepoints": [8733], "characters": "\u221D" },
+  "&varr;": { "codepoints": [8597], "characters": "\u2195" },
+  "&vArr;": { "codepoints": [8661], "characters": "\u21D5" },
+  "&varrho;": { "codepoints": [1009], "characters": "\u03F1" },
+  "&varsigma;": { "codepoints": [962], "characters": "\u03C2" },
+  "&varsubsetneq;": { "codepoints": [8842, 65024], "characters": "\u228A\uFE00" },
+  "&varsubsetneqq;": { "codepoints": [10955, 65024], "characters": "\u2ACB\uFE00" },
+  "&varsupsetneq;": { "codepoints": [8843, 65024], "characters": "\u228B\uFE00" },
+  "&varsupsetneqq;": { "codepoints": [10956, 65024], "characters": "\u2ACC\uFE00" },
+  "&vartheta;": { "codepoints": [977], "characters": "\u03D1" },
+  "&vartriangleleft;": { "codepoints": [8882], "characters": "\u22B2" },
+  "&vartriangleright;": { "codepoints": [8883], "characters": "\u22B3" },
+  "&vBar;": { "codepoints": [10984], "characters": "\u2AE8" },
+  "&Vbar;": { "codepoints": [10987], "characters": "\u2AEB" },
+  "&vBarv;": { "codepoints": [10985], "characters": "\u2AE9" },
+  "&Vcy;": { "codepoints": [1042], "characters": "\u0412" },
+  "&vcy;": { "codepoints": [1074], "characters": "\u0432" },
+  "&vdash;": { "codepoints": [8866], "characters": "\u22A2" },
+  "&vDash;": { "codepoints": [8872], "characters": "\u22A8" },
+  "&Vdash;": { "codepoints": [8873], "characters": "\u22A9" },
+  "&VDash;": { "codepoints": [8875], "characters": "\u22AB" },
+  "&Vdashl;": { "codepoints": [10982], "characters": "\u2AE6" },
+  "&veebar;": { "codepoints": [8891], "characters": "\u22BB" },
+  "&vee;": { "codepoints": [8744], "characters": "\u2228" },
+  "&Vee;": { "codepoints": [8897], "characters": "\u22C1" },
+  "&veeeq;": { "codepoints": [8794], "characters": "\u225A" },
+  "&vellip;": { "codepoints": [8942], "characters": "\u22EE" },
+  "&verbar;": { "codepoints": [124], "characters": "\u007C" },
+  "&Verbar;": { "codepoints": [8214], "characters": "\u2016" },
+  "&vert;": { "codepoints": [124], "characters": "\u007C" },
+  "&Vert;": { "codepoints": [8214], "characters": "\u2016" },
+  "&VerticalBar;": { "codepoints": [8739], "characters": "\u2223" },
+  "&VerticalLine;": { "codepoints": [124], "characters": "\u007C" },
+  "&VerticalSeparator;": { "codepoints": [10072], "characters": "\u2758" },
+  "&VerticalTilde;": { "codepoints": [8768], "characters": "\u2240" },
+  "&VeryThinSpace;": { "codepoints": [8202], "characters": "\u200A" },
+  "&Vfr;": { "codepoints": [120089], "characters": "\uD835\uDD19" },
+  "&vfr;": { "codepoints": [120115], "characters": "\uD835\uDD33" },
+  "&vltri;": { "codepoints": [8882], "characters": "\u22B2" },
+  "&vnsub;": { "codepoints": [8834, 8402], "characters": "\u2282\u20D2" },
+  "&vnsup;": { "codepoints": [8835, 8402], "characters": "\u2283\u20D2" },
+  "&Vopf;": { "codepoints": [120141], "characters": "\uD835\uDD4D" },
+  "&vopf;": { "codepoints": [120167], "characters": "\uD835\uDD67" },
+  "&vprop;": { "codepoints": [8733], "characters": "\u221D" },
+  "&vrtri;": { "codepoints": [8883], "characters": "\u22B3" },
+  "&Vscr;": { "codepoints": [119985], "characters": "\uD835\uDCB1" },
+  "&vscr;": { "codepoints": [120011], "characters": "\uD835\uDCCB" },
+  "&vsubnE;": { "codepoints": [10955, 65024], "characters": "\u2ACB\uFE00" },
+  "&vsubne;": { "codepoints": [8842, 65024], "characters": "\u228A\uFE00" },
+  "&vsupnE;": { "codepoints": [10956, 65024], "characters": "\u2ACC\uFE00" },
+  "&vsupne;": { "codepoints": [8843, 65024], "characters": "\u228B\uFE00" },
+  "&Vvdash;": { "codepoints": [8874], "characters": "\u22AA" },
+  "&vzigzag;": { "codepoints": [10650], "characters": "\u299A" },
+  "&Wcirc;": { "codepoints": [372], "characters": "\u0174" },
+  "&wcirc;": { "codepoints": [373], "characters": "\u0175" },
+  "&wedbar;": { "codepoints": [10847], "characters": "\u2A5F" },
+  "&wedge;": { "codepoints": [8743], "characters": "\u2227" },
+  "&Wedge;": { "codepoints": [8896], "characters": "\u22C0" },
+  "&wedgeq;": { "codepoints": [8793], "characters": "\u2259" },
+  "&weierp;": { "codepoints": [8472], "characters": "\u2118" },
+  "&Wfr;": { "codepoints": [120090], "characters": "\uD835\uDD1A" },
+  "&wfr;": { "codepoints": [120116], "characters": "\uD835\uDD34" },
+  "&Wopf;": { "codepoints": [120142], "characters": "\uD835\uDD4E" },
+  "&wopf;": { "codepoints": [120168], "characters": "\uD835\uDD68" },
+  "&wp;": { "codepoints": [8472], "characters": "\u2118" },
+  "&wr;": { "codepoints": [8768], "characters": "\u2240" },
+  "&wreath;": { "codepoints": [8768], "characters": "\u2240" },
+  "&Wscr;": { "codepoints": [119986], "characters": "\uD835\uDCB2" },
+  "&wscr;": { "codepoints": [120012], "characters": "\uD835\uDCCC" },
+  "&xcap;": { "codepoints": [8898], "characters": "\u22C2" },
+  "&xcirc;": { "codepoints": [9711], "characters": "\u25EF" },
+  "&xcup;": { "codepoints": [8899], "characters": "\u22C3" },
+  "&xdtri;": { "codepoints": [9661], "characters": "\u25BD" },
+  "&Xfr;": { "codepoints": [120091], "characters": "\uD835\uDD1B" },
+  "&xfr;": { "codepoints": [120117], "characters": "\uD835\uDD35" },
+  "&xharr;": { "codepoints": [10231], "characters": "\u27F7" },
+  "&xhArr;": { "codepoints": [10234], "characters": "\u27FA" },
+  "&Xi;": { "codepoints": [926], "characters": "\u039E" },
+  "&xi;": { "codepoints": [958], "characters": "\u03BE" },
+  "&xlarr;": { "codepoints": [10229], "characters": "\u27F5" },
+  "&xlArr;": { "codepoints": [10232], "characters": "\u27F8" },
+  "&xmap;": { "codepoints": [10236], "characters": "\u27FC" },
+  "&xnis;": { "codepoints": [8955], "characters": "\u22FB" },
+  "&xodot;": { "codepoints": [10752], "characters": "\u2A00" },
+  "&Xopf;": { "codepoints": [120143], "characters": "\uD835\uDD4F" },
+  "&xopf;": { "codepoints": [120169], "characters": "\uD835\uDD69" },
+  "&xoplus;": { "codepoints": [10753], "characters": "\u2A01" },
+  "&xotime;": { "codepoints": [10754], "characters": "\u2A02" },
+  "&xrarr;": { "codepoints": [10230], "characters": "\u27F6" },
+  "&xrArr;": { "codepoints": [10233], "characters": "\u27F9" },
+  "&Xscr;": { "codepoints": [119987], "characters": "\uD835\uDCB3" },
+  "&xscr;": { "codepoints": [120013], "characters": "\uD835\uDCCD" },
+  "&xsqcup;": { "codepoints": [10758], "characters": "\u2A06" },
+  "&xuplus;": { "codepoints": [10756], "characters": "\u2A04" },
+  "&xutri;": { "codepoints": [9651], "characters": "\u25B3" },
+  "&xvee;": { "codepoints": [8897], "characters": "\u22C1" },
+  "&xwedge;": { "codepoints": [8896], "characters": "\u22C0" },
+  "&Yacute;": { "codepoints": [221], "characters": "\u00DD" },
+  "&Yacute": { "codepoints": [221], "characters": "\u00DD" },
+  "&yacute;": { "codepoints": [253], "characters": "\u00FD" },
+  "&yacute": { "codepoints": [253], "characters": "\u00FD" },
+  "&YAcy;": { "codepoints": [1071], "characters": "\u042F" },
+  "&yacy;": { "codepoints": [1103], "characters": "\u044F" },
+  "&Ycirc;": { "codepoints": [374], "characters": "\u0176" },
+  "&ycirc;": { "codepoints": [375], "characters": "\u0177" },
+  "&Ycy;": { "codepoints": [1067], "characters": "\u042B" },
+  "&ycy;": { "codepoints": [1099], "characters": "\u044B" },
+  "&yen;": { "codepoints": [165], "characters": "\u00A5" },
+  "&yen": { "codepoints": [165], "characters": "\u00A5" },
+  "&Yfr;": { "codepoints": [120092], "characters": "\uD835\uDD1C" },
+  "&yfr;": { "codepoints": [120118], "characters": "\uD835\uDD36" },
+  "&YIcy;": { "codepoints": [1031], "characters": "\u0407" },
+  "&yicy;": { "codepoints": [1111], "characters": "\u0457" },
+  "&Yopf;": { "codepoints": [120144], "characters": "\uD835\uDD50" },
+  "&yopf;": { "codepoints": [120170], "characters": "\uD835\uDD6A" },
+  "&Yscr;": { "codepoints": [119988], "characters": "\uD835\uDCB4" },
+  "&yscr;": { "codepoints": [120014], "characters": "\uD835\uDCCE" },
+  "&YUcy;": { "codepoints": [1070], "characters": "\u042E" },
+  "&yucy;": { "codepoints": [1102], "characters": "\u044E" },
+  "&yuml;": { "codepoints": [255], "characters": "\u00FF" },
+  "&yuml": { "codepoints": [255], "characters": "\u00FF" },
+  "&Yuml;": { "codepoints": [376], "characters": "\u0178" },
+  "&Zacute;": { "codepoints": [377], "characters": "\u0179" },
+  "&zacute;": { "codepoints": [378], "characters": "\u017A" },
+  "&Zcaron;": { "codepoints": [381], "characters": "\u017D" },
+  "&zcaron;": { "codepoints": [382], "characters": "\u017E" },
+  "&Zcy;": { "codepoints": [1047], "characters": "\u0417" },
+  "&zcy;": { "codepoints": [1079], "characters": "\u0437" },
+  "&Zdot;": { "codepoints": [379], "characters": "\u017B" },
+  "&zdot;": { "codepoints": [380], "characters": "\u017C" },
+  "&zeetrf;": { "codepoints": [8488], "characters": "\u2128" },
+  "&ZeroWidthSpace;": { "codepoints": [8203], "characters": "\u200B" },
+  "&Zeta;": { "codepoints": [918], "characters": "\u0396" },
+  "&zeta;": { "codepoints": [950], "characters": "\u03B6" },
+  "&zfr;": { "codepoints": [120119], "characters": "\uD835\uDD37" },
+  "&Zfr;": { "codepoints": [8488], "characters": "\u2128" },
+  "&ZHcy;": { "codepoints": [1046], "characters": "\u0416" },
+  "&zhcy;": { "codepoints": [1078], "characters": "\u0436" },
+  "&zigrarr;": { "codepoints": [8669], "characters": "\u21DD" },
+  "&zopf;": { "codepoints": [120171], "characters": "\uD835\uDD6B" },
+  "&Zopf;": { "codepoints": [8484], "characters": "\u2124" },
+  "&Zscr;": { "codepoints": [119989], "characters": "\uD835\uDCB5" },
+  "&zscr;": { "codepoints": [120015], "characters": "\uD835\uDCCF" },
+  "&zwj;": { "codepoints": [8205], "characters": "\u200D" },
+  "&zwnj;": { "codepoints": [8204], "characters": "\u200C" }
+}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/common/form-submission.py b/third_party/WebKit/LayoutTests/imported/wpt/common/form-submission.py
index 78f96fe..4678754 100644
--- a/third_party/WebKit/LayoutTests/imported/wpt/common/form-submission.py
+++ b/third_party/WebKit/LayoutTests/imported/wpt/common/form-submission.py
@@ -1,17 +1,10 @@
 def main(request, response):
     if request.headers.get('Content-Type') == 'application/x-www-form-urlencoded':
-        if request.body == 'foo=bara':
-            return 'OK'
-        else:
-            return 'FAIL'
+        result = request.body == 'foo=bara'
     elif request.headers.get('Content-Type') == 'text/plain':
-        if request.body == 'qux=baz\r\n':
-            return 'OK'
-        else:
-            return 'FAIL'
+        result = request.body == 'qux=baz\r\n'
     else:
-        if request.POST.first('foo') == 'bar':
-            return 'OK'
-        else:
-            return 'FAIL'
+        result = request.POST.first('foo') == 'bar'
 
+    return ([("Content-Type", "text/plain")],
+            "OK" if result else "FAIL")
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/dom/nodes/Document-createEvent-expected.txt b/third_party/WebKit/LayoutTests/imported/wpt/dom/nodes/Document-createEvent-expected.txt
index 2b16dc3..157dd2d1 100644
--- a/third_party/WebKit/LayoutTests/imported/wpt/dom/nodes/Document-createEvent-expected.txt
+++ b/third_party/WebKit/LayoutTests/imported/wpt/dom/nodes/Document-createEvent-expected.txt
@@ -1,4 +1,3 @@
-CONSOLE WARNING: line 13: 'SVGZoomEvent' is deprecated and will be removed in M52, around July 2016. See https://www.chromestatus.com/features/5760883808534528 for more details.
 This is a testharness.js-based test.
 PASS AnimationEvent should be an alias for AnimationEvent. 
 PASS createEvent('AnimationEvent') should be initialized correctly. 
@@ -164,14 +163,14 @@
 FAIL createEvent('svgevents') should be initialized correctly. Cannot read property 'type' of undefined
 FAIL SVGEVENTS should be an alias for Event. Failed to execute 'createEvent' on 'Document': The provided event type ('SVGEVENTS') is invalid.
 FAIL createEvent('SVGEVENTS') should be initialized correctly. Cannot read property 'type' of undefined
-PASS SVGZoomEvent should be an alias for SVGZoomEvent. 
-PASS createEvent('SVGZoomEvent') should be initialized correctly. 
+FAIL SVGZoomEvent should be an alias for SVGZoomEvent. Failed to execute 'createEvent' on 'Document': The provided event type ('SVGZoomEvent') is invalid.
+FAIL createEvent('SVGZoomEvent') should be initialized correctly. Cannot read property 'type' of undefined
 FAIL svgzoomevent should be an alias for SVGZoomEvent. Failed to execute 'createEvent' on 'Document': The provided event type ('svgzoomevent') is invalid.
 FAIL createEvent('svgzoomevent') should be initialized correctly. Cannot read property 'type' of undefined
 FAIL SVGZOOMEVENT should be an alias for SVGZoomEvent. Failed to execute 'createEvent' on 'Document': The provided event type ('SVGZOOMEVENT') is invalid.
 FAIL createEvent('SVGZOOMEVENT') should be initialized correctly. Cannot read property 'type' of undefined
-PASS SVGZoomEvents should be an alias for SVGZoomEvent. 
-PASS createEvent('SVGZoomEvents') should be initialized correctly. 
+FAIL SVGZoomEvents should be an alias for SVGZoomEvent. Failed to execute 'createEvent' on 'Document': The provided event type ('SVGZoomEvents') is invalid.
+FAIL createEvent('SVGZoomEvents') should be initialized correctly. Cannot read property 'type' of undefined
 FAIL svgzoomevents should be an alias for SVGZoomEvent. Failed to execute 'createEvent' on 'Document': The provided event type ('svgzoomevents') is invalid.
 FAIL createEvent('svgzoomevents') should be initialized correctly. Cannot read property 'type' of undefined
 FAIL SVGZOOMEVENTS should be an alias for SVGZoomEvent. Failed to execute 'createEvent' on 'Document': The provided event type ('SVGZOOMEVENTS') is invalid.
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/document-metadata/the-link-element/document-without-browsing-context-expected.txt b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/document-metadata/the-link-element/document-without-browsing-context-expected.txt
new file mode 100644
index 0000000..782baefd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/document-metadata/the-link-element/document-without-browsing-context-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+FAIL Create a document, adopt the node assert_equals: expected "1" but got "def main(request, response):\n    try:\n        count = int(request.server.stash.take(request.GET[\"id\"]))\n    except:\n        count = 0\n    if \"count\" in request.GET:\n        return str(count)\n    request.server.stash.put(request.GET[\"id\"], str(count + 1))\n    return 'body { color: red }'\n"
+FAIL Create a stylesheet in innerHTML document assert_equals: expected "1" but got "def main(request, response):\n    try:\n        count = int(request.server.stash.take(request.GET[\"id\"]))\n    except:\n        count = 0\n    if \"count\" in request.GET:\n        return str(count)\n    request.server.stash.put(request.GET[\"id\"], str(count + 1))\n    return 'body { color: red }'\n"
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/document-metadata/the-link-element/document-without-browsing-context.html b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/document-metadata/the-link-element/document-without-browsing-context.html
new file mode 100644
index 0000000..127b253
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/document-metadata/the-link-element/document-without-browsing-context.html
@@ -0,0 +1,35 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Documents without browsing contexts should not load stylesheets</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
+<body>
+<script>
+  function count(id, t) {
+    var xhr = new XMLHttpRequest();
+    xhr.open('GET', 'stylesheet.py?count=1&id=' + id);
+    xhr.onload = t.step_func_done(function() {
+      assert_equals(xhr.responseText, "1");
+    });
+    xhr.onerror = t.unreached_func();
+    xhr.send();
+  }
+
+  async_test(function(t) {
+    var id = token();
+    var doc = (new DOMParser()).parseFromString('<link rel="stylesheet" href="stylesheet.py?id=' + id + '"></link>', 'text/html');
+    var link = doc.querySelector('link');
+    document.head.appendChild(link);
+    t.step_timeout(function() { count(id, t) }, 500);
+  }, 'Create a document, adopt the node');
+
+  async_test(function(t) {
+    var id = token();
+    var d = document.createElement('div');
+    document.body.appendChild(d);
+    d.innerHTML = '<link rel="stylesheet" href="stylesheet.py?id=' + id + '"></link>';
+    t.step_timeout(function() { count(id, t) }, 500);
+  }, 'Create a stylesheet in innerHTML document');
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/document-metadata/the-link-element/link-style-error-01.html b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/document-metadata/the-link-element/link-style-error-01.html
index ce35e03..0460846 100644
--- a/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/document-metadata/the-link-element/link-style-error-01.html
+++ b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/document-metadata/the-link-element/link-style-error-01.html
@@ -7,17 +7,32 @@
 <div id="log"></div>
 <div id="test">
 <script>
-//var t404 = async_test("Should get an error event for a 404 error.")
-//t404.step(function() {
-//  var elt = document.createElement("link");
-//  elt.onerror = t404.step_func(function() {
-//    assert_true(true, "Got error event for 404 error.")
-//    t404.done()
-//  })
-//  elt.rel = "stylesheet";
-//  elt.href = 404 error;
-//  document.getElementsByTagName("head")[0].appendChild(elt);
-//})
+var t404 = async_test("Should get an error event for a 404 error.")
+t404.step(function() {
+  var elt = document.createElement("link");
+  elt.onerror = t404.step_func(function() {
+    assert_true(true, "Got error event for 404 error.")
+    t404.step_timeout(function() { t404.done() }, 0);
+  })
+  elt.onload = t404.unreached_func("load event should not be fired");
+  elt.rel = "stylesheet";
+  elt.href = "nonexistent_stylesheet.css";
+  document.getElementsByTagName("head")[0].appendChild(elt);
+})
+
+var tUnsupported = async_test("Should get an error event for an unsupported URL.")
+tUnsupported.step(function() {
+  var elt = document.createElement("link");
+  elt.onerror = tUnsupported.step_func(function() {
+    assert_true(true, "Got error event for unsupported URL.")
+    tUnsupported.step_timeout(function() { tUnsupported.done() }, 0);
+  })
+  elt.onload = tUnsupported.unreached_func("load event should not be fired");
+  elt.rel = "stylesheet";
+  elt.href = "nonexistent:stylesheet.css";
+  document.getElementsByTagName("head")[0].appendChild(elt);
+})
+
 var tText = async_test("Should get an error event for a text/plain response.")
 tText.step(function() {
   var elt = document.createElement("link");
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/document-metadata/the-link-element/stylesheet.py b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/document-metadata/the-link-element/stylesheet.py
new file mode 100644
index 0000000..a312e9e8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/document-metadata/the-link-element/stylesheet.py
@@ -0,0 +1,9 @@
+def main(request, response):
+    try:
+        count = int(request.server.stash.take(request.GET["id"]))
+    except:
+        count = 0
+    if "count" in request.GET:
+        return str(count)
+    request.server.stash.put(request.GET["id"], str(count + 1))
+    return 'body { color: red }'
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/embedded-content/media-elements/interfaces/TextTrack/cues.html b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/embedded-content/media-elements/interfaces/TextTrack/cues.html
index 11d33b77..4b7808c9 100644
--- a/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/embedded-content/media-elements/interfaces/TextTrack/cues.html
+++ b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/embedded-content/media-elements/interfaces/TextTrack/cues.html
@@ -79,7 +79,7 @@
     var video = document.createElement('video');
     var t1 = video.addTextTrack('subtitles');
     var t1_cues = t1.cues;
-    t1.mode = 'showing';
+    t1.mode = 'hidden';
     var track = document.createElement('track');
     track['default'] = true;
     video.appendChild(track); // queues a task to "honor user preferences...", media element event task source
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/embedded-content/the-img-element/invalid-src.html b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/embedded-content/the-img-element/invalid-src.html
new file mode 100644
index 0000000..a4323da
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/embedded-content/the-img-element/invalid-src.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Loading a non-parsing URL as an image should silently fail; triggering appropriate events</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<img id=myimg />
+<script>
+async_test(function(t) {
+    var img = document.getElementById("myimg");
+    img.src = "http://also a broken url";
+    var errorevent = false;
+
+    // The errors should be queued in the event loop, so they should only trigger
+    // after this block of code finishes, not during the img.src setter itself
+    img.addEventListener('error', t.step_func(function(){errorevent = true;}));
+    img.addEventListener('loadend', t.step_func_done(function() {
+        assert_true(errorevent, "error event fired");
+    }));
+});
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html
index 5f52573..60d591ba 100644
--- a/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html
+++ b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html
@@ -32,6 +32,18 @@
   },'input setSelectionRange(0,input.value.length+1)');
 
   test(function() {
+    input.setSelectionRange(input.value.length+1,input.value.length+1)
+    assert_equals(input.selectionStart, input.value.length, "Arguments (start) greater than the length of the value of the text field must be treated as pointing at the end of the text field");
+    assert_equals(input.selectionEnd, input.value.length, "Arguments (end) greater than the length of the value of the text field must be treated as pointing at the end of the text field");
+  },'input setSelectionRange(input.value.length+1,input.value.length+1)');
+
+  test(function() {
+    input.setSelectionRange(input.value.length+1,1)
+    assert_equals(input.selectionStart, 1, "If end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end");
+    assert_equals(input.selectionEnd, 1, "element.selectionEnd should be 1");
+  },'input setSelectionRange(input.value.length+1,input.value.length+1)');
+
+  test(function() {
     input.setSelectionRange(2,2)
     assert_equals(input.selectionStart, 2, "If end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end");
     assert_equals(input.selectionEnd, 2, "If end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end");
@@ -74,6 +86,18 @@
   },'input direction of setSelectionRange(0,1)');
 
   test(function() {
+    input.setSelectionRange(1,-1);
+    assert_equals(input.selectionStart, 1, "element.selectionStart should be 1");
+    assert_equals(input.selectionEnd, input.value.length, "ECMAScript conversion to unsigned long");
+  },'input setSelectionRange(1,-1)');
+
+  test(function() {
+    input.setSelectionRange(-1,1);
+    assert_equals(input.selectionStart, 1, "ECMAScript conversion to unsigned long + if end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end");
+    assert_equals(input.selectionEnd, 1, "element.selectionEnd should be 1");
+  },'input setSelectionRange(-1,1)');
+
+  test(function() {
     input.setSelectionRange("string",1);
     assert_equals(input.selectionStart, 0, "element.selectionStart should be 0");
     assert_equals(input.selectionEnd, 1, "element.selectionEnd should be 1");
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/scripting-1/the-script-element/script-not-executed-after-shutdown.html b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/scripting-1/the-script-element/script-not-executed-after-shutdown.html
new file mode 100644
index 0000000..704e8ed
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/scripting-1/the-script-element/script-not-executed-after-shutdown.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Script is not executed after script thread is shutdown</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<iframe id="testiframe" src="script-not-executed-after-shutdown-child.html"></iframe>
+<script>
+async_test(function(t) {
+  window.script_executed = t.unreached_func("script executed in removed iframe");
+  let iframe = document.getElementById("testiframe");
+  iframe.onload = function() {
+    iframe.parentNode.removeChild(iframe);
+  };
+  setTimeout(function() {
+    t.done();
+  }, 5000);
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/scripting-1/the-script-element/script-not-executed-after-shutdown.js b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/scripting-1/the-script-element/script-not-executed-after-shutdown.js
new file mode 100644
index 0000000..ccdf14c0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/scripting-1/the-script-element/script-not-executed-after-shutdown.js
@@ -0,0 +1 @@
+script_executed();
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/html/the-xhtml-syntax/parsing-xhtml-documents/xhtml-mathml-dtd-entity-support.htm b/third_party/WebKit/LayoutTests/imported/wpt/html/the-xhtml-syntax/parsing-xhtml-documents/xhtml-mathml-dtd-entity-support.htm
index 4494f7f3..6d19229 100644
--- a/third_party/WebKit/LayoutTests/imported/wpt/html/the-xhtml-syntax/parsing-xhtml-documents/xhtml-mathml-dtd-entity-support.htm
+++ b/third_party/WebKit/LayoutTests/imported/wpt/html/the-xhtml-syntax/parsing-xhtml-documents/xhtml-mathml-dtd-entity-support.htm
@@ -35,8 +35,7 @@
   setup(function() {}, {explicit_done: true});
 
   var xhr = new XMLHttpRequest();
-  //xhr.open("GET", "entities.json");
-  xhr.open("GET", "https://w3c.github.io/html/entities.json");
+  xhr.open("GET", "/common/entities.json");
   xhr.onload = function () {
     // Note: for proper XML parsing of the Doctype, Edge requires a non-empty string for url part
     var entitiesJSON = JSON.parse(xhr.response);
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/README.md b/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/README.md
index 07004cf..0cc01909 100644
--- a/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/README.md
+++ b/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/README.md
@@ -1,6 +1,6 @@
 Directory for Pointer Events Tests
 
-Latest Editor's Draft: https://dvcs.w3.org/hg/pointerevents/raw-file/tip/pointerEvents.html
+Latest Editor's Draft: https://w3c.github.io/pointerevents/
 
 Latest W3C Technical Report: http://www.w3.org/TR/pointerevents/
 
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_button_attribute_mouse-manual.html b/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_button_attribute_mouse-manual.html
deleted file mode 100644
index a31e53d..0000000
--- a/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_button_attribute_mouse-manual.html
+++ /dev/null
@@ -1,57 +0,0 @@
-<!doctype html>
-<html>
-    <head>
-        <title>Button and buttons attribute test for mouse</title>
-        <meta name="viewport" content="width=device-width">
-        <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
-        <script src="/resources/testharness.js"></script>
-        <script src="/resources/testharnessreport.js"></script>
-        <script type="text/javascript" src="pointerevent_support.js"></script>
-    </head>
-    <body onload="run()">
-        <h1>Button attribute test for mouse</h1>
-        <h2>This test is for mouse only</h2>
-        <h4>
-            Test Description: This test checks if button attribute for mouse handled properly.
-            <p>Put your mouse over the black rectangle</p>
-        </h4>
-        <p>
-        <div id="target0" style="background:black"></div>
-        <script>
-            var eventTested = false;
-            var detected_pointertypes = {};
-
-            setup({ explicit_done: true });
-            add_completion_callback(showPointerTypes);
-
-            function run() {
-                var target0 = document.getElementById("target0");
-
-                // If pointerType is "mouse" and no mouse button is depressed, then the button attribute of the pointermove event must be -1 and the buttons attribute must be 0.
-                // TA: 5.8
-                on_event(target0, "pointerover", function (event) {
-                    detected_pointertypes[event.pointerType] = true;
-                    if(event.pointerType != "mouse") {
-                        alert("Use mouse for this test please!");
-                        return;
-                    }
-                    if (eventTested == false) {
-                        test(function() {
-                            assert_true(event.button == -1, "If mouse buttons are released button attribute is -1")
-                        }, "If mouse buttons are released button attribute is -1");
-                        test(function() {
-                            assert_true(event.buttons == 0, "If mouse buttons are released buttons attribute is 0")
-                        }, "If mouse buttons are released buttons attribute is 0");
-                        eventTested = true;
-                        done();
-                    }
-                });
-            }
-        </script>
-        <h1>Pointer Events button attribute test for mouse test</h1>
-        <div id="complete-notice">
-            <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
-        </div>
-        <div id="log"></div>
-    </body>
-</html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_properties_mouse-manual.html b/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_properties_mouse-manual.html
deleted file mode 100644
index adea65b2..0000000
--- a/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_properties_mouse-manual.html
+++ /dev/null
@@ -1,76 +0,0 @@
-<!doctype html>
-<html>
-    <head>
-        <title>Pointer Events properties tests</title>
-        <meta name="viewport" content="width=device-width">
-        <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
-        <script src="/resources/testharness.js"></script>
-        <script src="/resources/testharnessreport.js"></script>
-        <!-- Additional helper script for common checks across event types -->
-        <script type="text/javascript" src="pointerevent_support.js"></script>
-        <script>
-            var detected_pointertypes = {};
-            var detected_eventTypes = {};
-            var test_pointerEvent = async_test("pointerdown event received");
-            // showPointerTypes is defined in pointerevent_support.js
-            // Requirements: the callback function will reference the test_pointerEvent object and
-            // will fail unless the async_test is created with the var name "test_pointerEvent".
-            add_completion_callback(showPointerTypes);
-
-            function run() {
-                var square1 = document.getElementById("square1");
-                var rectSquare1 = square1.getBoundingClientRect();
-                var pointerover_event;
-
-                var eventList = ['pointerenter', 'pointerover', 'pointermove', 'pointerdown', 'pointerup', 'pointerout', 'pointerleave'];
-                eventList.forEach(function(eventName) {
-                    on_event(square1, eventName, function (event) {
-                        if (detected_eventTypes[event.type])
-                            return;
-                        detected_pointertypes[event.pointerType] = true;
-                        test(function () {
-                            assert_equals(event.pointerType, 'mouse', 'pointerType should be mouse');
-                        }, event.type + ".pointerType attribute is correct.");
-
-                        if (event.type != 'pointerout' && event.type != 'pointerleave' ) {
-                            test(function () {
-                                assert_true(event.clientX >= rectSquare1.left && event.clientX < rectSquare1.right, "ClientX should be in the boundaries of the black box");
-                            }, event.type + ".clientX attribute is correct.");
-                            test(function () {
-                              assert_true(event.clientY >= rectSquare1.top && event.clientY < rectSquare1.bottom, "ClientY should be in the boundaries of the black box");
-                            }, event.type + ".clientY attribute is correct.");
-                        } else {
-                            test(function () {
-                                assert_true(event.clientX < rectSquare1.left || event.clientX > rectSquare1.right - 1 || event.clientY < rectSquare1.top || event.clientY > rectSquare1.bottom - 1, "ClientX/Y should be out of the boundaries of the black box");
-                            }, event.type + "'s ClientX and ClientY attributes are correct.");
-                        }
-
-                        test(function () {
-                            assert_equals(event.isPrimary, true, "isPrimary should be true");
-                        }, event.type + ".isPrimary attribute is correct.");
-
-                        check_PointerEvent(event);
-                        detected_eventTypes[event.type] = true;
-                        if (Object.keys(detected_eventTypes).length == eventList.length)
-                            test_pointerEvent.done();
-                    });
-                });
-            }
-        </script>
-    </head>
-    <body onload="run()">
-        <h1>Pointer Events pointerdown tests</h1>
-        <h4>
-            Test Description: This test checks the properties of mouse pointer events. Move your mouse over the black square and click on it. Then move it off the black square.
-        </h4>
-        Test passes if the proper behavior of the events is observed.
-        <div id="square1" class="square"></div>
-        <div class="spacer"></div>
-        <div id="complete-notice">
-            <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
-            <p>Refresh the page to run the tests again with a different pointer type.</p>
-        </div>
-        <div id="log"></div>
-    </body>
-</html>
-
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_styles.css b/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_styles.css
index 70b037a9..d2acf94 100644
--- a/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_styles.css
+++ b/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_styles.css
@@ -31,6 +31,17 @@
 overflow-x: auto;
 }
 
+.touchActionNone {
+touch-action: none;
+}
+
+#innerframe {
+width: 90%;
+margin: 10px;
+margin-left: 10%;
+height: 200px;
+}
+
 .scroller {
 width: 700px;
 height: 430px;
@@ -66,6 +77,10 @@
 font-weight: bold;
 }
 
+#event-log {
+font-weight: bold;
+}
+
 #listener {
 background: orange;
 border: 1px solid orange;
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_support.js b/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_support.js
index b3fb661..6f399706 100644
--- a/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_support.js
+++ b/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_support.js
@@ -105,6 +105,14 @@
     complete_notice.style.display = "block";
 }
 
+function showLoggedEvents() {
+    var event_log_elem = document.getElementById("event-log");
+    event_log_elem.innerHTML = event_log.length ? event_log.join(", ") : "(none)";
+
+    var complete_notice = document.getElementById("complete-notice");
+    complete_notice.style.display = "block";
+}
+
 function log(msg, el) {
     if (++count > 10){
       count = 0;
@@ -167,4 +175,4 @@
     }
     catch(e) {
     }
-}
\ No newline at end of file
+}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_suppress_compat_events_on_click.html b/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_suppress_compat_events_on_click.html
new file mode 100644
index 0000000..71b8a082
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_suppress_compat_events_on_click.html
@@ -0,0 +1,101 @@
+<!doctype html>
+<html>
+  <head>
+    <title>Pointer Event: Suppress compatibility mouse events on click</title>
+    <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+    <link rel="author" title="Google" href="http://www.google.com "/>
+    <meta name="assert" content="When a pointerdown is canceled, a click/tap shouldn't fire any compatibility mouse events."/>
+    <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script type="text/javascript" src="pointerevent_support.js"></script>
+    <script type="text/javascript">
+      var test_pointerEvent = async_test("Suppress compat mouse events on click");
+      add_completion_callback(end_of_test);
+
+      var detected_pointertypes = {};
+      var event_log = [];
+
+      function end_of_test() {
+          showLoggedEvents();
+          showPointerTypes();
+      }
+
+      function end_of_interaction() {
+          test(function () {
+              assert_equals(event_log.join(", "),
+                  "mousedown@target1, mouseup@target1");
+          }, "Event log");
+
+          test_pointerEvent.done(); // complete test
+      }
+
+      function run() {
+          on_event(document.getElementById("done"), "click", end_of_interaction);
+
+          var target_list = ["target0", "target1"];
+          var pointer_event_list = ["pointerdown"];
+          var mouse_event_list = ["mousedown", "mouseup"];
+
+          target_list.forEach(function(targetId) {
+              var target = document.getElementById(targetId);
+
+              pointer_event_list.forEach(function(eventName) {
+                  on_event(target, eventName, function (event) {
+                      detected_pointertypes[event.pointerType] = true;
+                      var label = event.type + "@" + targetId;
+
+                      test(function () {
+                          assert_true(event.isPrimary);
+                      }, "primary pointer " + label);
+
+                      if (label === "pointerdown@target0")
+                          event.preventDefault();
+                  });
+              });
+
+              mouse_event_list.forEach(function(eventName) {
+                  on_event(target, eventName, function (event) {
+                      event_log.push(event.type + "@" + targetId);
+                  });
+              });
+          });
+      }
+    </script>
+    <style>
+      #target0, #target1 {
+        margin: 20px;
+      }
+
+      #done {
+        margin: 20px;
+        border: 2px solid black;
+      }
+    </style>
+  </head>
+  <body onload="run()">
+    <h1>Pointer Event: Suppress compatibility mouse events on click</h1>
+    <h4>
+      When a pointerdown is canceled, a click/tap shouldn't fire any compatibility mouse events.
+    </h4>
+    <ol>
+      <li> Click or tap on Target0.</li>
+      <li> Click or tap on Target1.</li>
+      <li> Click Done.</li>
+    </ol>
+    <div id="target0">
+      Target0
+    </div>
+    <div id="target1">
+      Target1
+    </div>
+    <div id="done">
+      Done
+    </div>
+    <div id="complete-notice">
+      <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+      <p>The following events were logged: <span id="event-log"></span>.</p>
+    </div>
+    <div id="log"></div>
+  </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_suppress_compat_events_on_drag_mouse.html b/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_suppress_compat_events_on_drag_mouse.html
new file mode 100644
index 0000000..02bca85
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_suppress_compat_events_on_drag_mouse.html
@@ -0,0 +1,114 @@
+<!doctype html>
+<html>
+  <head>
+    <title>Pointer Event: Suppress compatibility mouse events on drag</title>
+    <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+    <link rel="author" title="Google" href="http://www.google.com "/>
+    <meta name="assert" content="When a pointerdown is canceled, a mouse drag shouldn't fire any compatibility mouse events."/>
+    <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script type="text/javascript" src="pointerevent_support.js"></script>
+    <script type="text/javascript">
+      var test_pointerEvent = async_test("Suppress compat mouse events on drag");
+      add_completion_callback(end_of_test);
+
+      var detected_pointertypes = {};
+      var event_log = [];
+
+      function end_of_test() {
+          showLoggedEvents();
+          showPointerTypes();
+      }
+
+      var include_next_mousemove = false;
+
+      // Limits logging/testing of mousemove.
+      function drop_event(event_type) {
+          return (event_type == "mousemove" && !include_next_mousemove);
+      }
+
+      function end_of_interaction() {
+          test(function () {
+              assert_equals(event_log.join(", "),
+                  "mousedown@target1, mousemove@target1, mouseup@target1");
+          }, "Event log");
+
+          test_pointerEvent.done(); // complete test
+      }
+
+      function run() {
+          on_event(document.getElementById("done"), "click", end_of_interaction);
+
+          var target_list = ["target0", "target1"];
+          var pointer_event_list = ["pointerdown"];
+          var mouse_event_list = ["mousedown", "mouseup", "mousemove"];
+
+          target_list.forEach(function(targetId) {
+              var target = document.getElementById(targetId);
+
+              pointer_event_list.forEach(function(eventName) {
+                  on_event(target, eventName, function (event) {
+                      detected_pointertypes[event.pointerType] = true;
+                      var label = event.type + "@" + targetId;
+
+                      test(function () {
+                          assert_true(event.isPrimary);
+                      }, "primary pointer " + label);
+
+                      if (label === "pointerdown@target0")
+                          event.preventDefault();
+                  });
+              });
+
+              mouse_event_list.forEach(function(eventName) {
+                  on_event(target, eventName, function (event) {
+                      if (drop_event(event.type))
+                          return;
+
+                      event_log.push(event.type + "@" + targetId);
+
+                      include_next_mousemove = (event.type == "mousedown");
+                  });
+              });
+          });
+      }
+    </script>
+    <style>
+      #target0, #target1 {
+        margin: 20px;
+        touch-action: none;
+      }
+
+      #done {
+        margin: 20px;
+        border: 2px solid black;
+      }
+    </style>
+  </head>
+  <body onload="run()">
+    <h1>Pointer Event: Suppress compatibility mouse events on drag</h1>
+    <h4>
+      When a pointerdown is canceled, a mouse drag shouldn't fire any compatibility mouse events.
+    </h4>
+    <ol>
+      <li> Drag mouse within Target0 &amp; release.</li>
+      <li> Drag mouse within Target1 &amp; release.</li>
+      <li> Click Done.</li>
+    </ol>
+    <div id="target0">
+      Target0
+    </div>
+    <div id="target1">
+      Target1
+    </div>
+    <div id="done">
+      Done
+    </div>
+    <div id="complete-notice">
+      <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+      <p>The following events were logged: <span id="event-log"></span>.</p>
+    </div>
+    <div id="log"></div>
+  </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/resources/pointerevent_pointerId_scope-iframe.html b/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/resources/pointerevent_pointerId_scope-iframe.html
new file mode 100644
index 0000000..ad1a57f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/resources/pointerevent_pointerId_scope-iframe.html
@@ -0,0 +1,37 @@
+<!doctype html>
+<html>
+    <!--
+Test cases for Pointer Events v1 spec
+This document references Test Assertions (abbrev TA below) written by Cathy Chan
+http://www.w3.org/wiki/PointerEvents/TestAssertions
+-->
+    <head>
+        <title>Pointer Events pointerdown tests</title>
+        <meta name="viewport" content="width=device-width">
+        <link rel="stylesheet" type="text/css" href="../pointerevent_styles.css">
+        <script>
+            function run() {
+                var target1 = document.getElementById("target1");
+                var pointerover_event;
+                var ponterId = null;
+
+                var eventList = ['pointerenter', 'pointerover', 'pointermove', 'pointerout', 'pointerleave'];
+
+                eventList.forEach(function(eventName) {
+                    target1.addEventListener(eventName, function (event) {
+                        var pass_data = {
+                            'pointerId' : event.pointerId,
+                            'type' : event.type,
+                            'pointerType' : event.pointerType
+                        };
+                        top.postMessage(JSON.stringify(pass_data), "*");
+                    });
+               });
+            }
+        </script>
+    </head>
+    <body onload="run()">
+        <div id="target1" class="touchActionNone">
+        </div>
+    </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/resources/idlharness.js b/third_party/WebKit/LayoutTests/imported/wpt/resources/idlharness.js
index b6a16af..5002ec5 100644
--- a/third_party/WebKit/LayoutTests/imported/wpt/resources/idlharness.js
+++ b/third_party/WebKit/LayoutTests/imported/wpt/resources/idlharness.js
@@ -307,6 +307,28 @@
     return ret;
 };
 
+function exposed_in(globals) {
+    if ('document' in self) {
+        return globals.indexOf("Window") >= 0;
+    }
+    if ('DedicatedWorkerGlobalScope' in self &&
+        self instanceof DedicatedWorkerGlobalScope) {
+        return globals.indexOf("Worker") >= 0 ||
+               globals.indexOf("DedicatedWorker") >= 0;
+    }
+    if ('SharedWorkerGlobalScope' in self &&
+        self instanceof SharedWorkerGlobalScope) {
+        return globals.indexOf("Worker") >= 0 ||
+               globals.indexOf("SharedWorker") >= 0;
+    }
+    if ('ServiceWorkerGlobalScope' in self &&
+        self instanceof ServiceWorkerGlobalScope) {
+        return globals.indexOf("Worker") >= 0 ||
+               globals.indexOf("ServiceWorker") >= 0;
+    }
+    throw "Unexpected global object";
+}
+
 //@}
 IdlArray.prototype.test = function()
 //@{
@@ -353,6 +375,23 @@
     }
     this["implements"] = {};
 
+    Object.getOwnPropertyNames(this.members).forEach(function(memberName) {
+        var member = this.members[memberName];
+        if (!(member instanceof IdlInterface)) {
+            return;
+        }
+
+        var exposed = member.extAttrs.filter(function(a) { return a.name == "Exposed" });
+        if (exposed.length > 1) {
+            throw "Unexpected Exposed extended attributes on " + memberName + ": " + exposed;
+        }
+
+        var globals = exposed.length === 1
+                    ? exposed[0].rhs.value
+                    : ["Window"];
+        member.exposed = exposed_in(globals);
+    }.bind(this));
+
     // Now run test() on every member, and test_object() for every object.
     for (var name in this.members)
     {
@@ -678,6 +717,13 @@
         return;
     }
 
+    if (!this.exposed) {
+        test(function() {
+            assert_false(this.name in self);
+        }.bind(this), this.name + " interface: existence and properties of interface object");
+        return;
+    }
+
     if (!this.untested)
     {
         // First test things to do with the exception/interface object and
@@ -701,7 +747,6 @@
     test(function()
     {
         // This function tests WebIDL as of 2015-01-13.
-        // TODO: Consider [Exposed].
 
         // "For every interface that is exposed in a given ECMAScript global
         // environment and:
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/resources/testharness.js b/third_party/WebKit/LayoutTests/imported/wpt/resources/testharness.js
index ceb3a4b..91dfab5 100644
--- a/third_party/WebKit/LayoutTests/imported/wpt/resources/testharness.js
+++ b/third_party/WebKit/LayoutTests/imported/wpt/resources/testharness.js
@@ -471,6 +471,11 @@
             self instanceof ServiceWorkerGlobalScope) {
             return new ServiceWorkerTestEnvironment();
         }
+        if ('WorkerGlobalScope' in self &&
+            self instanceof WorkerGlobalScope) {
+            return new DedicatedWorkerTestEnvironment();
+        }
+
         throw new Error("Unsupported test environment");
     }
 
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/Document-prototype-currentScript-expected.txt b/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/Document-prototype-currentScript-expected.txt
index a100343..adb48a0 100644
--- a/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/Document-prototype-currentScript-expected.txt
+++ b/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/Document-prototype-currentScript-expected.txt
@@ -1,7 +1,7 @@
-CONSOLE ERROR: line 2440: Uncaught Error: assert_equals: expected Element node <script id="outerScriptElement">
+CONSOLE ERROR: line 2445: Uncaught Error: assert_equals: expected Element node <script id="outerScriptElement">
 
 var outerScriptElement ... but got null
-CONSOLE ERROR: line 2440: Uncaught Error: assert_equals: expected Element node <script id="outerScriptElement">
+CONSOLE ERROR: line 2445: Uncaught Error: assert_equals: expected Element node <script id="outerScriptElement">
 
 var outerScriptElement ... but got null
 This is a testharness.js-based test.
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/leaktests/html-collection.html b/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/leaktests/html-collection.html
index 4f864fd..d156569 100644
--- a/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/leaktests/html-collection.html
+++ b/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/leaktests/html-collection.html
@@ -11,7 +11,6 @@
 <template id='collection-template'>
   <img>
   <embed></embed>
-  <plugin></plugin>
   <applet></applet>
   <object type='application/x-java-applet'></object>
   <a href='http://example.com'></a>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-001.html b/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-001.html
deleted file mode 100644
index 94f7d1b..0000000
--- a/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-001.html
+++ /dev/null
@@ -1,86 +0,0 @@
-<!DOCTYPE html>
-<!--
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
--->
-<html>
-<head>
-<title>Shadow DOM Test: A_07_02_01</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#focus-navigation">
-<meta name="assert" content="User Interaction: The navigation order within a shadow tree must be computed as a list of focusable elements in tree order as-rendered">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../../../../html/resources/common.js"></script>
-<script src="../../../resources/shadow-dom-utils.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-var A_07_02_01_T01 = async_test('A_07_02_01_T01');
-
-A_07_02_01_T01.step(unit(function (ctx) {
-
-    var counter = 0;
-
-    var d = newRenderedHTMLDocument(ctx);
-
-    var chb1 = d.createElement('input');
-    chb1.setAttribute('type', 'checkbox');
-    chb1.setAttribute('id', 'chb1');
-    chb1.addEventListener('focus', A_07_02_01_T01.step_func(function(event) {
-        assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
-    }), false);
-    d.body.appendChild(chb1);
-
-    var host = d.createElement('div');
-    d.body.appendChild(host);
-    var s = host.attachShadow({mode: 'open'});
-
-    var inp1 = d.createElement('input');
-    inp1.setAttribute('type', 'text');
-    inp1.setAttribute('id', 'shInp1');
-    inp1.setAttribute('value', 'Input 1');
-    inp1.addEventListener('focus', A_07_02_01_T01.step_func(function(event) {
-        assert_equals(counter++, 1, 'Point 2: wrong focus navigation order');
-    }), false);
-    s.appendChild(inp1);
-
-    var inp2 = d.createElement('input');
-    inp2.setAttribute('type', 'text');
-    inp2.setAttribute('id', 'shInp2');
-    inp2.setAttribute('value', 'Input 2');
-    inp2.addEventListener('focus', A_07_02_01_T01.step_func(function(event) {
-        assert_equals(counter++, 2, 'Point 3: wrong focus navigation order');
-    }), false);
-    s.appendChild(inp2);
-
-    var chb2 = d.createElement('input');
-    chb2.setAttribute('type', 'checkbox');
-    chb2.setAttribute('id', 'chb2');
-    chb2.addEventListener('focus', A_07_02_01_T01.step_func(function(event) {
-        assert_equals(counter++, 3, 'Point 4: wrong focus navigation order');
-    }), false);
-    d.body.appendChild(chb2);
-
-    chb1.focus();
-
-    //simulate TAB clicks
-    fireKeyboardEvent(d, chb1, 'U+0009');
-
-    fireKeyboardEvent(d, inp1, 'U+0009');
-
-    fireKeyboardEvent(d, inp2, 'U+0009');
-
-    fireKeyboardEvent(d, chb2, 'U+0009');
-
-    A_07_02_01_T01.done();
-}));
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-002.html b/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-002.html
deleted file mode 100644
index 14c3219..0000000
--- a/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-002.html
+++ /dev/null
@@ -1,238 +0,0 @@
-<!DOCTYPE html>
-<!--
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
--->
-<html>
-<head>
-<title>Shadow DOM Test: A_07_02_02</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#focus-navigation">
-<meta name="assert" content="User Interaction: The navigation order within a shadow tree must be computed as a list of focusable elements in tree order as-rendered  with the exception of any elements, distributed its insertion points, and is called shadow DOM navigation order.">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../../../../html/resources/common.js"></script>
-<script src="../../../resources/shadow-dom-utils.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-var A_07_02_02_T01 = async_test('A_07_02_02_T01');
-var A_07_02_02_T02 = async_test('A_07_02_02_T02');
-
-A_07_02_02_T01.step(unit(function (ctx) {
-
-    var counter = 0;
-
-    var expectations = [];
-
-    var d = newRenderedHTMLDocument(ctx);
-
-    var host = d.createElement('div');
-    d.body.appendChild(host);
-
-    var chb1 = d.createElement('input');
-    chb1.setAttribute('type', 'checkbox');
-    chb1.setAttribute('id', 'chb1');
-    chb1.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
-        assert_true(false, 'Element shouldn\'t be rendered');
-    }), false);
-    host.appendChild(chb1);
-
-    var chb2 = d.createElement('input');
-    chb2.setAttribute('type', 'checkbox');
-    chb2.setAttribute('id', 'chb2');
-    chb2.setAttribute('slot', 'shadow');
-    chb2.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
-        assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
-        expectations[1] = true;
-    }), false);
-    expectations[1] = false;
-    host.appendChild(chb2);
-
-    var chb3 = d.createElement('input');
-    chb3.setAttribute('type', 'checkbox');
-    chb3.setAttribute('id', 'chb3');
-    chb3.setAttribute('slot', 'shadow');
-    chb3.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
-        assert_equals(counter++, 1, 'Point 2: wrong focus navigation order');
-        expectations[2] = true;
-    }), false);
-    expectations[2] = false;
-    host.appendChild(chb3);
-
-    var s = host.attachShadow({mode: 'open'});
-
-    var div = d.createElement('div');
-    div.innerHTML = '<slot name="shadow"></slot>';
-    s.appendChild(div);
-
-    var inp1 = d.createElement('input');
-    inp1.setAttribute('type', 'text');
-    inp1.setAttribute('id', 'shInp1');
-    inp1.setAttribute('value', 'Input 1');
-    inp1.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
-        expectations[3] = false;
-    }), false);
-    expectations[3] = true;
-    s.appendChild(inp1);
-
-    var inp2 = d.createElement('input');
-    inp2.setAttribute('type', 'text');
-    inp2.setAttribute('id', 'shInp2');
-    inp2.setAttribute('value', 'Input 2');
-    inp2.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
-        expectations[4] = false;
-    }), false);
-    expectations[4] = true;
-    s.appendChild(inp2);
-
-    var chb4 = d.createElement('input');
-    chb4.setAttribute('type', 'checkbox');
-    chb4.setAttribute('id', 'chb4');
-    chb4.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
-        assert_equals(counter++, 2, 'Point 5: wrong focus navigation order');
-        expectations[5] = true;
-    }), false);
-    expectations[5] = false;
-    d.body.appendChild(chb4);
-
-    chb2.focus();
-
-    //simulate TAB clicks
-    fireKeyboardEvent(d, chb2, 'U+0009');
-
-    fireKeyboardEvent(d, chb3, 'U+0009');
-
-    fireKeyboardEvent(d, inp1, 'U+0009');
-
-    fireKeyboardEvent(d, inp2, 'U+0009');
-
-    fireKeyboardEvent(d, chb4, 'U+0009');
-
-    for (var i = 1; i < expectations.length; i++) {
-        if (!expectations[i]) {
-            assert_true(false, 'Point ' + i + ' event listener was not invoked');
-        }
-    }
-
-    A_07_02_02_T01.done();
-}));
-
-
-
-A_07_02_02_T02.step(unit(function (ctx) {
-
-    var counter = 0;
-
-    var expectations = [];
-
-    var d = newRenderedHTMLDocument(ctx);
-
-    var chb0 = d.createElement('input');
-    chb0.setAttribute('type', 'checkbox');
-    chb0.setAttribute('id', 'chb0');
-        d.body.appendChild(chb0);
-
-
-    var host = d.createElement('div');
-    d.body.appendChild(host);
-
-    var chb1 = d.createElement('input');
-    chb1.setAttribute('type', 'checkbox');
-    chb1.setAttribute('id', 'chb1');
-    chb1.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
-        assert_true(false, 'Element shouldn\'t be rendered');
-    }), false);
-    host.appendChild(chb1);
-
-    var chb2 = d.createElement('input');
-    chb2.setAttribute('type', 'checkbox');
-    chb2.setAttribute('id', 'chb2');
-    chb2.setAttribute('slot', 'shadow');
-    chb2.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
-        assert_equals(counter++, 2, 'Point 3: wrong focus navigation order');
-        expectations[1] = true;
-    }), false);
-    expectations[1] = false;
-    host.appendChild(chb2);
-
-    var chb3 = d.createElement('input');
-    chb3.setAttribute('type', 'checkbox');
-    chb3.setAttribute('id', 'chb3');
-    chb3.setAttribute('slot', 'shadow');
-    chb3.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
-        assert_equals(counter++, 3, 'Point 4: wrong focus navigation order');
-        expectations[2] = true;
-    }), false);
-    expectations[2] = false;
-    host.appendChild(chb3);
-
-    var s = host.attachShadow({mode: 'open'});
-
-    var div = d.createElement('div');
-    div.innerHTML = '<slot name="shadow"></slot>';
-    s.appendChild(div);
-
-    var inp1 = d.createElement('input');
-    inp1.setAttribute('type', 'text');
-    inp1.setAttribute('id', 'shInp1');
-    inp1.setAttribute('value', 'Input 1');
-    inp1.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
-        assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
-
-        expectations[3] = true;
-    }), false);
-    expectations[3] = false;
-    s.appendChild(inp1);
-
-    var inp2 = d.createElement('input');
-    inp2.setAttribute('type', 'text');
-    inp2.setAttribute('id', 'shInp2');
-    inp2.setAttribute('value', 'Input 2');
-    inp2.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
-        assert_equals(counter++, 1, 'Point 2: wrong focus navigation order');
-        expectations[4] = true;
-    }), false);
-    expectations[4] = false;
-    s.appendChild(inp2);
-
-    var chb4 = d.createElement('input');
-    chb4.setAttribute('type', 'checkbox');
-    chb4.setAttribute('id', 'chb4');
-    chb4.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
-        assert_equals(counter++, 4, 'Point 5: wrong focus navigation order');
-        expectations[5] = true;
-    }), false);
-    expectations[5] = false;
-    d.body.appendChild(chb4);
-
-    chb0.focus();
-
-    //simulate TAB clicks
-    fireKeyboardEvent(d, inp1, 'U+0009');
-
-    fireKeyboardEvent(d, inp2, 'U+0009');
-
-    fireKeyboardEvent(d, chb2, 'U+0009');
-
-    fireKeyboardEvent(d, chb3, 'U+0009');
-
-    fireKeyboardEvent(d, chb4, 'U+0009');
-
-    for (var i = 1; i < expectations.length; i++) {
-        if (!expectations[i]) {
-            assert_true(false, 'Point ' + i + ' event listener was not invoked');
-        }
-    }
-
-    A_07_02_02_T02.done();
-}));
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-003.html b/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-003.html
deleted file mode 100644
index eec7620..0000000
--- a/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-003.html
+++ /dev/null
@@ -1,237 +0,0 @@
-<!DOCTYPE html>
-<!--
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
--->
-<html>
-<head>
-<title>Shadow DOM Test: A_07_02_03</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#focus-navigation">
-<meta name="assert" content="User Interaction: For sequential focus navigation, the shadow DOM navigation order sequence must be inserted into the document navigation order in place of the shadow host as if the shadow host were assigned the value of auto for determining its position and shadow host is not focusable">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../../../../html/resources/common.js"></script>
-<script src="../../../resources/shadow-dom-utils.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-var A_07_02_03_T01 = async_test('A_07_02_03_T01');
-
-A_07_02_03_T01.step(unit(function (ctx) {
-
-    var counter = 0;
-
-    var invoked = [];
-
-    var d = newRenderedHTMLDocument(ctx);
-
-    var chb1 = d.createElement('input');
-    chb1.setAttribute('type', 'checkbox');
-    // TODO according CSS3 nav-index is a replacement for tabindex
-    //chb1.setAttribute('nav-index', '4');
-    chb1.setAttribute('tabindex', '4');
-    chb1.setAttribute('id', 'chb1');
-    chb1.addEventListener('focus', A_07_02_03_T01.step_func(function(event) {
-        assert_equals(counter++, 1, 'Point 1: wrong focus navigation order');
-        invoked[1] = true;
-    }), false);
-    invoked[1] = false;
-    d.body.appendChild(chb1);
-
-    var host = d.createElement('div');
-    d.body.appendChild(host);
-    var s = host.attachShadow({mode: 'open'});
-
-    var inp1 = d.createElement('input');
-    inp1.setAttribute('type', 'text');
-    inp1.setAttribute('id', 'shInp1');
-    //inp1.setAttribute('nav-index', '3');
-    inp1.setAttribute('tabindex', '3');
-    inp1.setAttribute('value', 'Input 1');
-    inp1.addEventListener('focus', A_07_02_03_T01.step_func(function(event) {
-        assert_equals(counter++, 4, 'Point 2: wrong focus navigation order');
-        invoked[2] = true;
-    }), false);
-    invoked[2] = false;
-    s.appendChild(inp1);
-
-    var inp2 = d.createElement('input');
-    inp2.setAttribute('type', 'text');
-    inp2.setAttribute('id', 'shInp2');
-    //inp2.setAttribute('nav-index', '2');
-    inp2.setAttribute('tabindex', '2');
-    inp2.setAttribute('value', 'Input 2');
-    inp2.addEventListener('focus', A_07_02_03_T01.step_func(function(event) {
-        assert_equals(counter++, 3, 'Point 3: wrong focus navigation order');
-        invoked[3] = true;
-    }), false);
-    invoked[3] = false;
-    s.appendChild(inp2);
-
-    var chb2 = d.createElement('input');
-    chb2.setAttribute('type', 'checkbox');
-    chb2.setAttribute('id', 'chb2');
-    //chb2.setAttribute('nav-index', '1');
-    chb2.setAttribute('tabindex', '1');
-    chb2.addEventListener('focus', A_07_02_03_T01.step_func(function(event) {
-        assert_equals(counter++, 0, 'Point 4: wrong focus navigation order');
-        invoked[4] = true;
-    }), false);
-    invoked[4] = false;
-    d.body.appendChild(chb2);
-
-    var chb3 = d.createElement('input');
-    chb3.setAttribute('type', 'checkbox');
-    chb3.setAttribute('id', 'chb3');
-    //chb3.setAttribute('nav-index', '5');
-    chb3.setAttribute('tabindex', '5');
-    chb3.addEventListener('focus', A_07_02_03_T01.step_func(function(event) {
-        assert_equals(counter++, 2, 'Point 5: wrong focus navigation order');
-        invoked[5] = true;
-    }), false);
-    invoked[5] = false;
-    d.body.appendChild(chb3);
-
-    chb2.focus();
-
-    //simulate TAB clicks. Expected order: chb2, chb1, chb3, inp2, inp1
-    fireKeyboardEvent(d, chb2, 'U+0009');
-
-    fireKeyboardEvent(d, chb1, 'U+0009');
-
-    fireKeyboardEvent(d, chb3, 'U+0009');
-
-    fireKeyboardEvent(d, inp2, 'U+0009');
-
-    fireKeyboardEvent(d, inp1, 'U+0009');
-
-    for (var i = 1; i < invoked.length; i++) {
-        if (!invoked[i]) {
-            assert_true(false, 'Piont ' + i + ' event listener was not invoked');
-        }
-    }
-
-    A_07_02_03_T01.done();
-}));
-
-// test nodes, distributed into insertion points
-var A_07_02_03_T02 = async_test('A_07_02_03_T02');
-
-A_07_02_03_T02.step(unit(function (ctx) {
-
-    var counter = 0;
-
-    var invoked = [];
-
-    var d = newRenderedHTMLDocument(ctx);
-
-    var host = d.createElement('div');
-    d.body.appendChild(host);
-
-    var chb1 = d.createElement('input');
-    chb1.setAttribute('type', 'checkbox');
-    chb1.setAttribute('id', 'chb1');
-    chb1.setAttribute('tabindex', '1');
-    chb1.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
-        assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
-        invoked[1] = true;
-    }), false);
-    invoked[1] = false;
-    d.body.appendChild(chb1);
-
-    var chb2 = d.createElement('input');
-    chb2.setAttribute('type', 'checkbox');
-    chb2.setAttribute('id', 'chb2');
-    chb2.setAttribute('slot', 'shadow');
-    chb2.setAttribute('tabindex', '3');
-    chb2.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
-        assert_equals(counter++, 2, 'Point 2: wrong focus navigation order');
-        invoked[2] = true;
-    }), false);
-    invoked[2] = false;
-    host.appendChild(chb2);
-
-    var chb3 = d.createElement('input');
-    chb3.setAttribute('type', 'checkbox');
-    chb3.setAttribute('id', 'chb3');
-    chb3.setAttribute('slot', 'shadow');
-    chb3.setAttribute('tabindex', '2');
-    chb3.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
-        assert_equals(counter++, 1, 'Point 3: wrong focus navigation order');
-        invoked[3] = true;
-    }), false);
-    invoked[3] = false;
-    host.appendChild(chb3);
-
-    var s = host.attachShadow({mode: 'open'});
-
-    var div = d.createElement('div');
-    div.innerHTML = '<slot name="shadow"></slot>';
-    s.appendChild(div);
-
-    var inp1 = d.createElement('input');
-    inp1.setAttribute('type', 'text');
-    inp1.setAttribute('id', 'shInp1');
-    inp1.setAttribute('value', 'Input 1');
-    inp1.setAttribute('tabindex', '4');
-    inp1.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
-        assert_equals(counter++, 4, 'Point 4: wrong focus navigation order');
-        invoked[4] = true;
-    }), false);
-    invoked[4] = false;
-    s.appendChild(inp1);
-
-    var inp2 = d.createElement('input');
-    inp2.setAttribute('type', 'text');
-    inp2.setAttribute('id', 'shInp2');
-    inp2.setAttribute('value', 'Input 2');
-    inp2.setAttribute('tabindex', '5');
-    inp2.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
-        assert_equals(counter++, 5, 'Point 5: wrong focus navigation order');
-        invoked[5] = true;
-    }), false);
-    invoked[5] = false;
-    s.appendChild(inp2);
-
-    var chb4 = d.createElement('input');
-    chb4.setAttribute('type', 'checkbox');
-    chb4.setAttribute('id', 'chb4');
-    chb4.setAttribute('tabindex', '6');
-    chb4.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
-        assert_equals(counter++, 3, 'Point 6: wrong focus navigation order');
-        invoked[6] = true;
-    }), false);
-    invoked[6] = false;
-    d.body.appendChild(chb4);
-
-    chb1.focus();
-
-    //simulate TAB clicks
-    //Expected order: chb1, chb3, chb2, chb4, inp1, inp2
-    fireKeyboardEvent(d, chb1, 'U+0009');
-    fireKeyboardEvent(d, chb3, 'U+0009');
-    fireKeyboardEvent(d, chb2, 'U+0009');
-    fireKeyboardEvent(d, chb4, 'U+0009');
-    fireKeyboardEvent(d, inp1, 'U+0009');
-    fireKeyboardEvent(d, inp2, 'U+0009');
-
-
-
-    for (var i = 1; i < invoked.length; i++) {
-        if (!invoked[i]) {
-            assert_true(false, 'Piont ' + i + ' event listener was not invoked');
-        }
-    }
-
-    A_07_02_03_T02.done();
-}));
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-004.html b/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-004.html
deleted file mode 100644
index 29e02bd..0000000
--- a/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-004.html
+++ /dev/null
@@ -1,427 +0,0 @@
-<!DOCTYPE html>
-<!--
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
--->
-<html>
-<head>
-<title>Shadow DOM Test: A_07_02_04</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#focus-navigation">
-<meta name="assert" content="User Interaction: For sequential focus navigation, the shadow DOM navigation order sequence must be inserted into the document navigation order immediately after the shadow host, if the shadow host is focusable;">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../../../../html/resources/common.js"></script>
-<script src="../../../resources/shadow-dom-utils.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-var A_07_02_04_T01 = async_test('A_07_02_04_T01');
-
-A_07_02_04_T01.step(unit(function (ctx) {
-
-    var counter = 0;
-
-    var invoked = [];
-
-    var d = newRenderedHTMLDocument(ctx);
-
-    var chb1 = d.createElement('input');
-    chb1.setAttribute('type', 'checkbox');
-    // TODO according CSS3 nav-index is a replacement for tabindex
-    //chb1.setAttribute('nav-index', '4');
-    chb1.setAttribute('tabindex', '1');
-    chb1.setAttribute('id', 'chb1');
-    chb1.addEventListener('focus', A_07_02_04_T01.step_func(function(event) {
-        assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
-        invoked[1] = true;
-    }), false);
-    invoked[1] = false;
-    d.body.appendChild(chb1);
-
-    var host = d.createElement('div');
-    //make shadow host focusable
-    host.setAttribute('tabindex', '3');
-    d.body.appendChild(host);
-    var s = host.attachShadow({mode: 'open'});
-
-    var inp1 = d.createElement('input');
-    inp1.setAttribute('type', 'text');
-    inp1.setAttribute('id', 'shInp1');
-    //inp1.setAttribute('nav-index', '3');
-    inp1.setAttribute('tabindex', '2');
-    inp1.setAttribute('value', 'Input 1');
-    inp1.addEventListener('focus', A_07_02_04_T01.step_func(function(event) {
-        assert_equals(counter++, 3, 'Point 2: wrong focus navigation order');
-        invoked[2] = true;
-    }), false);
-    invoked[2] = false;
-    s.appendChild(inp1);
-
-    var inp2 = d.createElement('input');
-    inp2.setAttribute('type', 'text');
-    inp2.setAttribute('id', 'shInp2');
-    //inp2.setAttribute('nav-index', '2');
-    inp2.setAttribute('tabindex', '1');
-    inp2.setAttribute('value', 'Input 2');
-    inp2.addEventListener('focus', A_07_02_04_T01.step_func(function(event) {
-        assert_equals(counter++, 2, 'Point 3: wrong focus navigation order');
-        invoked[3] = true;
-    }), false);
-    invoked[3] = false;
-    s.appendChild(inp2);
-
-    var chb2 = d.createElement('input');
-    chb2.setAttribute('type', 'checkbox');
-    chb2.setAttribute('id', 'chb2');
-    //chb2.setAttribute('nav-index', '1');
-    chb2.setAttribute('tabindex', '2');
-    chb2.addEventListener('focus', A_07_02_04_T01.step_func(function(event) {
-        assert_equals(counter++, 1, 'Point 4: wrong focus navigation order');
-        invoked[4] = true;
-    }), false);
-    invoked[4] = false;
-    d.body.appendChild(chb2);
-
-    var chb3 = d.createElement('input');
-    chb3.setAttribute('type', 'checkbox');
-    chb3.setAttribute('id', 'chb3');
-    //chb3.setAttribute('nav-index', '5');
-    chb3.setAttribute('tabindex', '4');
-    chb3.addEventListener('focus', A_07_02_04_T01.step_func(function(event) {
-        assert_equals(counter++, 4, 'Point 5: wrong focus navigation order');
-        invoked[5] = true;
-    }), false);
-    invoked[5] = false;
-    d.body.appendChild(chb3);
-
-    chb1.focus();
-
-    //simulate TAB clicks. Expected order: chb1, chb2, inp2, inp1, chb3
-    fireKeyboardEvent(d, chb1, 'U+0009');
-
-    fireKeyboardEvent(d, chb2, 'U+0009');
-
-    fireKeyboardEvent(d, inp2, 'U+0009');
-
-    fireKeyboardEvent(d, inp1, 'U+0009');
-
-    fireKeyboardEvent(d, chb3, 'U+0009');
-
-    for (var i = 1; i < invoked.length; i++) {
-        if (!invoked[i]) {
-            assert_true(false, 'Piont ' + i + ' event listener was not invoked');
-        }
-    }
-
-    A_07_02_04_T01.done();
-}));
-
-
-
-// test nodes, distributed into insertion points
-var A_07_02_04_T02 = async_test('A_07_02_04_T02');
-
-A_07_02_04_T02.step(unit(function (ctx) {
-
-    var counter = 0;
-
-    var invoked = [];
-
-    var d = newRenderedHTMLDocument(ctx);
-
-    var host = d.createElement('div');
-    host.setAttribute('tabindex', '3');
-    d.body.appendChild(host);
-
-    var chb1 = d.createElement('input');
-    chb1.setAttribute('type', 'checkbox');
-    chb1.setAttribute('id', 'chb1');
-    chb1.setAttribute('tabindex', '1');
-    chb1.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
-        assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
-        invoked[1] = true;
-    }), false);
-    invoked[1] = false;
-    d.body.appendChild(chb1);
-
-    var chb2 = d.createElement('input');
-    chb2.setAttribute('type', 'checkbox');
-    chb2.setAttribute('id', 'chb2');
-    chb2.setAttribute('slot', 'shadow');
-    chb2.setAttribute('tabindex', '3');
-    chb2.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
-        assert_equals(counter++, 4, 'Point 2: wrong focus navigation order');
-        invoked[2] = true;
-    }), false);
-    invoked[2] = false;
-    host.appendChild(chb2);
-
-    var chb3 = d.createElement('input');
-    chb3.setAttribute('type', 'checkbox');
-    chb3.setAttribute('id', 'chb3');
-    chb3.setAttribute('slot', 'shadow');
-    chb3.setAttribute('tabindex', '2');
-    chb3.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
-        assert_equals(counter++, 1, 'Point 3: wrong focus navigation order');
-        invoked[3] = true;
-    }), false);
-    invoked[3] = false;
-    host.appendChild(chb3);
-
-    var s = host.attachShadow({mode: 'open'});
-
-    var div = d.createElement('div');
-    div.innerHTML = '<slot name="shadow"></slot>';
-    s.appendChild(div);
-
-    var inp1 = d.createElement('input');
-    inp1.setAttribute('type', 'text');
-    inp1.setAttribute('id', 'shInp1');
-    inp1.setAttribute('value', 'Input 1');
-    inp1.setAttribute('tabindex', '4');
-    inp1.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
-        assert_equals(counter++, 3, 'Point 4: wrong focus navigation order');
-        invoked[4] = true;
-    }), false);
-    invoked[4] = false;
-    s.appendChild(inp1);
-
-    var inp2 = d.createElement('input');
-    inp2.setAttribute('type', 'text');
-    inp2.setAttribute('id', 'shInp2');
-    inp2.setAttribute('value', 'Input 2');
-    inp2.setAttribute('tabindex', '4');
-    inp2.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
-        assert_equals(counter++, 5, 'Point 5: wrong focus navigation order');
-        invoked[5] = true;
-    }), false);
-    invoked[5] = false;
-    d.body.appendChild(inp2);
-
-    var chb4 = d.createElement('input');
-    chb4.setAttribute('type', 'checkbox');
-    chb4.setAttribute('id', 'chb4');
-    chb4.setAttribute('tabindex', '2');
-    chb4.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
-        assert_equals(counter++, 2, 'Point 6: wrong focus navigation order');
-        invoked[6] = true;
-    }), false);
-    invoked[6] = false;
-    d.body.appendChild(chb4);
-
-    chb1.focus();
-
-    //simulate TAB clicks
-    //Expected order: chb1, chb3, chb4, chb2, inp1, inp2
-    fireKeyboardEvent(d, chb1, 'U+0009');
-    fireKeyboardEvent(d, chb3, 'U+0009');
-    fireKeyboardEvent(d, chb4, 'U+0009');
-    fireKeyboardEvent(d, chb2, 'U+0009');
-    fireKeyboardEvent(d, inp1, 'U+0009');
-    fireKeyboardEvent(d, inp2, 'U+0009');
-
-
-
-    for (var i = 1; i < invoked.length; i++) {
-        if (!invoked[i]) {
-            assert_true(false, 'Point ' + i + ' event listener was not invoked');
-        }
-    }
-
-    A_07_02_04_T02.done();
-}));
-
-
-
-// Shadow root is the first in nav order
-var A_07_02_04_T03 = async_test('A_07_02_04_T03');
-
-A_07_02_04_T03.step(unit(function (ctx) {
-
-    var counter = 0;
-
-    var invoked = [];
-
-    var d = newRenderedHTMLDocument(ctx);
-
-    var chb1 = d.createElement('input');
-    chb1.setAttribute('type', 'checkbox');
-    chb1.setAttribute('tabindex', '3');
-    chb1.setAttribute('id', 'chb1');
-    chb1.addEventListener('focus', A_07_02_04_T03.step_func(function(event) {
-        assert_equals(counter++, 4, 'Point 1: wrong focus navigation order');
-        invoked[1] = true;
-    }), false);
-    invoked[1] = false;
-    d.body.appendChild(chb1);
-
-    var host = d.createElement('div');
-    host.setAttribute('tabindex', '1');
-    d.body.appendChild(host);
-    var s = host.attachShadow({mode: 'open'});
-
-    var inp1 = d.createElement('input');
-    inp1.setAttribute('type', 'text');
-    inp1.setAttribute('id', 'shInp1');
-    inp1.setAttribute('tabindex', '2');
-    inp1.setAttribute('value', 'Input 1');
-    inp1.addEventListener('focus', A_07_02_04_T03.step_func(function(event) {
-        assert_equals(counter++, 1, 'Point 2: wrong focus navigation order');
-        invoked[2] = true;
-    }), false);
-    invoked[2] = false;
-    s.appendChild(inp1);
-
-    var inp2 = d.createElement('input');
-    inp2.setAttribute('type', 'text');
-    inp2.setAttribute('id', 'shInp2');
-    inp2.setAttribute('tabindex', '1');
-    inp2.setAttribute('value', 'Input 2');
-    inp2.addEventListener('focus', A_07_02_04_T03.step_func(function(event) {
-        assert_equals(counter++, 0, 'Point 3: wrong focus navigation order');
-        invoked[3] = true;
-    }), false);
-    invoked[3] = false;
-    s.appendChild(inp2);
-
-    var chb2 = d.createElement('input');
-    chb2.setAttribute('type', 'checkbox');
-    chb2.setAttribute('id', 'chb2');
-    chb2.setAttribute('tabindex', '3');
-    chb2.addEventListener('focus', A_07_02_04_T03.step_func(function(event) {
-        assert_equals(counter++, 2, 'Point 4: wrong focus navigation order');
-        invoked[4] = true;
-    }), false);
-    invoked[4] = false;
-    s.appendChild(chb2);
-
-    var chb3 = d.createElement('input');
-    chb3.setAttribute('type', 'checkbox');
-    chb3.setAttribute('id', 'chb3');
-    chb3.setAttribute('tabindex', '2');
-    chb3.addEventListener('focus', A_07_02_04_T03.step_func(function(event) {
-        assert_equals(counter++, 3, 'Point 5: wrong focus navigation order');
-        invoked[5] = true;
-    }), false);
-    invoked[5] = false;
-    d.body.appendChild(chb3);
-
-    host.focus();
-
-    //simulate TAB clicks. Expected order: inp2, inp1, chb2, chb3, chb1
-    fireKeyboardEvent(d, inp2, 'U+0009');
-    fireKeyboardEvent(d, inp1, 'U+0009');
-    fireKeyboardEvent(d, chb2, 'U+0009');
-    fireKeyboardEvent(d, chb3, 'U+0009');
-    fireKeyboardEvent(d, chb1, 'U+0009');
-
-    for (var i = 1; i < invoked.length; i++) {
-        if (!invoked[i]) {
-            assert_true(false, 'Piont ' + i + ' event listener was not invoked');
-        }
-    }
-
-    A_07_02_04_T03.done();
-}));
-
-
-//Shadow root is the last in nav order
-var A_07_02_04_T04 = async_test('A_07_02_04_T04');
-
-A_07_02_04_T04.step(unit(function (ctx) {
-
-    var counter = 0;
-
-    var invoked = [];
-
-    var d = newRenderedHTMLDocument(ctx);
-
-    var chb1 = d.createElement('input');
-    chb1.setAttribute('type', 'checkbox');
-    chb1.setAttribute('tabindex', '1');
-    chb1.setAttribute('id', 'chb1');
-    chb1.addEventListener('focus', A_07_02_04_T04.step_func(function(event) {
-        assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
-        invoked[1] = true;
-    }), false);
-    invoked[1] = false;
-    d.body.appendChild(chb1);
-
-    var host = d.createElement('div');
-    host.setAttribute('tabindex', '3');
-    d.body.appendChild(host);
-    var s = host.attachShadow({mode: 'open'});
-
-    var inp1 = d.createElement('input');
-    inp1.setAttribute('type', 'text');
-    inp1.setAttribute('id', 'shInp1');
-    inp1.setAttribute('tabindex', '2');
-    inp1.setAttribute('value', 'Input 1');
-    inp1.addEventListener('focus', A_07_02_04_T04.step_func(function(event) {
-        assert_equals(counter++, 3, 'Point 2: wrong focus navigation order');
-        invoked[2] = true;
-    }), false);
-    invoked[2] = false;
-    s.appendChild(inp1);
-
-    var inp2 = d.createElement('input');
-    inp2.setAttribute('type', 'text');
-    inp2.setAttribute('id', 'shInp2');
-    inp2.setAttribute('tabindex', '1');
-    inp2.setAttribute('value', 'Input 2');
-    inp2.addEventListener('focus', A_07_02_04_T04.step_func(function(event) {
-        assert_equals(counter++, 2, 'Point 3: wrong focus navigation order');
-        invoked[3] = true;
-    }), false);
-    invoked[3] = false;
-    s.appendChild(inp2);
-
-    var chb2 = d.createElement('input');
-    chb2.setAttribute('type', 'checkbox');
-    chb2.setAttribute('id', 'chb2');
-    chb2.setAttribute('tabindex', '3');
-    chb2.addEventListener('focus', A_07_02_04_T04.step_func(function(event) {
-        assert_equals(counter++, 4, 'Point 4: wrong focus navigation order');
-        invoked[4] = true;
-    }), false);
-    invoked[4] = false;
-    s.appendChild(chb2);
-
-    var chb3 = d.createElement('input');
-    chb3.setAttribute('type', 'checkbox');
-    chb3.setAttribute('id', 'chb3');
-    chb3.setAttribute('tabindex', '2');
-    chb3.addEventListener('focus', A_07_02_04_T04.step_func(function(event) {
-        assert_equals(counter++, 1, 'Point 5: wrong focus navigation order');
-        invoked[5] = true;
-    }), false);
-    invoked[5] = false;
-    d.body.appendChild(chb3);
-
-    chb1.focus();
-
-    //simulate TAB clicks. Expected order: inp2, inp1, chb2, chb3, chb1
-    fireKeyboardEvent(d, chb1, 'U+0009');
-    fireKeyboardEvent(d, chb3, 'U+0009');
-    fireKeyboardEvent(d, inp2, 'U+0009');
-    fireKeyboardEvent(d, inp1, 'U+0009');
-    fireKeyboardEvent(d, chb2, 'U+0009');
-
-    for (var i = 1; i < invoked.length; i++) {
-        if (!invoked[i]) {
-            assert_true(false, 'Piont ' + i + ' event listener was not invoked');
-        }
-    }
-
-    A_07_02_04_T04.done();
-}));
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/uievents/keyboard/key-manual.css b/third_party/WebKit/LayoutTests/imported/wpt/uievents/keyboard/key-manual.css
deleted file mode 100644
index b2add2a..0000000
--- a/third_party/WebKit/LayoutTests/imported/wpt/uievents/keyboard/key-manual.css
+++ /dev/null
@@ -1,118 +0,0 @@
-.keyboard {
-    display: table;
-    border-collapse: separate;
-    border-spacing: 2px;
-    width: 800px;
-    border: 2px solid black;
-    border-radius: 10px;
-    padding: 5px;
-}
-
-.key-row {
-    display: table;
-    margin: 0;
-    padding: 0;
-}
-
-.key {
-    display: table-cell;
-    border: 2px solid black;
-    border-radius: 8px;
-    width: 50px;
-    height: 40px;
-    vertical-align: middle;
-    text-align: center;
-    margin: 0;
-    padding: 0;
-}
-
-.wide1 {
-    width: 70px;
-}
-
-.wide2 {
-    width: 90px;
-}
-
-.wide3 {
-    width: 110px;
-}
-
-.wide4 {
-    width: 130px;
-}
-
-.wide5 {
-    width: 300px;
-}
-
-.nextKey {
-    background-color: yellow;
-}
-
-.goodKey {
-    background-color: #80ff08;
-}
-
-.badKey {
-    background-color: #ff8080;
-}
-
-.activeModifierKey {
-    background-color: #a0a0ff;
-}
-
-.skippedKey {
-    background-color: #e0e0e0;
-}
-
-#options {
-    display: none;
-    margin: 20px;
-}
-
-#optionstoggle, #helptoggle {
-    font-size: 10pt;
-}
-
-.opttable {
-    border: 1px solid black;
-}
-
-.optcell {
-    vertical-align: top;
-    padding: 0 10px;
-}
-
-.opttitle {
-    font-weight: bold;
-}
-
-.error {
-    border: 1px solid red;
-    margin: 5px;
-    padding: 5px;
-}
-
-.error1 {
-    font-size: 12pt;
-    margin: 0 0 0 10px;
-    padding: 0;
-}
-
-.error2 {
-    font-size: 10pt;
-    margin: 0 0 0 20px;
-    padding: 0;
-}
-
-.help {
-    font-size: 11pt;
-    margin: 0 0 5px 20px;
-    padding: 0;
-}
-
-body {
-    margin: 10px;
-    padding: 0 20px;
-}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/uievents/keyboard/key-manual.js b/third_party/WebKit/LayoutTests/imported/wpt/uievents/keyboard/key-manual.js
deleted file mode 100644
index 175258b..0000000
--- a/third_party/WebKit/LayoutTests/imported/wpt/uievents/keyboard/key-manual.js
+++ /dev/null
@@ -1,671 +0,0 @@
-var _testing = false;
-
-// The index into _keyTable of the key currently being tested.
-var _currKey = 0;
-
-var _keysTotal = 0;
-var _keysGood = 0;
-var _keysBad = 0;
-var _keysSkipped = 0;
-
-var _modifierMode = "None";
-
-var _keydownCapture = [];
-var _keyupCapture = [];
-
-var CAPTURE_KEYCODE = 0;
-var CAPTURE_CODE = 1;
-var CAPTURE_KEY = 2;
-var CAPTURE_SHIFTKEY = 3;
-var CAPTURE_CONTROLKEY = 4;
-var CAPTURE_ALTKEY = 5;
-var CAPTURE_METAKEY = 6;
-
-// An array of KeyInfo for each key to be tested.
-var _keyTable = [];
-
-// KeyInfo fields.
-var KEYINFO_CODE = 0;       // |code| for this key
-var KEYINFO_ROW = 1;        // Keyboard row
-var KEYINFO_TYPE = 2;       // Key type (see below)
-var KEYINFO_WIDTH = 3;      // Width of key: 0=normal
-var KEYINFO_KEYCAP = 4;     // Keycap string to display
-var KEYINFO_KEY = 5;        // Unmodified key value
-var KEYINFO_KEY_SHIFT = 6;  // Shifted key value
-
-var KEYTYPE_NORMAL = 0;
-var KEYTYPE_DISABLED = 1;   // Key cannot be tested: e.g., CapsLock
-var KEYTYPE_END = 2;        // Used to mark end of KeyTable
-var KEYTYPE_MODIFIER = 3;   // Modifer key
-
-function clearChildren(e) {
-    while (e.firstChild !== null) {
-        e.removeChild(e.firstChild);
-    }
-}
-
-function setText(e, text) {
-    clearChildren(e);
-    e.appendChild(document.createTextNode(text));
-}
-
-function setUserAgent() {
-    var userAgent = navigator.userAgent;
-    uaDiv = document.getElementById("useragent");
-    setText(uaDiv, userAgent);
-}
-
-function addEventListener(obj, etype, handler) {
-    if (obj.addEventListener) {
-        obj.addEventListener(etype, handler, false);
-    } else if (obj.attachEvent) {
-        obj.attachEvent("on"+etype, handler);
-    } else {
-        obj["on"+etype] = handler;
-    }
-}
-
-function addClass(obj, className) {
-    obj.classList.add(className);
-}
-
-function removeClass(obj, className) {
-    obj.classList.remove(className);
-}
-
-function addInnerText(obj, text) {
-    obj.appendChild(document.createTextNode(text));
-}
-
-function calcLocation(loc) {
-    if (loc == 1) return "LEFT";
-    if (loc == 2) return "RIGHT";
-    if (loc == 3) return "NUMPAD";
-    return loc;
-}
-
-function isModifierKey(e) {
-    // Shift, Control, Alt
-    if (e.keyCode >= 16 && e.keyCode <= 18) {
-        return true;
-    }
-    // Windows, Command or Meta key.
-    if (e.keyCode == 224 // Right/Left: Gecko
-        || e.keyCode == 91    // Left: WebKit/Blink
-        || e.keyCode == 93    // Right: WebKit/Blink
-        ) {
-        return true;
-    }
-    return false;
-}
-
-function init(title, keytable) {
-    _keyTable = keytable;
-
-    createBody(title, keytable);
-
-    setUserAgent();
-
-    var input = document.getElementById("input");
-    input.disabled = true;
-    addEventListener(input, "keydown", onKeyDown);
-    addEventListener(input, "keyup", onKeyUp);
-    //addEventListener(input, "beforeInput", onBeforeInput);
-    //addEventListener(input, "input", onInput);
-}
-
-function onKeyDown(e) {
-    // Ignore modifier keys when checking modifier combinations.
-    if (_modifierMode != "None" && isModifierKey(e)) {
-        return;
-    }
-
-    _keydownInfo = [e.keyCode, e.code, e.key, e.shiftKey, e.ctrlKey, e.altKey, e.metaKey];
-    if (e.keyCode == 9 || e.code == "Tab") {
-        e.preventDefault();
-    }
-}
-
-function onKeyUp(e) {
-    // Ignore modifier keys when checking modifier combinations.
-    if (_modifierMode != "None" && isModifierKey(e)) {
-        return;
-    }
-
-    _keyupInfo = [e.keyCode, e.code, e.key, e.shiftKey, e.ctrlKey, e.altKey, e.metaKey];
-
-    if (_testing) {
-        verifyKey();
-        nextKey();
-    }
-}
-
-function onBeforeInput(e) {
-}
-
-function onInput(e) {
-}
-
-function addError(elem, str) {
-    var p = document.createElement('p');
-    p.classList.add("error2");
-    p.textContent = str;
-    elem.appendChild(p);
-}
-
-function addErrorIncorrect(elem, eventName, attrName, keyEventInfo, attr, expected) {
-    addError(elem, "Incorrect " + eventName
-        + " |" + attrName + "| = " + keyEventInfo[attr]
-        + " - Expected " + expected);
-}
-
-function verifyKeyEventFields(eventName, keyEventInfo, code, key, error) {
-    var verifyCode = document.getElementById("opt_attr_code").checked;
-    var verifyKey = document.getElementById("opt_attr_key").checked;
-    var verifyModifiers = document.getElementById("opt_attr_modifiers").checked;
-    var good = true;
-
-    if (!verifyCode && !verifyKey && !verifyModifiers) {
-        good = false;
-        addError(error, "Invalid test: At least one attribute must be selected for testing.");
-    }
-    if (verifyCode && keyEventInfo[CAPTURE_CODE] != code) {
-        good = false;
-        addErrorIncorrect(error, eventName, "code", keyEventInfo, CAPTURE_CODE, code);
-    }
-    if (verifyKey && keyEventInfo[CAPTURE_KEY] != key) {
-        good = false;
-        addErrorIncorrect(error, eventName, "key", keyEventInfo, CAPTURE_KEY, key);
-    }
-    if (verifyModifiers) {
-        if (keyEventInfo[CAPTURE_SHIFTKEY] != (_modifierMode == "Shift")) {
-            good = false;
-            addErrorIncorrect(error, eventName, "shiftKey", keyEventInfo, CAPTURE_SHIFTKEY, false);
-        }
-        if (keyEventInfo[CAPTURE_CONTROLKEY]) {
-            good = false;
-            addErrorIncorrect(error, eventName, "controlKey", keyEventInfo, CAPTURE_CONTROLKEY, false);
-        }
-        if (keyEventInfo[CAPTURE_ALTKEY]) {
-            good = false;
-            addErrorIncorrect(error, eventName, "altKey", keyEventInfo, CAPTURE_ALTKEY, false);
-        }
-        if (keyEventInfo[CAPTURE_METAKEY]) {
-            good = false;
-            addErrorIncorrect(error, eventName, "metaKey", keyEventInfo, CAPTURE_METAKEY, false);
-        }
-    }
-
-    return good;
-}
-
-function verifyKey() {
-    _keysTotal++;
-
-    var keyInfo = _keyTable[_currKey];
-    var code = keyInfo[KEYINFO_CODE];
-    var key = keyInfo[KEYINFO_KEY];
-    var keyShift = keyInfo[KEYINFO_KEY_SHIFT];
-
-    var keyCheck = key;
-    if (_modifierMode == "Shift") {
-        keyCheck = keyShift;
-    }
-
-    var verifyKeydown = document.getElementById("opt_event_keydown").checked;
-    var verifyKeyup = document.getElementById("opt_event_keyup").checked;
-
-    var error = document.createElement('div');
-    error.classList.add("error");
-    var good = true;
-
-    if (verifyKeydown) {
-        good = verifyKeyEventFields("keydown", _keydownInfo, code, keyCheck, error);
-    }
-    if (verifyKeyup) {
-        good = verifyKeyEventFields("keyup", _keyupInfo, code, keyCheck, error);
-    }
-
-    if (!verifyKeydown && !verifyKeyup) {
-        good = false;
-        addError(error, "Invalid test: At least one event must be selected for testing.");
-    }
-
-    // Allow Escape key to skip the current key.
-    var skipped = false;
-    if (_keydownInfo[CAPTURE_KEYCODE] == 27 || _keydownInfo[CAPTURE_CODE] == "Escape") {
-        good = true;
-        skipped = true;
-    }
-
-    if (!good) {
-        var p = document.createElement('p');
-        p.classList.add("error1");
-        p.textContent = "Error : " + code;
-        error.insertBefore(p, error.firstChild);
-    }
-
-    removeNextKeyHilight();
-    if (skipped) {
-        _keysSkipped++;
-        document.getElementById(code).classList.add("skippedKey")
-    } else if (good) {
-        _keysGood++;
-        document.getElementById(code).classList.add("goodKey")
-    } else {
-        _keysBad++;
-        document.getElementById(code).classList.add("badKey")
-    }
-    updateTestSummary(good ? null : error);
-}
-
-function updateTestSummary(error) {
-    document.getElementById("keys-total").textContent = _keysTotal;
-    document.getElementById("keys-good").textContent = _keysGood;
-    document.getElementById("keys-bad").textContent = _keysBad;
-    document.getElementById("keys-skipped").textContent = _keysSkipped;
-
-    if (error) {
-        var errors = document.getElementById("errors");
-        errors.insertBefore(error, errors.firstChild);
-    }
-}
-
-function resetTest() {
-    _keysTotal = 0;
-    _keysGood = 0;
-    _keysBad = 0;
-
-    _currKey = -1;
-    nextKey();
-
-    updateTestSummary();
-
-    // Remove previous test results.
-    clearChildren(document.getElementById("errors"));
-
-    // Remove highlighting from keys.
-    for (var i = 0; i < _keyTable.length; i++) {
-        var code = _keyTable[i][KEYINFO_CODE];
-        var type = _keyTable[i][KEYINFO_TYPE];
-        if (type != KEYTYPE_END) {
-            var key = document.getElementById(code);
-            key.classList.remove("goodKey");
-            key.classList.remove("badKey");
-            key.classList.remove("skippedKey");
-        }
-    }
-}
-
-function startTest() {
-    if (_testing) {
-        // Cancel the currently running test.
-        endTest();
-        return;
-    }
-
-    resetTest();
-    _testing = true;
-    document.getElementById("start").value = "Stop Test"
-
-    var input = document.getElementById("input");
-    input.value = "";
-    input.disabled = false;
-    input.focus();
-
-    // Show test instructions and info.
-    document.getElementById("test-info").style.display = 'block';
-    document.getElementById("instructions").style.display = 'block';
-    document.getElementById("test-done").style.display = 'none';
-}
-
-function endTest() {
-    _testing = false;
-    removeNextKeyHilight();
-    document.getElementById("start").value = "Restart Test"
-    document.getElementById("input").disabled = true;
-    document.getElementById("instructions").style.display = 'none';
-    document.getElementById("test-done").style.display = 'block';
-}
-
-function removeNextKeyHilight() {
-    var curr = document.getElementById(_keyTable[_currKey][KEYINFO_CODE]);
-    if (curr) {
-        removeClass(curr, "nextKey")
-    }
-}
-
-function addNextKeyHilight() {
-    var curr = document.getElementById(_keyTable[_currKey][KEYINFO_CODE]);
-    if (curr) {
-        addClass(curr, "nextKey")
-    }
-}
-
-function nextKey() {
-    var keyInfo;
-    var keepLooking = true;
-    do {
-        _currKey++;
-        keyInfo = _keyTable[_currKey];
-        var type = keyInfo[KEYINFO_TYPE];
-
-        // Skip over disabled keys.
-        keepLooking = (type == KEYTYPE_DISABLED);
-
-        // Skip over modifier keys if we're testing modifier combinations.
-        if (_modifierMode != "None" && type == KEYTYPE_MODIFIER) {
-            keepLooking = true;
-        }
-
-        // Skip over keys in disabled rows.
-        if (type != KEYTYPE_END) {
-            var row = keyInfo[KEYINFO_ROW];
-            var rowEnabled = document.getElementById("opt_row_" + row).checked;
-            keepLooking = keepLooking || !rowEnabled;
-        }
-    } while (keepLooking);
-
-    if (keyInfo[KEYINFO_TYPE] == KEYTYPE_END) {
-        endTest();
-    } else {
-        addNextKeyHilight();
-    }
-}
-
-function toggleOptions() {
-    var link = document.getElementById("optionstoggle");
-    var options = document.getElementById("options");
-    clearChildren(link);
-    if (options.style.display == "block") {
-        options.style.display = "none";
-        addInnerText(link, "Show Options");
-    }
-    else {
-        options.style.display = "block";
-        addInnerText(link, "Hide Options");
-    }
-}
-
-function toggleHelp() {
-    var link = document.getElementById("helptoggle");
-    var help = document.getElementById("help");
-    clearChildren(link);
-    if (help.style.display == "block") {
-        help.style.display = "none";
-        addInnerText(link, "Show Help");
-    }
-    else {
-        help.style.display = "block";
-        addInnerText(link, "Hide Help");
-    }
-}
-
-function createBody(title, keytable) {
-    var body = document.getElementsByTagName("body")[0];
-    var p;
-    var span;
-
-    var h1 = document.createElement('h1');
-    h1.textContent = "Keyboard Event Manual Test - " + title;
-    body.appendChild(h1);
-
-    // Display useragent.
-    p = document.createElement('p');
-    p.textContent = "UserAgent: ";
-    var useragent = document.createElement('span');
-    useragent.id = "useragent";
-    p.appendChild(useragent);
-    body.appendChild(p);
-
-    // Display input textedit.
-    p = document.createElement('p');
-    p.textContent = "Test Input: ";
-    var input1 = document.createElement('input');
-    input1.id = "input";
-    input1.type = "text";
-    input1.size = 80;
-    p.appendChild(input1);
-    p.appendChild(document.createTextNode(" "));
-    var input2 = document.createElement('input');
-    input2.id = "start";
-    input2.type = "button";
-    input2.onclick = function() { startTest(); return false; }
-    input2.value = "Start Test";
-    p.appendChild(input2);
-    p.appendChild(document.createTextNode(" "));
-    var optionsToggle = document.createElement('a');
-    optionsToggle.id = "optionstoggle";
-    optionsToggle.href = "javascript:toggleOptions()";
-    optionsToggle.textContent = "Show Options";
-    p.appendChild(optionsToggle);
-    p.appendChild(document.createTextNode(" "));
-    var helpToggle = document.createElement('a');
-    helpToggle.id = "helptoggle";
-    helpToggle.href = "javascript:toggleHelp()";
-    helpToggle.textContent = "Show Help";
-    p.appendChild(helpToggle);
-    body.appendChild(p);
-
-    createOptions(body);
-
-    createHelp(body);
-
-    createKeyboard(body, keytable);
-
-    // Test info and summary.
-    var test_info = document.createElement('div');
-    test_info.id = "test-info";
-    test_info.style.display = "none";
-
-    var instructions = document.createElement('div');
-    instructions.id = "instructions";
-    p = document.createElement('p');
-    p.textContent = "Press the highlighted key.";
-    instructions.appendChild(p);
-    test_info.appendChild(instructions);
-
-    var test_done = document.createElement('div');
-    test_done.id = "test-done";
-    p = document.createElement('p');
-    p.textContent = "Test complete!";
-    test_done.appendChild(p);
-    test_info.appendChild(test_done);
-
-    var summary = document.createElement('div');
-    summary.id = "summary";
-    p = document.createElement('p');
-    summary.appendChild(document.createTextNode("Keys Tested: "));
-    span = document.createElement('span');
-    span.id = "keys-total";
-    span.textContent = 0;
-    summary.appendChild(span);
-    summary.appendChild(document.createTextNode("; Passed "));
-    span = document.createElement('span');
-    span.id = "keys-good";
-    span.textContent = 0;
-    summary.appendChild(span);
-    summary.appendChild(document.createTextNode("; Failed "));
-    span = document.createElement('span');
-    span.id = "keys-bad";
-    span.textContent = 0;
-    summary.appendChild(span);
-    summary.appendChild(document.createTextNode("; Skipped "));
-    span = document.createElement('span');
-    span.id = "keys-skipped";
-    span.textContent = 0;
-    summary.appendChild(span);
-    test_info.appendChild(summary);
-
-    var errors = document.createElement('div');
-    errors.id = "errors";
-    test_info.appendChild(errors);
-
-    body.appendChild(test_info);
-}
-
-function addOptionTitle(cell, title) {
-    var span = document.createElement('span');
-    span.classList.add("opttitle");
-    span.textContent = title;
-    cell.appendChild(span);
-    cell.appendChild(document.createElement("br"));
-}
-
-function addOptionCheckbox(cell, id, text) {
-    var label = document.createElement("label");
-
-    var input = document.createElement("input");
-    input.type = "checkbox";
-    input.id = id;
-    input.checked = true;
-    label.appendChild(input);
-
-    label.appendChild(document.createTextNode(" " + text));
-    cell.appendChild(label);
-
-    cell.appendChild(document.createElement("br"));
-}
-
-function addOptionRadio(cell, group, text, handler, checked) {
-    var label = document.createElement("label");
-
-    var input = document.createElement("input");
-    input.type = "radio";
-    input.name = group;
-    input.value = text;
-    input.onclick = handler;
-    input.checked = checked;
-    label.appendChild(input);
-
-    label.appendChild(document.createTextNode(" " + text));
-    cell.appendChild(label);
-
-    cell.appendChild(document.createElement("br"));
-}
-
-function handleModifierGroup() {
-    var radio = document.querySelector("input[name=opt_modifier]:checked");
-    var oldMode = _modifierMode;
-    _modifierMode = radio.value;
-
-    if (oldMode == "Shift") {
-        document.getElementById("ShiftLeft").classList.remove("activeModifierKey");
-        document.getElementById("ShiftRight").classList.remove("activeModifierKey");
-    }
-
-    if (_modifierMode == "Shift") {
-        document.getElementById("ShiftLeft").classList.add("activeModifierKey");
-        document.getElementById("ShiftRight").classList.add("activeModifierKey");
-    }
-}
-
-function createOptions(body) {
-    var options = document.createElement('div');
-    options.id = "options";
-    options.style.display = "none";
-
-    var table = document.createElement('table');
-    table.classList.add("opttable");
-    var row = document.createElement('tr');
-    var cell;
-
-    cell = document.createElement('td');
-    cell.classList.add("optcell");
-    addOptionTitle(cell, "Keyboard Rows");
-    addOptionCheckbox(cell, "opt_row_0", "Row E (top)");
-    addOptionCheckbox(cell, "opt_row_1", "Row D");
-    addOptionCheckbox(cell, "opt_row_2", "Row C");
-    addOptionCheckbox(cell, "opt_row_3", "Row B");
-    addOptionCheckbox(cell, "opt_row_4", "Row A (bottom)");
-    row.appendChild(cell);
-
-    cell = document.createElement('td');
-    cell.classList.add("optcell");
-    addOptionTitle(cell, "Events");
-    addOptionCheckbox(cell, "opt_event_keydown", "keydown");
-    addOptionCheckbox(cell, "opt_event_keyup", "keyup");
-    row.appendChild(cell);
-
-    cell = document.createElement('td');
-    cell.classList.add("optcell");
-    addOptionTitle(cell, "Attributes");
-    addOptionCheckbox(cell, "opt_attr_code", "code");
-    addOptionCheckbox(cell, "opt_attr_key", "key");
-    addOptionCheckbox(cell, "opt_attr_modifiers", "modifiers");
-    row.appendChild(cell);
-
-    cell = document.createElement('td');
-    cell.classList.add("optcell");
-    addOptionTitle(cell, "Modifiers");
-    addOptionRadio(cell, "opt_modifier", "None", handleModifierGroup, true);
-    addOptionRadio(cell, "opt_modifier", "Shift", handleModifierGroup, false);
-    row.appendChild(cell);
-
-    table.appendChild(row);
-    options.appendChild(table);
-
-    body.appendChild(options);
-}
-
-function addHelpText(div, text) {
-    var p = document.createElement('p');
-    p.classList.add("help");
-    p.textContent = text;
-    div.appendChild(p);
-}
-
-function createHelp(body) {
-    var help = document.createElement('div');
-    help.id = "help";
-    help.style.display = "none";
-
-    addHelpText(help, "Click on the \"Start Test\" button to begin testing.");
-    addHelpText(help, "Press the hilighted key to test it.");
-    addHelpText(help, "Clicking anywhere outside the \"Test Input\" editbox will pause testing. To resume, click back inside the editbox.");
-    addHelpText(help, "To skip a key while testing, press Escape.");
-    addHelpText(help, "When testing with modifier keys, the modifier must be pressed before the keydown and released after the keyup of the key being tested.");
-
-    body.appendChild(help);
-}
-
-function createKeyboard(body, keytable) {
-    var keyboard = document.createElement('div');
-    keyboard.classList.add("keyboard");
-
-    var currRow = 0;
-    var row = document.createElement('div');
-    row.classList.add("key-row");
-
-    for (var i = 0; i < keytable.length; i++) {
-        var code = keytable[i][KEYINFO_CODE];
-        var rowId = keytable[i][KEYINFO_ROW];
-        var type = keytable[i][KEYINFO_TYPE];
-        var width = keytable[i][KEYINFO_WIDTH];
-        var keyCap = keytable[i][KEYINFO_KEYCAP];
-
-        if (type == KEYTYPE_END) {
-            continue;
-        }
-
-        if (rowId != currRow) {
-            keyboard.appendChild(row);
-            row = document.createElement('div');
-            row.classList.add("key-row");
-            currRow = rowId;
-        }
-
-        var key = document.createElement('div');
-        key.id = code;
-        key.classList.add("key");
-        if (width != 0) {
-            key.classList.add("wide" + width);
-        }
-        key.textContent = keyCap;
-
-        row.appendChild(key);
-    }
-
-    keyboard.appendChild(row);
-    body.appendChild(keyboard);
-}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/README.md b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/README.md
index ca01178a..c6d7c72 100644
--- a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/README.md
+++ b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/README.md
@@ -12,17 +12,17 @@
     For example, if you want to test setting the start time, you might be
     tempted to put all the tests in:
 
-    > `/web-animations/Animation/startTime.html`
+    > `/web-animations/interfaces/Animation/startTime.html`
 
     However, in the spec most of the logic is in the &ldquo;Set the animation
     start time&ldquo; procedure in the &ldquo;Timing model&rdquo; section.
 
     Instead, try something like:
 
-    > *   `/web-animations/timing-model/animation/set-the-animation-start-time.html`<br>
+    > *   `/web-animations/timing-model/animations/set-the-animation-start-time.html`<br>
     >     Tests all the branches and inputs to the procedure as defined in the
     >     spec (using the `Animation.startTime` API).
-    > *   `/web-animations/Animation/startTime.html`<br>
+    > *   `/web-animations/interfaces/Animation/startTime.html`<br>
     >     Tests API-layer specific issues like mapping unresolved values to
     >      null, etc.
 
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/animation-model/keyframe-effects/spacing-keyframes-expected.txt b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/animation-model/keyframe-effects/spacing-keyframes-expected.txt
new file mode 100644
index 0000000..b814546
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/animation-model/keyframe-effects/spacing-keyframes-expected.txt
@@ -0,0 +1,19 @@
+This is a testharness.js-based test.
+FAIL Test distribute spacing anim.effect.getKeyframes is not a function
+FAIL Test distribute spacing with specific offsets anim.effect.getKeyframes is not a function
+FAIL Test paced spacing without any keyframe anim.effect.getKeyframes is not a function
+FAIL Test paced spacing anim.effect.getKeyframes is not a function
+FAIL Test paced spacing with specific offsets anim.effect.getKeyframes is not a function
+FAIL Test paced spacing if some paced property values are equal anim.effect.getKeyframes is not a function
+FAIL Test falling back to distribute spacing if all paced property value are equal anim.effect.getKeyframes is not a function
+FAIL Test paced spacing if there a keyframe without the paced property anim.effect.getKeyframes is not a function
+FAIL Test paced spacing if a paced property that appears on only some keyframes anim.effect.getKeyframes is not a function
+FAIL Test paced spacing if a paced property that appears on only some keyframes and there is a specific offset anim.effect.getKeyframes is not a function
+FAIL Test paced spacing where there are some keyframes without offsets and without the paced property before the first paceable keyframe and after the last paceable keyframe anim.effect.getKeyframes is not a function
+FAIL Test paced spacing for using shorthand property anim.effect.getKeyframes is not a function
+FAIL Test paced spacing using shorthand property where only the longhand components are specified anim.effect.getKeyframes is not a function
+FAIL Test falling back to distribute spacing if all keyframe miss some components anim.effect.getKeyframes is not a function
+FAIL Test paced spacing only for keyframes specifying all longhand components, and falling back to distribute spacing for the reset anim.effect.getKeyframes is not a function
+FAIL Test paced spacing only for keyframes specifying all some components, and falling back to distribute spacing for the reset with some specific offsets anim.effect.getKeyframes is not a function
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/animation-model/keyframe-effects/spacing-keyframes.html b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/animation-model/keyframe-effects/spacing-keyframes.html
new file mode 100644
index 0000000..14dc32b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/animation-model/keyframe-effects/spacing-keyframes.html
@@ -0,0 +1,328 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Keyframe spacing tests</title>
+<link rel="help" href="https://w3c.github.io/web-animations/#spacing-keyframes">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<body>
+<div id="log"></div>
+<script>
+"use strict";
+
+test(function(t) {
+  var anim = createDiv(t).animate([ { marginLeft: '0px' },
+                                    { marginLeft: '-20px' },
+                                    { marginLeft: '100px' },
+                                    { marginLeft: '50px' } ],
+                                  { duration: 100 * MS_PER_SEC });
+
+  var frames = anim.effect.getKeyframes();
+  var slots = frames.length - 1;
+  assert_equals(frames[0].computedOffset, 0.0, '1st frame offset');
+  assert_equals(frames[1].computedOffset, 1.0 / slots, '2nd frame offset');
+  assert_equals(frames[2].computedOffset, 2.0 / slots, '3rd frame offset');
+  assert_equals(frames[3].computedOffset, 1.0, 'last frame offset');
+}, 'Test distribute spacing');
+
+test(function(t) {
+  var anim = createDiv(t).animate([ { marginLeft: '0px' },
+                                    { marginLeft: '-20px' },
+                                    { marginLeft: '100px', offset: 0.5 },
+                                    { marginLeft: '50px' } ],
+                                  { duration: 100 * MS_PER_SEC,
+                                    spacing: 'distribute' });
+
+  var frames = anim.effect.getKeyframes();
+  assert_equals(frames[0].computedOffset, 0.0, '1st frame offset');
+  assert_equals(frames[1].computedOffset, 0.5 * 1 / 2, '2nd frame offset');
+  assert_equals(frames[2].computedOffset, 0.5, '3rd frame offset');
+  assert_equals(frames[3].computedOffset, 1.0, 'last frame offset');
+}, 'Test distribute spacing with specific offsets');
+
+test(function(t) {
+  var anim = createDiv(t).animate(null,
+                                  { duration: 100 * MS_PER_SEC,
+                                    spacing: 'paced(margin-left)' });
+
+  var frames = anim.effect.getKeyframes();
+  assert_equals(frames.length, 0, "empty keyframe list");
+}, 'Test paced spacing without any keyframe');
+
+
+test(function(t) {
+  var anim = createDiv(t).animate([ { marginLeft: '0px' },
+                                    { marginLeft: '-20px' },
+                                    { marginLeft: '100px' },
+                                    { marginLeft: '50px' } ],
+                                  { duration: 100 * MS_PER_SEC,
+                                    spacing: 'paced(margin-left)' });
+
+  var frames = anim.effect.getKeyframes();
+  var cumDist = [0, 20, 140, 190];
+  assert_equals(frames[0].computedOffset, 0.0,
+                '1st frame offset');
+  assert_equals(frames[1].computedOffset, cumDist[1] / cumDist[3],
+                '2nd frame offset');
+  assert_equals(frames[2].computedOffset, cumDist[2] / cumDist[3],
+                '3rd frame offset');
+  assert_equals(frames[3].computedOffset, 1.0,
+                'last frame offset');
+}, 'Test paced spacing');
+
+test(function(t) {
+  var anim = createDiv(t).animate([ { marginLeft: '0px' },
+                                    { marginLeft: '-20px' },
+                                    { marginLeft: '100px', offset: 0.5 },
+                                    { marginLeft: '120px' },
+                                    { marginLeft: '50px' } ],
+                                  { duration: 100 * MS_PER_SEC,
+                                    spacing: 'paced(margin-left)' });
+
+  var frames = anim.effect.getKeyframes();
+  var cumDist1 = [ 0, 20, 140 ];
+  var cumDist2 = [ 0, 20, 90 ];
+  assert_equals(frames[1].computedOffset, 0.5 * cumDist1[1] / cumDist1[2],
+                '2nd frame offset');
+  assert_equals(frames[2].computedOffset, 0.5,
+                '3rd frame offset');
+  assert_equals(frames[3].computedOffset, 0.5 + 0.5 * cumDist2[1] / cumDist2[2],
+                '4th frame offset');
+}, 'Test paced spacing with specific offsets');
+
+test(function(t) {
+  var anim = createDiv(t).animate([ { marginLeft: '0px' },
+                                    { marginLeft: '0px' },
+                                    { marginLeft: '100px' },
+                                    { marginLeft: '50px' } ],
+                                  { duration: 100 * MS_PER_SEC,
+                                    spacing: 'paced(margin-left)' });
+
+  var frames = anim.effect.getKeyframes();
+  var cumDist = [0, 0, 100, 150];
+  assert_equals(frames[1].computedOffset, cumDist[1] / cumDist[3],
+                '2nd frame offset');
+  assert_equals(frames[2].computedOffset, cumDist[2] / cumDist[3],
+                '3rd frame offset');
+}, 'Test paced spacing if some paced property values are equal');
+
+test(function(t) {
+  var anim = createDiv(t).animate([ { marginLeft: '0px' },
+                                    { marginLeft: '0px' },
+                                    { marginLeft: '0px' },
+                                    { marginLeft: '0px' } ],
+                                  { duration: 100 * MS_PER_SEC,
+                                    spacing: 'paced(margin-left)' });
+
+  var frames = anim.effect.getKeyframes();
+  var slots = frames.length - 1;
+  assert_equals(frames[1].computedOffset, 1.0 / slots, '2nd frame offset');
+  assert_equals(frames[2].computedOffset, 2.0 / slots, '3rd frame offset');
+}, 'Test falling back to distribute spacing if all paced property value ' +
+   'are equal');
+
+test(function(t) {
+  var anim = createDiv(t).animate([ { margin: '0px' },
+                                    { marginTop: '-20px' },
+                                    { marginLeft: '100px' },
+                                    { margin: '50px' } ],
+                                  { duration: 100 * MS_PER_SEC,
+                                    spacing: 'paced(margin-left)' });
+
+  var frames = anim.effect.getKeyframes();
+  assert_equals(frames[1].computedOffset, frames[2].computedOffset * 1 / 2,
+                '2nd frame offset using distribute spacing');
+  assert_equals(frames[2].computedOffset, 100 / 150,
+                '3rd frame offset using paced spacing');
+}, 'Test paced spacing if there a keyframe without the paced property');
+
+test(function(t) {
+  var anim = createDiv(t).animate([ { margin: '0px' },
+                                    { marginTop: '40px' },
+                                    { marginTop: '-20px' },
+                                    { marginLeft: '40px' },
+                                    { marginTop: '60px' },
+                                    { margin: '10px' } ],
+                                  { duration: 100 * MS_PER_SEC,
+                                    spacing: 'paced(margin-left)' });
+
+  var frames = anim.effect.getKeyframes();
+  var cumDist = [0, 0, 0, 40, 40, 70];
+  assert_equals(frames[1].computedOffset, frames[3].computedOffset * 1 / 3,
+                '2nd frame offset using distribute spacing');
+  assert_equals(frames[2].computedOffset, frames[3].computedOffset * 2 / 3,
+                '3rd frame offset using distribute spacing');
+  assert_equals(frames[3].computedOffset, cumDist[3] / cumDist[5],
+                '4th frame offset using paced spacing');
+  assert_equals(frames[4].computedOffset,
+                frames[3].computedOffset +
+                  (1 - frames[3].computedOffset) * 1 / 2,
+                '5th frame offset using distribute spacing');
+}, 'Test paced spacing if a paced property that appears on only some ' +
+   'keyframes');
+
+test(function(t) {
+  var anim = createDiv(t).animate([ { margin: '0px' },
+                                    { marginTop: '-20px', offset: 0.5 },
+                                    { marginLeft: '40px' },
+                                    { marginLeft: '100px' },
+                                    { margin: '50px' } ],
+                                  { duration: 100 * MS_PER_SEC,
+                                    spacing: 'paced(margin-left)' });
+
+  var frames = anim.effect.getKeyframes();
+  assert_equals(frames[2].computedOffset, 0.5 + 0.5 * 1 / 3,
+                '3rd frame offset using distribute spacing because it is the ' +
+                'first paceable keyframe');
+  assert_equals(frames[3].computedOffset,
+                frames[2].computedOffset +
+                (1.0 - frames[2].computedOffset) * 60 / 110,
+                '4th frame offset using paced spacing');
+}, 'Test paced spacing if a paced property that appears on only some ' +
+   'keyframes and there is a specific offset');
+
+test(function(t) {
+  var anim = createDiv(t).animate([ { margin: '0px' },
+                                    { marginTop: '20px', offset: 0.2 },
+                                    { marginTop: '40px' },
+                                    { marginTop: '-20px' },
+                                    { marginLeft: '-20px' },
+                                    { marginLeft: '40px' },
+                                    { marginTop: '60px' },
+                                    { marginLeft: '100px' },
+                                    { marginTop: '50px' },
+                                    { marginTop: '100px', offset: 0.8 },
+                                    { margin: '0px' } ],
+                                  { duration: 100 * MS_PER_SEC,
+                                    spacing: 'paced(margin-left)' });
+  var frames = anim.effect.getKeyframes();
+  // Test distribute spacing in (A, Paced A] and [Paced B, frame B).
+  var slots = frames.length - 3;
+  var start = 0.2;
+  var diff = 0.8 - start;
+  assert_equals(frames[2].computedOffset, start + diff * 1.0 / slots,
+                '3nd frame offset using distribute spacing');
+  assert_equals(frames[3].computedOffset, start + diff * 2.0 / slots,
+                '4rd frame offset using distribute spacing');
+  assert_equals(frames[4].computedOffset, start + diff * 3.0 / slots,
+                '5th frame offset using distribute spacing because it is ' +
+                'the first paceable keyframe');
+  assert_equals(frames[7].computedOffset, start + diff * 6.0 / slots,
+                '8th frame offset using distribute spacing because it is ' +
+                'the last paceable keyframe');
+  assert_equals(frames[8].computedOffset, start + diff * 7.0 / slots,
+                '9th frame offset using distribute spacing');
+  // Test paced spacing and other null computed offsets in (Paced A, Paced B).
+  var cumDist = [0, 60, 60, 120];
+  assert_equals(frames[5].computedOffset,
+                frames[4].computedOffset + cumDist[2] / cumDist[3] *
+                  (frames[7].computedOffset - frames[4].computedOffset),
+                '6th frame offset using paced spacing');
+  assert_equals(frames[6].computedOffset,
+                frames[5].computedOffset + 1.0 / 2.0 *
+                  (frames[7].computedOffset - frames[5].computedOffset),
+                '7th frame offset using distribute spacing');
+}, 'Test paced spacing where there are some keyframes without offsets and ' +
+   'without the paced property before the first paceable keyframe and ' +
+   'after the last paceable keyframe');
+
+test(function(t) {
+  var anim = createDiv(t).animate([ { margin: '0px' },
+                                    { margin: '-20px' },
+                                    { margin: '100px' },
+                                    { margin: '50px' } ],
+                                  { duration: 100 * MS_PER_SEC,
+                                    spacing: 'paced(margin)' });
+
+  var frames = anim.effect.getKeyframes();
+  var cumDist = [0, 20, 140, 190];
+  assert_equals(frames[1].computedOffset, cumDist[1] / cumDist[3],
+                '2nd frame offset');
+  assert_equals(frames[2].computedOffset, cumDist[2] / cumDist[3],
+                '3rd frame offset');
+}, 'Test paced spacing for using shorthand property');
+
+test(function(t) {
+  var anim =
+    createDiv(t).animate([ { marginLeft: '0px',   marginRight:  '0px',
+                             marginTop:  '10px',  marginBottom: '10px' },
+                           { marginLeft: '-20px', marginRight:  '-20px',
+                             marginTop:  '0px',   marginBottom: '0px' },
+                           { marginLeft: '100px', marginRight:  '100px',
+                             marginTop:  '-50px', marginBottom: '-50px' },
+                           { marginLeft: '50px',  marginRight:  '50px',
+                             marginTop:  '80px',  marginBottom: '80px' } ],
+                         { duration: 100 * MS_PER_SEC,
+                           spacing: 'paced(margin)' });
+
+  var frames = anim.effect.getKeyframes();
+  var dist = [ 0,
+               Math.sqrt(20 * 20 * 2 + 10 * 10 * 2),
+               Math.sqrt(120 * 120 * 2 + 50 * 50 * 2),
+               Math.sqrt(50 * 50 * 2 + 130 * 130 * 2) ];
+  var cumDist = [];
+  dist.reduce(function(prev, curr, i) { return cumDist[i] = prev + curr; }, 0);
+  assert_approx_equals(frames[1].computedOffset, cumDist[1] / cumDist[3],
+                       0.0001, '2nd frame offset');
+  assert_approx_equals(frames[2].computedOffset, cumDist[2] / cumDist[3],
+                       0.0001, '3rd frame offset');
+}, 'Test paced spacing using shorthand property where only the longhand ' +
+   'components are specified');
+
+test(function(t) {
+  var anim = createDiv(t).animate([ { marginLeft: '0px', marginTop: '0px' },
+                                    { marginLeft: '-20px', marginTop: '-20px' },
+                                    { marginLeft: '100px', marginTop: '100px' },
+                                    { marginLeft: '50px', marginTop: '50px' } ],
+                                  { duration: 100 * MS_PER_SEC,
+                                    spacing: 'paced(margin)' });
+
+  var frames = anim.effect.getKeyframes();
+  var slots = frames.length - 1;
+  assert_equals(frames[1].computedOffset, 1 / slots, '2nd frame offset');
+  assert_equals(frames[2].computedOffset, 2 / slots, '3rd frame offset');
+}, 'Test falling back to distribute spacing if all keyframe miss some ' +
+   'components');
+
+test(function(t) {
+  var anim = createDiv(t).animate([ { margin: '0px' },
+                                    { marginLeft: '-20px' },
+                                    { marginTop: '40px' },
+                                    { margin: '100px' },
+                                    { margin: '50px' } ],
+                                  { duration: 100 * MS_PER_SEC,
+                                    spacing: 'paced(margin)' });
+
+  var frames = anim.effect.getKeyframes();
+  assert_equals(frames[1].computedOffset, frames[3].computedOffset * 1 / 3,
+                '2nd frame offset using distribute spacing');
+  assert_equals(frames[2].computedOffset, frames[3].computedOffset * 2 / 3,
+                '3rd frame offset using distribute spacing');
+  assert_equals(frames[3].computedOffset, 100 / 150,
+                '4th frame offset using paced spacing');
+}, 'Test paced spacing only for keyframes specifying all longhand ' +
+   'components, and falling back to distribute spacing for the reset');
+
+test(function(t) {
+  var anim = createDiv(t).animate([ { margin: '0px' },
+                                    { marginLeft: '-20px' },
+                                    { marginTop: '40px', offset: 0.5 },
+                                    { margin: '100px' },
+                                    { margin: '50px' } ],
+                                  { duration: 100 * MS_PER_SEC,
+                                    spacing: 'paced(margin)' });
+
+  var frames = anim.effect.getKeyframes();
+  assert_equals(frames[1].computedOffset, 0.5 * 1 / 2,
+                '2nd frame offset using distribute spacing');
+  assert_equals(frames[3].computedOffset, 0.5 + 0.5 * 1 / 2,
+                '4th frame offset using distribute spacing because it is the ' +
+                'first paceable keyframe from a non-null offset keyframe');
+}, 'Test paced spacing only for keyframes specifying all some components, ' +
+   'and falling back to distribute spacing for the reset with some specific ' +
+   'offsets');
+
+// Bug 1276193: Test for mixing percent and pixel values.
+
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/Animation/cancel.html b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/Animation/cancel.html
index 73f05ee..d7b0df2 100644
--- a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/Animation/cancel.html
+++ b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/Animation/cancel.html
@@ -13,7 +13,7 @@
 
 promise_test(function(t) {
   var div = createDiv(t);
-  var animation = div.animate({transform: ['none', 'translate(100px)']},
+  var animation = div.animate({transform: ['translate(100px)', 'translate(100px)']},
                               100 * MS_PER_SEC);
   return animation.ready.then(function() {
     assert_not_equals(getComputedStyle(div).transform, 'none',
@@ -26,7 +26,7 @@
 
 test(function(t) {
   var div = createDiv(t);
-  var animation = div.animate({marginLeft: ['0px', '100px']},
+  var animation = div.animate({marginLeft: ['100px', '200px']},
                               100 * MS_PER_SEC);
   animation.effect.timing.easing = 'linear';
   animation.cancel();
@@ -34,7 +34,7 @@
                 'margin-left style is not animated after cancelling');
 
   animation.currentTime = 50 * MS_PER_SEC;
-  assert_equals(getComputedStyle(div).marginLeft, '50px',
+  assert_equals(getComputedStyle(div).marginLeft, '150px',
                 'margin-left style is updated when cancelled animation is'
                 + ' seeked');
 }, 'After cancelling an animation, it can still be seeked');
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/AnimationTimeline/document-timeline.html b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/AnimationTimeline/document-timeline.html
index e4f5133f..0f782f50 100644
--- a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/AnimationTimeline/document-timeline.html
+++ b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/AnimationTimeline/document-timeline.html
@@ -1,6 +1,7 @@
 <!doctype html>
 <meta charset=utf-8>
-<title>Web Animations API: DocumentTimeline tests</title>
+<title>Default document timeline tests</title>
+<link rel="help" href="https://w3c.github.io/web-animations/#the-documents-default-timeline">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <div id="log"></div>
@@ -16,15 +17,9 @@
     'document.timeline returns a different object for each document');
   assert_not_equals(iframe.contentDocument.timeline, null,
     'document.timeline on an iframe is not null');
-},
-'document.timeline identity tests',
-{
-  help:   'http://dev.w3.org/fxtf/web-animations/#the-document-timeline',
-  assert: [ 'Each document has a timeline called the document timeline' ],
-  author: 'Brian Birtles'
-});
+}, 'document.timeline identity tests');
 
-async_test(function(t) {
+promise_test(function(t) {
   assert_true(document.timeline.currentTime > 0,
     'document.timeline.currentTime is positive');
   // document.timeline.currentTime should be set even before document
@@ -40,31 +35,14 @@
   // We can't just compare document.timeline.currentTime to
   // window.performance.now() because currentTime is only updated on a sample
   // so we use requestAnimationFrame instead.
-  window.requestAnimationFrame(t.step_func(function(rafTime) {
+  return window.requestAnimationFrame(t.step_func(function(rafTime) {
     assert_equals(document.timeline.currentTime, rafTime,
                   'document.timeline.currentTime matches' +
                   ' requestAnimationFrame time');
-    t.done();
   }));
-},
-'document.timeline.currentTime value tests',
-{
-  help: [
-    'http://dev.w3.org/fxtf/web-animations/#the-global-clock',
-    'http://dev.w3.org/fxtf/web-animations/#the-document-timeline'
-  ],
-  assert: [
-    'The global clock is a source of monotonically increasing time values',
-    'The time values of the document timeline are calculated as a fixed' +
-    ' offset from the global clock',
-    'the zero time corresponds to the navigationStart moment',
-    'the time value of each document timeline must be equal to the time ' +
-    'passed to animation frame request callbacks for that browsing context'
-  ],
-  author: 'Brian Birtles'
-});
+}, 'document.timeline.currentTime value tests');
 
-async_test(function(t) {
+promise_test(function(t) {
   var valueAtStart = document.timeline.currentTime;
   var timeAtStart = window.performance.now();
   while (window.performance.now() - timeAtStart < 100) {
@@ -72,18 +50,10 @@
   }
   assert_equals(document.timeline.currentTime, valueAtStart,
     'document.timeline.currentTime does not change within a script block');
-  window.requestAnimationFrame(t.step_func(function() {
+  return window.requestAnimationFrame(t.step_func(function() {
     assert_true(document.timeline.currentTime > valueAtStart,
       'document.timeline.currentTime increases between script blocks');
-    t.done();
   }));
-},
-'document.timeline.currentTime liveness tests',
-{
-  help: 'http://dev.w3.org/fxtf/web-animations/#script-execution-and-live-updates-to-the-model',
-  assert: [ 'The value returned by the currentTime attribute of a' +
-            ' document timeline will not change within a script block' ],
-  author: 'Brian Birtles'
-});
+}, 'document.timeline.currentTime liveness tests');
 
 </script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/AnimationTimeline/idlharness-expected.txt b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/AnimationTimeline/idlharness-expected.txt
index 977c872..5cb30a0 100644
--- a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/AnimationTimeline/idlharness-expected.txt
+++ b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/AnimationTimeline/idlharness-expected.txt
@@ -1,11 +1,5 @@
 This is a testharness.js-based test.
 PASS Web Animations API: DocumentTimeline tests 
-PASS AnimationTimeline interface: existence and properties of interface object 
-PASS AnimationTimeline interface object length 
-PASS AnimationTimeline interface object name 
-FAIL AnimationTimeline interface: existence and properties of interface prototype object assert_equals: class string of AnimationTimeline.prototype expected "[object AnimationTimelinePrototype]" but got "[object AnimationTimeline]"
-PASS AnimationTimeline interface: existence and properties of interface prototype object's "constructor" property 
-FAIL AnimationTimeline interface: attribute currentTime assert_equals: setter must be undefined for readonly attributes expected (undefined) undefined but got (function) function "function () { [native code] }"
 FAIL DocumentTimeline interface: existence and properties of interface object assert_own_property: self does not have own property "DocumentTimeline" expected property "DocumentTimeline" missing
 FAIL DocumentTimeline interface object length assert_own_property: self does not have own property "DocumentTimeline" expected property "DocumentTimeline" missing
 FAIL DocumentTimeline interface object name assert_own_property: self does not have own property "DocumentTimeline" expected property "DocumentTimeline" missing
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/AnimationTimeline/idlharness.html b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/AnimationTimeline/idlharness.html
index 9a489086..04afcada 100644
--- a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/AnimationTimeline/idlharness.html
+++ b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/AnimationTimeline/idlharness.html
@@ -6,11 +6,13 @@
 <script src="/resources/WebIDLParser.js"></script>
 <script src="/resources/idlharness.js"></script>
 <div id="log"></div>
-<script type="text/plain" id="DocumentTimeline-IDL">
+<script type="text/plain" id="AnimationTimeline-IDL">
 interface AnimationTimeline {
   readonly attribute double? currentTime;
 };
-
+</script>
+<script type="text/plain" id="DocumentTimeline-IDL">
+[Constructor (DOMHighResTimeStamp originTime)]
 interface DocumentTimeline : AnimationTimeline {
 };
 </script>
@@ -20,6 +22,8 @@
 var idlArray;
 test(function() {
   idlArray = new IdlArray();
+  idlArray.add_untested_idls(
+    document.getElementById('AnimationTimeline-IDL').textContent);
   idlArray.add_idls(
     document.getElementById('DocumentTimeline-IDL').textContent);
   idlArray.add_objects( { DocumentTimeline: ['document.timeline'] } );
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/DocumentTimeline/constructor-expected.txt b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/DocumentTimeline/constructor-expected.txt
new file mode 100644
index 0000000..e443eb4d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/DocumentTimeline/constructor-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+FAIL zero origin time DocumentTimeline is not defined
+FAIL positive origin time DocumentTimeline is not defined
+FAIL negative origin time DocumentTimeline is not defined
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/DocumentTimeline/constructor.html b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/DocumentTimeline/constructor.html
new file mode 100644
index 0000000..efdf1118
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/DocumentTimeline/constructor.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>DocumentTimeline constructor tests</title>
+<link rel="help" href="https://w3c.github.io/web-animations/#the-documenttimeline-interface">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<body>
+<div id="log"></div>
+<script>
+"use strict";
+
+test(function(t) {
+  var timeline = new DocumentTimeline(0);
+
+  assert_times_equal(timeline.currentTime, document.timeline.currentTime);
+}, 'zero origin time');
+
+test(function(t) {
+  var timeline = new DocumentTimeline(10 * MS_PER_SEC);
+
+  assert_times_equal(timeline.currentTime,
+                     (document.timeline.currentTime - 10 * MS_PER_SEC));
+}, 'positive origin time');
+
+test(function(t) {
+  var timeline = new DocumentTimeline(-10 * MS_PER_SEC);
+
+  assert_times_equal(timeline.currentTime,
+                (document.timeline.currentTime + 10 * MS_PER_SEC));
+}, 'negative origin time');
+
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/KeyframeEffect/setTarget-expected.txt b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/KeyframeEffect/setTarget-expected.txt
index 271de512..421c9d96 100644
--- a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/KeyframeEffect/setTarget-expected.txt
+++ b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/KeyframeEffect/setTarget-expected.txt
@@ -3,5 +3,8 @@
 FAIL Test setting target from null to a valid target Animation is not defined
 FAIL Test setting target from a valid target to null assert_equals: Value after clearing the target expected "10px" but got "50px"
 FAIL Test setting target from a valid target to another target assert_equals: Value of 1st element (currently not targeted) after changing the effect target expected "10px" but got "50px"
+FAIL Test falling back to distribute spacing mode after setting null target anim.effect.getKeyframes is not a function
+FAIL Test falling back to distribute spacing mode if there is no context element effect.getKeyframes is not a function
+FAIL Test paced spacing mode after setting a new target anim.effect.getKeyframes is not a function
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/KeyframeEffect/setTarget.html b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/KeyframeEffect/setTarget.html
index 49ef8402..2b07d3de 100644
--- a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/KeyframeEffect/setTarget.html
+++ b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/KeyframeEffect/setTarget.html
@@ -85,5 +85,76 @@
                 'changing the animation current time.');
 }, 'Test setting target from a valid target to another target');
 
+test(function(t) {
+  var anim = createDiv(t).animate([ { marginLeft: '0px' },
+                                    { marginLeft: '-20px' },
+                                    { marginLeft: '100px' },
+                                    { marginLeft: '50px' } ],
+                                  { duration: 100 * MS_PER_SEC,
+                                    spacing: 'paced(margin-left)' });
+
+  anim.effect.target = null;
+
+  var frames = anim.effect.getKeyframes();
+  var slots = frames.length - 1;
+  assert_equals(frames[0].computedOffset, 0.0, '1st frame offset');
+  assert_equals(frames[1].computedOffset, 1.0 / slots, '2nd frame offset');
+  assert_equals(frames[2].computedOffset, 2.0 / slots, '3rd frame offset');
+  assert_equals(frames[3].computedOffset, 1.0, 'last frame offset');
+}, 'Test falling back to distribute spacing mode after setting null target');
+
+test(function(t) {
+  var effect = new KeyframeEffect(null,
+                                  [ { marginLeft: '0px' },
+                                    { marginLeft: '-20px' },
+                                    { marginLeft: '100px' },
+                                    { marginLeft: '50px' } ],
+                                  { duration: 100 * MS_PER_SEC,
+                                    spacing: 'paced(margin-left)' });
+  var frames = effect.getKeyframes();
+  var slots = frames.length - 1;
+  assert_equals(frames[1].computedOffset, 1.0 / slots, '2nd frame offset');
+  assert_equals(frames[2].computedOffset, 2.0 / slots, '3rd frame offset');
+}, 'Test falling back to distribute spacing mode if there is no context ' +
+   'element');
+
+test(function(t) {
+  var div1 = createDiv(t);
+  var div2 = createDiv(t);
+  div1.style.marginLeft = '-20px';
+  div2.style.marginLeft = '-50px';
+  var child1 = document.createElement('div');
+  var child2 = document.createElement('div');
+  div1.appendChild(child1);
+  div2.appendChild(child2);
+  //      body
+  //    /      \
+  //  div1     div2
+  // (-20px)  (-50px)
+  //   |        |
+  // child1   child2
+  var anim = child1.animate([ { marginLeft: '0px' },
+                              { marginLeft: 'inherit' },
+                              { marginLeft: '100px' },
+                              { marginLeft: '50px' } ],
+                            { duration: 100 * MS_PER_SEC,
+                              spacing: 'paced(margin-left)' });
+
+  var frames = anim.effect.getKeyframes();
+  var cumDist = [0, 20, 140, 190];
+  assert_equals(frames[1].computedOffset, cumDist[1] / cumDist[3],
+                '2nd frame offset');
+  assert_equals(frames[2].computedOffset, cumDist[2] / cumDist[3],
+                '3rd frame offset');
+
+  anim.effect.target = child2;
+  frames = anim.effect.getKeyframes();
+  cumDist = [0, 50, 200, 250];
+  assert_equals(frames[1].computedOffset, cumDist[1] / cumDist[3],
+                '2nd frame offset after setting a new target');
+  assert_equals(frames[2].computedOffset, cumDist[2] / cumDist[3],
+                '3rd frame offset after setting a new target');
+}, 'Test paced spacing mode after setting a new target');
+
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/KeyframeEffectReadOnly/spacing-expected.txt b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/KeyframeEffectReadOnly/spacing-expected.txt
new file mode 100644
index 0000000..f876ed2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/KeyframeEffectReadOnly/spacing-expected.txt
@@ -0,0 +1,84 @@
+This is a testharness.js-based test.
+FAIL Test throwing TypeError if using empty string assert_throws: function "function () {
+    createDiv(t).animate(null, { spacing: '' });
+  }" did not throw
+FAIL Test throwing TypeError if not using the correct keyword assert_throws: function "function () {
+    createDiv(t).animate(null, { spacing: 'dist' });
+  }" did not throw
+FAIL Test throwing TypeError if adding leading spaces assert_throws: function "function () {
+    createDiv(t).animate(null, { spacing: ' paced(margin-left)' });
+  }" did not throw
+FAIL Test throwing TypeError if adding trailing spaces assert_throws: function "function () {
+    createDiv(t).animate(null, { spacing: 'paced(margin-left) ' });
+  }" did not throw
+FAIL Test throwing TypeError if adding leading spaces before the paced property assert_throws: function "function () {
+    createDiv(t).animate(null, { spacing: 'paced( margin-left)' });
+  }" did not throw
+FAIL Test throwing TypeError if adding trailing spaces after the paced property assert_throws: function "function () {
+    createDiv(t).animate(null, { spacing: 'paced(margin-left )' });
+  }" did not throw
+FAIL Test throwing TypeError if these is no paced property assert_throws: function "function () {
+    createDiv(t).animate(null, { spacing: 'paced()' });
+  }" did not throw
+FAIL Test throwing TypeError if using a non-ident started string assert_throws: function "function () {
+    createDiv(t).animate(null, { spacing: 'paced(.margin)' });
+  }" did not throw
+FAIL Test throwing TypeError if using a non-ident started string assert_throws: function "function () {
+    createDiv(t).animate(null, { spacing: 'paced(1margin)' });
+  }" did not throw
+FAIL Test throwing TypeError if using a non-ident started string with an invalid escape assert_throws: function "function () {
+    createDiv(t).animate(null, { spacing: 'paced(\\)' });
+  }" did not throw
+FAIL Test throwing TypeError if using a non-ident started string with an invalid escape (FF) assert_throws: function "function () {
+    createDiv(t).animate(null, { spacing: 'paced(\\\fmargin)' });
+  }" did not throw
+FAIL Test throwing TypeError if using a non-ident started string with an invalid escape (CR) assert_throws: function "function () {
+    createDiv(t).animate(null, { spacing: 'paced(\\\rmargin)' });
+  }" did not throw
+FAIL Test throwing TypeError if using a non-ident started string with an invalid escape (LF) assert_throws: function "function () {
+    createDiv(t).animate(null, { spacing: 'paced(\\\nmargin)' });
+  }" did not throw
+FAIL Test throwing TypeError if using a non-ident started string with a leading minus and an invalid name-start code point assert_throws: function "function () {
+    createDiv(t).animate(null, { spacing: 'paced(- )' });
+  }" did not throw
+FAIL Test throwing TypeError if using a non-ident started string with a leading minus and an invalid escape assert_throws: function "function () {
+    createDiv(t).animate(null, { spacing: 'paced(-\\)' });
+  }" did not throw
+FAIL Test throwing TypeError if using a non-ident started string with a leading minus and an invalid escape (FF) assert_throws: function "function () {
+    createDiv(t).animate(null, { spacing: 'paced(-\\\fmargin)' });
+  }" did not throw
+FAIL Test throwing TypeError if using a non-ident started string with a leading minus and an invalid escape (CR) assert_throws: function "function () {
+    createDiv(t).animate(null, { spacing: 'paced(-\\\rmargin)' });
+  }" did not throw
+FAIL Test throwing TypeError if using a non-ident started string with a leading minus and an invalid escape (LF) assert_throws: function "function () {
+    createDiv(t).animate(null, { spacing: 'paced(-\\\nmargin)' });
+  }" did not throw
+FAIL Test throwing TypeError if using a non-ident string with an invalid escape assert_throws: function "function () {
+    createDiv(t).animate(null, { spacing: 'paced(--\\)' });
+  }" did not throw
+FAIL Test throwing TypeError if using a non-ident string with an invalid escape (FF) assert_throws: function "function () {
+    createDiv(t).animate(null, { spacing: 'paced(--\\\fmargin)' });
+  }" did not throw
+FAIL Test throwing TypeError if using a non-ident string with an invalid escape (CR) assert_throws: function "function () {
+    createDiv(t).animate(null, { spacing: 'paced(--\\\rmargin)' });
+  }" did not throw
+FAIL Test throwing TypeError if using a non-ident string with an invalid escape (LF) assert_throws: function "function () {
+    createDiv(t).animate(null, { spacing: 'paced(--\\\nmargin)' });
+  }" did not throw
+FAIL Test throwing TypeError if using a non-ident string with an invalid name code point assert_throws: function "function () {
+    createDiv(t).animate(null, { spacing: 'paced(margin.left)' });
+  }" did not throw
+FAIL Test falling back to distribute spacing if using a unrecognized property assert_equals: spacing mode expected (string) "distribute" but got (undefined) undefined
+FAIL Test falling back to distribute spacing if using a unrecognized property which starts with a valid escape (Full stop) assert_equals: spacing mode expected (string) "distribute" but got (undefined) undefined
+FAIL Test falling back to distribute spacing if using a unrecognized property which starts with a valid escape (white space) assert_equals: spacing mode expected (string) "distribute" but got (undefined) undefined
+FAIL Test falling back to distribute spacing if using a unrecognized property which starts with a valid escape (low line) assert_equals: spacing mode expected (string) "distribute" but got (undefined) undefined
+FAIL Test falling back to distribute spacing if using a unrecognized property which starts with a minus and a low line assert_equals: spacing mode expected (string) "distribute" but got (undefined) undefined
+FAIL Test falling back to distribute spacing if using a unrecognized property which starts with a minus and a valid escape assert_equals: spacing mode expected (string) "distribute" but got (undefined) undefined
+FAIL Test falling back to distribute spacing if using CSS variables assert_equals: spacing mode expected (string) "distribute" but got (undefined) undefined
+FAIL Test falling back to distribute spacing if using a non-animatable shorthand property assert_equals: spacing mode expected (string) "distribute" but got (undefined) undefined
+FAIL Test falling back to distribute spacing if using a non-animatable property assert_equals: spacing mode expected (string) "distribute" but got (undefined) undefined
+FAIL Test default value of spacing assert_equals: spacing mode expected (string) "distribute" but got (undefined) undefined
+FAIL Test spacing value if setting distribute assert_equals: spacing mode expected (string) "distribute" but got (undefined) undefined
+FAIL Test spacing value if setting paced assert_equals: spacing mode expected (string) "paced(margin-left)" but got (undefined) undefined
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/KeyframeEffectReadOnly/spacing.html b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/KeyframeEffectReadOnly/spacing.html
new file mode 100644
index 0000000..c83d1eb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/KeyframeEffectReadOnly/spacing.html
@@ -0,0 +1,237 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>KeyframeEffectReadOnly spacing attribute tests</title>
+<link rel="help"
+href="https://w3c.github.io/web-animations/#dom-keyframeeffectreadonly-spacing">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<body>
+<div id="log"></div>
+<script>
+"use strict";
+
+test(function(t) {
+  assert_throws(new TypeError, function() {
+    createDiv(t).animate(null, { spacing: '' });
+  });
+}, 'Test throwing TypeError if using empty string');
+
+test(function(t) {
+  assert_throws(new TypeError, function() {
+    createDiv(t).animate(null, { spacing: 'dist' });
+  });
+}, 'Test throwing TypeError if not using the correct keyword');
+
+test(function(t) {
+  assert_throws(new TypeError, function() {
+    createDiv(t).animate(null, { spacing: ' paced(margin-left)' });
+  });
+}, 'Test throwing TypeError if adding leading spaces');
+
+test(function(t) {
+  assert_throws(new TypeError, function() {
+    createDiv(t).animate(null, { spacing: 'paced(margin-left) ' });
+  });
+}, 'Test throwing TypeError if adding trailing spaces');
+
+test(function(t) {
+  assert_throws(new TypeError, function() {
+    createDiv(t).animate(null, { spacing: 'paced( margin-left)' });
+  });
+}, 'Test throwing TypeError if adding leading spaces before the ' +
+   'paced property');
+
+test(function(t) {
+  assert_throws(new TypeError, function() {
+    createDiv(t).animate(null, { spacing: 'paced(margin-left )' });
+  });
+}, 'Test throwing TypeError if adding trailing spaces after the ' +
+   'paced property');
+
+test(function(t) {
+  assert_throws(new TypeError, function() {
+    createDiv(t).animate(null, { spacing: 'paced()' });
+  });
+}, 'Test throwing TypeError if these is no paced property');
+
+test(function(t) {
+  assert_throws(new TypeError, function() {
+    createDiv(t).animate(null, { spacing: 'paced(.margin)' });
+  });
+}, 'Test throwing TypeError if using a non-ident started string');
+
+test(function(t) {
+  assert_throws(new TypeError, function() {
+    createDiv(t).animate(null, { spacing: 'paced(1margin)' });
+  });
+}, 'Test throwing TypeError if using a non-ident started string');
+
+test(function(t) {
+  assert_throws(new TypeError, function() {
+    createDiv(t).animate(null, { spacing: 'paced(\\)' });
+  });
+}, 'Test throwing TypeError if using a non-ident started string with ' +
+   'an invalid escape');
+
+test(function(t) {
+  assert_throws(new TypeError, function() {
+    createDiv(t).animate(null, { spacing: 'paced(\\\fmargin)' });
+  });
+}, 'Test throwing TypeError if using a non-ident started string with ' +
+   'an invalid escape (FF)');
+
+test(function(t) {
+  assert_throws(new TypeError, function() {
+    createDiv(t).animate(null, { spacing: 'paced(\\\rmargin)' });
+  });
+}, 'Test throwing TypeError if using a non-ident started string with ' +
+   'an invalid escape (CR)');
+
+test(function(t) {
+  assert_throws(new TypeError, function() {
+    createDiv(t).animate(null, { spacing: 'paced(\\\nmargin)' });
+  });
+}, 'Test throwing TypeError if using a non-ident started string with ' +
+   'an invalid escape (LF)');
+
+test(function(t) {
+  assert_throws(new TypeError, function() {
+    createDiv(t).animate(null, { spacing: 'paced(- )' });
+  });
+}, 'Test throwing TypeError if using a non-ident started string with ' +
+   'a leading minus and an invalid name-start code point');
+
+test(function(t) {
+  assert_throws(new TypeError, function() {
+    createDiv(t).animate(null, { spacing: 'paced(-\\)' });
+  });
+}, 'Test throwing TypeError if using a non-ident started string with ' +
+   'a leading minus and an invalid escape');
+
+test(function(t) {
+  assert_throws(new TypeError, function() {
+    createDiv(t).animate(null, { spacing: 'paced(-\\\fmargin)' });
+  });
+}, 'Test throwing TypeError if using a non-ident started string with ' +
+   'a leading minus and an invalid escape (FF)');
+
+test(function(t) {
+  assert_throws(new TypeError, function() {
+    createDiv(t).animate(null, { spacing: 'paced(-\\\rmargin)' });
+  });
+}, 'Test throwing TypeError if using a non-ident started string with ' +
+   'a leading minus and an invalid escape (CR)');
+
+test(function(t) {
+  assert_throws(new TypeError, function() {
+    createDiv(t).animate(null, { spacing: 'paced(-\\\nmargin)' });
+  });
+}, 'Test throwing TypeError if using a non-ident started string with ' +
+   'a leading minus and an invalid escape (LF)');
+
+test(function(t) {
+  assert_throws(new TypeError, function() {
+    createDiv(t).animate(null, { spacing: 'paced(--\\)' });
+  });
+}, 'Test throwing TypeError if using a non-ident string with an invalid ' +
+   'escape');
+
+test(function(t) {
+  assert_throws(new TypeError, function() {
+    createDiv(t).animate(null, { spacing: 'paced(--\\\fmargin)' });
+  });
+}, 'Test throwing TypeError if using a non-ident string with an invalid ' +
+   'escape (FF)');
+
+test(function(t) {
+  assert_throws(new TypeError, function() {
+    createDiv(t).animate(null, { spacing: 'paced(--\\\rmargin)' });
+  });
+}, 'Test throwing TypeError if using a non-ident string with an invalid ' +
+   'escape (CR)');
+
+test(function(t) {
+  assert_throws(new TypeError, function() {
+    createDiv(t).animate(null, { spacing: 'paced(--\\\nmargin)' });
+  });
+}, 'Test throwing TypeError if using a non-ident string with an invalid ' +
+   'escape (LF)');
+
+test(function(t) {
+  assert_throws(new TypeError, function() {
+    createDiv(t).animate(null, { spacing: 'paced(margin.left)' });
+  });
+}, 'Test throwing TypeError if using a non-ident string with an invalid name ' +
+   'code point');
+
+test(function(t) {
+  var anim = createDiv(t).animate(null, { spacing: 'paced(A)' });
+  assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
+}, 'Test falling back to distribute spacing if using a unrecognized property');
+
+test(function(t) {
+  var anim = createDiv(t).animate(null, { spacing: 'paced(\\.margin)' });
+  assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
+}, 'Test falling back to distribute spacing if using a unrecognized property ' +
+   'which starts with a valid escape (Full stop)');
+
+test(function(t) {
+  var anim = createDiv(t).animate(null, { spacing: 'paced(\\ margin)' });
+  assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
+}, 'Test falling back to distribute spacing if using a unrecognized property ' +
+   'which starts with a valid escape (white space)');
+
+test(function(t) {
+  var anim = createDiv(t).animate(null, { spacing: 'paced(_margin)' });
+  assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
+}, 'Test falling back to distribute spacing if using a unrecognized property ' +
+   'which starts with a valid escape (low line)');
+
+test(function(t) {
+  var anim = createDiv(t).animate(null, { spacing: 'paced(-_margin)' });
+  assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
+}, 'Test falling back to distribute spacing if using a unrecognized property ' +
+   'which starts with a minus and a low line');
+
+test(function(t) {
+  var anim = createDiv(t).animate(null, { spacing: 'paced(-\\.margin)' });
+  assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
+}, 'Test falling back to distribute spacing if using a unrecognized property ' +
+   'which starts with a minus and a valid escape');
+
+test(function(t) {
+  var anim = createDiv(t).animate(null, { spacing: 'paced(--bg-color)' });
+  assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
+}, 'Test falling back to distribute spacing if using CSS variables');
+
+test(function(t) {
+  var anim = createDiv(t).animate(null, { spacing: 'paced(animation)' });
+  assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
+}, 'Test falling back to distribute spacing if using a non-animatable ' +
+   'shorthand property');
+
+test(function(t) {
+  var anim = createDiv(t).animate(null,
+                                  { spacing: 'paced(animation-duration)' });
+  assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
+}, 'Test falling back to distribute spacing if using a non-animatable ' +
+   'property');
+
+test(function(t) {
+  var anim = createDiv(t).animate(null);
+  assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
+}, 'Test default value of spacing');
+
+test(function(t) {
+  var anim = createDiv(t).animate(null, { spacing: 'distribute' });
+  assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
+}, 'Test spacing value if setting distribute');
+
+test(function(t) {
+  var anim = createDiv(t).animate(null, { spacing: 'paced(margin-left)' });
+  assert_equals(anim.effect.spacing, 'paced(margin-left)', 'spacing mode');
+}, 'Test spacing value if setting paced');
+
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/console/console-line-and-column-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/console/console-line-and-column-expected.txt
index 0713d4f..f38b264 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/console/console-line-and-column-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/console/console-line-and-column-expected.txt
@@ -8,9 +8,9 @@
     stack : {
         callFrames : [
             [0] : {
-                columnNumber : 9
+                columnNumber : 8
                 functionName : 
-                lineNumber : 1
+                lineNumber : 0
                 scriptId : 0
                 url : 
             }
@@ -28,9 +28,9 @@
     stack : {
         callFrames : [
             [0] : {
-                columnNumber : 3
+                columnNumber : 2
                 functionName : 
-                lineNumber : 2
+                lineNumber : 1
                 scriptId : 0
                 url : 
             }
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/continueToLocation.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/continueToLocation.html
index 18168c82..dec791a 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/continueToLocation.html
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/continueToLocation.html
@@ -23,13 +23,17 @@
     function callbackEvalFunctionObject(response)
     {
         var functionObjectId = response.result.result.objectId;
-        InspectorTest.sendCommand("Debugger.getFunctionDetails", { functionId: functionObjectId }, callbackFunctionDetails);
+        InspectorTest.sendCommand("Runtime.getProperties", { objectId: functionObjectId }, callbackFunctionDetails);
     }
 
     function callbackFunctionDetails(response)
     {
         var result = response.result;
-        var scriptId = result.details.location.scriptId;
+        var scriptId;
+        for (var prop of result.internalProperties) {
+            if (prop.name === "[[FunctionLocation]]")
+                scriptId = prop.value.value.scriptId;
+        }
 
         nextScenarioStep(0);
 
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/setScriptSource.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/setScriptSource.html
index ff34b440..3bec1c92 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/setScriptSource.html
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/setScriptSource.html
@@ -9,7 +9,7 @@
     // A general-purpose engine for sending a sequence of protocol commands.
     // The clients provide requests and response handlers, while the engine catches
     // errors and makes sure that once there's nothing to do completeTest() is called.
-    // @param step is an object with command, params and callback fields 
+    // @param step is an object with command, params and callback fields
     function runRequestSeries(step) {
         processStep(step);
 
@@ -21,7 +21,7 @@
                 InspectorTest.completeTest();
             }
         }
-        
+
         function processStepOrFail(currentStep) {
             if (!currentStep) {
                 InspectorTest.completeTest();
@@ -64,7 +64,7 @@
             InspectorTest.sendCommand(currentStep.command, currentStep.params, innerCallback);
         }
     }
-    
+
     function logEqualsCheck(actual, expected)
     {
         if (actual == expected) {
@@ -77,57 +77,63 @@
     {
         InspectorTest.log(description + ": " + (success ? "PASS" : "FAIL"));
     }
-    
+
     var firstStep = { callback: enableDebugger };
 
     runRequestSeries(firstStep);
-    
+
     function enableDebugger() {
         return { command: "Debugger.enable", params: {}, callback: evalFunction };
     }
-    
+
     function evalFunction(response) {
         var expression = "TestExpression(2, 4)";
         return { command: "Runtime.evaluate", params: { expression: expression }, callback: callbackEvalFunction };
     }
-    
+
     function callbackEvalFunction(result) {
         InspectorTest.log("Function evaluate: " + JSON.stringify(result.result));
         logEqualsCheck(result.result.value, 6);
 
         return { command: "Runtime.evaluate", params: { expression: "TestExpression" }, callback: callbackEvalFunctionObject };
     }
-    
+
     function callbackEvalFunctionObject(result) {
-        return { command: "Debugger.getFunctionDetails", params: { functionId: result.result.objectId }, callback: callbackFunctionDetails };
-    }
-    
-    function callbackFunctionDetails(result) {
-        return createScriptManipulationArc(result.details.location.scriptId, null);
+        return { command: "Runtime.getProperties", params: { objectId: result.result.objectId }, callback: callbackFunctionDetails };
     }
 
-    // Several steps with scriptId in context.    
+    function callbackFunctionDetails(result)
+    {
+        var scriptId;
+        for (var prop of result.internalProperties) {
+            if (prop.name === "[[FunctionLocation]]")
+                scriptId = prop.value.value.scriptId;
+        }
+        return createScriptManipulationArc(scriptId, null);
+    }
+
+    // Several steps with scriptId in context.
     function createScriptManipulationArc(scriptId, next) {
         return { command: "Debugger.getScriptSource", params: { scriptId: scriptId }, callback: callbackGetScriptSource };
-        
+
         var originalText;
-        
+
         function callbackGetScriptSource(result) {
             originalText = result.scriptSource;
             var patched = originalText.replace("a + b", "a * b");
 
             return { command: "Debugger.setScriptSource", params: { scriptId: scriptId, scriptSource: patched }, callback: callbackSetScriptSource };
         }
-        
+
         function callbackSetScriptSource(result) {
             var expression = "TestExpression(2, 4)";
             return { command: "Runtime.evaluate", params: { expression: expression }, callback: callbackEvalFunction2 };
         }
-        
+
         function callbackEvalFunction2(result) {
             InspectorTest.log("Function evaluate: " + JSON.stringify(result.result));
             logEqualsCheck(result.result.value, 8);
-    
+
             var patched = originalText.replace("a + b", "a # b");
 
             return { command: "Debugger.setScriptSource", params: { scriptId: scriptId, scriptSource: patched }, callback: errorCallbackSetScriptSource2 };
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/network/websocket-initiator-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/network/websocket-initiator-expected.txt
index fd18f8e1..b7e73710 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/network/websocket-initiator-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/network/websocket-initiator-expected.txt
@@ -7,5 +7,5 @@
 Stack #0
   functionName: createSocket
   url: websocket-initiator.html
-  lineNumber: 10
+  lineNumber: 9
 
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/resources/worker-console-worker.js b/third_party/WebKit/LayoutTests/inspector-protocol/resources/worker-console-worker.js
index 8c5f0035..5151327 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/resources/worker-console-worker.js
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/resources/worker-console-worker.js
@@ -1,6 +1,9 @@
 self.onmessage = function(event)
 {
-    console.log(event.data);
+    if (event.data.indexOf("throw") === 0)
+        Promise.reject(event.data);
+    else
+        console.log(event.data);
     self.postMessage(event.data);
 }
 self.postMessage("ready");
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-getFunctionDetails-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-getFunctionDetails-expected.txt
deleted file mode 100644
index b216bd45..0000000
--- a/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-getFunctionDetails-expected.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-
-{
-    "details": {
-        "location": {
-            "scriptId": "0",
-            "lineNumber": -1,
-            "columnNumber": -1
-        },
-        "functionName": "",
-        "isGenerator": false
-    }
-}
-
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-getFunctionDetails.html b/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-getFunctionDetails.html
deleted file mode 100644
index a5dd9c71..0000000
--- a/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-getFunctionDetails.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<html>
-<head>
-<script type="text/javascript" src="../../http/tests/inspector-protocol/inspector-protocol-test.js"></script>
-<script>
-
-function test()
-{
-    InspectorTest.sendCommand("Debugger.enable", { });
-    InspectorTest.sendCommand("Runtime.evaluate", { "expression": "document.querySelector('object')" }, callbackEvaluate);
-
-    function callbackEvaluate(result)
-    {
-        InspectorTest.sendCommand("Debugger.getFunctionDetails", { "functionId": result.result.result.objectId }, callbackGetFunctionDetails);
-    }
-
-    function callbackGetFunctionDetails(result)
-    {
-        InspectorTest.log(JSON.stringify(result.result, null, 4));
-        InspectorTest.completeTest();
-    }
-}
-</script>
-</head>
-<body onLoad="runTest();">
-<object type="application/pdf" data="data:text/plain,"></object>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/worker/worker-console-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/worker/worker-console-expected.txt
index 6c2d156c..1e54b7d 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/worker/worker-console-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/worker/worker-console-expected.txt
@@ -1,38 +1,46 @@
-CONSOLE MESSAGE: line 3: message0
-CONSOLE MESSAGE: line 3: message1
-CONSOLE MESSAGE: line 3: message2
-CONSOLE MESSAGE: line 3: message3
-CONSOLE MESSAGE: line 3: message4
-CONSOLE MESSAGE: line 3: message5
-CONSOLE MESSAGE: line 3: message6
+CONSOLE MESSAGE: line 6: message0
+CONSOLE MESSAGE: line 6: message1
+CONSOLE MESSAGE: line 6: message2
+CONSOLE ERROR: line 4: Uncaught (in promise) throw1
+CONSOLE MESSAGE: line 6: message3
+CONSOLE MESSAGE: line 6: message4
+CONSOLE MESSAGE: line 6: message5
+CONSOLE MESSAGE: line 6: message6
 Starting worker
 Logging in worker: message0
-Stopping worker
 Got console message from page: message0
+Stopping worker
 Starting worker
 Logging in worker: message1
+Got console message from page: message1
 Sending Worker.enable
 Worker.created
 Sending Console.enable to worker
 Got console message from worker: message1
 Logging in worker: message2
+Got console message from page: message2
 Got console message from worker: message2
+Logging in worker: throw1
+Got console message from page: Uncaught (in promise) throw1
 Sending Worker.disable
 Logging in worker: message3
+Got console message from page: message3
 Stopping worker
 Sending Worker.enable
 Starting worker
 Worker.created
 Logging in worker: message4
+Got console message from page: message4
 Sending Console.enable to worker
 Got console message from worker: message4
 Logging in worker: message5
+Got console message from page: message5
 Got console message from worker: message5
 Stopping worker
 Starting worker
 Worker.created
 Logging in worker: message6
-Stopping worker
 Got console message from page: message6
+Stopping worker
 Sending Worker.disable
 
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/worker/worker-console.html b/third_party/WebKit/LayoutTests/inspector-protocol/worker/worker-console.html
index bc201b9..97823329 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/worker/worker-console.html
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/worker/worker-console.html
@@ -38,11 +38,10 @@
 
 function test()
 {
-    var workerEventHandler = [];
-    InspectorTest.eventHandler["Console.messageAdded"] = onConsoleMessage.bind(null, false);
+    var workerEventHandler = {};
     InspectorTest.eventHandler["Worker.workerCreated"] = onWorkerCreated;
     InspectorTest.eventHandler["Worker.dispatchMessageFromWorker"] = onWorkerMessage;
-    workerEventHandler["Console.messageAdded"] = onConsoleMessage.bind(null, true);
+    workerEventHandler["Console.messageAdded"] = onConsoleMessageFromWorker;
 
     var workerId;
 
@@ -91,20 +90,25 @@
     function logInWorker(message, next)
     {
         InspectorTest.log("Logging in worker: " + message);
-        if (next)
-            InspectorTest.evaluateInPageAsync("logInWorkerFromPage(\"" + message + "\", %callback)", next);
-        else
-            InspectorTest.evaluateInPage("logInWorkerFromPage(\"" + message + "\")");
+        InspectorTest.eventHandler["Console.messageAdded"] = onConsoleMessage;
+        InspectorTest.evaluateInPage("logInWorkerFromPage(\"" + message + "\")");
+
+        function onConsoleMessage(payload)
+        {
+            InspectorTest.log("Got console message from page: " + payload.params.message.text);
+            delete InspectorTest.eventHandler["Console.messageAdded"];
+            next();
+        }
     }
 
     var gotMessages = [];
     var waitingForMessage;
     var waitingForMessageCallback;
 
-    function onConsoleMessage(fromWorker, payload)
+    function onConsoleMessageFromWorker(payload)
     {
         var message = payload.params.message.text;
-        InspectorTest.log("Got console message from " + (fromWorker ? "worker" : "page") + ": " + message);
+        InspectorTest.log("Got console message from worker: " + message);
         gotMessages.push(message);
         if (message === waitingForMessage)
             waitingForMessageCallback();
@@ -140,8 +144,7 @@
         function stop0(next)
         {
             InspectorTest.log("Stopping worker");
-            waitForMessage("message0", next);
-            InspectorTest.evaluateInPage("stopWorker()");
+            InspectorTest.evaluateInPage("stopWorker()", next);
         },
 
         function start1(next)
@@ -170,8 +173,17 @@
 
         function log2(next)
         {
+            logInWorker("message2", next);
+        },
+
+        function waitForMessage2(next)
+        {
             waitForMessage("message2", next);
-            logInWorker("message2");
+        },
+
+        function throw1(next)
+        {
+            logInWorker("throw1", next);
         },
 
         function disable1(next)
@@ -218,8 +230,12 @@
 
         function log5(next)
         {
+            logInWorker("message5", next);
+        },
+
+        function waitForMessage5(next)
+        {
             waitForMessage("message5", next);
-            logInWorker("message5");
         },
 
         function stop2(next)
@@ -242,8 +258,7 @@
         function stop3(next)
         {
             InspectorTest.log("Stopping worker");
-            waitForMessage("message6", next);
-            InspectorTest.evaluateInPage("stopWorker()");
+            InspectorTest.evaluateInPage("stopWorker()", next);
         },
 
         function disable2(next)
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-dir-expected.txt b/third_party/WebKit/LayoutTests/inspector/console/console-dir-expected.txt
index 679c8f5..a04d1d6 100644
--- a/third_party/WebKit/LayoutTests/inspector/console/console-dir-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/console/console-dir-expected.txt
@@ -40,8 +40,8 @@
     name: ""
     prototype: Object
     __proto__: ()
-    <function scope>
-        Global: Window
+    [[FunctionLocation]]: console-dir.html:19
+    [[Scopes]]: Scopes[1]
 console-dir.html:23 inner
     __proto__: Object
 console-dir.html:26 Object
@@ -56,8 +56,7 @@
     length: 0
     name: "get __proto__"
     __proto__: ()
-    <function scope>
-        No Scopes
+    [[FunctionLocation]]: <unknown>
 console-dir.html:34 Uint8Array[400000000]
     [0 … 99999999]
     [100000000 … 199999999]
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-eval-exception-report-expected.txt b/third_party/WebKit/LayoutTests/inspector/console/console-eval-exception-report-expected.txt
index b3775fd..6da5f5d5 100644
--- a/third_party/WebKit/LayoutTests/inspector/console/console-eval-exception-report-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/console/console-eval-exception-report-expected.txt
@@ -10,7 +10,7 @@
         }
         boo();
 VM:3 Uncaught Object {a: 239}foo @ VM:3boo @ VM:7(anonymous function) @ VM:9
-call frame:foo at :3
-call frame:boo at :7
-call frame: at :9
+call frame:foo at :2
+call frame:boo at :6
+call frame: at :8
 
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/execution-context-sorted-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/execution-context-sorted-expected.txt
new file mode 100644
index 0000000..2918702
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/execution-context-sorted-expected.txt
@@ -0,0 +1,7 @@
+
+Tests how execution context and target are selected.
+
+top
+execution-context-iframe1.html
+execution-context-iframe2.html
+
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/execution-context-sorted.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/execution-context-sorted.html
new file mode 100644
index 0000000..7958d84
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/execution-context-sorted.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<script src="../../../http/tests/inspector/inspector-test.js"></script>
+<script>
+
+function test()
+{
+    var contexts = InspectorTest.runtimeModel.executionContexts();
+    for (var c of contexts)
+        InspectorTest.addResult(c.target().resourceTreeModel.frameForId(c.frameId).displayName());
+    InspectorTest.completeTest();
+}
+
+</script>
+</head>
+
+<body onload="runTest()">
+    <iframe src="../resources/execution-context-iframe1.html"></iframe>
+<p>
+Tests how execution context and target are selected.
+</p>
+
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/function-details-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/function-details-expected.txt
index b8809ce..3f34200 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/function-details-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/function-details-expected.txt
@@ -8,8 +8,7 @@
 columnNumber: 36
 scriptId is valid: true
 functionName: firstLineFunction
-isGenerator: false
-scopeChain #0: global; <global object properties omitted>
+scopeChain #0: Global; <global object properties omitted>
 
 Running: testGetNonFirstLineFunctionDetails
 notFirstLineFunction type = function
@@ -18,8 +17,7 @@
 columnNumber: 32
 scriptId is valid: true
 functionName: notFirstLineFunction
-isGenerator: false
-scopeChain #0: global; <global object properties omitted>
+scopeChain #0: Global; <global object properties omitted>
 
 Running: testGetDetailsOfFunctionWithInferredName
 obj.m type = function
@@ -28,8 +26,7 @@
 columnNumber: 15
 scriptId is valid: true
 functionName: m
-isGenerator: false
-scopeChain #0: global; <global object properties omitted>
+scopeChain #0: Global; <global object properties omitted>
 
 Running: testGetDetailsOfFunctionWithDisplayName
 functionWithDisplayName type = function
@@ -38,8 +35,7 @@
 columnNumber: 32
 scriptId is valid: true
 functionName: user-friendly name
-isGenerator: false
-scopeChain #0: global; <global object properties omitted>
+scopeChain #0: Global; <global object properties omitted>
 
 Running: testGetDetailsOfFunctionWithDisplayNameGetter
 functionWithDisplayNameGetter type = function
@@ -48,8 +44,7 @@
 columnNumber: 38
 scriptId is valid: true
 functionName: functionWithDisplayNameGetter
-isGenerator: false
-scopeChain #0: global; <global object properties omitted>
+scopeChain #0: Global; <global object properties omitted>
 
 Running: testSmallClosure
 smallClosure type = function
@@ -58,9 +53,8 @@
 columnNumber: 49
 scriptId is valid: true
 functionName: 
-isGenerator: false
-scopeChain #0: closure; p: "Capybara"
-scopeChain #1: global; <global object properties omitted>
+scopeChain #0: Closure; p: "Capybara"
+scopeChain #1: Global; <global object properties omitted>
 
 Running: testBigClosure
 bigClosure type = function
@@ -69,9 +63,18 @@
 columnNumber: 27
 scriptId is valid: true
 functionName: 
-isGenerator: false
-scopeChain #0: catch; ex: <no string representation>
-scopeChain #1: with; __proto__: <no string representation>,e: 7,f: 5,u: <no value>,v: <no value>
-scopeChain #2: closure; p: <no string representation>
-scopeChain #3: global; <global object properties omitted>
+scopeChain #0: Catch; ex: <no string representation>
+scopeChain #1: With Block; __proto__: <no string representation>,e: 7,f: 5,u: <no value>,v: <no value>
+scopeChain #2: Closure; p: <no string representation>
+scopeChain #3: Global; <global object properties omitted>
+
+Running: testGenFunction
+gen type = function
+Function details: 
+lineNumber: 45
+columnNumber: 13
+scriptId is valid: true
+functionName: gen
+isGenerator: true
+scopeChain #0: Global; <global object properties omitted>
 
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/function-details.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/function-details.html
index 10d9760..0e7aa52 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/function-details.html
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/function-details.html
@@ -43,16 +43,20 @@
     }
 })({});
 
+function* gen() { yield [1,2,3] }
+
 function test()
 {
-    function dumpFunctionDetails(details)
+    function dumpFunctionDetails(properties)
     {
+        var location = properties.get("[[FunctionLocation]]").value.value;
         InspectorTest.addResult("Function details: ");
-        InspectorTest.addResult("lineNumber: " + details.location.lineNumber);
-        InspectorTest.addResult("columnNumber: " + details.location.columnNumber);
-        InspectorTest.addResult("scriptId is valid: " + !!details.location.scriptId);
-        InspectorTest.addResult("functionName: " + details.functionName);
-        InspectorTest.addResult("isGenerator: " + details.isGenerator);
+        InspectorTest.addResult("lineNumber: " + location.lineNumber);
+        InspectorTest.addResult("columnNumber: " + location.columnNumber);
+        InspectorTest.addResult("scriptId is valid: " + !!location.scriptId);
+        InspectorTest.addResult("functionName: " + properties.get("name").value.value);
+        if (properties.has("[[IsGenerator]]"))
+            InspectorTest.addResult("isGenerator: " + properties.get("[[IsGenerator]]").value.value);
     }
 
     function dumpFunctionNoScopes()
@@ -63,7 +67,7 @@
     function dumpFunctionScope(pos, type, propertyDescriptors)
     {
         var variables;
-        if (type == "global") {
+        if (type == "Global") {
             variables = "<global object properties omitted>";
         } else {
             var varArray = [];
@@ -88,28 +92,37 @@
 
     function loadAndDumpScopeObjects(scopeChain, end)
     {
+        var scopes = [];
         function loadScopeObject(pos, next)
         {
-            if (pos >= scopeChain.length) {
+            if (pos >= scopes.length) {
                 next();
                 return;
             }
-            var scopeJson = scopeChain[pos];
-            InspectorTest.RuntimeAgent.getProperties(scopeJson.object.objectId, true, didGetProperties);
+            InspectorTest.RuntimeAgent.getProperties(scopes[pos].objectId, true, didGetProperties);
 
             function didGetProperties(error, propertyDescriptors)
             {
-                dumpFunctionScope(pos, scopeJson.type, propertyDescriptors);
+                dumpFunctionScope(pos, scopes[pos].description, propertyDescriptors);
                 loadScopeObject(pos + 1, next);
             }
         }
 
         if (scopeChain) {
-            loadScopeObject(0, end);
+            InspectorTest.RuntimeAgent.getProperties(scopeChain.value.objectId, true, didGetScopes);
         } else {
             dumpFunctionNoScopes();
             end();
         }
+
+        function didGetScopes(error, properties)
+        {
+            for (var prop of properties) {
+                if (String(prop.name >>> 0) === prop.name)
+                    scopes.push(prop.value);
+            }
+            loadScopeObject(0, end);
+        }
     }
 
     function performStandardTestCase(pageExpression, next)
@@ -119,12 +132,23 @@
         function didEvaluate(remote)
         {
             InspectorTest.addResult(pageExpression + " type = " + remote.type);
-            InspectorTest.DebuggerAgent.getFunctionDetails(remote.objectId, didGetDetails);
+            InspectorTest.RuntimeAgent.getProperties(remote.objectId, /* isOwnProperty */ false, didGetDetails);
         }
-        function didGetDetails(error, response)
+        function didGetDetails(error, properties, internalProperties)
         {
-            dumpFunctionDetails(response);
-            loadAndDumpScopeObjects(response.scopeChain, next);
+            var propertiesMap = new Map();
+            for (var prop of internalProperties)
+                propertiesMap.set(prop.name, prop);
+            for (var prop of properties) {
+                if (prop.name === "name" && prop.value && prop.value.type === "string")
+                    propertiesMap.set("name", prop);
+                if (prop.name === "displayName" && prop.value && prop.value.type === "string") {
+                    propertiesMap.set("name", prop);
+                    break;
+                }
+            }
+            dumpFunctionDetails(propertiesMap);
+            loadAndDumpScopeObjects(propertiesMap.get("[[Scopes]]"), next);
         }
     }
 
@@ -156,6 +180,10 @@
         function testBigClosure(next)
         {
             performStandardTestCase("bigClosure", next);
+        },
+        function testGenFunction(next)
+        {
+            performStandardTestCase("gen", next);
         }
     ]);
 };
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/last-execution-context-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/last-execution-context-expected.txt
index 65041c9..77541f53 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/last-execution-context-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/last-execution-context-expected.txt
@@ -9,7 +9,7 @@
 Adding sw target
 
 Removing page main frame
-Execution context selected: contentScript1
+Execution context selected: mock-target-page-target:iframe1
 
 Readding page main frame
 Execution context selected: mock-target-page-target:42
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/last-execution-context.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/last-execution-context.html
index 23d3892..a34f310 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/last-execution-context.html
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/last-execution-context.html
@@ -54,7 +54,7 @@
 
     InspectorTest.addResult("");
     InspectorTest.addResult("User selected content script");
-    context.setFlavor(WebInspector.ExecutionContext, pageTarget.runtimeModel.executionContexts()[0]);
+    context.setFlavor(WebInspector.ExecutionContext, pageTarget.runtimeModel.executionContexts()[2]);
 
     InspectorTest.addResult("");
     InspectorTest.addResult("Switching to sw target");
@@ -66,7 +66,7 @@
 
     InspectorTest.addResult("");
     InspectorTest.addResult("User selected iframe1");
-    context.setFlavor(WebInspector.ExecutionContext, pageTarget.runtimeModel.executionContexts()[1]);
+    context.setFlavor(WebInspector.ExecutionContext, pageTarget.runtimeModel.executionContexts()[0]);
 
     InspectorTest.addResult("");
     InspectorTest.addResult("Switching to sw target");
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/watch-expressions-preserve-expansion-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/watch-expressions-preserve-expansion-expected.txt
index aef0c356..0794d3d 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/watch-expressions-preserve-expansion-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/watch-expressions-preserve-expansion-expected.txt
@@ -4,8 +4,8 @@
 Watch expressions added.
 expanded foo [object Object]
 expanded bar [object Object]
-expanded <function scope> 
-expanded Closure 
+expanded [[Scopes]] [object Object]
+expanded 0 [object Object]
 expanded a [object Object]
 expanded [200 .. 299] 
 expanded 299 [object Object]
@@ -129,11 +129,12 @@
     name: 
     prototype: Object
     __proto__: function () {}
-    <function scope>
-      Closure
+    [[FunctionLocation]]: Object
+    [[Scopes]]: Scopes[2]
+      0: Closure
         a: 10
         b: 100
-      Global: Window
+      1: Global
 Page reloaded.
 Watch expressions after page reload:
 globalObject: Object
@@ -255,9 +256,10 @@
     name: 
     prototype: Object
     __proto__: function () {}
-    <function scope>
-      Closure
+    [[FunctionLocation]]: Object
+    [[Scopes]]: Scopes[2]
+      0: Closure
         a: 10
         b: 100
-      Global: Window
+      1: Global
 
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/watch-expressions-preserve-expansion.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/watch-expressions-preserve-expansion.html
index 94349a93..a80c4414 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/watch-expressions-preserve-expansion.html
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/watch-expressions-preserve-expansion.html
@@ -38,7 +38,7 @@
     {
         InspectorTest.addResult("Watch expressions added.");
         var expandArray = expandWatchExpression.bind(null, ["array", "[200 \u2026 299]", "299"], step3);
-        var expandFunc = expandWatchExpression.bind(null, ["func", "<function scope>", "Closure", "a"], expandArray);
+        var expandFunc = expandWatchExpression.bind(null, ["func", "[[Scopes]]", "0", "a"], expandArray);
         expandWatchExpression(["globalObject", "foo", "bar"], expandFunc);
     }
 
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger/debugger-compile-and-run-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger/debugger-compile-and-run-expected.txt
index 878de58c..cb41034 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger/debugger-compile-and-run-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger/debugger-compile-and-run-expected.txt
@@ -16,7 +16,7 @@
    exceptionDetails stack trace:
        url: test.js
        function: 
-       line: 1
+       line: 0
 
 Running: testCompileError
 Compiling script
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger/properties-special-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger/properties-special-expected.txt
index 427e428..36d5ec9 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger/properties-special-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger/properties-special-expected.txt
@@ -1,6 +1,7 @@
 CONSOLE MESSAGE: line 10: true
 CONSOLE MESSAGE: line 11: function (a,b) { return a + b; }
 CONSOLE MESSAGE: line 12: function () { [native code] }
+CONSOLE MESSAGE: line 13: function* () { yeild [1,2,3] }
 Tests how debugger presents special properties of closures, bound functions and object wrappers.
 
 properties-special.html:10 Boolean
@@ -13,8 +14,9 @@
     name: ""
     prototype: Object
     __proto__: ()
-    <function scope>
-properties-special.html:12 anonymous()
+    [[FunctionLocation]]: properties-special.html:11
+    [[Scopes]]: Scopes[1]
+properties-special.html:12 bound ()
     arguments: (...)
     caller: (...)
     length: 1
@@ -23,4 +25,14 @@
     [[TargetFunction]]: (a,b)
     [[BoundThis]]: Object
     [[BoundArgs]]: Array[1]
+properties-special.html:13 anonymous()
+    arguments: (...)
+    caller: (...)
+    length: 0
+    name: ""
+    prototype: Generator
+    __proto__: GeneratorFunction
+    [[FunctionLocation]]: properties-special.html:13
+    [[IsGenerator]]: true
+    [[Scopes]]: Scopes[1]
 
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger/properties-special.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger/properties-special.html
index 4749b20..f87c8164 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger/properties-special.html
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger/properties-special.html
@@ -10,6 +10,7 @@
     console.dir(Object(true));
     console.dir((function(a,b) { return a + b; }));
     console.dir((function(a,b) { return a + b; }).bind({}, 2));
+    console.dir((function*() { yeild [1,2,3] }));
     runTest();
 }
 
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/resources/execution-context-iframe1.html b/third_party/WebKit/LayoutTests/inspector/sources/resources/execution-context-iframe1.html
new file mode 100644
index 0000000..3b11606
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/sources/resources/execution-context-iframe1.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+    <head>
+    </head>
+    <body>
+        iframe 1
+        <iframe src="execution-context-iframe2.html"></iframe>
+    </bodY>
+</html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/resources/execution-context-iframe2.html b/third_party/WebKit/LayoutTests/inspector/sources/resources/execution-context-iframe2.html
new file mode 100644
index 0000000..8e28820f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/sources/resources/execution-context-iframe2.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<html>
+    <head>
+    </head>
+    <body>
+        iframe 2
+    </bodY>
+</html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/iframe-scrollbar-hover-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/iframe-scrollbar-hover-expected.txt
new file mode 100644
index 0000000..b27b6bd8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/iframe-scrollbar-hover-expected.txt
@@ -0,0 +1,26 @@
+{
+  "name": "Content Root Layer",
+  "bounds": [800, 600],
+  "children": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "drawsContent": true,
+      "paintInvalidations": [
+        {
+          "object": "LayoutView #document",
+          "rect": [187, 102, 15, 200],
+          "reason": "scroll"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "VerticalScrollbar",
+      "reason": "scroll"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/iframe-scrollbar-hover.html b/third_party/WebKit/LayoutTests/paint/invalidation/iframe-scrollbar-hover.html
new file mode 100644
index 0000000..561030d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/iframe-scrollbar-hover.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<script src="../../fast/repaint/resources/text-based-repaint.js"></script>
+<script>
+function repaintTest() {
+  eventSender.mouseMoveTo(195, 120);
+}
+if (window.eventSender)
+  onload = runRepaintTest;
+</script>
+Tests paint invalidation when mouse hovers on the scrollbar in an iframe.
+<iframe id="iframe"
+    style="position: absolute; top: 100px; left: 0; width: 200px; height: 200px"
+    srcdoc="<div style='height: 300px'></div>"></iframe>
diff --git a/third_party/WebKit/LayoutTests/payments/payment-request-interface.html b/third_party/WebKit/LayoutTests/payments/payment-request-interface.html
index c0854654..670f291 100644
--- a/third_party/WebKit/LayoutTests/payments/payment-request-interface.html
+++ b/third_party/WebKit/LayoutTests/payments/payment-request-interface.html
@@ -204,6 +204,10 @@
     ['Duplicate supported payment method identifiers should throw TypeError.', null, function() {
         new PaymentRequest([{'supportedMethods': ['foo']}, {'supportedMethods': ['foo']}], buildDetails(), {})
     }],
+    ['Duplicate shipping option identifiers should throw TypeError.', null, function() {
+        var shippingOptions = [buildItem({'id': 'express', 'selected': false}), buildItem({'id': 'express', 'selected': true})];
+        new PaymentRequest([{'supportedMethods': ['foo']}], {'total': buildItem(), 'displayItems': [buildItem()], 'shippingOptions': shippingOptions}, {'requestShipping': true})
+    }],
     ['Absence of total should throw TypeError.', null, function() {
         new PaymentRequest([{'supportedMethods': ['foo']}], {'displayItems': [buildItem()]})
     }],
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/css/object-fit-grow-landscape-expected.png b/third_party/WebKit/LayoutTests/platform/android/fast/css/object-fit-grow-landscape-expected.png
new file mode 100644
index 0000000..3c2500b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/fast/css/object-fit-grow-landscape-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/css/object-fit-grow-portrait-expected.png b/third_party/WebKit/LayoutTests/platform/android/fast/css/object-fit-grow-portrait-expected.png
new file mode 100644
index 0000000..5d41825
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/fast/css/object-fit-grow-portrait-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance-expected.png
deleted file mode 100644
index 3800115..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance-expected.png
deleted file mode 100644
index 48bb2ea7..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance-expected.png
deleted file mode 100644
index 5719692b..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance-expected.png
deleted file mode 100644
index 9d5233a..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance-expected.png
deleted file mode 100644
index 2ae568db..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance-expected.png
deleted file mode 100644
index 5dc078d..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/img-layer-object-fit-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/img-layer-object-fit-expected.png
new file mode 100644
index 0000000..0f664d90
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/img-layer-object-fit-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/img-layer-object-fit-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/compositing/img-layer-object-fit-expected.txt
new file mode 100644
index 0000000..65d36b2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/img-layer-object-fit-expected.txt
@@ -0,0 +1,17 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x156
+  LayoutBlockFlow {HTML} at (0,0) size 800x156
+    LayoutBlockFlow {BODY} at (8,8) size 784x140
+      LayoutBR {BR} at (100,15) size 0x19
+      LayoutBR {BR} at (100,50) size 0x19
+      LayoutBR {BR} at (100,85) size 0x19
+      LayoutBR {BR} at (100,120) size 0x19
+layer at (8,8) size 100x30
+  LayoutImage {IMG} at (0,0) size 100x30
+layer at (8,43) size 100x30
+  LayoutImage {IMG} at (0,35) size 100x30
+layer at (8,78) size 100x30
+  LayoutImage {IMG} at (0,70) size 100x30
+layer at (8,113) size 100x30
+  LayoutImage {IMG} at (0,105) size 100x30
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/tiled-layers-hidpi-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/compositing/tiled-layers-hidpi-expected.txt
new file mode 100644
index 0000000..702643f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/tiled-layers-hidpi-expected.txt
@@ -0,0 +1,23 @@
+{
+  "name": "Content Root Layer",
+  "bounds": [1808, 585],
+  "children": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [1808, 585],
+      "contentsOpaque": true,
+      "drawsContent": true,
+      "children": [
+        {
+          "name": "LayoutBlockFlow DIV id='composited'",
+          "position": [8, 8],
+          "bounds": [1800, 10],
+          "contentsOpaque": true,
+          "drawsContent": true,
+          "backgroundColor": "#0000FF"
+        }
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-hidpi-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-hidpi-expected.txt
new file mode 100644
index 0000000..3a37906
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-hidpi-expected.txt
@@ -0,0 +1,27 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutBlockFlow {HTML} at (0,0) size 800x600
+    LayoutBlockFlow {BODY} at (8,8) size 784x584
+      LayoutSVGRoot {svg} at (8,8) size 0x0
+        LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
+          LayoutSVGResourceFilter {filter} [id="displacement"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
+            [feDisplacementMap scale="10.00" xChannelSelector="RED" yChannelSelector="GREEN"]
+              [SourceGraphic]
+              [SourceGraphic]
+          LayoutSVGResourceFilter {filter} [id="turbulence"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
+            [feTurbulence type="TURBULENCE" baseFrequency="0.05, 0.05" seed="0.00" numOctaves="2" stitchTiles="0"]
+      LayoutText {#text} at (0,0) size 0x0
+      LayoutText {#text} at (0,0) size 0x0
+      LayoutText {#text} at (0,0) size 0x0
+      LayoutText {#text} at (0,0) size 0x0
+      LayoutText {#text} at (0,0) size 0x0
+      LayoutText {#text} at (0,0) size 0x0
+layer at (20,20) size 160x90
+  LayoutImage (positioned) {IMG} at (20,20) size 160x90
+layer at (220,20) size 160x90
+  LayoutImage (positioned) {IMG} at (220,20) size 160x90
+layer at (20,150) size 160x90
+  LayoutImage (positioned) {IMG} at (20,150) size 160x90
+layer at (220,150) size 160x90
+  LayoutImage (positioned) {IMG} at (220,150) size 160x90
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-hidpi-hw-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-hidpi-hw-expected.txt
new file mode 100644
index 0000000..3a37906
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-hidpi-hw-expected.txt
@@ -0,0 +1,27 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutBlockFlow {HTML} at (0,0) size 800x600
+    LayoutBlockFlow {BODY} at (8,8) size 784x584
+      LayoutSVGRoot {svg} at (8,8) size 0x0
+        LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
+          LayoutSVGResourceFilter {filter} [id="displacement"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
+            [feDisplacementMap scale="10.00" xChannelSelector="RED" yChannelSelector="GREEN"]
+              [SourceGraphic]
+              [SourceGraphic]
+          LayoutSVGResourceFilter {filter} [id="turbulence"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
+            [feTurbulence type="TURBULENCE" baseFrequency="0.05, 0.05" seed="0.00" numOctaves="2" stitchTiles="0"]
+      LayoutText {#text} at (0,0) size 0x0
+      LayoutText {#text} at (0,0) size 0x0
+      LayoutText {#text} at (0,0) size 0x0
+      LayoutText {#text} at (0,0) size 0x0
+      LayoutText {#text} at (0,0) size 0x0
+      LayoutText {#text} at (0,0) size 0x0
+layer at (20,20) size 160x90
+  LayoutImage (positioned) {IMG} at (20,20) size 160x90
+layer at (220,20) size 160x90
+  LayoutImage (positioned) {IMG} at (220,20) size 160x90
+layer at (20,150) size 160x90
+  LayoutImage (positioned) {IMG} at (20,150) size 160x90
+layer at (220,150) size 160x90
+  LayoutImage (positioned) {IMG} at (220,150) size 160x90
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/backgrounds/gradient-background-leakage-hidpi-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/backgrounds/gradient-background-leakage-hidpi-expected.txt
new file mode 100644
index 0000000..2c151137
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/backgrounds/gradient-background-leakage-hidpi-expected.txt
@@ -0,0 +1,7 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x68
+  LayoutBlockFlow {HTML} at (0,0) size 800x68
+    LayoutBlockFlow {BODY} at (8,8) size 784x52
+      LayoutBlockFlow {DIV} at (0,0) size 220x52 [bgcolor=#FF0000]
+        LayoutBlockFlow {DIV} at (10,10) size 202x32 [border: (1px solid #008000)]
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/css/object-fit-grow-landscape-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/css/object-fit-grow-landscape-expected.png
new file mode 100644
index 0000000..51e608b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/css/object-fit-grow-landscape-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/css/object-fit-grow-landscape-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/css/object-fit-grow-landscape-expected.txt
new file mode 100644
index 0000000..f807a257
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/css/object-fit-grow-landscape-expected.txt
@@ -0,0 +1,18 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x358
+  LayoutBlockFlow {HTML} at (0,0) size 800x358
+    LayoutBlockFlow {BODY} at (8,8) size 784x342
+      LayoutImage {IMG} at (10,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (166,151) size 4x19
+        text run at (166,151) width 4: " "
+      LayoutImage {IMG} at (180,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (336,151) size 4x19
+        text run at (336,151) width 4: " "
+      LayoutImage {IMG} at (350,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (506,151) size 4x19
+        text run at (506,151) width 4: " "
+      LayoutImage {IMG} at (520,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (0,0) size 0x0
+      LayoutImage {IMG} at (10,181) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/css/object-fit-grow-portrait-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/css/object-fit-grow-portrait-expected.png
new file mode 100644
index 0000000..2d36ac6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/css/object-fit-grow-portrait-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/css/object-fit-grow-portrait-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/css/object-fit-grow-portrait-expected.txt
new file mode 100644
index 0000000..f807a257
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/css/object-fit-grow-portrait-expected.txt
@@ -0,0 +1,18 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x358
+  LayoutBlockFlow {HTML} at (0,0) size 800x358
+    LayoutBlockFlow {BODY} at (8,8) size 784x342
+      LayoutImage {IMG} at (10,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (166,151) size 4x19
+        text run at (166,151) width 4: " "
+      LayoutImage {IMG} at (180,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (336,151) size 4x19
+        text run at (336,151) width 4: " "
+      LayoutImage {IMG} at (350,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (506,151) size 4x19
+        text run at (506,151) width 4: " "
+      LayoutImage {IMG} at (520,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (0,0) size 0x0
+      LayoutImage {IMG} at (10,181) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/select/menulist-appearance-none-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/select/menulist-appearance-none-expected.png
new file mode 100644
index 0000000..90524e8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/select/menulist-appearance-none-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/select/menulist-appearance-none-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/select/menulist-appearance-none-expected.txt
new file mode 100644
index 0000000..0ca2ae51
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/select/menulist-appearance-none-expected.txt
@@ -0,0 +1,24 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutBlockFlow {HTML} at (0,0) size 800x600
+    LayoutBlockFlow {BODY} at (8,8) size 784x584
+      LayoutBlockFlow {P} at (0,0) size 784x40
+        LayoutText {#text} at (0,0) size 111x19
+          text run at (0,0) width 111: "Rendering test for "
+        LayoutInline {I} at (0,0) size 779x39
+          LayoutInline {A} at (0,0) size 410x19 [color=#0000EE]
+            LayoutText {#text} at (111,0) size 410x19
+              text run at (111,0) width 410: "https://bugs.chromium.org/p/chromium/issues/detail?id=626278"
+          LayoutText {#text} at (520,0) size 779x39
+            text run at (520,0) width 5: " "
+            text run at (524,0) width 255: "Regression: HTML Select's text appears"
+            text run at (0,20) width 234: "chopped if appearance is set to none"
+        LayoutText {#text} at (234,20) size 4x19
+          text run at (234,20) width 4: "."
+      LayoutBlockFlow (anonymous) at (0,56) size 784x42
+        LayoutMenuList {SELECT} at (0,0) size 26x42 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
+          LayoutBlockFlow (anonymous) at (1,1) size 24x40
+            LayoutText (anonymous) at (0,12) size 24x16
+              text run at (0,12) width 24: "Test"
+        LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/device-scale-factor-paint-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/device-scale-factor-paint-expected.txt
new file mode 100644
index 0000000..9dc946c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/device-scale-factor-paint-expected.txt
@@ -0,0 +1,7 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x8
+  LayoutBlockFlow {HTML} at (0,0) size 800x8
+    LayoutBlockFlow {BODY} at (8,8) size 784x0
+layer at (5,10) size 50x50
+  LayoutBlockFlow (positioned) {DIV} at (5,10) size 50x50 [bgcolor=#008000]
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/focus-rings-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/focus-rings-expected.png
new file mode 100644
index 0000000..837ac39
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/focus-rings-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/focus-rings-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/focus-rings-expected.txt
new file mode 100644
index 0000000..ff6671b4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/focus-rings-expected.txt
@@ -0,0 +1,6 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x168
+  LayoutBlockFlow {HTML} at (0,0) size 800x168
+    LayoutBlockFlow {BODY} at (8,8) size 784x152
+      LayoutBlockFlow {DIV} at (0,0) size 302x152 [border: (1px solid #000000)]
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/gradient-with-scaled-ancestor-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/gradient-with-scaled-ancestor-expected.txt
new file mode 100644
index 0000000..d24aa5a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/gradient-with-scaled-ancestor-expected.txt
@@ -0,0 +1,8 @@
+layer at (0,0) size 800x600 scrollWidth 1184
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x318
+  LayoutBlockFlow {HTML} at (0,0) size 800x318
+    LayoutBlockFlow {BODY} at (8,8) size 784x302
+layer at (8,8) size 784x302
+  LayoutBlockFlow {DIV} at (0,0) size 784x302
+    LayoutBlockFlow {DIV} at (0,0) size 302x302 [border: (1px solid #000000)]
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/image-srcset-intrinsic-size-zero-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/image-srcset-intrinsic-size-zero-expected.txt
new file mode 100644
index 0000000..27bb9c4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/image-srcset-intrinsic-size-zero-expected.txt
@@ -0,0 +1,6 @@
+PASS successfullyParsed is true
+
+TEST COMPLETE
+PASS imgWidth is 33554431
+This test passes if the image is displayed with infinite dimensions.
+
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/sub-pixel/shadows-hidpi-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/sub-pixel/shadows-hidpi-expected.txt
new file mode 100644
index 0000000..8d1c2ecc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/sub-pixel/shadows-hidpi-expected.txt
@@ -0,0 +1,20 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x58
+  LayoutBlockFlow {HTML} at (0,0) size 800x58
+    LayoutBlockFlow {BODY} at (8,8) size 784x42
+      LayoutBlockFlow {DIV} at (0,0) size 784x10
+        LayoutText {#text} at (0,0) size 30x10
+          text run at (0,0) width 30: "XXX"
+      LayoutBlockFlow (anonymous) at (0,10) size 784x32
+        LayoutBR {BR} at (0,0) size 0x10
+        LayoutBR {BR} at (0,10) size 0x10
+        LayoutBlockFlow {DIV} at (0,20) size 32x12 [border: (1px solid #000000)]
+          LayoutText {#text} at (1,1) size 30x10
+            text run at (1,1) width 30: "XXX"
+        LayoutText {#text} at (32,21) size 10x10
+          text run at (32,21) width 10: " "
+        LayoutBlockFlow {DIV} at (42,20) size 32x12 [border: (1px solid #000000)]
+          LayoutText {#text} at (1,1) size 30x10
+            text run at (1,1) width 30: "XXX"
+        LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/outline-containing-image-in-non-standard-mode-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/outline-containing-image-in-non-standard-mode-expected.txt
new file mode 100644
index 0000000..28ceb64
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/outline-containing-image-in-non-standard-mode-expected.txt
@@ -0,0 +1,47 @@
+{
+  "name": "Content Root Layer",
+  "bounds": [800, 600],
+  "children": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "drawsContent": true,
+      "paintInvalidations": [
+        {
+          "object": "LayoutInline SPAN id='target'",
+          "rect": [6, 6, 204, 58],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutImage IMG",
+          "rect": [8, 8, 200, 50],
+          "reason": "forced by layout"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow BODY",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "LayoutInline SPAN id='target'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutImage IMG",
+      "reason": "forced by layout"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/filters/filter-source-position-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/filters/filter-source-position-expected.png
deleted file mode 100644
index 45ad640..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/filters/filter-source-position-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-none-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-none-expected.png
new file mode 100644
index 0000000..d813324e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-none-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-none-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-none-expected.txt
new file mode 100644
index 0000000..c9a371a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-none-expected.txt
@@ -0,0 +1,24 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutBlockFlow {HTML} at (0,0) size 800x600
+    LayoutBlockFlow {BODY} at (8,8) size 784x584
+      LayoutBlockFlow {P} at (0,0) size 784x36
+        LayoutText {#text} at (0,0) size 120x18
+          text run at (0,0) width 120: "Rendering test for "
+        LayoutInline {I} at (0,0) size 739x36
+          LayoutInline {A} at (0,0) size 414x18 [color=#0000EE]
+            LayoutText {#text} at (119,0) size 414x18
+              text run at (119,0) width 414: "https://bugs.chromium.org/p/chromium/issues/detail?id=626278"
+          LayoutText {#text} at (533,0) size 739x36
+            text run at (533,0) width 4: " "
+            text run at (537,0) width 202: "Regression: HTML Select's text"
+            text run at (0,18) width 291: "appears chopped if appearance is set to none"
+        LayoutText {#text} at (290,18) size 5x18
+          text run at (290,18) width 5: "."
+      LayoutBlockFlow (anonymous) at (0,52) size 784x42
+        LayoutMenuList {SELECT} at (0,0) size 23x42 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 21x40
+            LayoutText (anonymous) at (0,13) size 21x13
+              text run at (0,13) width 21: "Test"
+        LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-none-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-none-expected.png
new file mode 100644
index 0000000..9db9d55
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-none-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-none-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-none-expected.txt
new file mode 100644
index 0000000..741aebe
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-none-expected.txt
@@ -0,0 +1,24 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutBlockFlow {HTML} at (0,0) size 800x600
+    LayoutBlockFlow {BODY} at (8,8) size 784x584
+      LayoutBlockFlow {P} at (0,0) size 784x36
+        LayoutText {#text} at (0,0) size 120x18
+          text run at (0,0) width 120: "Rendering test for "
+        LayoutInline {I} at (0,0) size 739x36
+          LayoutInline {A} at (0,0) size 414x18 [color=#0000EE]
+            LayoutText {#text} at (119,0) size 414x18
+              text run at (119,0) width 414: "https://bugs.chromium.org/p/chromium/issues/detail?id=626278"
+          LayoutText {#text} at (533,0) size 739x36
+            text run at (533,0) width 4: " "
+            text run at (537,0) width 202: "Regression: HTML Select's text"
+            text run at (0,18) width 291: "appears chopped if appearance is set to none"
+        LayoutText {#text} at (290,18) size 5x18
+          text run at (290,18) width 5: "."
+      LayoutBlockFlow (anonymous) at (0,52) size 784x42
+        LayoutMenuList {SELECT} at (0,0) size 25x42 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 23x40
+            LayoutText (anonymous) at (0,13) size 23x13
+              text run at (0,13) width 23: "Test"
+        LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance-expected.png
deleted file mode 100644
index a68f08e4..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance-expected.png
deleted file mode 100644
index cf65cf9..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance-expected.png
deleted file mode 100644
index aa6a2fb..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance-expected.png
deleted file mode 100644
index aa84c0a..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance-expected.png
deleted file mode 100644
index 9462fd8..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance-expected.png
deleted file mode 100644
index 22f8cc8..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/img-layer-object-fit-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/compositing/img-layer-object-fit-expected.txt
new file mode 100644
index 0000000..08ab093
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/img-layer-object-fit-expected.txt
@@ -0,0 +1,17 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x152
+  LayoutBlockFlow {HTML} at (0,0) size 800x152
+    LayoutBlockFlow {BODY} at (8,8) size 784x136
+      LayoutBR {BR} at (100,16) size 0x18
+      LayoutBR {BR} at (100,50) size 0x18
+      LayoutBR {BR} at (100,84) size 0x18
+      LayoutBR {BR} at (100,118) size 0x18
+layer at (8,8) size 100x30
+  LayoutImage {IMG} at (0,0) size 100x30
+layer at (8,42) size 100x30
+  LayoutImage {IMG} at (0,34) size 100x30
+layer at (8,76) size 100x30
+  LayoutImage {IMG} at (0,68) size 100x30
+layer at (8,110) size 100x30
+  LayoutImage {IMG} at (0,102) size 100x30
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/css/object-fit-grow-landscape-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/css/object-fit-grow-landscape-expected.png
new file mode 100644
index 0000000..7352cb57
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/css/object-fit-grow-landscape-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/css/object-fit-grow-landscape-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/css/object-fit-grow-landscape-expected.txt
new file mode 100644
index 0000000..c977439
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/css/object-fit-grow-landscape-expected.txt
@@ -0,0 +1,18 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x356
+  LayoutBlockFlow {HTML} at (0,0) size 800x356
+    LayoutBlockFlow {BODY} at (8,8) size 784x340
+      LayoutImage {IMG} at (10,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (166,152) size 4x18
+        text run at (166,152) width 4: " "
+      LayoutImage {IMG} at (180,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (336,152) size 4x18
+        text run at (336,152) width 4: " "
+      LayoutImage {IMG} at (350,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (506,152) size 4x18
+        text run at (506,152) width 4: " "
+      LayoutImage {IMG} at (520,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (0,0) size 0x0
+      LayoutImage {IMG} at (10,180) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/css/object-fit-grow-portrait-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/css/object-fit-grow-portrait-expected.png
new file mode 100644
index 0000000..159d3cb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/css/object-fit-grow-portrait-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/css/object-fit-grow-portrait-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/css/object-fit-grow-portrait-expected.txt
new file mode 100644
index 0000000..c977439
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/css/object-fit-grow-portrait-expected.txt
@@ -0,0 +1,18 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x356
+  LayoutBlockFlow {HTML} at (0,0) size 800x356
+    LayoutBlockFlow {BODY} at (8,8) size 784x340
+      LayoutImage {IMG} at (10,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (166,152) size 4x18
+        text run at (166,152) width 4: " "
+      LayoutImage {IMG} at (180,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (336,152) size 4x18
+        text run at (336,152) width 4: " "
+      LayoutImage {IMG} at (350,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (506,152) size 4x18
+        text run at (506,152) width 4: " "
+      LayoutImage {IMG} at (520,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (0,0) size 0x0
+      LayoutImage {IMG} at (10,180) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-none-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-none-expected.png
new file mode 100644
index 0000000..0b66b1f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-none-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-none-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-none-expected.txt
new file mode 100644
index 0000000..741aebe
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-none-expected.txt
@@ -0,0 +1,24 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutBlockFlow {HTML} at (0,0) size 800x600
+    LayoutBlockFlow {BODY} at (8,8) size 784x584
+      LayoutBlockFlow {P} at (0,0) size 784x36
+        LayoutText {#text} at (0,0) size 120x18
+          text run at (0,0) width 120: "Rendering test for "
+        LayoutInline {I} at (0,0) size 739x36
+          LayoutInline {A} at (0,0) size 414x18 [color=#0000EE]
+            LayoutText {#text} at (119,0) size 414x18
+              text run at (119,0) width 414: "https://bugs.chromium.org/p/chromium/issues/detail?id=626278"
+          LayoutText {#text} at (533,0) size 739x36
+            text run at (533,0) width 4: " "
+            text run at (537,0) width 202: "Regression: HTML Select's text"
+            text run at (0,18) width 291: "appears chopped if appearance is set to none"
+        LayoutText {#text} at (290,18) size 5x18
+          text run at (290,18) width 5: "."
+      LayoutBlockFlow (anonymous) at (0,52) size 784x42
+        LayoutMenuList {SELECT} at (0,0) size 25x42 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 23x40
+            LayoutText (anonymous) at (0,13) size 23x13
+              text run at (0,13) width 23: "Test"
+        LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/img-layer-object-fit-expected.txt b/third_party/WebKit/LayoutTests/platform/win/compositing/img-layer-object-fit-expected.txt
new file mode 100644
index 0000000..2470a2a4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/compositing/img-layer-object-fit-expected.txt
@@ -0,0 +1,17 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x152
+  LayoutBlockFlow {HTML} at (0,0) size 800x152
+    LayoutBlockFlow {BODY} at (8,8) size 784x136
+      LayoutBR {BR} at (100,16) size 0x17
+      LayoutBR {BR} at (100,50) size 0x17
+      LayoutBR {BR} at (100,84) size 0x17
+      LayoutBR {BR} at (100,118) size 0x17
+layer at (8,8) size 100x30
+  LayoutImage {IMG} at (0,0) size 100x30
+layer at (8,42) size 100x30
+  LayoutImage {IMG} at (0,34) size 100x30
+layer at (8,76) size 100x30
+  LayoutImage {IMG} at (0,68) size 100x30
+layer at (8,110) size 100x30
+  LayoutImage {IMG} at (0,102) size 100x30
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/tiled-layers-hidpi-expected.txt b/third_party/WebKit/LayoutTests/platform/win/compositing/tiled-layers-hidpi-expected.txt
new file mode 100644
index 0000000..a6cbb89
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/compositing/tiled-layers-hidpi-expected.txt
@@ -0,0 +1,23 @@
+{
+  "name": "Content Root Layer",
+  "bounds": [3616, 1170],
+  "children": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [3616, 1170],
+      "contentsOpaque": true,
+      "drawsContent": true,
+      "children": [
+        {
+          "name": "LayoutBlockFlow DIV id='composited'",
+          "position": [16, 16],
+          "bounds": [3600, 20],
+          "contentsOpaque": true,
+          "drawsContent": true,
+          "backgroundColor": "#0000FF"
+        }
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-hidpi-expected.txt b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-hidpi-expected.txt
new file mode 100644
index 0000000..7e0b8609
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-hidpi-expected.txt
@@ -0,0 +1,27 @@
+layer at (0,0) size 1600x1200
+  LayoutView at (0,0) size 1600x1200
+layer at (0,0) size 1600x1200
+  LayoutBlockFlow {HTML} at (0,0) size 1600x1200
+    LayoutBlockFlow {BODY} at (16,16) size 1568x1168
+      LayoutSVGRoot {svg} at (16,16) size 0x0
+        LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
+          LayoutSVGResourceFilter {filter} [id="displacement"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
+            [feDisplacementMap scale="10.00" xChannelSelector="RED" yChannelSelector="GREEN"]
+              [SourceGraphic]
+              [SourceGraphic]
+          LayoutSVGResourceFilter {filter} [id="turbulence"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
+            [feTurbulence type="TURBULENCE" baseFrequency="0.05, 0.05" seed="0.00" numOctaves="2" stitchTiles="0"]
+      LayoutText {#text} at (0,0) size 0x0
+      LayoutText {#text} at (0,0) size 0x0
+      LayoutText {#text} at (0,0) size 0x0
+      LayoutText {#text} at (0,0) size 0x0
+      LayoutText {#text} at (0,0) size 0x0
+      LayoutText {#text} at (0,0) size 0x0
+layer at (40,40) size 320x180
+  LayoutImage (positioned) {IMG} at (40,40) size 320x180
+layer at (440,40) size 320x180
+  LayoutImage (positioned) {IMG} at (440,40) size 320x180
+layer at (40,300) size 320x180
+  LayoutImage (positioned) {IMG} at (40,300) size 320x180
+layer at (440,300) size 320x180
+  LayoutImage (positioned) {IMG} at (440,300) size 320x180
diff --git a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-hidpi-hw-expected.txt b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-hidpi-hw-expected.txt
new file mode 100644
index 0000000..7e0b8609
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-hidpi-hw-expected.txt
@@ -0,0 +1,27 @@
+layer at (0,0) size 1600x1200
+  LayoutView at (0,0) size 1600x1200
+layer at (0,0) size 1600x1200
+  LayoutBlockFlow {HTML} at (0,0) size 1600x1200
+    LayoutBlockFlow {BODY} at (16,16) size 1568x1168
+      LayoutSVGRoot {svg} at (16,16) size 0x0
+        LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
+          LayoutSVGResourceFilter {filter} [id="displacement"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
+            [feDisplacementMap scale="10.00" xChannelSelector="RED" yChannelSelector="GREEN"]
+              [SourceGraphic]
+              [SourceGraphic]
+          LayoutSVGResourceFilter {filter} [id="turbulence"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
+            [feTurbulence type="TURBULENCE" baseFrequency="0.05, 0.05" seed="0.00" numOctaves="2" stitchTiles="0"]
+      LayoutText {#text} at (0,0) size 0x0
+      LayoutText {#text} at (0,0) size 0x0
+      LayoutText {#text} at (0,0) size 0x0
+      LayoutText {#text} at (0,0) size 0x0
+      LayoutText {#text} at (0,0) size 0x0
+      LayoutText {#text} at (0,0) size 0x0
+layer at (40,40) size 320x180
+  LayoutImage (positioned) {IMG} at (40,40) size 320x180
+layer at (440,40) size 320x180
+  LayoutImage (positioned) {IMG} at (440,40) size 320x180
+layer at (40,300) size 320x180
+  LayoutImage (positioned) {IMG} at (40,300) size 320x180
+layer at (440,300) size 320x180
+  LayoutImage (positioned) {IMG} at (440,300) size 320x180
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/spelling/grammar-markers-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/spelling/grammar-markers-hidpi-expected.png
index cbd9217..7add1851 100644
--- a/third_party/WebKit/LayoutTests/platform/win/editing/spelling/grammar-markers-hidpi-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/editing/spelling/grammar-markers-hidpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/spelling/inline-spelling-markers-hidpi-composited-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/spelling/inline-spelling-markers-hidpi-composited-expected.png
index 9b0a45b..02ffae2 100644
--- a/third_party/WebKit/LayoutTests/platform/win/editing/spelling/inline-spelling-markers-hidpi-composited-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/editing/spelling/inline-spelling-markers-hidpi-composited-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/spelling/inline-spelling-markers-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/spelling/inline-spelling-markers-hidpi-expected.png
index 65f5988b..4c89f6c 100644
--- a/third_party/WebKit/LayoutTests/platform/win/editing/spelling/inline-spelling-markers-hidpi-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/editing/spelling/inline-spelling-markers-hidpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/backgrounds/gradient-background-leakage-hidpi-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/backgrounds/gradient-background-leakage-hidpi-expected.txt
new file mode 100644
index 0000000..c7e9a68
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/backgrounds/gradient-background-leakage-hidpi-expected.txt
@@ -0,0 +1,7 @@
+layer at (0,0) size 1600x1200
+  LayoutView at (0,0) size 1600x1200
+layer at (0,0) size 1600x136
+  LayoutBlockFlow {HTML} at (0,0) size 1600x136
+    LayoutBlockFlow {BODY} at (16,16) size 1568x104
+      LayoutBlockFlow {DIV} at (0,0) size 440x104 [bgcolor=#FF0000]
+        LayoutBlockFlow {DIV} at (20,20) size 404x64 [border: (2px solid #008000)]
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/canvas/canvas-hidpi-blurry-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/canvas/canvas-hidpi-blurry-expected.png
new file mode 100644
index 0000000..6a9b251
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/canvas/canvas-hidpi-blurry-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/css/object-fit-grow-landscape-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/css/object-fit-grow-landscape-expected.png
new file mode 100644
index 0000000..bd72523
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/css/object-fit-grow-landscape-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/css/object-fit-grow-landscape-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/css/object-fit-grow-landscape-expected.txt
new file mode 100644
index 0000000..650f620
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/css/object-fit-grow-landscape-expected.txt
@@ -0,0 +1,18 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x356
+  LayoutBlockFlow {HTML} at (0,0) size 800x356
+    LayoutBlockFlow {BODY} at (8,8) size 784x340
+      LayoutImage {IMG} at (10,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (166,152) size 4x17
+        text run at (166,152) width 4: " "
+      LayoutImage {IMG} at (180,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (336,152) size 4x17
+        text run at (336,152) width 4: " "
+      LayoutImage {IMG} at (350,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (506,152) size 4x17
+        text run at (506,152) width 4: " "
+      LayoutImage {IMG} at (520,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (0,0) size 0x0
+      LayoutImage {IMG} at (10,180) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/css/object-fit-grow-portrait-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/css/object-fit-grow-portrait-expected.png
new file mode 100644
index 0000000..ce5c0bfd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/css/object-fit-grow-portrait-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/css/object-fit-grow-portrait-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/css/object-fit-grow-portrait-expected.txt
new file mode 100644
index 0000000..650f620
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/css/object-fit-grow-portrait-expected.txt
@@ -0,0 +1,18 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x356
+  LayoutBlockFlow {HTML} at (0,0) size 800x356
+    LayoutBlockFlow {BODY} at (8,8) size 784x340
+      LayoutImage {IMG} at (10,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (166,152) size 4x17
+        text run at (166,152) width 4: " "
+      LayoutImage {IMG} at (180,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (336,152) size 4x17
+        text run at (336,152) width 4: " "
+      LayoutImage {IMG} at (350,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (506,152) size 4x17
+        text run at (506,152) width 4: " "
+      LayoutImage {IMG} at (520,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (0,0) size 0x0
+      LayoutImage {IMG} at (10,180) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)]
+      LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/menulist-appearance-none-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/menulist-appearance-none-expected.png
new file mode 100644
index 0000000..7ed686f7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/menulist-appearance-none-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/menulist-appearance-none-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/menulist-appearance-none-expected.txt
new file mode 100644
index 0000000..d9edd6a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/menulist-appearance-none-expected.txt
@@ -0,0 +1,24 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutBlockFlow {HTML} at (0,0) size 800x600
+    LayoutBlockFlow {BODY} at (8,8) size 784x584
+      LayoutBlockFlow {P} at (0,0) size 784x36
+        LayoutText {#text} at (0,0) size 120x17
+          text run at (0,0) width 120: "Rendering test for "
+        LayoutInline {I} at (0,0) size 739x35
+          LayoutInline {A} at (0,0) size 414x17 [color=#0000EE]
+            LayoutText {#text} at (119,0) size 414x17
+              text run at (119,0) width 414: "https://bugs.chromium.org/p/chromium/issues/detail?id=626278"
+          LayoutText {#text} at (532,0) size 739x35
+            text run at (532,0) width 5: " "
+            text run at (536,0) width 203: "Regression: HTML Select's text"
+            text run at (0,18) width 291: "appears chopped if appearance is set to none"
+        LayoutText {#text} at (290,18) size 5x17
+          text run at (290,18) width 5: "."
+      LayoutBlockFlow (anonymous) at (0,52) size 784x42
+        LayoutMenuList {SELECT} at (0,0) size 26x42 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+          LayoutBlockFlow (anonymous) at (1,1) size 24x40
+            LayoutText (anonymous) at (0,12) size 24x16
+              text run at (0,12) width 24: "Test"
+        LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-icon-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-icon-hidpi-expected.png
index 057c02d..cbe0ac6 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-icon-hidpi-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-icon-hidpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-icon-hidpi-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-icon-hidpi-expected.txt
index ce6b59d..efa9043 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-icon-hidpi-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-icon-hidpi-expected.txt
@@ -1,17 +1,17 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x58
-  LayoutBlockFlow {HTML} at (0,0) size 800x58
-    LayoutBlockFlow {BODY} at (8,8) size 784x42
-      LayoutBlockFlow {DIV} at (0,0) size 784x18
-        LayoutText {#text} at (0,0) size 755x17
-          text run at (0,0) width 755: "This test passes if the broken image icon appears high-resolution in HiDPI and if the outline is of the appropriate size."
-      LayoutBlockFlow (anonymous) at (0,18) size 784x24
-        LayoutBlockFlow {IMG} at (0,0) size 20x24
+layer at (0,0) size 1600x1200
+  LayoutView at (0,0) size 1600x1200
+layer at (0,0) size 1600x117
+  LayoutBlockFlow {HTML} at (0,0) size 1600x117
+    LayoutBlockFlow {BODY} at (16,16) size 1568x85
+      LayoutBlockFlow {DIV} at (0,0) size 1568x37
+        LayoutText {#text} at (0,0) size 1510x36
+          text run at (0,0) width 1510: "This test passes if the broken image icon appears high-resolution in HiDPI and if the outline is of the appropriate size."
+      LayoutBlockFlow (anonymous) at (0,37) size 1568x48
+        LayoutBlockFlow {IMG} at (0,0) size 40x48
         LayoutText {#text} at (0,0) size 0x0
         LayoutText {#text} at (0,0) size 0x0
-layer at (8,26) size 20x20 clip at (9,27) size 18x18
-  LayoutBlockFlow {DIV} at (0,0) size 20x20 [border: (1px solid #C0C0C0)]
-    LayoutImage (floating) {IMG} at (2,2) size 16x16
-layer at (26,28) size 0x0
-  LayoutBlockFlow {DIV} at (18,2) size 0x0
+layer at (16,53) size 40x40 clip at (18,55) size 36x36
+  LayoutBlockFlow {DIV} at (0,0) size 40x40 [border: (2px solid #C0C0C0)]
+    LayoutImage (floating) {IMG} at (4,4) size 32x32
+layer at (52,57) size 0x0
+  LayoutBlockFlow {DIV} at (36,4) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-with-size-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-with-size-hidpi-expected.png
index ede3843c..a4009dd 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-with-size-hidpi-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-with-size-hidpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-with-size-hidpi-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-with-size-hidpi-expected.txt
index c536f23e..e222846b 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-with-size-hidpi-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-with-size-hidpi-expected.txt
@@ -1,17 +1,17 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x188
-  LayoutBlockFlow {HTML} at (0,0) size 800x188
-    LayoutBlockFlow {BODY} at (8,8) size 784x172
-      LayoutBlockFlow {DIV} at (0,0) size 784x18
-        LayoutText {#text} at (0,0) size 652x17
-          text run at (0,0) width 652: "This test passes if the broken image icon appears high-resolution in HiDPI and is the appropriate size."
-      LayoutBlockFlow (anonymous) at (0,18) size 784x154
-        LayoutBlockFlow {IMG} at (0,0) size 300x150
+layer at (0,0) size 1600x1200
+  LayoutView at (0,0) size 1600x1200
+layer at (0,0) size 1600x377
+  LayoutBlockFlow {HTML} at (0,0) size 1600x377
+    LayoutBlockFlow {BODY} at (16,16) size 1568x345
+      LayoutBlockFlow {DIV} at (0,0) size 1568x37
+        LayoutText {#text} at (0,0) size 1304x36
+          text run at (0,0) width 1304: "This test passes if the broken image icon appears high-resolution in HiDPI and is the appropriate size."
+      LayoutBlockFlow (anonymous) at (0,37) size 1568x308
+        LayoutBlockFlow {IMG} at (0,0) size 600x300
         LayoutText {#text} at (0,0) size 0x0
         LayoutText {#text} at (0,0) size 0x0
-layer at (8,26) size 300x150 clip at (9,27) size 298x148
-  LayoutBlockFlow {DIV} at (0,0) size 300x150 [border: (1px solid #C0C0C0)]
-    LayoutImage (floating) {IMG} at (2,2) size 16x16
-layer at (26,28) size 280x0
-  LayoutBlockFlow {DIV} at (18,2) size 280x0
+layer at (16,53) size 600x300 clip at (18,55) size 596x296
+  LayoutBlockFlow {DIV} at (0,0) size 600x300 [border: (2px solid #C0C0C0)]
+    LayoutImage (floating) {IMG} at (4,4) size 32x32
+layer at (52,57) size 560x0
+  LayoutBlockFlow {DIV} at (36,4) size 560x0
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/clip-text-in-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/clip-text-in-hidpi-expected.png
index fe1f4ec..981ddf2d 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/clip-text-in-hidpi-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/clip-text-in-hidpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/clip-text-in-hidpi-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/clip-text-in-hidpi-expected.txt
index f689fe0..ba3e16e 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/clip-text-in-hidpi-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/clip-text-in-hidpi-expected.txt
@@ -1,14 +1,14 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x34
-  LayoutBlockFlow {HTML} at (0,0) size 800x34
-    LayoutBlockFlow {BODY} at (8,8) size 784x18
-      LayoutInline {SPAN} at (0,0) size 360x17 [bgcolor=#FF0000]
-        LayoutText {#text} at (0,0) size 360x17
-          text run at (0,0) width 360: "This text should be nice and sharp. devicePixelRatio is: "
+layer at (0,0) size 1600x1200
+  LayoutView at (0,0) size 1600x1200
+layer at (0,0) size 1600x69
+  LayoutBlockFlow {HTML} at (0,0) size 1600x69
+    LayoutBlockFlow {BODY} at (16,16) size 1568x37
+      LayoutInline {SPAN} at (0,0) size 719x36 [bgcolor=#FF0000]
+        LayoutText {#text} at (0,0) size 719x36
+          text run at (0,0) width 719: "This text should be nice and sharp. devicePixelRatio is: "
       LayoutText {#text} at (0,0) size 0x0
-      LayoutInline {SPAN} at (0,0) size 9x17
-        LayoutText {#text} at (359,0) size 9x17
-          text run at (359,0) width 9: "2"
+      LayoutInline {SPAN} at (0,0) size 17x36
+        LayoutText {#text} at (718,0) size 17x36
+          text run at (718,0) width 17: "2"
       LayoutText {#text} at (0,0) size 0x0
       LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/device-scale-factor-paint-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/device-scale-factor-paint-expected.txt
new file mode 100644
index 0000000..8e122b1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/device-scale-factor-paint-expected.txt
@@ -0,0 +1,7 @@
+layer at (0,0) size 1600x1200
+  LayoutView at (0,0) size 1600x1200
+layer at (0,0) size 1600x16
+  LayoutBlockFlow {HTML} at (0,0) size 1600x16
+    LayoutBlockFlow {BODY} at (16,16) size 1568x0
+layer at (10,20) size 100x100
+  LayoutBlockFlow (positioned) {DIV} at (10,20) size 100x100 [bgcolor=#008000]
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/focus-rings-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/focus-rings-expected.png
index 837ac39..5fd8184 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/focus-rings-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/focus-rings-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/focus-rings-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/focus-rings-expected.txt
new file mode 100644
index 0000000..b64aafba
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/focus-rings-expected.txt
@@ -0,0 +1,6 @@
+layer at (0,0) size 1600x1200
+  LayoutView at (0,0) size 1600x1200
+layer at (0,0) size 1600x336
+  LayoutBlockFlow {HTML} at (0,0) size 1600x336
+    LayoutBlockFlow {BODY} at (16,16) size 1568x304
+      LayoutBlockFlow {DIV} at (0,0) size 604x304 [border: (2px solid #000000)]
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/gradient-with-scaled-ancestor-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/gradient-with-scaled-ancestor-expected.txt
new file mode 100644
index 0000000..9dc9f5a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/gradient-with-scaled-ancestor-expected.txt
@@ -0,0 +1,8 @@
+layer at (0,0) size 1600x1200 scrollWidth 2368
+  LayoutView at (0,0) size 1600x1200
+layer at (0,0) size 1600x636
+  LayoutBlockFlow {HTML} at (0,0) size 1600x636
+    LayoutBlockFlow {BODY} at (16,16) size 1568x604
+layer at (16,16) size 1568x604
+  LayoutBlockFlow {DIV} at (0,0) size 1568x604
+    LayoutBlockFlow {DIV} at (0,0) size 604x604 [border: (2px solid #000000)]
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/image-srcset-intrinsic-size-zero-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/image-srcset-intrinsic-size-zero-expected.txt
new file mode 100644
index 0000000..af1c507d4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/image-srcset-intrinsic-size-zero-expected.txt
@@ -0,0 +1,6 @@
+PASS successfullyParsed is true
+
+TEST COMPLETE
+PASS imgWidth is 16777216
+This test passes if the image is displayed with infinite dimensions.
+
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/resize-corner-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/resize-corner-hidpi-expected.png
index e9a4abe..dd8545e 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/resize-corner-hidpi-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/resize-corner-hidpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/resize-corner-hidpi-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/resize-corner-hidpi-expected.txt
index 4470182..7f27e05 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/resize-corner-hidpi-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/resize-corner-hidpi-expected.txt
@@ -1,14 +1,14 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x76
-  LayoutBlockFlow {HTML} at (0,0) size 800x76
-    LayoutBlockFlow {BODY} at (8,8) size 784x60
-      LayoutBlockFlow {DIV} at (0,0) size 784x18
-        LayoutText {#text} at (0,0) size 476x17
-          text run at (0,0) width 476: "This test passes if the resize corner icon appears high-resolution in HiDPI."
-      LayoutBlockFlow (anonymous) at (0,18) size 784x42
+layer at (0,0) size 1600x1200
+  LayoutView at (0,0) size 1600x1200
+layer at (0,0) size 1600x149
+  LayoutBlockFlow {HTML} at (0,0) size 1600x149
+    LayoutBlockFlow {BODY} at (16,16) size 1568x117
+      LayoutBlockFlow {DIV} at (0,0) size 1568x37
+        LayoutText {#text} at (0,0) size 951x36
+          text run at (0,0) width 951: "This test passes if the resize corner icon appears high-resolution in HiDPI."
+      LayoutBlockFlow (anonymous) at (0,37) size 1568x80
         LayoutText {#text} at (0,0) size 0x0
         LayoutText {#text} at (0,0) size 0x0
-layer at (8,26) size 181x38 clip at (9,27) size 179x36
-  LayoutTextControl {TEXTAREA} at (0,0) size 181x38 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
-    LayoutBlockFlow {DIV} at (3,3) size 175x16
+layer at (16,53) size 347x72 clip at (18,55) size 343x68
+  LayoutTextControl {TEXTAREA} at (0,0) size 347x72 [bgcolor=#FFFFFF] [border: (2px solid #A9A9A9)]
+    LayoutBlockFlow {DIV} at (6,6) size 335x30
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/sub-pixel/shadows-hidpi-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/sub-pixel/shadows-hidpi-expected.txt
new file mode 100644
index 0000000..d7695196
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/sub-pixel/shadows-hidpi-expected.txt
@@ -0,0 +1,20 @@
+layer at (0,0) size 1600x1200
+  LayoutView at (0,0) size 1600x1200
+layer at (0,0) size 1600x116
+  LayoutBlockFlow {HTML} at (0,0) size 1600x116
+    LayoutBlockFlow {BODY} at (16,16) size 1568x84
+      LayoutBlockFlow {DIV} at (0,0) size 1568x20
+        LayoutText {#text} at (0,0) size 60x20
+          text run at (0,0) width 60: "XXX"
+      LayoutBlockFlow (anonymous) at (0,20) size 1568x64
+        LayoutBR {BR} at (0,0) size 0x20
+        LayoutBR {BR} at (0,20) size 0x20
+        LayoutBlockFlow {DIV} at (0,40) size 64x24 [border: (2px solid #000000)]
+          LayoutText {#text} at (2,2) size 60x20
+            text run at (2,2) width 60: "XXX"
+        LayoutText {#text} at (64,42) size 20x20
+          text run at (64,42) width 20: " "
+        LayoutBlockFlow {DIV} at (84,40) size 64x24 [border: (2px solid #000000)]
+          LayoutText {#text} at (2,2) size 60x20
+            text run at (2,2) width 60: "XXX"
+        LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/outline-containing-image-in-non-standard-mode-expected.txt b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/outline-containing-image-in-non-standard-mode-expected.txt
new file mode 100644
index 0000000..fd99d4f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/outline-containing-image-in-non-standard-mode-expected.txt
@@ -0,0 +1,47 @@
+{
+  "name": "Content Root Layer",
+  "bounds": [800, 600],
+  "children": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "drawsContent": true,
+      "paintInvalidations": [
+        {
+          "object": "LayoutInline SPAN id='target'",
+          "rect": [6, 6, 204, 57],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutImage IMG",
+          "rect": [8, 8, 200, 50],
+          "reason": "forced by layout"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow BODY",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "LayoutInline SPAN id='target'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutImage IMG",
+      "reason": "forced by layout"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/as-image/image-respects-deviceScaleFactor-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/as-image/image-respects-deviceScaleFactor-expected.png
index 1de1f4d..195c9e8 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/as-image/image-respects-deviceScaleFactor-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/as-image/image-respects-deviceScaleFactor-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/as-image/image-respects-deviceScaleFactor-expected.txt b/third_party/WebKit/LayoutTests/platform/win/svg/as-image/image-respects-deviceScaleFactor-expected.txt
index e3afdb4..9374d44e 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/as-image/image-respects-deviceScaleFactor-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/as-image/image-respects-deviceScaleFactor-expected.txt
@@ -1,14 +1,14 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
-      LayoutBlockFlow {P} at (0,0) size 784x18
-        LayoutText {#text} at (0,0) size 527x17
-          text run at (0,0) width 527: "This test passes if both of the circles have sharp edges when deviceScaleFactor=2."
-      LayoutBlockFlow (anonymous) at (0,34) size 784x132
-        LayoutImage {IMG} at (0,0) size 128x128
-        LayoutText {#text} at (128,114) size 4x17
-          text run at (128,114) width 4: " "
-        LayoutImage {IMG} at (132,0) size 128x128
+layer at (0,0) size 1600x1200
+  LayoutView at (0,0) size 1600x1200
+layer at (0,0) size 1600x1200
+  LayoutBlockFlow {HTML} at (0,0) size 1600x1200
+    LayoutBlockFlow {BODY} at (16,16) size 1568x1168
+      LayoutBlockFlow {P} at (0,0) size 1568x37
+        LayoutText {#text} at (0,0) size 1054x36
+          text run at (0,0) width 1054: "This test passes if both of the circles have sharp edges when deviceScaleFactor=2."
+      LayoutBlockFlow (anonymous) at (0,69) size 1568x264
+        LayoutImage {IMG} at (0,0) size 256x256
+        LayoutText {#text} at (256,227) size 8x36
+          text run at (256,227) width 8: " "
+        LayoutImage {IMG} at (264,0) size 256x256
         LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/custom/masking-clipping-hidpi-expected.txt b/third_party/WebKit/LayoutTests/platform/win/svg/custom/masking-clipping-hidpi-expected.txt
index f870203..bcc57d4 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/custom/masking-clipping-hidpi-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/custom/masking-clipping-hidpi-expected.txt
@@ -1,15 +1,15 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutSVGRoot {svg} at (0,0) size 292x362
+layer at (0,0) size 1600x1200
+  LayoutView at (0,0) size 1600x1200
+layer at (0,0) size 1600x1200
+  LayoutSVGRoot {svg} at (0,0) size 583x724
     LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
       LayoutSVGResourceMasker {mask} [id="textMask"] [maskUnits=objectBoundingBox] [maskContentUnits=userSpaceOnUse]
-        LayoutSVGRect {rect} at (0,0) size 800x600 [fill={[type=SOLID] [color=#FFFFFF]}] [x=0.00] [y=0.00] [width=800.00] [height=600.00]
+        LayoutSVGRect {rect} at (0,0) size 1600x1200 [fill={[type=SOLID] [color=#FFFFFF]}] [x=0.00] [y=0.00] [width=800.00] [height=600.00]
         LayoutSVGText {text} at (0,-3) size 165x19 contains 1 chunk(s)
           LayoutSVGInlineText {#text} at (0,0) size 165x18
             chunk 1 text run 1 at (0.00,12.00) startOffset 0 endOffset 26 width 164.87: "This text should be sharp."
-    LayoutSVGRect {rect} at (0,0) size 200x100 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=0.00] [width=200.00] [height=100.00]
-    LayoutSVGRect {rect} at (0,0) size 200x100 [fill={[type=SOLID] [color=#FFFFFF]}] [x=0.00] [y=0.00] [width=200.00] [height=100.00]
+    LayoutSVGRect {rect} at (0,0) size 400x200 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=0.00] [width=200.00] [height=100.00]
+    LayoutSVGRect {rect} at (0,0) size 400x200 [fill={[type=SOLID] [color=#FFFFFF]}] [x=0.00] [y=0.00] [width=200.00] [height=100.00]
       [masker="textMask"] LayoutSVGResourceMasker {mask} at (0,-2.50) size 220x112.50
     LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
       LayoutSVGResourceLinearGradient {linearGradient} [id="blackGradient"] [gradientUnits=objectBoundingBox] [start=(0,0)] [end=(1,0)]
@@ -21,10 +21,10 @@
     LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
       LayoutSVGResourceClipper {clipPath} [id="circleClipPath"] [clipPathUnits=objectBoundingBox]
         LayoutSVGEllipse {circle} at (0,0) size 1x1 [fill={[type=SOLID] [color=#000000]}] [cx=0.25] [cy=0.25] [r=0.20]
-        LayoutSVGEllipse {circle} at (0,0) size 1x1 [fill={[type=SOLID] [color=#000000]}] [cx=0.25] [cy=0.75] [r=0.20]
-    LayoutSVGRect {rect} at (4,65) size 41x90 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=60.00] [width=100.00] [height=100.00]
+        LayoutSVGEllipse {circle} at (0,1) size 1x1 [fill={[type=SOLID] [color=#000000]}] [cx=0.25] [cy=0.75] [r=0.20]
+    LayoutSVGRect {rect} at (9,130) size 81x180 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=60.00] [width=100.00] [height=100.00]
       [clipPath="circleClipPath"] LayoutSVGResourceClipper {clipPath} at (5,65) size 40x90
     LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
       LayoutSVGResourcePattern {pattern} [id="Pattern"] [patternUnits=objectBoundingBox] [patternContentUnits=userSpaceOnUse]
-        LayoutSVGEllipse {circle} at (5,5) size 40x40 [fill={[type=LINEAR-GRADIENT] [id="blackGradient"]}] [cx=25.00] [cy=25.00] [r=20.00]
-    LayoutSVGRect {rect} at (0,162) size 200x200 [fill={[type=PATTERN] [id="Pattern"]}] [x=0.00] [y=162.00] [width=200.00] [height=200.00]
+        LayoutSVGEllipse {circle} at (10,10) size 80x80 [fill={[type=LINEAR-GRADIENT] [id="blackGradient"]}] [cx=25.00] [cy=25.00] [r=20.00]
+    LayoutSVGRect {rect} at (0,324) size 400x400 [fill={[type=PATTERN] [id="Pattern"]}] [x=0.00] [y=162.00] [width=200.00] [height=200.00]
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/filters/filter-source-position-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/filters/filter-source-position-expected.png
index af54d677..45ad640 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/filters/filter-source-position-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/filters/filter-source-position-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/display_list_2d_canvas/fast/canvas/canvas-hidpi-blurry-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/display_list_2d_canvas/fast/canvas/canvas-hidpi-blurry-expected.png
new file mode 100644
index 0000000..6a9b251
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/display_list_2d_canvas/fast/canvas/canvas-hidpi-blurry-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-hidpi-blurry-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-hidpi-blurry-expected.png
new file mode 100644
index 0000000..92e03005
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-hidpi-blurry-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance-expected.png
index f7a547d..45aed31 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance-expected.png
index c2cbe03c..86a8e04a 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance-expected.png
index e4f124f7..38e0c9f 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance-expected.png
index 3c0a74c..5143b15 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance-expected.png
index 2281f56e..b730167d 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance-expected.png
index f592d2a..890a68e2 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/editing/spelling/inline-spelling-markers-hidpi-composited-expected.png b/third_party/WebKit/LayoutTests/platform/win7/editing/spelling/inline-spelling-markers-hidpi-composited-expected.png
new file mode 100644
index 0000000..efd7dc2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win7/editing/spelling/inline-spelling-markers-hidpi-composited-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/svg/filters/filter-source-position-expected.png b/third_party/WebKit/LayoutTests/platform/win7/svg/filters/filter-source-position-expected.png
new file mode 100644
index 0000000..af54d677
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win7/svg/filters/filter-source-position-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance-expected.png
index 8168623..4f7790e 100644
--- a/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance-expected.png
deleted file mode 100644
index c2cbe03c..0000000
--- a/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance-expected.png
deleted file mode 100644
index e4f124f7..0000000
--- a/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance-expected.png
index 7e20663..9d787d8 100644
--- a/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance-expected.png
deleted file mode 100644
index 2281f56e..0000000
--- a/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance-expected.png
deleted file mode 100644
index f592d2a..0000000
--- a/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/resources/idlharness.js b/third_party/WebKit/LayoutTests/resources/idlharness.js
index b6a16af..5002ec5 100644
--- a/third_party/WebKit/LayoutTests/resources/idlharness.js
+++ b/third_party/WebKit/LayoutTests/resources/idlharness.js
@@ -307,6 +307,28 @@
     return ret;
 };
 
+function exposed_in(globals) {
+    if ('document' in self) {
+        return globals.indexOf("Window") >= 0;
+    }
+    if ('DedicatedWorkerGlobalScope' in self &&
+        self instanceof DedicatedWorkerGlobalScope) {
+        return globals.indexOf("Worker") >= 0 ||
+               globals.indexOf("DedicatedWorker") >= 0;
+    }
+    if ('SharedWorkerGlobalScope' in self &&
+        self instanceof SharedWorkerGlobalScope) {
+        return globals.indexOf("Worker") >= 0 ||
+               globals.indexOf("SharedWorker") >= 0;
+    }
+    if ('ServiceWorkerGlobalScope' in self &&
+        self instanceof ServiceWorkerGlobalScope) {
+        return globals.indexOf("Worker") >= 0 ||
+               globals.indexOf("ServiceWorker") >= 0;
+    }
+    throw "Unexpected global object";
+}
+
 //@}
 IdlArray.prototype.test = function()
 //@{
@@ -353,6 +375,23 @@
     }
     this["implements"] = {};
 
+    Object.getOwnPropertyNames(this.members).forEach(function(memberName) {
+        var member = this.members[memberName];
+        if (!(member instanceof IdlInterface)) {
+            return;
+        }
+
+        var exposed = member.extAttrs.filter(function(a) { return a.name == "Exposed" });
+        if (exposed.length > 1) {
+            throw "Unexpected Exposed extended attributes on " + memberName + ": " + exposed;
+        }
+
+        var globals = exposed.length === 1
+                    ? exposed[0].rhs.value
+                    : ["Window"];
+        member.exposed = exposed_in(globals);
+    }.bind(this));
+
     // Now run test() on every member, and test_object() for every object.
     for (var name in this.members)
     {
@@ -678,6 +717,13 @@
         return;
     }
 
+    if (!this.exposed) {
+        test(function() {
+            assert_false(this.name in self);
+        }.bind(this), this.name + " interface: existence and properties of interface object");
+        return;
+    }
+
     if (!this.untested)
     {
         // First test things to do with the exception/interface object and
@@ -701,7 +747,6 @@
     test(function()
     {
         // This function tests WebIDL as of 2015-01-13.
-        // TODO: Consider [Exposed].
 
         // "For every interface that is exposed in a given ECMAScript global
         // environment and:
diff --git a/third_party/WebKit/LayoutTests/resources/testharness.js b/third_party/WebKit/LayoutTests/resources/testharness.js
index ceb3a4b..91dfab5 100644
--- a/third_party/WebKit/LayoutTests/resources/testharness.js
+++ b/third_party/WebKit/LayoutTests/resources/testharness.js
@@ -471,6 +471,11 @@
             self instanceof ServiceWorkerGlobalScope) {
             return new ServiceWorkerTestEnvironment();
         }
+        if ('WorkerGlobalScope' in self &&
+            self instanceof WorkerGlobalScope) {
+            return new DedicatedWorkerTestEnvironment();
+        }
+
         throw new Error("Unsupported test environment");
     }
 
diff --git a/third_party/WebKit/LayoutTests/svg/custom/global-constructors-expected.txt b/third_party/WebKit/LayoutTests/svg/custom/global-constructors-expected.txt
index 94caad7e..863ab20 100644
--- a/third_party/WebKit/LayoutTests/svg/custom/global-constructors-expected.txt
+++ b/third_party/WebKit/LayoutTests/svg/custom/global-constructors-expected.txt
@@ -102,7 +102,6 @@
 PASS SVGViewElement.toString() is 'function SVGViewElement() { [native code] }'
 PASS SVGScriptElement.toString() is 'function SVGScriptElement() { [native code] }'
 FAIL SVGEvent.toString() should be function SVGEvent() { [native code] }. Threw exception ReferenceError: SVGEvent is not defined
-PASS SVGZoomEvent.toString() is 'function SVGZoomEvent() { [native code] }'
 PASS SVGAnimationElement.toString() is 'function SVGAnimationElement() { [native code] }'
 PASS SVGAnimateElement.toString() is 'function SVGAnimateElement() { [native code] }'
 PASS SVGSetElement.toString() is 'function SVGSetElement() { [native code] }'
diff --git a/third_party/WebKit/LayoutTests/svg/custom/immutable-properties-expected.txt b/third_party/WebKit/LayoutTests/svg/custom/immutable-properties-expected.txt
index a02ef36..1f8e471 100644
--- a/third_party/WebKit/LayoutTests/svg/custom/immutable-properties-expected.txt
+++ b/third_party/WebKit/LayoutTests/svg/custom/immutable-properties-expected.txt
@@ -1,4 +1,3 @@
-CONSOLE WARNING: line 15: 'SVGZoomEvent' is deprecated and will be removed in M52, around July 2016. See https://www.chromestatus.com/features/5760883808534528 for more details.
 Tests whether immutable properties can not be modified.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
@@ -7,19 +6,6 @@
 PASS viewport.x is 0
 PASS viewport.x is 100
 PASS svgDoc.documentElement.viewport.x is 0
-PASS zoomRectScreen.x is 0
-PASS zoomRectScreen.x = 100; threw exception NoModificationAllowedError: Failed to set the 'x' property on 'SVGRect': The attribute is read-only..
-PASS zoomEvent.previousScale is 0
-PASS zoomEvent.previousScale is 0
-PASS previousTranslate.x is 0
-PASS previousTranslate.x = 300; threw exception NoModificationAllowedError: Failed to set the 'x' property on 'SVGPoint': The attribute is read-only..
-PASS zoomEvent.previousTranslate.x is 0
-PASS zoomEvent.newScale is 0
-FAIL zoomEvent.newScale = 200; should throw an exception. Was 200.
-PASS zoomEvent.newScale is 0
-PASS newTranslate.x is 0
-PASS newTranslate.x = 300; threw exception NoModificationAllowedError: Failed to set the 'x' property on 'SVGPoint': The attribute is read-only..
-PASS newTranslate.x is 0
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/svg/custom/script-tests/global-constructors.js b/third_party/WebKit/LayoutTests/svg/custom/script-tests/global-constructors.js
index 1096664..6b73d03b 100644
--- a/third_party/WebKit/LayoutTests/svg/custom/script-tests/global-constructors.js
+++ b/third_party/WebKit/LayoutTests/svg/custom/script-tests/global-constructors.js
@@ -105,7 +105,6 @@
 shouldBeDefined("SVGViewElement");
 shouldBeDefined("SVGScriptElement");
 shouldBeDefined("SVGEvent");
-shouldBeDefined("SVGZoomEvent");
 shouldBeDefined("SVGAnimationElement");
 shouldBeDefined("SVGAnimateElement");
 shouldBeDefined("SVGSetElement");
diff --git a/third_party/WebKit/LayoutTests/svg/custom/script-tests/immutable-properties.js b/third_party/WebKit/LayoutTests/svg/custom/script-tests/immutable-properties.js
index d0c14ac..8d6db64 100644
--- a/third_party/WebKit/LayoutTests/svg/custom/script-tests/immutable-properties.js
+++ b/third_party/WebKit/LayoutTests/svg/custom/script-tests/immutable-properties.js
@@ -11,38 +11,4 @@
 shouldBe("viewport.x", "100");
 shouldBe("svgDoc.documentElement.viewport.x", "0");
 
-// Every attribute of SVGZoomEvent is immutable (Spec: The object itself and its contents are both readonly.)
-var zoomEvent = svgDoc.createEvent("SVGZoomEvents");
-
-// 'zoomRectScreen' property
-var zoomRectScreen = zoomEvent.zoomRectScreen;
-
-shouldBe("zoomRectScreen.x", "0");
-shouldThrow("zoomRectScreen.x = 100;");
-
-// 'previousScale' property
-shouldBe("zoomEvent.previousScale", "0")
-zoomEvent.previousScale = 200;
-shouldBe("zoomEvent.previousScale", "0")
-
-// 'previousTranslate' property
-var previousTranslate = zoomEvent.previousTranslate;
-
-shouldBe("previousTranslate.x", "0");
-shouldThrow("previousTranslate.x = 300;");
-
-shouldBe("zoomEvent.previousTranslate.x", "0");
-
-// 'newScale' property
-shouldBe("zoomEvent.newScale", "0");
-shouldThrow("zoomEvent.newScale = 200;");
-shouldBe("zoomEvent.newScale", "0");
-
-// 'newTranslate' property
-var newTranslate = zoomEvent.newTranslate;
-
-shouldBe("newTranslate.x", "0");
-shouldThrow("newTranslate.x = 300;");
-shouldBe("newTranslate.x", "0");
-
 var successfullyParsed = true;
diff --git a/third_party/WebKit/LayoutTests/svg/dom/svg2-inheritance-expected.txt b/third_party/WebKit/LayoutTests/svg/dom/svg2-inheritance-expected.txt
index 1d4b0534..ddb9fe6 100644
--- a/third_party/WebKit/LayoutTests/svg/dom/svg2-inheritance-expected.txt
+++ b/third_party/WebKit/LayoutTests/svg/dom/svg2-inheritance-expected.txt
@@ -84,7 +84,6 @@
 PASS SVGUseElement inherits SVGGraphicsElement
 PASS SVGViewElement inherits SVGElement
 PASS SVGViewSpec inherits Object
-PASS SVGZoomEvent inherits UIEvent
 FAIL TimeEvent is not defined
 PASS successfullyParsed is true
 
diff --git a/third_party/WebKit/LayoutTests/svg/dom/svg2-inheritance.html b/third_party/WebKit/LayoutTests/svg/dom/svg2-inheritance.html
index 4a5e3cc..fff1ab9 100644
--- a/third_party/WebKit/LayoutTests/svg/dom/svg2-inheritance.html
+++ b/third_party/WebKit/LayoutTests/svg/dom/svg2-inheritance.html
@@ -105,7 +105,6 @@
 checkParent("SVGUseElement", "SVGGraphicsElement");
 checkParent("SVGViewElement", "SVGElement");
 checkParent("SVGViewSpec", "Object");
-checkParent("SVGZoomEvent", "UIEvent");
 checkParent("TimeEvent", "Event");
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/typedcssom/cssVariableReferenceValue.html b/third_party/WebKit/LayoutTests/typedcssom/cssVariableReferenceValue.html
new file mode 100644
index 0000000..028cfee
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/typedcssom/cssVariableReferenceValue.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+
+<script>
+
+test(function() {
+    var expected = 'anything';
+    var variableReferenceValue = new CSSVariableReferenceValue(expected);
+    assert_true(variableReferenceValue instanceof CSSVariableReferenceValue);
+    assert_equals(variableReferenceValue.variable, expected);
+}, "The 'variable' attribute is correct");
+
+</script>
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 c217e975..23d6476 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
@@ -4985,14 +4985,6 @@
     getter zoomAndPan
     method constructor
     setter zoomAndPan
-interface SVGZoomEvent : UIEvent
-    attribute @@toStringTag
-    getter newScale
-    getter newTranslate
-    getter previousScale
-    getter previousTranslate
-    getter zoomRectScreen
-    method constructor
 interface Screen
     attribute @@toStringTag
     getter availHeight
diff --git a/third_party/WebKit/LayoutTests/virtual/threaded/animations/composited-pseudo-element-animation-expected.html b/third_party/WebKit/LayoutTests/virtual/threaded/animations/composited-pseudo-element-animation-expected.html
new file mode 100644
index 0000000..06b3765
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/threaded/animations/composited-pseudo-element-animation-expected.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<style>
+div {
+  width: 100px;
+  height: 100px;
+  background: orange;
+}
+div::before {
+  content: ":)";
+  transform: translateX(20px);
+  transition-property: transform;
+  transition-duration: 1ms;
+  display: block;
+}
+</style>
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/virtual/threaded/animations/composited-pseudo-element-animation.html b/third_party/WebKit/LayoutTests/virtual/threaded/animations/composited-pseudo-element-animation.html
new file mode 100644
index 0000000..f7bd3422
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/threaded/animations/composited-pseudo-element-animation.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<style>
+div {
+  width: 100px;
+  height: 100px;
+  background: orange;
+}
+div::before {
+  content: ":)";
+  transition-property: transform;
+  transition-duration: 1ms;
+
+  /* Make the pseudo element "transformable" as per
+   * https://www.w3.org/TR/css-transforms-1/#transformable-element.
+   */
+  display: block;
+}
+</style>
+<div></div>
+<script>
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+requestAnimationFrame(function(ts) {
+  document.styleSheets[0].addRule('div::before',  'transform: translateX(20px)');
+  requestAnimationFrame(function(ts) {
+    requestAnimationFrame(function(ts) {
+      if (window.testRunner)
+        window.testRunner.notifyDone();
+    });
+  });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/player-cancel-event.html b/third_party/WebKit/LayoutTests/web-animations-api/animation-cancel-event.html
similarity index 79%
rename from third_party/WebKit/LayoutTests/web-animations-api/player-cancel-event.html
rename to third_party/WebKit/LayoutTests/web-animations-api/animation-cancel-event.html
index 5aa7298..57260498 100644
--- a/third_party/WebKit/LayoutTests/web-animations-api/player-cancel-event.html
+++ b/third_party/WebKit/LayoutTests/web-animations-api/animation-cancel-event.html
@@ -1,12 +1,15 @@
 <!DOCTYPE html>
-<body>
+<meta charset=utf-8>
+<title>Canceling an animation: cancel event</title>
+<link rel="help" href="https://w3c.github.io/web-animations/#canceling-an-animation-section">
 <script src="../resources/testharness.js"></script>
 <script src="../resources/testharnessreport.js"></script>
+<body>
 <script>
 var anim1 = document.body.animate([], 100000);
 var anim2 = document.body.animate([], 100000);
 
-var cancelTest = async_test('Cancelling animation should create cancel event.');
+var cancelTest = async_test('Cancelling animation should fire a cancel event.');
 var fired = false;
 
 anim1.oncancel = function(event) {
@@ -28,4 +31,3 @@
 anim1.cancel();
 anim2.finish();
 </script>
-</body>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/animation-cancel-ready-finished-ordering.html b/third_party/WebKit/LayoutTests/web-animations-api/animation-cancel-ready-finished-ordering.html
new file mode 100644
index 0000000..38489f16
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/web-animations-api/animation-cancel-ready-finished-ordering.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Cancel an animation: ready/finished ordering</title
+<link rel="help" href="https://w3c.github.io/web-animations/#canceling-an-animation-section">
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script>
+async_test(function(t) {
+  var animation = document.documentElement.animate([], 100000);
+  var ready = false;
+  animation.ready.then(null, function() {
+    t.step(function() {
+      ready = true;
+    });
+  });
+  animation.finished.then(null, function() {
+    t.step(function() {
+      assert_true(ready);
+    });
+    t.done();
+  });
+  animation.cancel();
+}, 'The ready promise should be rejected before the finished promise');
+</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/animation-constructor.html b/third_party/WebKit/LayoutTests/web-animations-api/animation-constructor.html
deleted file mode 100644
index 6c131ee..0000000
--- a/third_party/WebKit/LayoutTests/web-animations-api/animation-constructor.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-
-<div id='e'></div>
-
-<script>
-var element = document.getElementById('e');
-
-var keyframes = [{opacity: '1'}, {opacity: '0'}];
-var timingObject = {duration: 2, iterations: 5};
-
-test(function() {
-    var keyframeEffect = new KeyframeEffect(element, keyframes, timingObject);
-    assert_not_equals(keyframeEffect, undefined);
-    assert_equals(keyframeEffect.constructor, KeyframeEffect);
-}, 'Calling new KeyframeEffect() with a timing object input should create an keyframeEffect.');
-
-test(function() {
-    var keyframeEffect = new KeyframeEffect(element, keyframes, 2);
-    assert_not_equals(keyframeEffect, undefined);
-    assert_equals(keyframeEffect.constructor, KeyframeEffect);
-}, 'Calling new KeyframeEffect() with a duration input should create an keyframeEffect.');
-
-test(function() {
-    var keyframeEffect = new KeyframeEffect(element, keyframes);
-    assert_not_equals(keyframeEffect, undefined);
-    assert_equals(keyframeEffect.constructor, KeyframeEffect);
-}, 'Calling new KeyframeEffect() with no timing input should create an keyframeEffect.');
-
-test(function() {
-    var keyframeEffect = new KeyframeEffect(null, keyframes);
-    assert_not_equals(keyframeEffect, undefined);
-    assert_equals(keyframeEffect.constructor, KeyframeEffect);
-}, 'Calling new KeyframeEffect() with no target should create an keyframeEffect.');
-</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/player-cancel-events-nofinish.html b/third_party/WebKit/LayoutTests/web-animations-api/animation-finish-event-cancelled.html
similarity index 79%
rename from third_party/WebKit/LayoutTests/web-animations-api/player-cancel-events-nofinish.html
rename to third_party/WebKit/LayoutTests/web-animations-api/animation-finish-event-cancelled.html
index 09413239..c85dc9c 100644
--- a/third_party/WebKit/LayoutTests/web-animations-api/player-cancel-events-nofinish.html
+++ b/third_party/WebKit/LayoutTests/web-animations-api/animation-finish-event-cancelled.html
@@ -1,7 +1,10 @@
 <!DOCTYPE html>
-<body>
+<meta charset=utf-8>
+<title>Canceling an animation: finish event</title>
+<link rel="help" href="https://w3c.github.io/web-animations/#canceling-an-animation-section">
 <script src="../resources/testharness.js"></script>
 <script src="../resources/testharnessreport.js"></script>
+<body>
 <script>
 var anim1 = document.body.animate([], 100000);
 var anim2 = document.body.animate([], 100000);
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/animation-finish-ready-finished-ordering.html b/third_party/WebKit/LayoutTests/web-animations-api/animation-finish-ready-finished-ordering.html
new file mode 100644
index 0000000..ea77ea1b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/web-animations-api/animation-finish-ready-finished-ordering.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Finishing an animation: ready/finished ordering</title
+<link rel="help" href="https://w3c.github.io/web-animations/#finishing-an-animation-section">
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+
+<script>
+async_test(function(t) {
+  var animation = document.documentElement.animate([], 100000);
+  var ready = false;
+  animation.ready.then(function() {
+    t.step(function() {
+      ready = true;
+    });
+  });
+  animation.finished.then(function() {
+    t.step(function() {
+      assert_true(ready);
+    });
+    t.done();
+  });
+  animation.finish();
+}, 'The ready promise should be resolved before the finished promise');
+</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/animation-play-after-finish-restarts.html b/third_party/WebKit/LayoutTests/web-animations-api/animation-play-after-finish-restarts.html
new file mode 100644
index 0000000..18e511b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/web-animations-api/animation-play-after-finish-restarts.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Animation resets when play() called after finish()</title>
+<link rel="help" href="http://w3c.github.io/web-animations/#play-an-animation">
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+
+<div id='element'></div>
+
+<script>
+var element = document.getElementById('element');
+
+test(function() {
+    var animation = element.animate([{left: '0px'}, {left: '100px'}], 10);
+    animation.finish();
+    assert_equals(getComputedStyle(element).left, 'auto');
+
+    animation.play();
+    assert_equals(getComputedStyle(element).left, '0px');
+}, 'Calling play() after finish() causes the animation to reset');
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/animation-set-timeline-expected.txt b/third_party/WebKit/LayoutTests/web-animations-api/animation-set-timeline-expected.txt
new file mode 100644
index 0000000..ffb4933
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/web-animations-api/animation-set-timeline-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL Animations are retriggered if timeline time changes promise_test: Unhandled rejection with value: object "ReferenceError: DocumentTimeline is not defined"
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/animation-set-timeline.html b/third_party/WebKit/LayoutTests/web-animations-api/animation-set-timeline.html
new file mode 100644
index 0000000..728f5c5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/web-animations-api/animation-set-timeline.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Animations are retriggered if timeline time changes</title>
+<link rel="help" href="http://w3c.github.io/web-animations/#set-the-timeline-of-an-animation">
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script src="../imported/wpt/web-animations/testcommon.js"></script>
+
+<div id="div"></div>
+
+<script>
+
+promise_test(function(t) {
+  var animation = div.animate([], 10);
+
+  return animation.ready.then(function() {
+    animation.timeline = new DocumentTimeline(-5);
+    animation.startTime = document.timeline.currentTime;
+    assert_times_equal(animation.currentTime, 5);
+    assert_equals(animation.playState, "running");
+
+    animation.timeline = new DocumentTimeline(-15);
+    animation.startTime = document.timeline.currentTime;
+    assert_times_equal(animation.currentTime, 10);
+    assert_equals(animation.playState, "finished");
+
+    animation.timeline = new DocumentTimeline(0);
+    animation.startTime = document.timeline.currentTime;
+    assert_times_equal(animation.currentTime, 0);
+    assert_equals(animation.playState, "running");
+
+    animation.timeline = new DocumentTimeline(-5);
+    animation.startTime = document.timeline.currentTime;
+    assert_times_equal(animation.currentTime, 5);
+    assert_equals(animation.playState, "running");
+  });
+}, 'Animations are retriggered if timeline time changes');
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/animation-state-changes-negative-playback-rate.html b/third_party/WebKit/LayoutTests/web-animations-api/animation-state-changes-negative-playback-rate.html
index e6903c7..0c254b55 100644
--- a/third_party/WebKit/LayoutTests/web-animations-api/animation-state-changes-negative-playback-rate.html
+++ b/third_party/WebKit/LayoutTests/web-animations-api/animation-state-changes-negative-playback-rate.html
@@ -1,4 +1,8 @@
 <!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test play state changes for animations with a negative playback rate</title>
+<link rel="help" href="http://w3c.github.io/web-animations/#play-state">
+<script src="../imported/wpt/web-animations/testcommon.js"></script>
 <script src="../resources/testharness.js"></script>
 <script src="../resources/testharnessreport.js"></script>
 
@@ -23,7 +27,7 @@
   return animation;
 }
 
-function pendingStartTimeAnimation() {
+function pendingAnimation() {
   var animation = idleAnimation();
   animation.play();
   return animation;
@@ -48,35 +52,35 @@
   assert_unresolved(animation.startTime);
   assert_unresolved(animation.currentTime);
   assert_equals(animation.playState, 'idle');
-}, "idle");
+}, "Play state is idle after cancelling a reversed animation");
 
 test(function() {
-  var animation = pendingStartTimeAnimation();
+  var animation = pendingAnimation();
   assert_unresolved(animation.startTime);
   assert_equals(animation.currentTime, duration);
   assert_equals(animation.playState, 'pending');
-}, "pending startTime");
+}, "Play state is pending after playing a cancelled reversed animation");
 
 test(function() {
   var animation = runningAnimation();
-  assert_equals(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime));
-  assert_approx_equals(animation.currentTime, duration / 2, 0.000001);
+  assert_times_equal(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime));
+  assert_times_equal(animation.currentTime, duration / 2);
   assert_equals(animation.playState, 'running');
-}, "running");
+}, "Play state is running after playing and setting start time of a cancelled reversed animation");
 
 test(function() {
   var animation = pausedAnimation();
   assert_unresolved(animation.startTime);
   assert_equals(animation.currentTime, duration);
   assert_equals(animation.playState, 'paused');
-}, "paused");
+}, "Play state is paused after pausing and setting current time of a cancelled reversed animation");
 
 test(function() {
   var animation = finishedAnimation();
   assert_equals(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime));
   assert_equals(animation.currentTime, 0);
   assert_equals(animation.playState, 'finished');
-}, "finished");
+}, "Play state is finished after playing and finishing a cancelled reversed animation");
 
 test(function() {
   var animation = idleAnimation();
@@ -84,7 +88,7 @@
   assert_unresolved(animation.startTime);
   assert_equals(animation.currentTime, duration);
   assert_equals(animation.playState, 'pending');
-}, "idle -> play()");
+}, "Calling play() on an idle animation");
 
 test(function() {
   var animation = idleAnimation();
@@ -92,7 +96,7 @@
   assert_unresolved(animation.startTime);
   assert_equals(animation.currentTime, duration);
   assert_equals(animation.playState, 'pending');
-}, "idle -> pause()");
+}, "Calling pause() on an idle animation");
 
 test(function() {
   var animation = idleAnimation();
@@ -100,7 +104,7 @@
   assert_unresolved(animation.startTime);
   assert_unresolved(animation.currentTime);
   assert_equals(animation.playState, 'idle');
-}, "idle -> cancel()");
+}, "Calling cancel() on an idle animation");
 
 test(function() {
   var animation = idleAnimation();
@@ -108,7 +112,7 @@
   assert_equals(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime));
   assert_equals(animation.currentTime, 0);
   assert_equals(animation.playState, 'finished');
-}, "idle -> finish()");
+}, "Calling finish() on an idle animation");
 
 test(function() {
   var animation = idleAnimation();
@@ -116,7 +120,7 @@
   assert_unresolved(animation.startTime);
   assert_equals(animation.currentTime, 0);
   assert_equals(animation.playState, 'pending');
-}, "idle -> reverse()");
+}, "Calling reverse() on an idle animation");
 
 test(function() {
   var animation = idleAnimation();
@@ -124,71 +128,71 @@
   assert_unresolved(animation.startTime);
   assert_equals(animation.currentTime, 1000);
   assert_equals(animation.playState, 'paused');
-}, "idle -> set currentTime");
+}, "Setting currentTime on an idle animation");
 
 test(function() {
   var animation = idleAnimation();
   animation.startTime = document.timeline.currentTime + 1000;
-  assert_equals(animation.startTime, document.timeline.currentTime + 1000);
-  assert_equals(animation.currentTime, 1000);
+  assert_times_equal(animation.startTime, document.timeline.currentTime + 1000);
+  assert_times_equal(animation.currentTime, 1000);
   assert_equals(animation.playState, 'running');
-}, "idle -> set startTime");
+}, "Setting startTime on an idle animation");
 
 test(function() {
-  var animation = pendingStartTimeAnimation();
+  var animation = pendingAnimation();
   animation.play();
   assert_unresolved(animation.startTime);
   assert_equals(animation.currentTime, duration);
   assert_equals(animation.playState, 'pending');
-}, "pending startTime -> play()");
+}, "Calling play() on a pending animation");
 
 test(function() {
-  var animation = pendingStartTimeAnimation();
+  var animation = pendingAnimation();
   animation.pause();
   assert_unresolved(animation.startTime);
   assert_equals(animation.currentTime, duration);
   assert_equals(animation.playState, 'pending');
-}, "pending startTime -> pause()");
+}, "Calling pause() on a pending animation");
 
 test(function() {
-  var animation = pendingStartTimeAnimation();
+  var animation = pendingAnimation();
   animation.cancel();
   assert_unresolved(animation.startTime);
   assert_unresolved(animation.currentTime);
   assert_equals(animation.playState, 'idle');
-}, "pending startTime -> cancel()");
+}, "Calling cancel() on a pending animation");
 
 test(function() {
-  var animation = pendingStartTimeAnimation();
+  var animation = pendingAnimation();
   animation.finish();
-  assert_equals(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime));
+  assert_times_equal(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime));
   assert_equals(animation.currentTime, 0);
   assert_equals(animation.playState, 'finished');
-}, "pending startTime -> finish()");
+}, "Calling finish() on a pending animation");
 
 test(function() {
-  var animation = pendingStartTimeAnimation();
+  var animation = pendingAnimation();
   animation.reverse();
   assert_unresolved(animation.startTime);
   assert_equals(animation.currentTime, 0);
   assert_equals(animation.playState, 'pending');
-}, "pending startTime -> reverse()");
+}, "Calling reverse() on a pending animation");
 
 test(function() {
-  var animation = pendingStartTimeAnimation();
+  var animation = pendingAnimation();
   animation.currentTime = 1000;
   assert_unresolved(animation.startTime);
   assert_equals(animation.currentTime, 1000);
   assert_equals(animation.playState, 'pending');
-}, "pending startTime -> set currentTime");
+}, "Setting currentTime on a pending animation");
 
 test(function() {
-  var animation = pendingStartTimeAnimation();
+  var animation = pendingAnimation();
   animation.startTime = document.timeline.currentTime + 1000;
-  assert_equals(animation.startTime, document.timeline.currentTime + 1000);
-  assert_equals(animation.currentTime, 1000);
+  assert_times_equal(animation.startTime, document.timeline.currentTime + 1000);
+  assert_times_equal(animation.currentTime, 1000);
   assert_equals(animation.playState, 'running');
-}, "pending startTime -> set startTime");
+}, "Setting startTime on a pending animation");
 
 test(function() {
   var animation = runningAnimation();
@@ -198,15 +202,15 @@
   assert_equals(animation.startTime, startTime);
   assert_equals(animation.currentTime, currentTime);
   assert_equals(animation.playState, 'running');
-}, "running -> play()");
+}, "Calling play() on a running animation");
 
 test(function() {
   var animation = runningAnimation();
   animation.pause();
   assert_unresolved(animation.startTime);
-  assert_approx_equals(animation.currentTime, duration / 2, 0.000001);
+  assert_times_equal(animation.currentTime, duration / 2);
   assert_equals(animation.playState, 'pending');
-}, "running -> pause()");
+}, "Calling pause() on a running animation");
 
 test(function() {
   var animation = runningAnimation();
@@ -214,39 +218,39 @@
   assert_unresolved(animation.startTime);
   assert_unresolved(animation.currentTime);
   assert_equals(animation.playState, 'idle');
-}, "running -> cancel()");
+}, "Calling cancel() on a running animation");
 
 test(function() {
   var animation = runningAnimation();
   animation.finish();
-  assert_equals(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime));
+  assert_times_equal(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime));
   assert_equals(animation.currentTime, 0);
   assert_equals(animation.playState, 'finished');
-}, "running -> finish()");
+}, "Calling finish() on a running animation");
 
 test(function() {
   var animation = runningAnimation();
   animation.reverse();
   assert_unresolved(animation.startTime);
-  assert_approx_equals(animation.currentTime, duration / 2, 0.000001);
+  assert_times_equal(animation.currentTime, duration / 2);
   assert_equals(animation.playState, 'pending');
-}, "running -> reverse()");
+}, "Calling reverse() on a running animation");
 
 test(function() {
   var animation = runningAnimation();
   animation.currentTime = 1000;
-  assert_equals(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime));
+  assert_times_equal(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime));
   assert_equals(animation.currentTime, 1000);
   assert_equals(animation.playState, 'running');
-}, "running -> set currentTime");
+}, "Setting currentTime on a running animation");
 
 test(function() {
   var animation = runningAnimation();
   animation.startTime = document.timeline.currentTime + 1000;
-  assert_equals(animation.startTime, document.timeline.currentTime + 1000);
-  assert_equals(animation.currentTime, 1000);
+  assert_times_equal(animation.startTime, document.timeline.currentTime + 1000);
+  assert_times_equal(animation.currentTime, 1000);
   assert_equals(animation.playState, 'running');
-}, "running -> set startTime");
+}, "Setting startTime on a running animation");
 
 test(function() {
   var animation = pausedAnimation();
@@ -254,7 +258,7 @@
   assert_unresolved(animation.startTime);
   assert_equals(animation.currentTime, duration);
   assert_equals(animation.playState, 'pending');
-}, "paused -> play()");
+}, "Calling play() on a paused animation");
 
 test(function() {
   var animation = pausedAnimation();
@@ -262,7 +266,7 @@
   assert_unresolved(animation.startTime);
   assert_equals(animation.currentTime, duration);
   assert_equals(animation.playState, 'paused');
-}, "paused -> pause()");
+}, "Calling pause() on a paused animation");
 
 test(function() {
   var animation = pausedAnimation();
@@ -270,15 +274,15 @@
   assert_unresolved(animation.startTime);
   assert_unresolved(animation.currentTime);
   assert_equals(animation.playState, 'idle');
-}, "paused -> cancel()");
+}, "Calling cancel() on a paused animation");
 
 test(function() {
   var animation = pausedAnimation();
   animation.finish();
-  assert_equals(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime));
+  assert_times_equal(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime));
   assert_equals(animation.currentTime, 0);
   assert_equals(animation.playState, 'finished');
-}, "paused -> finish()");
+}, "Calling finish() on a paused animation");
 
 test(function() {
   var animation = pausedAnimation();
@@ -286,7 +290,7 @@
   assert_unresolved(animation.startTime);
   assert_equals(animation.currentTime, 0);
   assert_equals(animation.playState, 'pending');
-}, "paused -> reverse()");
+}, "Calling reverse() on a paused animation");
 
 test(function() {
   var animation = pausedAnimation();
@@ -294,15 +298,15 @@
   assert_unresolved(animation.startTime);
   assert_equals(animation.currentTime, 1000);
   assert_equals(animation.playState, 'paused');
-}, "paused -> set currentTime");
+}, "Setting currentTime on a paused animation");
 
 test(function() {
   var animation = pausedAnimation();
   animation.startTime = document.timeline.currentTime + 1000;
-  assert_equals(animation.startTime, document.timeline.currentTime + 1000);
-  assert_equals(animation.currentTime, 1000);
+  assert_times_equal(animation.startTime, document.timeline.currentTime + 1000);
+  assert_times_equal(animation.currentTime, 1000);
   assert_equals(animation.playState, 'running');
-}, "paused -> set startTime");
+}, "Setting startTime on a paused animation");
 
 test(function() {
   var animation = finishedAnimation();
@@ -310,7 +314,7 @@
   assert_unresolved(animation.startTime);
   assert_equals(animation.currentTime, duration);
   assert_equals(animation.playState, 'pending');
-}, "finished -> play()");
+}, "Calling play() on a finished animation");
 
 test(function() {
   var animation = finishedAnimation();
@@ -318,7 +322,7 @@
   assert_unresolved(animation.startTime);
   assert_equals(animation.currentTime, 0);
   assert_equals(animation.playState, 'pending');
-}, "finished -> pause()");
+}, "Calling pause() on a finished animation");
 
 test(function() {
   var animation = finishedAnimation();
@@ -326,15 +330,15 @@
   assert_unresolved(animation.startTime);
   assert_unresolved(animation.currentTime);
   assert_equals(animation.playState, 'idle');
-}, "finished -> cancel()");
+}, "Calling cancel() on a finished animation");
 
 test(function() {
   var animation = finishedAnimation();
   animation.finish();
-  assert_equals(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime));
+  assert_times_equal(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime));
   assert_equals(animation.currentTime, 0);
   assert_equals(animation.playState, 'finished');
-}, "finished -> finish()");
+}, "Calling finish() on a finished animation");
 
 test(function() {
   var animation = finishedAnimation();
@@ -342,13 +346,13 @@
   assert_unresolved(animation.startTime);
   assert_equals(animation.currentTime, 0);
   assert_equals(animation.playState, 'pending');
-}, "finished -> reverse()");
+}, "Calling reverse() on a finished animation");
 
 test(function() {
   var animation = finishedAnimation();
   animation.currentTime = 1000;
-  assert_equals(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime));
+  assert_times_equal(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime));
   assert_equals(animation.currentTime, 1000);
   assert_equals(animation.playState, 'running');
-}, "finished -> set currentTime");
+}, "Setting currentTime on a finished animation");
 </script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/animation-state-changes.html b/third_party/WebKit/LayoutTests/web-animations-api/animation-state-changes.html
deleted file mode 100644
index ba22634..0000000
--- a/third_party/WebKit/LayoutTests/web-animations-api/animation-state-changes.html
+++ /dev/null
@@ -1,392 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-
-<script>
-var duration = 100000;
-
-function assert_unresolved(value) {
-  assert_equals(value, null);
-}
-
-function idleAnimation() {
-  var animation = document.documentElement.animate([], duration);
-  animation.cancel();
-  return animation;
-}
-
-function runningAnimation() {
-  var animation = idleAnimation();
-  animation.play();
-  animation.startTime = document.timeline.currentTime;
-  return animation;
-}
-
-function pendingStartTimeAnimation() {
-  var animation = idleAnimation();
-  animation.play();
-  return animation;
-}
-
-function pendingStartTimeAndCurrentTimeAnimation() {
-  var animation = idleAnimation();
-  animation.play();
-  animation.pause();
-  animation.play();
-  return animation;
-}
-
-function pausedAnimation() {
-  var animation = idleAnimation();
-  animation.pause();
-  animation.currentTime = 0;
-  return animation;
-}
-
-function finishedAnimation() {
-  var animation = idleAnimation();
-  animation.play();
-  animation.finish();
-  return animation;
-}
-
-test(function() {
-  var animation = idleAnimation();
-  assert_unresolved(animation.startTime);
-  assert_unresolved(animation.currentTime);
-  assert_equals(animation.playState, 'idle');
-}, "idle");
-
-test(function() {
-  var animation = pendingStartTimeAnimation();
-  assert_unresolved(animation.startTime);
-  assert_equals(animation.currentTime, 0);
-  assert_equals(animation.playState, 'pending');
-}, "pending startTime");
-
-test(function() {
-  var animation = runningAnimation();
-  assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime);
-  assert_equals(animation.currentTime, 0);
-  assert_equals(animation.playState, 'running');
-}, "running");
-
-test(function() {
-  var animation = pausedAnimation();
-  assert_unresolved(animation.startTime);
-  assert_equals(animation.currentTime, 0);
-  assert_equals(animation.playState, 'paused');
-}, "paused");
-
-test(function() {
-  var animation = finishedAnimation();
-  assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime);
-  assert_equals(animation.currentTime, duration);
-  assert_equals(animation.playState, 'finished');
-}, "finished");
-
-test(function() {
-  var animation = idleAnimation();
-  animation.play();
-  assert_unresolved(animation.startTime);
-  assert_equals(animation.currentTime, 0);
-  assert_equals(animation.playState, 'pending');
-}, "idle -> play()");
-
-test(function() {
-  var animation = idleAnimation();
-  animation.pause();
-  assert_unresolved(animation.startTime);
-  assert_equals(animation.currentTime, 0);
-  assert_equals(animation.playState, 'pending');
-}, "idle -> pause()");
-
-test(function() {
-  var animation = idleAnimation();
-  animation.cancel();
-  assert_unresolved(animation.startTime);
-  assert_unresolved(animation.currentTime);
-  assert_equals(animation.playState, 'idle');
-}, "idle -> cancel()");
-
-test(function() {
-  var animation = idleAnimation();
-  animation.finish();
-  assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime);
-  assert_equals(animation.currentTime, duration);
-  assert_equals(animation.playState, 'finished');
-}, "idle -> finish()");
-
-test(function() {
-  var animation = idleAnimation();
-  animation.reverse();
-  assert_unresolved(animation.startTime);
-  assert_equals(animation.currentTime, duration);
-  assert_equals(animation.playState, 'pending');
-}, "idle -> reverse()");
-
-test(function() {
-  var animation = idleAnimation();
-  animation.currentTime = 1000;
-  assert_unresolved(animation.startTime);
-  assert_equals(animation.currentTime, 1000);
-  assert_equals(animation.playState, 'paused');
-}, "idle -> set currentTime");
-
-test(function() {
-  var animation = idleAnimation();
-  animation.startTime = document.timeline.currentTime - 1000;
-  assert_equals(animation.startTime, document.timeline.currentTime - 1000);
-  assert_equals(animation.currentTime, 1000);
-  assert_equals(animation.playState, 'running');
-}, "idle -> set startTime");
-
-test(function() {
-  var animation = pendingStartTimeAnimation();
-  animation.play();
-  assert_unresolved(animation.startTime);
-  assert_equals(animation.currentTime, 0);
-  assert_equals(animation.playState, 'pending');
-}, "pending startTime -> play()");
-
-test(function() {
-  var animation = pendingStartTimeAnimation();
-  animation.pause();
-  assert_unresolved(animation.startTime);
-  assert_equals(animation.currentTime, 0);
-  assert_equals(animation.playState, 'pending');
-}, "pending startTime -> pause()");
-
-test(function() {
-  var animation = pendingStartTimeAnimation();
-  animation.cancel();
-  assert_unresolved(animation.startTime);
-  assert_unresolved(animation.currentTime);
-  assert_equals(animation.playState, 'idle');
-}, "pending startTime -> cancel()");
-
-test(function() {
-  var animation = pendingStartTimeAnimation();
-  animation.finish();
-  assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime);
-  assert_equals(animation.currentTime, duration);
-  assert_equals(animation.playState, 'finished');
-}, "pending startTime -> finish()");
-
-test(function() {
-  var animation = pendingStartTimeAnimation();
-  animation.reverse();
-  assert_unresolved(animation.startTime);
-  assert_equals(animation.currentTime, duration);
-  assert_equals(animation.playState, 'pending');
-}, "pending startTime -> reverse()");
-
-test(function() {
-  var animation = pendingStartTimeAnimation();
-  animation.currentTime = 1000;
-  assert_unresolved(animation.startTime);
-  assert_equals(animation.currentTime, 1000);
-  assert_equals(animation.playState, 'pending');
-}, "pending startTime -> set currentTime");
-
-test(function() {
-  var animation = pendingStartTimeAnimation();
-  animation.startTime = document.timeline.currentTime - 1000;
-  assert_equals(animation.startTime, document.timeline.currentTime - 1000);
-  assert_equals(animation.currentTime, 1000);
-  assert_equals(animation.playState, 'running');
-}, "pending startTime -> set startTime");
-
-test(function() {
-  var animation = runningAnimation();
-  var startTime = animation.startTime;
-  var currentTime = animation.currentTime;
-  animation.play();
-  assert_equals(animation.startTime, startTime);
-  assert_equals(animation.currentTime, currentTime);
-  assert_equals(animation.playState, 'running');
-}, "running -> play()");
-
-test(function() {
-  var animation = runningAnimation();
-  animation.pause();
-  assert_unresolved(animation.startTime);
-  assert_equals(animation.currentTime, 0);
-  assert_equals(animation.playState, 'pending');
-}, "running -> pause()");
-
-test(function() {
-  var animation = runningAnimation();
-  animation.cancel();
-  assert_unresolved(animation.startTime);
-  assert_unresolved(animation.currentTime);
-  assert_equals(animation.playState, 'idle');
-}, "running -> cancel()");
-
-test(function() {
-  var animation = runningAnimation();
-  animation.finish();
-  assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime);
-  assert_equals(animation.currentTime, duration);
-  assert_equals(animation.playState, 'finished');
-}, "running -> finish()");
-
-test(function() {
-  var animation = runningAnimation();
-  animation.reverse();
-  assert_unresolved(animation.startTime);
-  assert_equals(animation.currentTime, duration);
-  assert_equals(animation.playState, 'pending');
-}, "running -> reverse()");
-
-test(function() {
-  var animation = runningAnimation();
-  animation.currentTime = 1000;
-  assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime);
-  assert_equals(animation.currentTime, 1000);
-  assert_equals(animation.playState, 'running');
-}, "running -> set currentTime");
-
-test(function() {
-  var animation = runningAnimation();
-  animation.startTime = document.timeline.currentTime - 1000;
-  assert_equals(animation.startTime, document.timeline.currentTime - 1000);
-  assert_equals(animation.currentTime, 1000);
-  assert_equals(animation.playState, 'running');
-}, "running -> set startTime");
-
-test(function() {
-  var animation = pausedAnimation();
-  animation.play();
-  assert_unresolved(animation.startTime);
-  assert_equals(animation.currentTime, 0);
-  assert_equals(animation.playState, 'pending');
-}, "paused -> play()");
-
-test(function() {
-  var animation = pausedAnimation();
-  animation.pause();
-  assert_unresolved(animation.startTime);
-  assert_equals(animation.currentTime, 0);
-  assert_equals(animation.playState, 'paused');
-}, "paused -> pause()");
-
-test(function() {
-  var animation = pausedAnimation();
-  animation.cancel();
-  assert_unresolved(animation.startTime);
-  assert_unresolved(animation.currentTime);
-  assert_equals(animation.playState, 'idle');
-}, "paused -> cancel()");
-
-test(function() {
-  var animation = pausedAnimation();
-  animation.finish();
-  assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime);
-  assert_equals(animation.currentTime, duration);
-  assert_equals(animation.playState, 'finished');
-}, "paused -> finish()");
-
-test(function() {
-  var animation = pausedAnimation();
-  animation.reverse();
-  assert_unresolved(animation.startTime);
-  assert_equals(animation.currentTime, duration);
-  assert_equals(animation.playState, 'pending');
-}, "paused -> reverse()");
-
-test(function() {
-  var animation = pausedAnimation();
-  animation.currentTime = 1000;
-  assert_unresolved(animation.startTime);
-  assert_equals(animation.currentTime, 1000);
-  assert_equals(animation.playState, 'paused');
-}, "paused -> set currentTime");
-
-test(function() {
-  var animation = pausedAnimation();
-  animation.startTime = document.timeline.currentTime - 1000;
-  assert_equals(animation.startTime, document.timeline.currentTime - 1000);
-  assert_equals(animation.currentTime, 1000);
-  assert_equals(animation.playState, 'running');
-}, "paused -> set startTime");
-
-test(function() {
-  var animation = finishedAnimation();
-  animation.play();
-  assert_unresolved(animation.startTime);
-  assert_equals(animation.currentTime, 0);
-  assert_equals(animation.playState, 'pending');
-}, "finished -> play()");
-
-test(function() {
-  var animation = finishedAnimation();
-  animation.pause();
-  assert_unresolved(animation.startTime);
-  assert_equals(animation.currentTime, duration);
-  assert_equals(animation.playState, 'pending');
-}, "finished -> pause()");
-
-test(function() {
-  var animation = finishedAnimation();
-  animation.cancel();
-  assert_unresolved(animation.startTime);
-  assert_unresolved(animation.currentTime);
-  assert_equals(animation.playState, 'idle');
-}, "finished -> cancel()");
-
-test(function() {
-  var animation = finishedAnimation();
-  animation.finish();
-  assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime);
-  assert_equals(animation.currentTime, duration);
-  assert_equals(animation.playState, 'finished');
-}, "finished -> finish()");
-
-test(function() {
-  var animation = finishedAnimation();
-  animation.reverse();
-  assert_unresolved(animation.startTime);
-  assert_equals(animation.currentTime, duration);
-  assert_equals(animation.playState, 'pending');
-}, "finished -> reverse()");
-
-test(function() {
-  var animation = finishedAnimation();
-  animation.currentTime = 1000;
-  assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime);
-  assert_equals(animation.currentTime, 1000);
-  assert_equals(animation.playState, 'running');
-}, "finished -> set currentTime");
-
-{
-  let test = async_test("pending (play) -> ready.then()");
-  let animation = idleAnimation();
-  animation.play();
-  let animationCurrentTime = animation.currentTime;
-  let timelineCurrentTime = document.timeline.currentTime;
-  animation.ready.then(() => {
-    test.step(() => {
-      assert_equals(animation.playState, 'running');
-      assert_greater_than_equal(animation.startTime, timelineCurrentTime);
-      assert_greater_than_equal(animation.currentTime, animationCurrentTime);
-    });
-    test.done();
-  });
-}
-
-{
-  let test = async_test("pending (pause) -> ready.then()");
-  let animation = runningAnimation();
-  animation.pause();
-  let animationCurrentTime = animation.currentTime;
-  animation.ready.then(() => {
-    test.step(() => {
-      assert_equals(animation.playState, 'paused');
-      assert_unresolved(animation.startTime);
-      assert_greater_than_equal(animation.currentTime, animationCurrentTime);
-    });
-    test.done();
-  });
-}
-</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/animation-update-effect.html b/third_party/WebKit/LayoutTests/web-animations-api/animation-update-effect.html
new file mode 100644
index 0000000..56acf2d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/web-animations-api/animation-update-effect.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Element style is updated when the Animation's effect is update</title>
+<link rel="help" href="http://w3c.github.io/web-animations/#set-the-target-effect-of-an-animation">
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+
+<div id='element'></div>
+
+<script>
+var element = document.getElementById('element');
+
+test(function() {
+    var animation = element.animate([{left: '0px'}, {left: '100px'}], 10);
+    assert_equals(getComputedStyle(element).left, '0px');
+
+    var effect = animation.effect
+    animation.effect = null;
+    assert_equals(getComputedStyle(element).left, 'auto');
+
+    animation.effect = effect;
+    assert_equals(getComputedStyle(element).left, '0px');
+}, 'Element style updated after clear and set effect');
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/eased-keyframes.html b/third_party/WebKit/LayoutTests/web-animations-api/eased-keyframes.html
deleted file mode 100644
index 902dbc7..0000000
--- a/third_party/WebKit/LayoutTests/web-animations-api/eased-keyframes.html
+++ /dev/null
@@ -1,108 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script src="w3c/resources/keyframes-test.js"></script>
-<script>
-// FIXME: Remove the need for and use of this function.
-// Currently our animation timeline is not stable during page load script execution.
-// By deferring the tests to requestAnimationFrame() we can get a stable timeline and
-// avoid flaky test results.
-function testInRAF(testFunction, description, properties) {
-  async_test(function(testHandle) {
-    requestAnimationFrame(function() {
-      testHandle.step(testFunction);
-      testHandle.done();
-    })
-  }, description, properties);
-}
-
-testInRAF(function() {
-  assertAnimationStyles([
-    {opacity: '0', left: '0px', easing: 'steps(2, start)'},
-    {opacity: '0.25', left: '25px'},
-    {opacity: '0.75', left: '75px'},
-  ], {
-    0: {opacity: '0.125', left: '12.5px'},
-    0.125: {opacity: '0.125', left: '12.5px'},
-    0.25: {opacity: '0.25', left: '25px'},
-    0.375: {opacity: '0.25', left: '25px'},
-    0.5: {opacity: '0.25', left: '25px'},
-    0.625: {opacity: '0.375', left: '37.5px'},
-    0.75: {opacity: '0.5', left: '50px'},
-    0.875: {opacity: '0.625', left: '62.5px'},
-    1: {opacity: '0.75', left: '75px'},
-  }, 'with easing on first keyframe');
-
-  assertAnimationStyles([
-    {opacity: '0', left: '0px'},
-    {opacity: '0.5', left: '50px', easing: 'steps(2, start)'},
-    {opacity: '0.75', left: '75px'},
-  ], {
-    0: {opacity: '0', left: '0px'},
-    0.125: {opacity: '0.125', left: '12.5px'},
-    0.25: {opacity: '0.25', left: '25px'},
-    0.375: {opacity: '0.375', left: '37.5px'},
-    0.5: {opacity: '0.625', left: '62.5px'},
-    0.625: {opacity: '0.625', left: '62.5px'},
-    0.75: {opacity: '0.75', left: '75px'},
-    0.875: {opacity: '0.75', left: '75px'},
-    1: {opacity: '0.75', left: '75px'},
-  }, 'with easing on second keyframe');
-},
-'element.animate() with eased keyframe',
-{
-  help: 'http://dev.w3.org/fxtf/web-animations/#the-keyframe-dictionary',
-  assert: [
-    'element.animate() should start an animation when keyframes are specified with timing functions',
-    'for their easing property. The animation should use the given timing function between consecutive',
-    'keyframe offsets.',
-  ],
-  author: 'Alan Cutter',
-});
-
-testInRAF(function() {
-  assertAnimationStyles([
-    {opacity: '0', offset: 0, easing: 'steps(2, start)'},
-    {left: '0px', offset: 0},
-    {opacity: '0.5', left: '50px'},
-  ], {
-    0: {opacity: '0.25', left: '0px'},
-    0.25: {opacity: '0.25', left: '12.5px'},
-    0.5: {opacity: '0.5', left: '25px'},
-    0.75: {opacity: '0.5', left: '37.5px'},
-    1: {opacity: '0.5', left: '50px'},
-  });
-},
-'element.animate() with eased keyframe on single property',
-{
-  help: 'http://dev.w3.org/fxtf/web-animations/#the-keyframe-dictionary',
-  assert: [
-    'element.animate() should start an animation when keyframes are specified with timing functions',
-    'for their easing property. The animation should use the given timing function only on the properties',
-    'specified in the same keyframe.',
-  ],
-  author: 'Alan Cutter',
-});
-
-testInRAF(function() {
-  assertAnimationStyles([
-    {opacity: '0', left: '0px'},
-    {opacity: '0.5', left: '50px', easing: 'steps(2, start)'},
-  ], {
-    0: {opacity: '0', left: '0px'},
-    0.25: {opacity: '0.125', left: '12.5px'},
-    0.5: {opacity: '0.25', left: '25px'},
-    0.75: {opacity: '0.375', left: '37.5px'},
-    1: {opacity: '0.5', left: '50px'},
-  });
-},
-'element.animate() with easing on last keyframe',
-{
-  help: 'http://dev.w3.org/fxtf/web-animations/#the-keyframe-dictionary',
-  assert: [
-    'element.animate() should start an animation when keyframes are specified with timing functions',
-    'for their easing property. Easing on the last keyframes should have no effect on the animation.',
-  ],
-  author: 'Alan Cutter',
-});
-</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/infinite-end-time.html b/third_party/WebKit/LayoutTests/web-animations-api/infinite-end-time.html
deleted file mode 100644
index 5c5e2ce..0000000
--- a/third_party/WebKit/LayoutTests/web-animations-api/infinite-end-time.html
+++ /dev/null
@@ -1,54 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<body>
-<script>
-function infiniteAnimation() {
-  var anim = document.body.animate([],
-      {duration: 1000, iterations: Infinity});
-  anim.cancel();
-  return anim;
-}
-
-test(function() {
-  var anim = infiniteAnimation();
-  try {
-    anim.finish();
-    assert_unreached();
-  } catch (e) {
-    assert_equals(e.code, DOMException.INVALID_STATE_ERR);
-  }
-}, "finishing an infinite animation");
-
-test(function() {
-  var anim = infiniteAnimation();
-  anim.playbackRate = -1;
-  try {
-    anim.pause();
-    assert_unreached();
-  } catch (e) {
-    assert_equals(e.code, DOMException.INVALID_STATE_ERR);
-  }
-}, "pausing a reversed infinite animation");
-
-test(function() {
-  var anim = infiniteAnimation();
-  anim.playbackRate = -1;
-  try {
-    anim.play();
-    assert_unreached();
-  } catch (e) {
-    assert_equals(e.code, DOMException.INVALID_STATE_ERR);
-  }
-}, "playing a reversed infinite animation");
-
-test(function() {
-  var anim = infiniteAnimation();
-  try {
-    anim.reverse();
-    assert_unreached();
-  } catch (e) {
-    assert_equals(e.code, DOMException.INVALID_STATE_ERR);
-  }
-}, "reversing an infinite animation");
-</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/playState-changes.html b/third_party/WebKit/LayoutTests/web-animations-api/playState-changes.html
new file mode 100644
index 0000000..6398c09
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/web-animations-api/playState-changes.html
@@ -0,0 +1,384 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Tests for discrete animation</title>
+<link rel="help" href="https://w3c.github.io/web-animations/#play-state">
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script src="../imported/wpt/web-animations/testcommon.js"></script>
+<body>
+<script>
+'use strict';
+function createIdleAnimation(t) {
+  var animation = createDiv(t).animate([], 100000);
+  animation.cancel();
+  return animation;
+}
+
+function createRunningAnimation(t) {
+  var animation = createIdleAnimation(t);
+  animation.play();
+  animation.startTime = document.timeline.currentTime;
+  return animation;
+}
+
+function createPendingStartTimeAnimation(t) {
+  var animation = createIdleAnimation(t);
+  animation.play();
+  return animation;
+}
+
+function createPausedAnimation(t) {
+  var animation = createIdleAnimation(t);
+  animation.pause();
+  animation.currentTime = 0;
+  return animation;
+}
+
+function createFinishedAnimation(t) {
+  var animation = createIdleAnimation(t);
+  animation.play();
+  animation.finish();
+  return animation;
+}
+
+// Initial animation states
+test(function(t) {
+  var animation = createIdleAnimation(t);
+  assert_equals(animation.startTime, null);
+  assert_equals(animation.currentTime, null);
+  assert_equals(animation.playState, 'idle');
+}, "Play state is idle after cancelling an animation");
+
+test(function(t) {
+  var animation = createPendingStartTimeAnimation(t);
+  assert_equals(animation.startTime, null);
+  assert_equals(animation.currentTime, 0);
+  assert_equals(animation.playState, 'pending');
+}, "Play state is pending after playing a cancelled animation");
+
+test(function(t) {
+  var animation = createRunningAnimation(t);
+  assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime);
+  assert_equals(animation.currentTime, 0);
+  assert_equals(animation.playState, 'running');
+}, "Play state is running after playing and setting start time of a cancelled animation");
+
+test(function(t) {
+  var animation = createPausedAnimation(t);
+  assert_equals(animation.startTime, null);
+  assert_equals(animation.currentTime, 0);
+  assert_equals(animation.playState, 'paused');
+}, "Play state is paused after pausing and setting current time of a cancelled animation");
+
+test(function(t) {
+  var animation = createFinishedAnimation(t);
+  assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime);
+  assert_equals(animation.currentTime, 100000);
+  assert_equals(animation.playState, 'finished');
+}, "Play state is finished after playing and finishing a cancelled animation");
+
+// Changed animation states
+test(function(t) {
+  var animation = createIdleAnimation(t);
+  animation.play();
+  assert_equals(animation.startTime, null);
+  assert_equals(animation.currentTime, 0);
+  assert_equals(animation.playState, 'pending');
+}, "Calling play() on an idle animation");
+
+test(function(t) {
+  var animation = createIdleAnimation(t);
+  animation.pause();
+  assert_equals(animation.startTime, null);
+  assert_equals(animation.currentTime, 0);
+  assert_equals(animation.playState, 'pending');
+}, "Calling pause() on an idle animation");
+
+test(function(t) {
+  var animation = createIdleAnimation(t);
+  animation.cancel();
+  assert_equals(animation.startTime, null);
+  assert_equals(animation.currentTime, null);
+  assert_equals(animation.playState, 'idle');
+}, "Calling cancel() on an idle animation");
+
+test(function(t) {
+  var animation = createIdleAnimation(t);
+  animation.finish();
+  assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime);
+  assert_equals(animation.currentTime, 100000);
+  assert_equals(animation.playState, 'finished');
+}, "Calling finish() on an idle animation");
+
+test(function(t) {
+  var animation = createIdleAnimation(t);
+  animation.reverse();
+  assert_equals(animation.startTime, null);
+  assert_equals(animation.currentTime, 100000);
+  assert_equals(animation.playState, 'pending');
+}, "Calling reverse() on an idle animation");
+
+test(function(t) {
+  var animation = createIdleAnimation(t);
+  animation.currentTime = 1000;
+  assert_equals(animation.startTime, null);
+  assert_equals(animation.currentTime, 1000);
+  assert_equals(animation.playState, 'paused');
+}, "Setting currentTime on an idle animation");
+
+test(function(t) {
+  var animation = createIdleAnimation(t);
+  animation.startTime = document.timeline.currentTime - 1000;
+  assert_equals(animation.startTime, document.timeline.currentTime - 1000);
+  assert_equals(animation.currentTime, 1000);
+  assert_equals(animation.playState, 'running');
+}, "Setting startTime on an idle animation");
+
+test(function(t) {
+  var animation = createPendingStartTimeAnimation(t);
+  animation.play();
+  assert_equals(animation.startTime, null);
+  assert_equals(animation.currentTime, 0);
+  assert_equals(animation.playState, 'pending');
+}, "Calling play() on a pending starttime animation");
+
+test(function(t) {
+  var animation = createPendingStartTimeAnimation(t);
+  animation.pause();
+  assert_equals(animation.startTime, null);
+  assert_equals(animation.currentTime, 0);
+  assert_equals(animation.playState, 'pending');
+}, "Calling pause() on a pending starttime animation");
+
+test(function(t) {
+  var animation = createPendingStartTimeAnimation(t);
+  animation.cancel();
+  assert_equals(animation.startTime, null);
+  assert_equals(animation.currentTime, null);
+  assert_equals(animation.playState, 'idle');
+}, "Calling cancel() on a pending starttime animation");
+
+test(function(t) {
+  var animation = createPendingStartTimeAnimation(t);
+  animation.finish();
+  assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime);
+  assert_equals(animation.currentTime, 100000);
+  assert_equals(animation.playState, 'finished');
+}, "Calling finish() on a pending starttime animation");
+
+test(function(t) {
+  var animation = createPendingStartTimeAnimation(t);
+  animation.reverse();
+  assert_equals(animation.startTime, null);
+  assert_equals(animation.currentTime, 100000);
+  assert_equals(animation.playState, 'pending');
+}, "Calling reverse() on a pending starttime animation");
+
+test(function(t) {
+  var animation = createPendingStartTimeAnimation(t);
+  animation.currentTime = 1000;
+  assert_equals(animation.startTime, null);
+  assert_equals(animation.currentTime, 1000);
+  assert_equals(animation.playState, 'pending');
+}, "Setting currentTime on a pending starttime animation");
+
+test(function(t) {
+  var animation = createPendingStartTimeAnimation(t);
+  animation.startTime = document.timeline.currentTime - 1000;
+  assert_equals(animation.startTime, document.timeline.currentTime - 1000);
+  assert_equals(animation.currentTime, 1000);
+  assert_equals(animation.playState, 'running');
+}, "Setting startTime on a pending starttime animation");
+
+test(function(t) {
+  var animation = createRunningAnimation(t);
+  var startTime = animation.startTime;
+  var currentTime = animation.currentTime;
+  animation.play();
+  assert_equals(animation.startTime, startTime);
+  assert_equals(animation.currentTime, currentTime);
+  assert_equals(animation.playState, 'running');
+}, "Setting play() on a running animation");
+
+test(function(t) {
+  var animation = createRunningAnimation(t);
+  animation.pause();
+  assert_equals(animation.startTime, null);
+  assert_equals(animation.currentTime, 0);
+  assert_equals(animation.playState, 'pending');
+}, "Setting pause() on a running animation");
+
+test(function(t) {
+  var animation = createRunningAnimation(t);
+  animation.cancel();
+  assert_equals(animation.startTime, null);
+  assert_equals(animation.currentTime, null);
+  assert_equals(animation.playState, 'idle');
+}, "Setting cancel() on a running animation");
+
+test(function(t) {
+  var animation = createRunningAnimation(t);
+  animation.finish();
+  assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime);
+  assert_equals(animation.currentTime, 100000);
+  assert_equals(animation.playState, 'finished');
+}, "Setting finish() on a running animation");
+
+test(function(t) {
+  var animation = createRunningAnimation(t);
+  animation.reverse();
+  assert_equals(animation.startTime, null);
+  assert_equals(animation.currentTime, 100000);
+  assert_equals(animation.playState, 'pending');
+}, "Setting reverse() on a running animation");
+
+
+test(function(t) {
+  var animation = createRunningAnimation(t);
+  animation.currentTime = 1000;
+  assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime);
+  assert_equals(animation.currentTime, 1000);
+  assert_equals(animation.playState, 'running');
+}, "Setting currentTime on a running animation");
+
+test(function(t) {
+  var animation = createRunningAnimation(t);
+  animation.startTime = document.timeline.currentTime - 1000;
+  assert_equals(animation.startTime, document.timeline.currentTime - 1000);
+  assert_equals(animation.currentTime, 1000);
+  assert_equals(animation.playState, 'running');
+}, "Setting startTime on a running animation");
+
+test(function(t) {
+  var animation = createPausedAnimation(t);
+  animation.play();
+  assert_equals(animation.startTime, null);
+  assert_equals(animation.currentTime, 0);
+  assert_equals(animation.playState, 'pending');
+}, "Calling play() on a paused animation");
+
+test(function(t) {
+  var animation = createPausedAnimation(t);
+  animation.pause();
+  assert_equals(animation.startTime, null);
+  assert_equals(animation.currentTime, 0);
+  assert_equals(animation.playState, 'paused');
+}, "Calling pause() on a paused animation");
+
+test(function(t) {
+  var animation = createPausedAnimation(t);
+  animation.cancel();
+  assert_equals(animation.startTime, null);
+  assert_equals(animation.currentTime, null);
+  assert_equals(animation.playState, 'idle');
+}, "Calling cancel() on a paused animation");
+
+test(function(t) {
+  var animation = createPausedAnimation(t);
+  animation.finish();
+  assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime);
+  assert_equals(animation.currentTime, 100000);
+  assert_equals(animation.playState, 'finished');
+}, "Calling finish() on a paused animation");
+
+test(function(t) {
+  var animation = createPausedAnimation(t);
+  animation.reverse();
+  assert_equals(animation.startTime, null);
+  assert_equals(animation.currentTime, 100000);
+  assert_equals(animation.playState, 'pending');
+}, "Calling reverse() on a paused animation");
+
+test(function(t) {
+  var animation = createPausedAnimation(t);
+  animation.currentTime = 1000;
+  assert_equals(animation.startTime, null);
+  assert_equals(animation.currentTime, 1000);
+  assert_equals(animation.playState, 'paused');
+}, "Setting currentTime on a paused animation");
+
+test(function(t) {
+  var animation = createPausedAnimation(t);
+  animation.startTime = document.timeline.currentTime - 1000;
+  assert_equals(animation.startTime, document.timeline.currentTime - 1000);
+  assert_equals(animation.currentTime, 1000);
+  assert_equals(animation.playState, 'running');
+}, "Setting startTime on a paused animation");
+
+test(function(t) {
+  var animation = createFinishedAnimation(t);
+  animation.play();
+  assert_equals(animation.startTime, null);
+  assert_equals(animation.currentTime, 0);
+  assert_equals(animation.playState, 'pending');
+}, "Calling play() on a finished animation");
+
+test(function(t) {
+  var animation = createFinishedAnimation(t);
+  animation.pause();
+  assert_equals(animation.startTime, null);
+  assert_equals(animation.currentTime, 100000);
+  assert_equals(animation.playState, 'pending');
+}, "Calling pause() on a finished animation");
+
+test(function(t) {
+  var animation = createFinishedAnimation(t);
+  animation.cancel();
+  assert_equals(animation.startTime, null);
+  assert_equals(animation.currentTime, null);
+  assert_equals(animation.playState, 'idle');
+}, "Calling cancel() on a finished animation");
+
+test(function(t) {
+  var animation = createFinishedAnimation(t);
+  animation.finish();
+  assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime);
+  assert_equals(animation.currentTime, 100000);
+  assert_equals(animation.playState, 'finished');
+}, "Calling finish() on a finished animation");
+
+test(function(t) {
+  var animation = createFinishedAnimation(t);
+  animation.reverse();
+  assert_equals(animation.startTime, null);
+  assert_equals(animation.currentTime, 100000);
+  assert_equals(animation.playState, 'pending');
+}, "Calling reverse() on a finished animation");
+
+test(function(t) {
+  var animation = createFinishedAnimation(t);
+  animation.currentTime = 1000;
+  assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime);
+  assert_equals(animation.currentTime, 1000);
+  assert_equals(animation.playState, 'running');
+}, "Setting currentTime on a finished animation");
+
+async_test(function(t) {
+  var animation = createIdleAnimation(t);
+  animation.play();
+  var animationCurrentTime = animation.currentTime;
+  var timelineCurrentTime = document.timeline.currentTime;
+  animation.ready.then(() => {
+    t.step(() => {
+      assert_equals(animation.playState, 'running');
+      assert_greater_than_equal(animation.startTime, timelineCurrentTime);
+      assert_greater_than_equal(animation.currentTime, animationCurrentTime);
+    });
+    t.done();
+  });
+}, "PlayState is 'running' while playing a cancelled animation");
+
+async_test(function(t) {
+  let animation = createRunningAnimation(t);
+  animation.pause();
+  let animationCurrentTime = animation.currentTime;
+  animation.ready.then(() => {
+    t.step(() => {
+      assert_equals(animation.playState, 'paused');
+      assert_equals(animation.startTime, null);
+      assert_greater_than_equal(animation.currentTime, animationCurrentTime);
+    });
+    t.done();
+  });
+}, "PlayState is 'running' while pausing a running animation");
+</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/player-ready-finished-ordering.html b/third_party/WebKit/LayoutTests/web-animations-api/player-ready-finished-ordering.html
deleted file mode 100644
index f3f54126..0000000
--- a/third_party/WebKit/LayoutTests/web-animations-api/player-ready-finished-ordering.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-
-<script>
-async_test(function(t) {
-  var player = document.documentElement.animate([], 100000);
-  var ready = false;
-  player.ready.then(function() {
-    t.step(function() {
-      ready = true;
-    });
-  });
-  player.finished.then(function() {
-    t.step(function() {
-      assert_true(ready);
-    });
-    t.done();
-  });
-  player.finish();
-}, 'The ready promise should be resolved before the finished promise');
-
-async_test(function(t) {
-  var player = document.documentElement.animate([], 100000);
-  var ready = false;
-  player.ready.then(null, function() {
-    t.step(function() {
-      ready = true;
-    });
-  });
-  player.finished.then(null, function() {
-    t.step(function() {
-      assert_true(ready);
-    });
-    t.done();
-  });
-  player.cancel();
-}, 'The ready promise should be rejected before the finished promise');
-</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/player-unresolved-times.html b/third_party/WebKit/LayoutTests/web-animations-api/player-unresolved-times.html
deleted file mode 100644
index cbdacfe..0000000
--- a/third_party/WebKit/LayoutTests/web-animations-api/player-unresolved-times.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-
-<script>
-function assert_unresolved(value) {
-  assert_equals(value, null);
-}
-
-test(function() {
-  var player = document.documentElement.animate([], 100000);
-  player.cancel();
-  assert_unresolved(player.startTime);
-  assert_unresolved(player.currentTime);
-}, "unresolved startTime and currentTime");
-
-</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/quirky-keyframes.html b/third_party/WebKit/LayoutTests/web-animations-api/quirky-keyframes.html
deleted file mode 100644
index d0bcf22..0000000
--- a/third_party/WebKit/LayoutTests/web-animations-api/quirky-keyframes.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-
-<style>
-body {
-  color: blue;
-}
-
-#target {
-  color: green;
-}
-</style>
-
-<body>
-  <div id="target"></div>
-</body>
-
-<script>
-test(function() {
-  var animation = target.animate([{
-    color: '-webkit-text',
-  }, {
-    color: '-webkit-text',
-  }], 1);
-  animation.pause();
-  animation.currentTime = 0;
-  assert_equals(getComputedStyle(target).color, 'rgb(0, 128, 0)');
-}, 'KeyframeEffects do not support quirky values.');
-</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/startTime-expected.txt b/third_party/WebKit/LayoutTests/web-animations-api/startTime-expected.txt
new file mode 100644
index 0000000..420d718
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/web-animations-api/startTime-expected.txt
@@ -0,0 +1,9 @@
+This is a testharness.js-based test.
+FAIL startTime of a newly created (idle) animation is unresolved Animation is not defined
+FAIL startTime of a play-pending animation is unresolved Animation is not defined
+FAIL startTime of a pause-pending animation is unresolved Animation is not defined
+PASS startTime of a play-pending animation created using Element.animate shortcut is unresolved 
+PASS startTime is resolved when running 
+PASS startTime and currentTime are unresolved when animation is cancelled 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/startTime.html b/third_party/WebKit/LayoutTests/web-animations-api/startTime.html
new file mode 100644
index 0000000..cd840416
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/web-animations-api/startTime.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Animation.startTime tests</title>
+<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-starttime">
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script src="../imported/wpt/web-animations/testcommon.js"></script>
+<link rel="stylesheet" href="../resources/testharness.css">
+<body>
+<div>This test is a copy of LayoutTests/imported/wpt/web-animations/interfaces/Animation/startTime.html. Make sure to upstream this to the w3c test suite as it contains an added test that would fit well there.</div>
+<div id="log"></div>
+<script>
+'use strict';
+
+test(function(t) {
+  var animation = new Animation(new KeyframeEffect(createDiv(t), null),
+                                document.timeline);
+  assert_equals(animation.startTime, null, 'startTime is unresolved');
+}, 'startTime of a newly created (idle) animation is unresolved');
+
+test(function(t) {
+  var animation = new Animation(new KeyframeEffect(createDiv(t), null),
+                                document.timeline);
+  animation.play();
+  assert_equals(animation.startTime, null, 'startTime is unresolved');
+}, 'startTime of a play-pending animation is unresolved');
+
+test(function(t) {
+  var animation = new Animation(new KeyframeEffect(createDiv(t), null),
+                                document.timeline);
+  animation.pause();
+  assert_equals(animation.startTime, null, 'startTime is unresolved');
+}, 'startTime of a pause-pending animation is unresolved');
+
+test(function(t) {
+  var animation = createDiv(t).animate(null);
+  assert_equals(animation.startTime, null, 'startTime is unresolved');
+}, 'startTime of a play-pending animation created using Element.animate'
+   + ' shortcut is unresolved');
+
+promise_test(function(t) {
+  var animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
+  return animation.ready.then(function() {
+    assert_greater_than(animation.startTime, 0, 'startTime when running');
+  });
+}, 'startTime is resolved when running');
+
+test(function() {
+  var player = document.documentElement.animate([], 100000);
+  player.cancel();
+  assert_equals(player.startTime, null);
+  assert_equals(player.currentTime, null);
+}, "startTime and currentTime are unresolved when animation is cancelled");
+
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/the-effect-value-of-a-keyframe-effect.html b/third_party/WebKit/LayoutTests/web-animations-api/the-effect-value-of-a-keyframe-effect.html
new file mode 100644
index 0000000..6d655f6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/web-animations-api/the-effect-value-of-a-keyframe-effect.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Keyframe handling tests</title>
+<link rel="help" href="https://w3c.github.io/web-animations/#the-effect-value-of-a-keyframe-animation-effect">
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script src="../imported/wpt/web-animations/testcommon.js"></script>
+<body>
+<div id="log"></div>
+<div id="target"></div>
+<script>
+'use strict';
+
+test(function(t) {
+  var div = createDiv(t);
+  div.style.color = 'rgb(0, 0, 0)';
+  var anim = div.animate({ color: [ '-webkit-text', '-webkit-text'] }, 1000);
+
+  anim.pause();
+  anim.currentTime = 0;
+
+  assert_equals(getComputedStyle(div).color, 'rgb(0, 0, 0)');
+
+}, 'Tests keyframes with property values which are unsupported are removed');
+</script>
+</body>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/timed-item-specified-setters.html b/third_party/WebKit/LayoutTests/web-animations-api/timed-item-specified-setters.html
deleted file mode 100644
index 105ed3c..0000000
--- a/third_party/WebKit/LayoutTests/web-animations-api/timed-item-specified-setters.html
+++ /dev/null
@@ -1,118 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script>
-var typeError = {name: 'TypeError'};
-var timing = new KeyframeEffect(null, null).timing;
-
-test(function() {
-    timing.delay = 2;
-    assert_equals(timing.delay, 2);
-    timing.delay = -4;
-    assert_equals(timing.delay, -4);
-
-    assert_throws(typeError, () => timing.delay = NaN);
-    assert_equals(timing.delay, -4);
-
-    assert_throws(typeError, () => timing.delay = Infinity);
-    assert_equals(timing.delay, -4);
-}, 'AnimationEffectTiming should have a setter for delay.');
-
-test(function() {
-    timing.endDelay = 0.5;
-    assert_equals(timing.endDelay, 0.5);
-
-    timing.endDelay = -5;
-    assert_equals(timing.endDelay, -5);
-
-    assert_throws(typeError, () => timing.endDelay = NaN);
-    assert_equals(timing.endDelay, -5);
-
-    assert_throws(typeError, () => timing.endDelay = Infinity);
-    assert_equals(timing.endDelay, -5);
-}, 'AnimationEffectTiming should have a setter for endDelay.');
-
-test(function() {
-    timing.fill = 'backwards';
-    assert_equals(timing.fill, 'backwards');
-
-    timing.fill = 'both';
-    assert_equals(timing.fill, 'both');
-}, 'AnimationEffectTiming should have a setter for fill.');
-
-test(function() {
-    timing.iterationStart = 1.5;
-    assert_equals(timing.iterationStart, 1.5);
-
-    assert_throws(typeError, () => timing.iterationStart = -0.5);
-    assert_equals(timing.iterationStart, 1.5);
-
-    assert_throws(typeError, () => timing.iterationStart = NaN);
-    assert_equals(timing.iterationStart, 1.5);
-
-    assert_throws(typeError, () => timing.iterationStart = Infinity);
-    assert_equals(timing.iterationStart, 1.5);
-}, 'AnimationEffectTiming should have a setter for iterationStart.');
-
-test(function() {
-    timing.iterations = 10;
-    assert_equals(timing.iterations, 10);
-
-    timing.iterations = Infinity;
-    assert_equals(timing.iterations, Infinity);
-
-    assert_throws(typeError, () => timing.iterations = -20);
-    assert_equals(timing.iterations, Infinity);
-
-    assert_throws(typeError, () => timing.iterations = NaN);
-    assert_equals(timing.iterations, Infinity);
-}, 'AnimationEffectTiming should have a setter for iterations.');
-
-test(function() {
-    timing.duration = Infinity;
-    assert_equals(timing.duration, Infinity);
-
-    timing.duration = 1234;
-    assert_equals(timing.duration, 1234);
-
-    assert_throws(typeError, () => timing.duration = -10);
-    assert_equals(timing.duration, 1234);
-
-    assert_throws(typeError, () => timing.duration = NaN);
-    assert_equals(timing.duration, 1234);
-
-    assert_throws(typeError, () => timing.duration = 'very long');
-    assert_equals(timing.duration, 1234);
-}, 'AnimationEffectTiming should have a setter for duration.');
-
-test(function() {
-    timing.playbackRate = 2;
-    assert_equals(timing.playbackRate, 2);
-
-    timing.playbackRate = -2;
-    assert_equals(timing.playbackRate, -2);
-
-    assert_throws(typeError, () => timing.playbackRate = NaN);
-    assert_equals(timing.playbackRate, -2);
-}, 'AnimationEffectTiming should have a setter for playbackRate.');
-
-test(function() {
-    timing.direction = 'reverse';
-    assert_equals(timing.direction, 'reverse');
-
-    timing.direction = 'alternate';
-    assert_equals(timing.direction, 'alternate');
-}, 'AnimationEffectTiming should have a setter for direction.');
-
-test(function() {
-    timing.easing = "step-start";
-    assert_equals(timing.easing, 'step-start');
-
-    timing.easing = "eAse\\2d iN-ouT";
-    assert_equals(timing.easing, 'ease-in-out');
-
-
-    assert_throws(typeError, () => timing.easing = 'ponies');
-    assert_equals(timing.easing, 'ease-in-out');
-}, 'AnimationEffectTiming should have a setter for easing.');
-</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/timeline-set-current-time.html b/third_party/WebKit/LayoutTests/web-animations-api/timeline-set-current-time.html
deleted file mode 100644
index 5e78f2c1..0000000
--- a/third_party/WebKit/LayoutTests/web-animations-api/timeline-set-current-time.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-
-<!-- This tests that animation timeline current time affects players correctly. -->
-
-<div id='element'></div>
-
-<script>
-async_test(function(t) {
-  var player = element.animate([], 10);
-  var readyPromise = player.ready.then(function() {
-    t.step(function() {
-      assert_equals(player.currentTime, 0);
-      document.timeline.currentTime = player.startTime + 5;
-      assert_approx_equals(player.currentTime, 5, 0.1);
-      assert_equals(player.playState, "running");
-
-      document.timeline.currentTime = player.startTime + 15;
-      assert_approx_equals(player.currentTime, 10, 0.1);
-      assert_equals(player.playState, "finished");
-
-      document.timeline.currentTime = player.startTime;
-      assert_equals(player.currentTime, 0);
-      assert_equals(player.playState, "running");
-
-      document.timeline.currentTime = player.startTime + 5;
-      assert_approx_equals(player.currentTime, 5, 0.1);
-      assert_equals(player.playState, "running");
-    });
-    t.done();
-  });
-}, 'Animation players are retriggered if timeline time changes');
-
-</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/timeline-time.html b/third_party/WebKit/LayoutTests/web-animations-api/timeline-time.html
index a608400b..76c3aaa 100644
--- a/third_party/WebKit/LayoutTests/web-animations-api/timeline-time.html
+++ b/third_party/WebKit/LayoutTests/web-animations-api/timeline-time.html
@@ -1,4 +1,7 @@
 <!DOCTYPE html>
+<meta charset=utf-8>
+<title>Document timeline is increasing</title>
+<link rel="help" href="http://w3c.github.io/web-animations/#the-documents-default-timeline">
 <script src="../resources/testharness.js"></script>
 <script src="../resources/testharnessreport.js"></script>
 
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/timeline-updates-players.html b/third_party/WebKit/LayoutTests/web-animations-api/timeline-updates-players.html
deleted file mode 100644
index 13f50d82..0000000
--- a/third_party/WebKit/LayoutTests/web-animations-api/timeline-updates-players.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-
-<!-- This tests that players get updated even if they have previously had their effect removed or go out of effect. -->
-
-<div id='element'></div>
-
-<script>
-var element = document.getElementById('element');
-var keyframeEffect = new KeyframeEffect(element, [{left: '0px'}, {left: '100px'}], 10);
-test(function() {
-    var player = document.timeline.play(keyframeEffect);
-    player.finish();
-    assert_equals(getComputedStyle(element).left, 'auto');
-
-    player.play();
-    assert_equals(getComputedStyle(element).left, '0px');
-
-    player.finish();
-}, 'Player updated after finish and play');
-
-test(function() {
-    var player = document.timeline.play(keyframeEffect);
-    assert_equals(getComputedStyle(element).left, '0px');
-    var effect = player.effect
-    player.effect = null;
-    assert_equals(getComputedStyle(element).left, 'auto');
-
-    player.effect = effect;
-    assert_equals(getComputedStyle(element).left, '0px');
-
-    player.finish();
-}, 'Player updated after clear and set effect');
-</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/w3c/eased-keyframes.html b/third_party/WebKit/LayoutTests/web-animations-api/w3c/eased-keyframes.html
deleted file mode 100644
index d278b09f..0000000
--- a/third_party/WebKit/LayoutTests/web-animations-api/w3c/eased-keyframes.html
+++ /dev/null
@@ -1,95 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="resources/keyframes-test.js"></script>
-<script>
-test(function() {
-  assertAnimationStyles([
-    {opacity: '0', left: '0px', easing: 'steps(2, start)'},
-    {opacity: '0.25', left: '25px'},
-    {opacity: '0.75', left: '75px'},
-  ], {
-    0: {opacity: '0.125', left: '12.5px'},
-    0.125: {opacity: '0.125', left: '12.5px'},
-    0.25: {opacity: '0.25', left: '25px'},
-    0.375: {opacity: '0.25', left: '25px'},
-    0.5: {opacity: '0.25', left: '25px'},
-    0.625: {opacity: '0.375', left: '37.5px'},
-    0.75: {opacity: '0.5', left: '50px'},
-    0.875: {opacity: '0.625', left: '62.5px'},
-    1: {opacity: '0.75', left: '75px'},
-  }, 'with easing on first keyframe');
-
-  assertAnimationStyles([
-    {opacity: '0', left: '0px'},
-    {opacity: '0.5', left: '50px', easing: 'steps(2, start)'},
-    {opacity: '0.75', left: '75px'},
-  ], {
-    0: {opacity: '0', left: '0px'},
-    0.125: {opacity: '0.125', left: '12.5px'},
-    0.25: {opacity: '0.25', left: '25px'},
-    0.375: {opacity: '0.375', left: '37.5px'},
-    0.5: {opacity: '0.625', left: '62.5px'},
-    0.625: {opacity: '0.625', left: '62.5px'},
-    0.75: {opacity: '0.75', left: '75px'},
-    0.875: {opacity: '0.75', left: '75px'},
-    1: {opacity: '0.75', left: '75px'},
-  }, 'with easing on second keyframe');
-},
-'element.animate() with eased keyframe',
-{
-  help: 'http://dev.w3.org/fxtf/web-animations/#the-keyframe-dictionary',
-  assert: [
-    'element.animate() should start an animation when keyframes are specified with timing functions',
-    'for their easing property. The animation should use the given timing function between consecutive',
-    'keyframe offsets.',
-  ],
-  author: 'Alan Cutter',
-});
-
-test(function() {
-  assertAnimationStyles([
-    {opacity: '0', offset: 0, easing: 'steps(2, start)'},
-    {left: '0px', offset: 0},
-    {opacity: '0.5', left: '50px'},
-  ], {
-    0: {opacity: '0.25', left: '0px'},
-    0.25: {opacity: '0.25', left: '12.5px'},
-    0.5: {opacity: '0.5', left: '25px'},
-    0.75: {opacity: '0.5', left: '37.5px'},
-    1: {opacity: '0.5', left: '50px'},
-  });
-},
-'element.animate() with eased keyframe on single property',
-{
-  help: 'http://dev.w3.org/fxtf/web-animations/#the-keyframe-dictionary',
-  assert: [
-    'element.animate() should start an animation when keyframes are specified with timing functions',
-    'for their easing property. The animation should use the given timing function only on the properties',
-    'specified in the same keyframe.',
-  ],
-  author: 'Alan Cutter',
-});
-
-test(function() {
-  assertAnimationStyles([
-    {opacity: '0', left: '0px'},
-    {opacity: '0.5', left: '50px', easing: 'steps(2, start)'},
-  ], {
-    0: {opacity: '0', left: '0px'},
-    0.25: {opacity: '0.125', left: '12.5px'},
-    0.5: {opacity: '0.25', left: '25px'},
-    0.75: {opacity: '0.375', left: '37.5px'},
-    1: {opacity: '0.5', left: '50px'},
-  });
-},
-'element.animate() with easing on last keyframe',
-{
-  help: 'http://dev.w3.org/fxtf/web-animations/#the-keyframe-dictionary',
-  assert: [
-    'element.animate() should start an animation when keyframes are specified with timing functions',
-    'for their easing property. Easing on the last keyframes should have no effect on the animation.',
-  ],
-  author: 'Alan Cutter',
-});
-</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/w3c/out-of-order-keyframes.html b/third_party/WebKit/LayoutTests/web-animations-api/w3c/out-of-order-keyframes.html
deleted file mode 100644
index 6c80fd4..0000000
--- a/third_party/WebKit/LayoutTests/web-animations-api/w3c/out-of-order-keyframes.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!doctype html>
-<title>Web Animations API: Out of order Keyframe tests</title>
-<script src='../../resources/testharness.js'></script>
-<script src='../../resources/testharnessreport.js'></script>
-<div id='log'></div>
-<div id='div'></div>
-<script>
-
-test(function() {
-  assert_throws({name: 'TypeError'}, function() {
-    div.animate([{height: '100px', offset: 0.5}, {height: '200px', offset: 0}, {height: '300px', offset: 1}], 1);
-  }, 'Out-of-order properties should not work');
-
-  assert_throws({name: 'TypeError'}, function() {
-    div.animate([{height: '100px', offset: 0.5}, {height: '150px'},
-                 {height: '200px', offset: 0}, {height: '300px', offset: 1}], 1);
-  }, 'Auto offsets combined with out-of-order properties should not work');
-},
-'Out-of-order Keyframe tests',
-{
-  help:   'http://dev.w3.org/fxtf/web-animations/#normalizing-a-sequence-of-keyframes',
-  assert: 'Keyframes with out-of-order offsets should work, unless there are also auto offsets',
-  author: 'Shane Stephens'
-});
-
-</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/w3c/same-offset-keyframes.html b/third_party/WebKit/LayoutTests/web-animations-api/w3c/same-offset-keyframes.html
deleted file mode 100644
index f3c5da9..0000000
--- a/third_party/WebKit/LayoutTests/web-animations-api/w3c/same-offset-keyframes.html
+++ /dev/null
@@ -1,52 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="resources/keyframes-test.js"></script>
-<script>
-test(function() {
-  assertAnimationStyles([
-    {opacity: '0', left: '0px'},
-    {opacity: '0.5', left: '50px', offset: 0.5},
-    {opacity: '0', left: '0px', offset: 0.5},
-    {opacity: '0.75', left: '75px', offset: 0.5},
-    {opacity: '0.25', left: '25px'},
-  ], {
-    0.25: {opacity: '0.25', left: '25px'},
-    0.5: {opacity: '0.75', left: '75px'},
-    0.75: {opacity: '0.5', left: '50px'},
-  })
-},
-'element.animate() with keyframes at the same offset with overlapping properties',
-{
-  help: 'http://dev.w3.org/fxtf/web-animations/#the-unaccumulated-animation-value-of-a-keyframe-animation-effect',
-  assert: [
-    'element.animate() should start an animation when keyframes have equal offset values.',
-    'The overlapping properties in the equal offset keyframes should see a disjoint',
-    'interpolation pattern at the offset relative to the ordering of the keyframes.',
-  ],
-  author: 'Alan Cutter',
-});
-
-test(function() {
-  assertAnimationStyles([
-    {opacity: '0', left: '0px'},
-    {opacity: '0.75', offset: 0.5},
-    {left: '75px', offset: 0.5},
-    {opacity: '0.25', left: '25px'},
-  ], {
-    0.25: {opacity: '0.375', left: '37.5px'},
-    0.5: {opacity: '0.75', left: '75px'},
-    0.75: {opacity: '0.5', left: '50px'},
-  })
-},
-'element.animate() with keyframes at the same offset with disjoint properties',
-{
-  help: 'http://dev.w3.org/fxtf/web-animations/#the-unaccumulated-animation-value-of-a-keyframe-animation-effect',
-  assert: [
-    'element.animate() should start an animation when keyframes have equal offset values.',
-    'If the properties of the equal offset keyframes are disjoint then the animation should',
-    'be equivalent to having a single keyframe at that offset (assuming the easings are equal too).',
-  ],
-  author: 'Alan Cutter',
-});
-</script>
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 3dea1c1..a314202f 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -642,6 +642,10 @@
     getter y
     getter z
     method constructor
+interface CSSVariableReferenceValue
+    attribute @@toStringTag
+    getter variable
+    method constructor
 interface CSSViewportRule : CSSRule
     attribute @@toStringTag
     getter style
@@ -5794,14 +5798,6 @@
     getter zoomAndPan
     method constructor
     setter zoomAndPan
-interface SVGZoomEvent : UIEvent
-    attribute @@toStringTag
-    getter newScale
-    getter newTranslate
-    getter previousScale
-    getter previousTranslate
-    getter zoomRectScreen
-    method constructor
 interface Screen
     attribute @@toStringTag
     getter availHeight
diff --git a/third_party/WebKit/Source/bindings/core/v8/Nullable.h b/third_party/WebKit/Source/bindings/core/v8/Nullable.h
index 8598486b..31b0f612 100644
--- a/third_party/WebKit/Source/bindings/core/v8/Nullable.h
+++ b/third_party/WebKit/Source/bindings/core/v8/Nullable.h
@@ -65,9 +65,7 @@
     T& get() { ASSERT(!m_isNull); return m_value; }
     bool isNull() const { return m_isNull; }
 
-    // See comment in RefPtr.h about what UnspecifiedBoolType is.
-    typedef const T* UnspecifiedBoolType;
-    operator UnspecifiedBoolType() const { return m_isNull ? 0 : &m_value; }
+    explicit operator bool() const { return !m_isNull; }
 
     bool operator==(const Nullable& other) const
     {
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp
index 88d1096..895dab34 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp
@@ -1626,7 +1626,7 @@
         return false;
     if (m_position + length > m_length)
         return false;
-    *value = v8AtomicString(isolate(), reinterpret_cast<const char*>(m_buffer + m_position), length);
+    *value = v8StringFromUtf8(isolate(), reinterpret_cast<const char*>(m_buffer + m_position), length);
     m_position += length;
     return true;
 }
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8Binding.h b/third_party/WebKit/Source/bindings/core/v8/V8Binding.h
index eabb4a2..906fe6f 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8Binding.h
+++ b/third_party/WebKit/Source/bindings/core/v8/V8Binding.h
@@ -50,6 +50,7 @@
 #include "platform/heap/Handle.h"
 #include "platform/text/CompressibleString.h"
 #include "wtf/text/AtomicString.h"
+#include "wtf/text/StringView.h"
 #include <v8.h>
 
 namespace blink {
@@ -421,16 +422,18 @@
     return V8PerIsolateData::from(isolate)->getStringCache()->v8ExternalString(isolate, string);
 }
 
-inline v8::Local<v8::String> v8AtomicString(v8::Isolate* isolate, const char* str, int length = -1)
+inline v8::Local<v8::String> v8AtomicString(v8::Isolate* isolate, const StringView& string)
 {
-    ASSERT(isolate);
-    v8::Local<v8::String> value;
-    if (LIKELY(v8::String::NewFromUtf8(isolate, str, v8::NewStringType::kInternalized, length).ToLocal(&value)))
-        return value;
-    // Immediately crashes when NewFromUtf8() fails because it only fails the
-    // given str is too long.
-    RELEASE_NOTREACHED();
-    return v8::String::Empty(isolate);
+    DCHECK(isolate);
+    if (string.is8Bit())
+        return v8CallOrCrash(v8::String::NewFromOneByte(isolate, reinterpret_cast<const uint8_t*>(string.characters8()), v8::NewStringType::kInternalized, static_cast<int>(string.length())));
+    return v8CallOrCrash(v8::String::NewFromTwoByte(isolate, reinterpret_cast<const uint16_t*>(string.characters16()), v8::NewStringType::kInternalized, static_cast<int>(string.length())));
+}
+
+inline v8::Local<v8::String> v8StringFromUtf8(v8::Isolate* isolate, const char* bytes, int length)
+{
+    DCHECK(isolate);
+    return v8CallOrCrash(v8::String::NewFromUtf8(isolate, bytes, v8::NewStringType::kNormal, length));
 }
 
 inline v8::Local<v8::Value> v8Undefined()
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8PerIsolateData.cpp b/third_party/WebKit/Source/bindings/core/v8/V8PerIsolateData.cpp
index 00a1df1..cff1640 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8PerIsolateData.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8PerIsolateData.cpp
@@ -113,10 +113,6 @@
     case v8::Isolate::kLegacyConst:
         blinkFeature = UseCounter::LegacyConst;
         break;
-    case v8::Isolate::kObjectObserve:
-        blinkFeature = UseCounter::ObjectObserve;
-        deprecated = true;
-        break;
     case v8::Isolate::kSloppyMode:
         blinkFeature = UseCounter::V8SloppyMode;
         break;
diff --git a/third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp b/third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp
index c6cb296..a8d4be01 100644
--- a/third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp
@@ -466,10 +466,9 @@
         token = frameSecurityToken + token;
     }
 
-    CString utf8Token = token.utf8();
     // NOTE: V8 does identity comparison in fast path, must use a symbol
     // as the security token.
-    context->SetSecurityToken(v8AtomicString(m_isolate, utf8Token.data(), utf8Token.length()));
+    context->SetSecurityToken(v8AtomicString(m_isolate, token));
 }
 
 void WindowProxy::updateDocument()
diff --git a/third_party/WebKit/Source/build/scripts/make_event_factory.py b/third_party/WebKit/Source/build/scripts/make_event_factory.py
index 9ffcfb0..34d1479 100755
--- a/third_party/WebKit/Source/build/scripts/make_event_factory.py
+++ b/third_party/WebKit/Source/build/scripts/make_event_factory.py
@@ -68,21 +68,10 @@
             or name == 'TouchEvent')
 
 
-def create_event_deprecate_list(name):
-    return (name == 'SVGZoomEvent'
-            or name == 'SVGZoomEvents')
-
-
 def measure_name(name):
     return 'DocumentCreateEvent' + name
 
 
-def deprecate_name(name):
-    if (name.startswith('SVGZoomEvent')):
-        return 'SVGZoomEvent'
-    return None
-
-
 class EventFactoryWriter(in_generator.Writer):
     defaults = {
         'ImplementedAs': None,
@@ -98,9 +87,7 @@
         'lower_first': name_utilities.lower_first,
         'script_name': name_utilities.script_name,
         'create_event_whitelist': create_event_whitelist,
-        'create_event_deprecate_list': create_event_deprecate_list,
         'measure_name': measure_name,
-        'deprecate_name': deprecate_name,
     }
 
     def __init__(self, in_file_path):
diff --git a/third_party/WebKit/Source/build/scripts/templates/EventFactory.cpp.tmpl b/third_party/WebKit/Source/build/scripts/templates/EventFactory.cpp.tmpl
index cd9f0a9..fa0067d0 100644
--- a/third_party/WebKit/Source/build/scripts/templates/EventFactory.cpp.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/EventFactory.cpp.tmpl
@@ -22,12 +22,8 @@
     if (type == "{{event|script_name}}"{% if event.RuntimeEnabled %} && RuntimeEnabledFeatures::{{event.RuntimeEnabled|lower_first}}(){% endif %}) {
     {% endif %}
         {% if not event|script_name|create_event_whitelist %}
-        {% if event|script_name|create_event_deprecate_list %}
-        Deprecation::countDeprecation(executionContext, UseCounter::{{event|script_name|deprecate_name}});
-        {% else %}
         UseCounter::count(executionContext, UseCounter::{{event|script_name|measure_name}});
         {% endif %}
-        {% endif %}
         return {{event|cpp_name}}::create();
     }
     {% endfor %}
diff --git a/third_party/WebKit/Source/core/animation/SVGLengthInterpolationType.cpp b/third_party/WebKit/Source/core/animation/SVGLengthInterpolationType.cpp
index 54e47b4..29b6bf2e 100644
--- a/third_party/WebKit/Source/core/animation/SVGLengthInterpolationType.cpp
+++ b/third_party/WebKit/Source/core/animation/SVGLengthInterpolationType.cpp
@@ -23,6 +23,10 @@
     LengthInterpolatedEXS,
     LengthInterpolatedREMS,
     LengthInterpolatedCHS,
+    LengthInterpolatedViewportWidth,
+    LengthInterpolatedViewportHeight,
+    LengthInterpolatedViewportMin,
+    LengthInterpolatedViewportMax,
 };
 
 static const CSSPrimitiveValue::UnitType unitTypes[] = {
@@ -31,7 +35,11 @@
     CSSPrimitiveValue::UnitType::Ems,
     CSSPrimitiveValue::UnitType::Exs,
     CSSPrimitiveValue::UnitType::Rems,
-    CSSPrimitiveValue::UnitType::Chs
+    CSSPrimitiveValue::UnitType::Chs,
+    CSSPrimitiveValue::UnitType::ViewportWidth,
+    CSSPrimitiveValue::UnitType::ViewportHeight,
+    CSSPrimitiveValue::UnitType::ViewportMin,
+    CSSPrimitiveValue::UnitType::ViewportMax,
 };
 
 const size_t numLengthInterpolatedUnits = WTF_ARRAY_LENGTH(unitTypes);
@@ -71,6 +79,14 @@
         return LengthInterpolatedREMS;
     case CSSPrimitiveValue::UnitType::Chs:
         return LengthInterpolatedCHS;
+    case CSSPrimitiveValue::UnitType::ViewportWidth:
+        return LengthInterpolatedViewportWidth;
+    case CSSPrimitiveValue::UnitType::ViewportHeight:
+        return LengthInterpolatedViewportHeight;
+    case CSSPrimitiveValue::UnitType::ViewportMin:
+        return LengthInterpolatedViewportMin;
+    case CSSPrimitiveValue::UnitType::ViewportMax:
+        return LengthInterpolatedViewportMax;
     }
 }
 
diff --git a/third_party/WebKit/Source/core/animation/StringKeyframe.cpp b/third_party/WebKit/Source/core/animation/StringKeyframe.cpp
index 3829675..9cc5716 100644
--- a/third_party/WebKit/Source/core/animation/StringKeyframe.cpp
+++ b/third_party/WebKit/Source/core/animation/StringKeyframe.cpp
@@ -29,7 +29,7 @@
         m_cssPropertyMap->setProperty(property, value, false, styleSheetContents);
 }
 
-void StringKeyframe::setCSSPropertyValue(CSSPropertyID property, CSSValue* value)
+void StringKeyframe::setCSSPropertyValue(CSSPropertyID property, const CSSValue* value)
 {
     ASSERT(property != CSSPropertyInvalid);
     ASSERT(CSSAnimations::isAnimatableProperty(property));
diff --git a/third_party/WebKit/Source/core/animation/StringKeyframe.h b/third_party/WebKit/Source/core/animation/StringKeyframe.h
index 51c343b0..6469a52a 100644
--- a/third_party/WebKit/Source/core/animation/StringKeyframe.h
+++ b/third_party/WebKit/Source/core/animation/StringKeyframe.h
@@ -23,18 +23,18 @@
     }
 
     void setCSSPropertyValue(CSSPropertyID, const String& value, Element*, StyleSheetContents*);
-    void setCSSPropertyValue(CSSPropertyID, CSSValue*);
+    void setCSSPropertyValue(CSSPropertyID, const CSSValue*);
     void setPresentationAttributeValue(CSSPropertyID, const String& value, Element*, StyleSheetContents*);
     void setSVGAttributeValue(const QualifiedName&, const String& value);
 
-    CSSValue* cssPropertyValue(CSSPropertyID property) const
+    const CSSValue* cssPropertyValue(CSSPropertyID property) const
     {
         int index = m_cssPropertyMap->findPropertyIndex(property);
         RELEASE_ASSERT(index >= 0);
         return m_cssPropertyMap->propertyAt(static_cast<unsigned>(index)).value();
     }
 
-    CSSValue* presentationAttributeValue(CSSPropertyID property) const
+    const CSSValue* presentationAttributeValue(CSSPropertyID property) const
     {
         int index = m_presentationAttributeMap->findPropertyIndex(property);
         RELEASE_ASSERT(index >= 0);
diff --git a/third_party/WebKit/Source/core/core.gypi b/third_party/WebKit/Source/core/core.gypi
index aec61cf8..64a5ed7bd 100644
--- a/third_party/WebKit/Source/core/core.gypi
+++ b/third_party/WebKit/Source/core/core.gypi
@@ -55,6 +55,7 @@
             'css/cssom/CSSTransformComponent.idl',
             'css/cssom/CSSTransformValue.idl',
             'css/cssom/CSSTranslation.idl',
+            'css/cssom/CSSVariableReferenceValue.idl',
             'css/cssom/StylePropertyMap.idl',
             'dom/ArrayBuffer.idl',
             'dom/ArrayBufferView.idl',
@@ -367,7 +368,6 @@
             'svg/SVGUseElement.idl',
             'svg/SVGViewElement.idl',
             'svg/SVGViewSpec.idl',
-            'svg/SVGZoomEvent.idl',
             'timing/MemoryInfo.idl',
             'timing/Performance.idl',
             'timing/PerformanceCompositeTiming.idl',
@@ -493,7 +493,6 @@
             'events/UIEvent.idl',
             'events/WheelEvent.idl',
             'html/track/TrackEvent.idl',
-            'svg/SVGZoomEvent.idl',
         ],
         # IDL files that only have typedefs/enums.
         'core_typedefs_enums_only_idl_files': [
@@ -1361,6 +1360,7 @@
             'css/cssom/CSSSkew.h',
             'css/cssom/CSSStyleValue.cpp',
             'css/cssom/CSSStyleValue.h',
+            'css/cssom/CSSStyleVariableReferenceValue.h',
             'css/cssom/CSSTransformComponent.cpp',
             'css/cssom/CSSTransformComponent.h',
             'css/cssom/CSSTransformValue.cpp',
@@ -1766,7 +1766,6 @@
             'frame/LocalDOMWindow.h',
             'frame/LocalFrame.cpp',
             'frame/LocalFrame.h',
-            'frame/LocalFrameLifecycleNotifier.cpp',
             'frame/LocalFrameLifecycleNotifier.h',
             'frame/LocalFrameLifecycleObserver.h',
             'frame/Location.cpp',
@@ -2271,6 +2270,7 @@
             'workers/Worker.h',
             'workers/WorkerBackingThread.cpp',
             'workers/WorkerBackingThread.h',
+            'workers/WorkerClients.cpp',
             'workers/WorkerClients.h',
             'workers/WorkerEventQueue.cpp',
             'workers/WorkerEventQueue.h',
@@ -2623,6 +2623,8 @@
             'dom/StyleSheetCollection.h',
             'dom/TagCollection.cpp',
             'dom/TagCollection.h',
+            'dom/TaskRunnerHelper.cpp',
+            'dom/TaskRunnerHelper.h',
             'dom/Text.cpp',
             'dom/TextLinkColors.cpp',
             'dom/TextLinkColors.h',
@@ -3692,8 +3694,6 @@
             'svg/SVGViewSpec.h',
             'svg/SVGZoomAndPan.cpp',
             'svg/SVGZoomAndPan.h',
-            'svg/SVGZoomEvent.cpp',
-            'svg/SVGZoomEvent.h',
             'svg/animation/SMILTime.cpp',
             'svg/animation/SMILTimeContainer.cpp',
             'svg/animation/SMILTimeContainer.h',
diff --git a/third_party/WebKit/Source/core/css/CSSBasicShapeValues.cpp b/third_party/WebKit/Source/core/css/CSSBasicShapeValues.cpp
index 9194706..96b71234 100644
--- a/third_party/WebKit/Source/core/css/CSSBasicShapeValues.cpp
+++ b/third_party/WebKit/Source/core/css/CSSBasicShapeValues.cpp
@@ -325,7 +325,7 @@
             }
             if (horizontalRadii != verticalRadii) {
                 result.append(separator);
-                result.append("/");
+                result.append('/');
 
                 for (size_t i = 0; i < verticalRadii.size(); ++i) {
                     result.append(separator);
diff --git a/third_party/WebKit/Source/core/css/CSSFontFaceSrcValue.cpp b/third_party/WebKit/Source/core/css/CSSFontFaceSrcValue.cpp
index fb46e0c..dc58bdd 100644
--- a/third_party/WebKit/Source/core/css/CSSFontFaceSrcValue.cpp
+++ b/third_party/WebKit/Source/core/css/CSSFontFaceSrcValue.cpp
@@ -58,14 +58,14 @@
     if (isLocal()) {
         result.append("local(");
         result.append(serializeString(m_absoluteResource));
-        result.append(")");
+        result.append(')');
     } else {
         result.append(serializeURI(m_specifiedResource));
     }
     if (!m_format.isEmpty()) {
         result.append(" format(");
         result.append(serializeString(m_format));
-        result.append(")");
+        result.append(')');
     }
     return result.toString();
 }
diff --git a/third_party/WebKit/Source/core/css/CSSGridAutoRepeatValue.cpp b/third_party/WebKit/Source/core/css/CSSGridAutoRepeatValue.cpp
index 238c6ed..a27a586 100644
--- a/third_party/WebKit/Source/core/css/CSSGridAutoRepeatValue.cpp
+++ b/third_party/WebKit/Source/core/css/CSSGridAutoRepeatValue.cpp
@@ -15,7 +15,7 @@
     result.append(getValueName(autoRepeatID()));
     result.append(", ");
     result.append(CSSValueList::customCSSText());
-    result.append(")");
+    result.append(')');
     return result.toString();
 }
 
diff --git a/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.cpp b/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.cpp
index d48c615..600f0b5 100644
--- a/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.cpp
+++ b/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.cpp
@@ -118,7 +118,7 @@
     m_images.add(size, image);
 }
 
-PassRefPtr<Image> CSSImageGeneratorValue::image(const LayoutObject& layoutObject, const IntSize& size)
+PassRefPtr<Image> CSSImageGeneratorValue::image(const LayoutObject& layoutObject, const IntSize& size, float zoom)
 {
     switch (getClassType()) {
     case CrossfadeClass:
@@ -126,7 +126,7 @@
     case LinearGradientClass:
         return toCSSLinearGradientValue(this)->image(layoutObject, size);
     case PaintClass:
-        return toCSSPaintValue(this)->image(layoutObject, size);
+        return toCSSPaintValue(this)->image(layoutObject, size, zoom);
     case RadialGradientClass:
         return toCSSRadialGradientValue(this)->image(layoutObject, size);
     default:
diff --git a/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.h b/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.h
index bb378f6d..759c7b1 100644
--- a/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.h
+++ b/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.h
@@ -60,7 +60,7 @@
 
     void addClient(const LayoutObject*, const IntSize&);
     void removeClient(const LayoutObject*);
-    PassRefPtr<Image> image(const LayoutObject&, const IntSize&);
+    PassRefPtr<Image> image(const LayoutObject&, const IntSize&, float zoom);
 
     bool isFixedSize() const;
     IntSize fixedSize(const LayoutObject&, const FloatSize& defaultObjectSize);
diff --git a/third_party/WebKit/Source/core/css/CSSNamespaceRule.cpp b/third_party/WebKit/Source/core/css/CSSNamespaceRule.cpp
index 220d7eac..f1401d6 100644
--- a/third_party/WebKit/Source/core/css/CSSNamespaceRule.cpp
+++ b/third_party/WebKit/Source/core/css/CSSNamespaceRule.cpp
@@ -26,7 +26,7 @@
     result.append("@namespace ");
     serializeIdentifier(prefix(), result);
     if (!prefix().isEmpty())
-        result.append(" ");
+        result.append(' ');
     result.append("url(");
     result.append(serializeString(namespaceURI()));
     result.append(");");
diff --git a/third_party/WebKit/Source/core/css/CSSPageRule.cpp b/third_party/WebKit/Source/core/css/CSSPageRule.cpp
index fa99594..1fc0c5b1 100644
--- a/third_party/WebKit/Source/core/css/CSSPageRule.cpp
+++ b/third_party/WebKit/Source/core/css/CSSPageRule.cpp
@@ -79,7 +79,7 @@
     String pageSelectors = selectorText();
     result.append(pageSelectors);
     if (!pageSelectors.isEmpty())
-        result.append(" ");
+        result.append(' ');
     result.append("{ ");
     String decls = m_pageRule->properties().asText();
     result.append(decls);
diff --git a/third_party/WebKit/Source/core/css/CSSPaintImageGenerator.h b/third_party/WebKit/Source/core/css/CSSPaintImageGenerator.h
index 59b56ba..069ab3c 100644
--- a/third_party/WebKit/Source/core/css/CSSPaintImageGenerator.h
+++ b/third_party/WebKit/Source/core/css/CSSPaintImageGenerator.h
@@ -39,7 +39,7 @@
 
     // Invokes the CSS Paint API 'paint' callback. May return a nullptr
     // representing an invalid image if an error occurred.
-    virtual PassRefPtr<Image> paint(const LayoutObject&, const IntSize&) = 0;
+    virtual PassRefPtr<Image> paint(const LayoutObject&, const IntSize&, float zoom) = 0;
 
     virtual const Vector<CSSPropertyID>& nativeInvalidationProperties() const = 0;
     virtual const Vector<AtomicString>& customInvalidationProperties() const = 0;
diff --git a/third_party/WebKit/Source/core/css/CSSPaintValue.cpp b/third_party/WebKit/Source/core/css/CSSPaintValue.cpp
index 82cc7572..7d6652a 100644
--- a/third_party/WebKit/Source/core/css/CSSPaintValue.cpp
+++ b/third_party/WebKit/Source/core/css/CSSPaintValue.cpp
@@ -36,12 +36,12 @@
     return m_name->value();
 }
 
-PassRefPtr<Image> CSSPaintValue::image(const LayoutObject& layoutObject, const IntSize& size)
+PassRefPtr<Image> CSSPaintValue::image(const LayoutObject& layoutObject, const IntSize& size, float zoom)
 {
     if (!m_generator)
         m_generator = CSSPaintImageGenerator::create(name(), layoutObject.document(), m_paintImageGeneratorObserver);
 
-    return m_generator->paint(layoutObject, size);
+    return m_generator->paint(layoutObject, size, zoom);
 }
 
 void CSSPaintValue::Observer::paintImageGeneratorReady()
diff --git a/third_party/WebKit/Source/core/css/CSSPaintValue.h b/third_party/WebKit/Source/core/css/CSSPaintValue.h
index bfc41aa..ed3fa7d 100644
--- a/third_party/WebKit/Source/core/css/CSSPaintValue.h
+++ b/third_party/WebKit/Source/core/css/CSSPaintValue.h
@@ -24,7 +24,7 @@
 
     String name() const;
 
-    PassRefPtr<Image> image(const LayoutObject&, const IntSize&);
+    PassRefPtr<Image> image(const LayoutObject&, const IntSize&, float zoom);
     bool isFixedSize() const { return false; }
     IntSize fixedSize(const LayoutObject&) { return IntSize(); }
 
diff --git a/third_party/WebKit/Source/core/css/RemoteFontFaceSource.cpp b/third_party/WebKit/Source/core/css/RemoteFontFaceSource.cpp
index 06b2d69f..4175b43 100644
--- a/third_party/WebKit/Source/core/css/RemoteFontFaceSource.cpp
+++ b/third_party/WebKit/Source/core/css/RemoteFontFaceSource.cpp
@@ -325,10 +325,10 @@
     const int boundary = 1 << 2;
 
     DEFINE_STATIC_LOCAL(EnumerationHistogram, interventionHistogram, ("WebFont.InterventionResult", boundary));
-    DEFINE_STATIC_LOCAL(EnumerationHistogram, missCachedInterventionHistogram, ("WebFont.MissCachedInterventionResult", boundary));
+    DEFINE_STATIC_LOCAL(EnumerationHistogram, missedCacheInterventionHistogram, ("WebFont.InterventionResult.MissedCache", boundary));
     interventionHistogram.count(interventionResult);
     if (isLoadedFromNetwork)
-        missCachedInterventionHistogram.count(interventionResult);
+        missedCacheInterventionHistogram.count(interventionResult);
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp b/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp
index 02a5a13..dd15534e 100644
--- a/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp
+++ b/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp
@@ -853,7 +853,7 @@
         builder.append("repeat-x");
     } else {
         builder.append(repeatX.cssText());
-        builder.append(" ");
+        builder.append(' ');
         builder.append(repeatY.cssText());
     }
 }
diff --git a/third_party/WebKit/Source/core/css/StylePropertySet.cpp b/third_party/WebKit/Source/core/css/StylePropertySet.cpp
index da201110..c464170 100644
--- a/third_party/WebKit/Source/core/css/StylePropertySet.cpp
+++ b/third_party/WebKit/Source/core/css/StylePropertySet.cpp
@@ -307,7 +307,7 @@
     return CSSParser::parseValueForCustomProperty(this, customPropertyName, value, important, contextStyleSheet);
 }
 
-void MutableStylePropertySet::setProperty(CSSPropertyID propertyID, CSSValue* value, bool important)
+void MutableStylePropertySet::setProperty(CSSPropertyID propertyID, const CSSValue* value, bool important)
 {
     StylePropertyShorthand shorthand = shorthandForProperty(propertyID);
     if (!shorthand.length()) {
diff --git a/third_party/WebKit/Source/core/css/StylePropertySet.h b/third_party/WebKit/Source/core/css/StylePropertySet.h
index 8732c54..91c92b7e 100644
--- a/third_party/WebKit/Source/core/css/StylePropertySet.h
+++ b/third_party/WebKit/Source/core/css/StylePropertySet.h
@@ -203,7 +203,7 @@
     // These expand shorthand properties into multiple properties.
     bool setProperty(CSSPropertyID unresolvedProperty, const String& value, bool important = false, StyleSheetContents* contextStyleSheet = 0);
     bool setProperty(const AtomicString& customPropertyName, const String& value, bool important = false, StyleSheetContents* contextStyleSheet = 0);
-    void setProperty(CSSPropertyID, CSSValue*, bool important = false);
+    void setProperty(CSSPropertyID, const CSSValue*, bool important = false);
 
     // These do not. FIXME: This is too messy, we can do better.
     bool setProperty(CSSPropertyID, CSSValueID identifier, bool important = false);
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSStyleVariableReferenceValue.h b/third_party/WebKit/Source/core/css/cssom/CSSStyleVariableReferenceValue.h
new file mode 100644
index 0000000..068b52c
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/cssom/CSSStyleVariableReferenceValue.h
@@ -0,0 +1,37 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CSSStyleVariableReferenceValue_h
+#define CSSStyleVariableReferenceValue_h
+
+#include "bindings/core/v8/ScriptWrappable.h"
+#include "core/CoreExport.h"
+
+namespace blink {
+
+class CORE_EXPORT CSSStyleVariableReferenceValue final : public GarbageCollectedFinalized<CSSStyleVariableReferenceValue>, public ScriptWrappable {
+    WTF_MAKE_NONCOPYABLE(CSSStyleVariableReferenceValue);
+    DEFINE_WRAPPERTYPEINFO();
+public:
+    virtual ~CSSStyleVariableReferenceValue() { }
+
+    // TODO(anthonyhkf): add fallback: create(variable, fallback)
+    static CSSStyleVariableReferenceValue* create(const String& variable)
+    {
+        return new CSSStyleVariableReferenceValue(variable);
+    }
+
+    DEFINE_INLINE_TRACE() { }
+
+    const String& variable() const { return m_variable; }
+
+protected:
+    CSSStyleVariableReferenceValue(String variable): m_variable(variable) { }
+
+    String m_variable;
+};
+
+} // namespace blink
+
+#endif // CSSStyleVariableReference_h
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSVariableReferenceValue.idl b/third_party/WebKit/Source/core/css/cssom/CSSVariableReferenceValue.idl
new file mode 100644
index 0000000..4e76631
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/cssom/CSSVariableReferenceValue.idl
@@ -0,0 +1,15 @@
+// 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.
+
+[
+    // TODO(anthonyhkf): add fallback: Constructor(DOMString variable, CSSTokenStreamValue fallback)
+    Constructor(DOMString variable),
+    Exposed=(Window,PaintWorklet),
+    RuntimeEnabled=CSSTypedOM,
+    // TODO(anthonyhkf): rename CSSStyleVariableReferenceValue
+    ImplementedAs=CSSStyleVariableReferenceValue
+] interface CSSVariableReferenceValue {
+    readonly attribute DOMString variable;
+    // TODO(anthonyhkf): add fallback: readonly attribute CSSTokenStreamValue fallback;
+};
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserToken.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserToken.cpp
index fb46fac5..adfb8763 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSParserToken.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSParserToken.cpp
@@ -219,7 +219,7 @@
     case UrlToken:
         builder.append("url(");
         serializeIdentifier(value().toString(), builder);
-        return builder.append(")");
+        return builder.append(')');
     case DelimiterToken:
         if (delimiter() == '\\')
             return builder.append("\\\n");
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserToken.h b/third_party/WebKit/Source/core/css/parser/CSSParserToken.h
index 6158842c..fa88236 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSParserToken.h
+++ b/third_party/WebKit/Source/core/css/parser/CSSParserToken.h
@@ -94,7 +94,9 @@
     CSSParserTokenType type() const { return static_cast<CSSParserTokenType>(m_type); }
     StringView value() const
     {
-        return StringView(m_valueDataCharRaw, m_valueLength, m_valueIs8Bit);
+        if (m_valueIs8Bit)
+            return StringView(reinterpret_cast<const LChar*>(m_valueDataCharRaw), m_valueLength);
+        return StringView(reinterpret_cast<const UChar*>(m_valueDataCharRaw), m_valueLength);
     }
 
     UChar delimiter() const;
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
index a0bb361..9199cbe 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
@@ -63,7 +63,7 @@
     m_range.consumeWhitespace();
 }
 
-void CSSPropertyParser::addProperty(CSSPropertyID property, CSSPropertyID currentShorthand, CSSValue* value, bool important, bool implicit)
+void CSSPropertyParser::addProperty(CSSPropertyID property, CSSPropertyID currentShorthand, const CSSValue& value, bool important, bool implicit)
 {
     ASSERT(!isPropertyAlias(property));
 
@@ -78,10 +78,10 @@
             shorthandIndex = indexOfShorthandForLonghand(currentShorthand, shorthands);
     }
 
-    m_parsedProperties->append(CSSProperty(property, *value, important, setFromShorthand, shorthandIndex, implicit));
+    m_parsedProperties->append(CSSProperty(property, value, important, setFromShorthand, shorthandIndex, implicit));
 }
 
-void CSSPropertyParser::addExpandedPropertyForValue(CSSPropertyID property, CSSValue* value, bool important)
+void CSSPropertyParser::addExpandedPropertyForValue(CSSPropertyID property, const CSSValue& value, bool important)
 {
     const StylePropertyShorthand& shorthand = shorthandForProperty(property);
     unsigned shorthandLength = shorthand.length();
@@ -159,9 +159,9 @@
         if (parseShorthand(unresolvedProperty, important))
             return true;
     } else {
-        if (CSSValue* parsedValue = parseSingleValue(unresolvedProperty)) {
+        if (const CSSValue* parsedValue = parseSingleValue(unresolvedProperty)) {
             if (m_range.atEnd()) {
-                addProperty(propertyId, CSSPropertyInvalid, parsedValue, important);
+                addProperty(propertyId, CSSPropertyInvalid, *parsedValue, important);
                 return true;
             }
         }
@@ -171,10 +171,10 @@
         CSSVariableReferenceValue* variable = CSSVariableReferenceValue::create(CSSVariableData::create(originalRange));
 
         if (isShorthand) {
-            CSSPendingSubstitutionValue* pendingValue = CSSPendingSubstitutionValue::create(propertyId, variable);
+            const CSSPendingSubstitutionValue& pendingValue = *CSSPendingSubstitutionValue::create(propertyId, variable);
             addExpandedPropertyForValue(propertyId, pendingValue, important);
         } else {
-            addProperty(propertyId, CSSPropertyInvalid, variable, important);
+            addProperty(propertyId, CSSPropertyInvalid, *variable, important);
         }
         return true;
     }
@@ -279,9 +279,9 @@
     if (!shorthand.length()) {
         if (CSSPropertyMetadata::isDescriptorOnly(unresolvedProperty))
             return false;
-        addProperty(property, CSSPropertyInvalid, value, important);
+        addProperty(property, CSSPropertyInvalid, *value, important);
     } else {
-        addExpandedPropertyForValue(property, value, important);
+        addExpandedPropertyForValue(property, *value, important);
     }
     m_range = rangeCopy;
     return true;
@@ -1330,7 +1330,7 @@
     }
 
     for (size_t i = 0; i < longhandCount; ++i)
-        addProperty(shorthand.properties()[i], shorthand.id(), longhands[i], important);
+        addProperty(shorthand.properties()[i], shorthand.id(), *longhands[i], important);
 
     return m_range.atEnd();
 }
@@ -4094,7 +4094,7 @@
     if (!parsedValue || !m_range.atEnd())
         return false;
 
-    addProperty(propId, CSSPropertyInvalid, parsedValue, false);
+    addProperty(propId, CSSPropertyInvalid, *parsedValue, false);
     return true;
 }
 
@@ -4111,18 +4111,18 @@
     AtomicString fontFamily;
     LayoutTheme::theme().systemFont(systemFontID, fontStyle, fontWeight, fontSize, fontFamily);
 
-    addProperty(CSSPropertyFontStyle, CSSPropertyFont, CSSPrimitiveValue::createIdentifier(fontStyle == FontStyleItalic ? CSSValueItalic : CSSValueNormal), important);
-    addProperty(CSSPropertyFontWeight, CSSPropertyFont, CSSPrimitiveValue::create(fontWeight), important);
-    addProperty(CSSPropertyFontSize, CSSPropertyFont, CSSPrimitiveValue::create(fontSize, CSSPrimitiveValue::UnitType::Pixels), important);
+    addProperty(CSSPropertyFontStyle, CSSPropertyFont, *CSSPrimitiveValue::createIdentifier(fontStyle == FontStyleItalic ? CSSValueItalic : CSSValueNormal), important);
+    addProperty(CSSPropertyFontWeight, CSSPropertyFont, *CSSPrimitiveValue::create(fontWeight), important);
+    addProperty(CSSPropertyFontSize, CSSPropertyFont, *CSSPrimitiveValue::create(fontSize, CSSPrimitiveValue::UnitType::Pixels), important);
     CSSValueList* fontFamilyList = CSSValueList::createCommaSeparated();
     fontFamilyList->append(*CSSFontFamilyValue::create(fontFamily));
-    addProperty(CSSPropertyFontFamily, CSSPropertyFont, fontFamilyList, important);
+    addProperty(CSSPropertyFontFamily, CSSPropertyFont, *fontFamilyList, important);
 
-    addProperty(CSSPropertyFontStretch, CSSPropertyFont, CSSPrimitiveValue::createIdentifier(CSSValueNormal), important);
-    addProperty(CSSPropertyFontVariantCaps, CSSPropertyFont, CSSPrimitiveValue::createIdentifier(CSSValueNormal), important);
-    addProperty(CSSPropertyFontVariantLigatures, CSSPropertyFont, CSSPrimitiveValue::createIdentifier(CSSValueNormal), important);
-    addProperty(CSSPropertyFontVariantNumeric, CSSPropertyFont, CSSPrimitiveValue::createIdentifier(CSSValueNormal), important);
-    addProperty(CSSPropertyLineHeight, CSSPropertyFont, CSSPrimitiveValue::createIdentifier(CSSValueNormal), important);
+    addProperty(CSSPropertyFontStretch, CSSPropertyFont, *CSSPrimitiveValue::createIdentifier(CSSValueNormal), important);
+    addProperty(CSSPropertyFontVariantCaps, CSSPropertyFont, *CSSPrimitiveValue::createIdentifier(CSSValueNormal), important);
+    addProperty(CSSPropertyFontVariantLigatures, CSSPropertyFont, *CSSPrimitiveValue::createIdentifier(CSSValueNormal), important);
+    addProperty(CSSPropertyFontVariantNumeric, CSSPropertyFont, *CSSPrimitiveValue::createIdentifier(CSSValueNormal), important);
+    addProperty(CSSPropertyLineHeight, CSSPropertyFont, *CSSPrimitiveValue::createIdentifier(CSSValueNormal), important);
     return true;
 }
 
@@ -4167,28 +4167,28 @@
     if (m_range.atEnd())
         return false;
 
-    addProperty(CSSPropertyFontStyle, CSSPropertyFont, fontStyle ? fontStyle : CSSPrimitiveValue::createIdentifier(CSSValueNormal), important);
-    addProperty(CSSPropertyFontVariantCaps, CSSPropertyFont, fontVariantCaps ? fontVariantCaps : CSSPrimitiveValue::createIdentifier(CSSValueNormal), important);
-    addProperty(CSSPropertyFontVariantLigatures, CSSPropertyFont, CSSPrimitiveValue::createIdentifier(CSSValueNormal), important);
-    addProperty(CSSPropertyFontVariantNumeric, CSSPropertyFont, CSSPrimitiveValue::createIdentifier(CSSValueNormal), important);
+    addProperty(CSSPropertyFontStyle, CSSPropertyFont, fontStyle ? *fontStyle : *CSSPrimitiveValue::createIdentifier(CSSValueNormal), important);
+    addProperty(CSSPropertyFontVariantCaps, CSSPropertyFont, fontVariantCaps ? *fontVariantCaps : *CSSPrimitiveValue::createIdentifier(CSSValueNormal), important);
+    addProperty(CSSPropertyFontVariantLigatures, CSSPropertyFont, *CSSPrimitiveValue::createIdentifier(CSSValueNormal), important);
+    addProperty(CSSPropertyFontVariantNumeric, CSSPropertyFont, *CSSPrimitiveValue::createIdentifier(CSSValueNormal), important);
 
-    addProperty(CSSPropertyFontWeight, CSSPropertyFont, fontWeight ? fontWeight : CSSPrimitiveValue::createIdentifier(CSSValueNormal), important);
-    addProperty(CSSPropertyFontStretch, CSSPropertyFont, fontStretch ? fontStretch : CSSPrimitiveValue::createIdentifier(CSSValueNormal), important);
+    addProperty(CSSPropertyFontWeight, CSSPropertyFont, fontWeight ? *fontWeight : *CSSPrimitiveValue::createIdentifier(CSSValueNormal), important);
+    addProperty(CSSPropertyFontStretch, CSSPropertyFont, fontStretch ? *fontStretch : *CSSPrimitiveValue::createIdentifier(CSSValueNormal), important);
 
     // Now a font size _must_ come.
     CSSValue* fontSize = consumeFontSize(m_range, m_context.mode());
     if (!fontSize || m_range.atEnd())
         return false;
 
-    addProperty(CSSPropertyFontSize, CSSPropertyFont, fontSize, important);
+    addProperty(CSSPropertyFontSize, CSSPropertyFont, *fontSize, important);
 
     if (consumeSlashIncludingWhitespace(m_range)) {
         CSSPrimitiveValue* lineHeight = consumeLineHeight(m_range, m_context.mode());
         if (!lineHeight)
             return false;
-        addProperty(CSSPropertyLineHeight, CSSPropertyFont, lineHeight, important);
+        addProperty(CSSPropertyLineHeight, CSSPropertyFont, *lineHeight, important);
     } else {
-        addProperty(CSSPropertyLineHeight, CSSPropertyFont, CSSPrimitiveValue::createIdentifier(CSSValueNormal), important);
+        addProperty(CSSPropertyLineHeight, CSSPropertyFont, *CSSPrimitiveValue::createIdentifier(CSSValueNormal), important);
     }
 
     // Font family must come now.
@@ -4196,7 +4196,7 @@
     if (!parsedFamilyValue)
         return false;
 
-    addProperty(CSSPropertyFontFamily, CSSPropertyFont, parsedFamilyValue, important);
+    addProperty(CSSPropertyFontFamily, CSSPropertyFont, *parsedFamilyValue, important);
 
     // FIXME: http://www.w3.org/TR/2011/WD-css3-fonts-20110324/#font-prop requires that
     // "font-stretch", "font-size-adjust", and "font-kerning" be reset to their initial values
@@ -4207,8 +4207,8 @@
 bool CSSPropertyParser::consumeFontVariantShorthand(bool important)
 {
     if (identMatches<CSSValueNormal, CSSValueNone>(m_range.peek().id())) {
-        addProperty(CSSPropertyFontVariantLigatures, CSSPropertyFontVariant, consumeIdent(m_range), important);
-        addProperty(CSSPropertyFontVariantCaps, CSSPropertyFontVariant, CSSPrimitiveValue::createIdentifier(CSSValueNormal), important);
+        addProperty(CSSPropertyFontVariantLigatures, CSSPropertyFontVariant, *consumeIdent(m_range), important);
+        addProperty(CSSPropertyFontVariantCaps, CSSPropertyFontVariant, *CSSPrimitiveValue::createIdentifier(CSSValueNormal), important);
         return m_range.atEnd();
     }
 
@@ -4244,9 +4244,9 @@
         }
     } while (!m_range.atEnd());
 
-    addProperty(CSSPropertyFontVariantLigatures, CSSPropertyFontVariant, ligaturesParser.finalizeValue(), important);
-    addProperty(CSSPropertyFontVariantNumeric, CSSPropertyFontVariant, numericParser.finalizeValue(), important);
-    addProperty(CSSPropertyFontVariantCaps, CSSPropertyFontVariant, capsValue ? capsValue : CSSPrimitiveValue::createIdentifier(CSSValueNormal), important);
+    addProperty(CSSPropertyFontVariantLigatures, CSSPropertyFontVariant, *ligaturesParser.finalizeValue(), important);
+    addProperty(CSSPropertyFontVariantNumeric, CSSPropertyFontVariant, *numericParser.finalizeValue(), important);
+    addProperty(CSSPropertyFontVariantCaps, CSSPropertyFontVariant, capsValue ? *capsValue : *CSSPrimitiveValue::createIdentifier(CSSValueNormal), important);
     return true;
 }
 
@@ -4260,8 +4260,8 @@
         verticalSpacing = consumeLength(m_range, m_context.mode(), ValueRangeNonNegative, UnitlessQuirk::Allow);
     if (!verticalSpacing || !m_range.atEnd())
         return false;
-    addProperty(CSSPropertyWebkitBorderHorizontalSpacing, CSSPropertyBorderSpacing, horizontalSpacing, important);
-    addProperty(CSSPropertyWebkitBorderVerticalSpacing, CSSPropertyBorderSpacing, verticalSpacing, important);
+    addProperty(CSSPropertyWebkitBorderHorizontalSpacing, CSSPropertyBorderSpacing, *horizontalSpacing, important);
+    addProperty(CSSPropertyWebkitBorderVerticalSpacing, CSSPropertyBorderSpacing, *verticalSpacing, important);
     return true;
 }
 
@@ -4313,8 +4313,8 @@
             maxWidth = consumeSingleViewportDescriptor(m_range, CSSPropertyMaxWidth, m_context.mode());
         if (!maxWidth || !m_range.atEnd())
             return false;
-        addProperty(CSSPropertyMinWidth, CSSPropertyInvalid, minWidth, important);
-        addProperty(CSSPropertyMaxWidth, CSSPropertyInvalid, maxWidth, important);
+        addProperty(CSSPropertyMinWidth, CSSPropertyInvalid, *minWidth, important);
+        addProperty(CSSPropertyMaxWidth, CSSPropertyInvalid, *maxWidth, important);
         return true;
     }
     case CSSPropertyHeight: {
@@ -4326,8 +4326,8 @@
             maxHeight = consumeSingleViewportDescriptor(m_range, CSSPropertyMaxHeight, m_context.mode());
         if (!maxHeight || !m_range.atEnd())
             return false;
-        addProperty(CSSPropertyMinHeight, CSSPropertyInvalid, minHeight, important);
-        addProperty(CSSPropertyMaxHeight, CSSPropertyInvalid, maxHeight, important);
+        addProperty(CSSPropertyMinHeight, CSSPropertyInvalid, *minHeight, important);
+        addProperty(CSSPropertyMaxHeight, CSSPropertyInvalid, *maxHeight, important);
         return true;
     }
     case CSSPropertyMinWidth:
@@ -4342,7 +4342,7 @@
         CSSValue* parsedValue = consumeSingleViewportDescriptor(m_range, propId, m_context.mode());
         if (!parsedValue || !m_range.atEnd())
             return false;
-        addProperty(propId, CSSPropertyInvalid, parsedValue, important);
+        addProperty(propId, CSSPropertyInvalid, *parsedValue, important);
         return true;
     }
     default:
@@ -4379,8 +4379,8 @@
         columnWidth = CSSPrimitiveValue::createIdentifier(CSSValueAuto);
     if (!columnCount)
         columnCount = CSSPrimitiveValue::createIdentifier(CSSValueAuto);
-    addProperty(CSSPropertyColumnWidth, CSSPropertyInvalid, columnWidth, important);
-    addProperty(CSSPropertyColumnCount, CSSPropertyInvalid, columnCount, important);
+    addProperty(CSSPropertyColumnWidth, CSSPropertyInvalid, *columnWidth, important);
+    addProperty(CSSPropertyColumnCount, CSSPropertyInvalid, *columnCount, important);
     return true;
 }
 
@@ -4404,9 +4404,9 @@
 
     for (size_t i = 0; i < shorthand.length(); ++i) {
         if (longhands[i])
-            addProperty(shorthandProperties[i], shorthand.id(), longhands[i], important);
+            addProperty(shorthandProperties[i], shorthand.id(), *longhands[i], important);
         else
-            addProperty(shorthandProperties[i], shorthand.id(), CSSInitialValue::createLegacyImplicit(), important);
+            addProperty(shorthandProperties[i], shorthand.id(), *CSSInitialValue::createLegacyImplicit(), important);
     }
     return true;
 }
@@ -4459,9 +4459,9 @@
 
     if (!m_range.atEnd())
         return false;
-    addProperty(CSSPropertyFlexGrow, CSSPropertyFlex, CSSPrimitiveValue::create(clampTo<float>(flexGrow), CSSPrimitiveValue::UnitType::Number), important);
-    addProperty(CSSPropertyFlexShrink, CSSPropertyFlex, CSSPrimitiveValue::create(clampTo<float>(flexShrink), CSSPrimitiveValue::UnitType::Number), important);
-    addProperty(CSSPropertyFlexBasis, CSSPropertyFlex, flexBasis, important);
+    addProperty(CSSPropertyFlexGrow, CSSPropertyFlex, *CSSPrimitiveValue::create(clampTo<float>(flexGrow), CSSPrimitiveValue::UnitType::Number), important);
+    addProperty(CSSPropertyFlexShrink, CSSPropertyFlex, *CSSPrimitiveValue::create(clampTo<float>(flexShrink), CSSPrimitiveValue::UnitType::Number), important);
+    addProperty(CSSPropertyFlexBasis, CSSPropertyFlex, *flexBasis, important);
     return true;
 }
 
@@ -4500,10 +4500,10 @@
     if (!color)
         color = CSSInitialValue::createLegacyImplicit();
 
-    addExpandedPropertyForValue(CSSPropertyBorderWidth, width, important);
-    addExpandedPropertyForValue(CSSPropertyBorderStyle, style, important);
-    addExpandedPropertyForValue(CSSPropertyBorderColor, color, important);
-    addExpandedPropertyForValue(CSSPropertyBorderImage, CSSInitialValue::createLegacyImplicit(), important);
+    addExpandedPropertyForValue(CSSPropertyBorderWidth, *width, important);
+    addExpandedPropertyForValue(CSSPropertyBorderStyle, *style, important);
+    addExpandedPropertyForValue(CSSPropertyBorderColor, *color, important);
+    addExpandedPropertyForValue(CSSPropertyBorderImage, *CSSInitialValue::createLegacyImplicit(), important);
 
     return m_range.atEnd();
 }
@@ -4532,10 +4532,10 @@
     if (!left)
         left = right;
 
-    addProperty(longhands[0], shorthand.id(), top, important);
-    addProperty(longhands[1], shorthand.id(), right, important);
-    addProperty(longhands[2], shorthand.id(), bottom, important);
-    addProperty(longhands[3], shorthand.id(), left, important);
+    addProperty(longhands[0], shorthand.id(), *top, important);
+    addProperty(longhands[1], shorthand.id(), *right, important);
+    addProperty(longhands[2], shorthand.id(), *bottom, important);
+    addProperty(longhands[3], shorthand.id(), *left, important);
 
     return m_range.atEnd();
 }
@@ -4550,18 +4550,18 @@
     if (consumeBorderImageComponents(property, m_range, m_context, source, slice, width, outset, repeat)) {
         switch (property) {
         case CSSPropertyWebkitMaskBoxImage:
-            addProperty(CSSPropertyWebkitMaskBoxImageSource, CSSPropertyWebkitMaskBoxImage, source ? source : CSSInitialValue::createLegacyImplicit(), important);
-            addProperty(CSSPropertyWebkitMaskBoxImageSlice, CSSPropertyWebkitMaskBoxImage, slice ? slice : CSSInitialValue::createLegacyImplicit(), important);
-            addProperty(CSSPropertyWebkitMaskBoxImageWidth, CSSPropertyWebkitMaskBoxImage, width ? width : CSSInitialValue::createLegacyImplicit(), important);
-            addProperty(CSSPropertyWebkitMaskBoxImageOutset, CSSPropertyWebkitMaskBoxImage, outset ? outset : CSSInitialValue::createLegacyImplicit(), important);
-            addProperty(CSSPropertyWebkitMaskBoxImageRepeat, CSSPropertyWebkitMaskBoxImage, repeat ? repeat : CSSInitialValue::createLegacyImplicit(), important);
+            addProperty(CSSPropertyWebkitMaskBoxImageSource, CSSPropertyWebkitMaskBoxImage, source ? *source : *CSSInitialValue::createLegacyImplicit(), important);
+            addProperty(CSSPropertyWebkitMaskBoxImageSlice, CSSPropertyWebkitMaskBoxImage, slice ? *slice : *CSSInitialValue::createLegacyImplicit(), important);
+            addProperty(CSSPropertyWebkitMaskBoxImageWidth, CSSPropertyWebkitMaskBoxImage, width ? *width : *CSSInitialValue::createLegacyImplicit(), important);
+            addProperty(CSSPropertyWebkitMaskBoxImageOutset, CSSPropertyWebkitMaskBoxImage, outset ? *outset : *CSSInitialValue::createLegacyImplicit(), important);
+            addProperty(CSSPropertyWebkitMaskBoxImageRepeat, CSSPropertyWebkitMaskBoxImage, repeat ? *repeat : *CSSInitialValue::createLegacyImplicit(), important);
             return true;
         case CSSPropertyBorderImage:
-            addProperty(CSSPropertyBorderImageSource, CSSPropertyBorderImage, source ? source : CSSInitialValue::createLegacyImplicit(), important);
-            addProperty(CSSPropertyBorderImageSlice, CSSPropertyBorderImage, slice ? slice : CSSInitialValue::createLegacyImplicit(), important);
-            addProperty(CSSPropertyBorderImageWidth, CSSPropertyBorderImage, width ? width : CSSInitialValue::createLegacyImplicit(), important);
-            addProperty(CSSPropertyBorderImageOutset, CSSPropertyBorderImage, outset ? outset : CSSInitialValue::createLegacyImplicit(), important);
-            addProperty(CSSPropertyBorderImageRepeat, CSSPropertyBorderImage, repeat ? repeat : CSSInitialValue::createLegacyImplicit(), important);
+            addProperty(CSSPropertyBorderImageSource, CSSPropertyBorderImage, source ? *source : *CSSInitialValue::createLegacyImplicit(), important);
+            addProperty(CSSPropertyBorderImageSlice, CSSPropertyBorderImage, slice ? *slice : *CSSInitialValue::createLegacyImplicit(), important);
+            addProperty(CSSPropertyBorderImageWidth, CSSPropertyBorderImage, width ? *width : *CSSInitialValue::createLegacyImplicit(), important);
+            addProperty(CSSPropertyBorderImageOutset, CSSPropertyBorderImage, outset ? *outset : *CSSInitialValue::createLegacyImplicit(), important);
+            addProperty(CSSPropertyBorderImageRepeat, CSSPropertyBorderImage, repeat ? *repeat : *CSSInitialValue::createLegacyImplicit(), important);
             return true;
         default:
             ASSERT_NOT_REACHED();
@@ -4637,7 +4637,7 @@
         return false;
 
     CSSPropertyID genericBreakProperty = mapFromLegacyBreakProperty(property);
-    addProperty(genericBreakProperty, property, CSSPrimitiveValue::createIdentifier(value), important);
+    addProperty(genericBreakProperty, property, *CSSPrimitiveValue::createIdentifier(value), important);
     return true;
 }
 
@@ -4772,7 +4772,7 @@
         CSSPropertyID property = shorthand.properties()[i];
         if (property == CSSPropertyBackgroundSize && longhands[i] && m_context.useLegacyBackgroundSizeShorthandBehavior())
             continue;
-        addProperty(property, shorthand.id(), longhands[i], important, implicit);
+        addProperty(property, shorthand.id(), *longhands[i], important, implicit);
     }
     return true;
 }
@@ -4796,8 +4796,8 @@
     }
     if (!m_range.atEnd())
         return false;
-    addProperty(shorthand.properties()[0], shorthandId, startValue, important);
-    addProperty(shorthand.properties()[1], shorthandId, endValue, important);
+    addProperty(shorthand.properties()[0], shorthandId, *startValue, important);
+    addProperty(shorthand.properties()[1], shorthandId, *endValue, important);
     return true;
 }
 
@@ -4835,10 +4835,10 @@
     if (!columnEndValue)
         columnEndValue = columnStartValue->isCustomIdentValue() ? columnStartValue : CSSPrimitiveValue::createIdentifier(CSSValueAuto);
 
-    addProperty(CSSPropertyGridRowStart, CSSPropertyGridArea, rowStartValue, important);
-    addProperty(CSSPropertyGridColumnStart, CSSPropertyGridArea, columnStartValue, important);
-    addProperty(CSSPropertyGridRowEnd, CSSPropertyGridArea, rowEndValue, important);
-    addProperty(CSSPropertyGridColumnEnd, CSSPropertyGridArea, columnEndValue, important);
+    addProperty(CSSPropertyGridRowStart, CSSPropertyGridArea, *rowStartValue, important);
+    addProperty(CSSPropertyGridColumnStart, CSSPropertyGridArea, *columnStartValue, important);
+    addProperty(CSSPropertyGridRowEnd, CSSPropertyGridArea, *rowEndValue, important);
+    addProperty(CSSPropertyGridColumnEnd, CSSPropertyGridArea, *columnEndValue, important);
     return true;
 }
 
@@ -4887,9 +4887,9 @@
     } else {
         columnsValue = CSSPrimitiveValue::createIdentifier(CSSValueNone);
     }
-    addProperty(CSSPropertyGridTemplateRows, shorthandId, templateRows, important);
-    addProperty(CSSPropertyGridTemplateColumns, shorthandId, columnsValue, important);
-    addProperty(CSSPropertyGridTemplateAreas, shorthandId, CSSGridTemplateAreasValue::create(gridAreaMap, rowCount, columnCount), important);
+    addProperty(CSSPropertyGridTemplateRows, shorthandId, *templateRows, important);
+    addProperty(CSSPropertyGridTemplateColumns, shorthandId, *columnsValue, important);
+    addProperty(CSSPropertyGridTemplateAreas, shorthandId, *CSSGridTemplateAreasValue::create(gridAreaMap, rowCount, columnCount), important);
     return true;
 }
 
@@ -4903,9 +4903,9 @@
 
     // 1- 'none' case.
     if (rowsValue && m_range.atEnd()) {
-        addProperty(CSSPropertyGridTemplateRows, shorthandId, CSSPrimitiveValue::createIdentifier(CSSValueNone), important);
-        addProperty(CSSPropertyGridTemplateColumns, shorthandId, CSSPrimitiveValue::createIdentifier(CSSValueNone), important);
-        addProperty(CSSPropertyGridTemplateAreas, shorthandId, CSSPrimitiveValue::createIdentifier(CSSValueNone), important);
+        addProperty(CSSPropertyGridTemplateRows, shorthandId, *CSSPrimitiveValue::createIdentifier(CSSValueNone), important);
+        addProperty(CSSPropertyGridTemplateColumns, shorthandId, *CSSPrimitiveValue::createIdentifier(CSSValueNone), important);
+        addProperty(CSSPropertyGridTemplateAreas, shorthandId, *CSSPrimitiveValue::createIdentifier(CSSValueNone), important);
         return true;
     }
 
@@ -4920,9 +4920,9 @@
         if (!columnsValue || !m_range.atEnd())
             return false;
 
-        addProperty(CSSPropertyGridTemplateRows, shorthandId, rowsValue, important);
-        addProperty(CSSPropertyGridTemplateColumns, shorthandId, columnsValue, important);
-        addProperty(CSSPropertyGridTemplateAreas, shorthandId, CSSPrimitiveValue::createIdentifier(CSSValueNone), important);
+        addProperty(CSSPropertyGridTemplateRows, shorthandId, *rowsValue, important);
+        addProperty(CSSPropertyGridTemplateColumns, shorthandId, *columnsValue, important);
+        addProperty(CSSPropertyGridTemplateAreas, shorthandId, *CSSPrimitiveValue::createIdentifier(CSSValueNone), important);
         return true;
     }
 
@@ -4942,11 +4942,11 @@
     if (consumeGridTemplateShorthand(CSSPropertyGrid, important)) {
         // It can only be specified the explicit or the implicit grid properties in a single grid declaration.
         // The sub-properties not specified are set to their initial value, as normal for shorthands.
-        addProperty(CSSPropertyGridAutoFlow, CSSPropertyGrid, CSSInitialValue::createLegacyImplicit(), important);
-        addProperty(CSSPropertyGridAutoColumns, CSSPropertyGrid, CSSInitialValue::createLegacyImplicit(), important);
-        addProperty(CSSPropertyGridAutoRows, CSSPropertyGrid, CSSInitialValue::createLegacyImplicit(), important);
-        addProperty(CSSPropertyGridColumnGap, CSSPropertyGrid, CSSInitialValue::createLegacyImplicit(), important);
-        addProperty(CSSPropertyGridRowGap, CSSPropertyGrid, CSSInitialValue::createLegacyImplicit(), important);
+        addProperty(CSSPropertyGridAutoFlow, CSSPropertyGrid, *CSSInitialValue::createLegacyImplicit(), important);
+        addProperty(CSSPropertyGridAutoColumns, CSSPropertyGrid, *CSSInitialValue::createLegacyImplicit(), important);
+        addProperty(CSSPropertyGridAutoRows, CSSPropertyGrid, *CSSInitialValue::createLegacyImplicit(), important);
+        addProperty(CSSPropertyGridColumnGap, CSSPropertyGrid, *CSSInitialValue::createLegacyImplicit(), important);
+        addProperty(CSSPropertyGridRowGap, CSSPropertyGrid, *CSSInitialValue::createLegacyImplicit(), important);
         return true;
     }
 
@@ -4983,14 +4983,14 @@
 
     // It can only be specified the explicit or the implicit grid properties in a single grid declaration.
     // The sub-properties not specified are set to their initial value, as normal for shorthands.
-    addProperty(CSSPropertyGridTemplateColumns, CSSPropertyGrid, CSSInitialValue::createLegacyImplicit(), important);
-    addProperty(CSSPropertyGridTemplateRows, CSSPropertyGrid, CSSInitialValue::createLegacyImplicit(), important);
-    addProperty(CSSPropertyGridTemplateAreas, CSSPropertyGrid, CSSInitialValue::createLegacyImplicit(), important);
-    addProperty(CSSPropertyGridAutoFlow, CSSPropertyGrid, gridAutoFlow, important);
-    addProperty(CSSPropertyGridAutoColumns, CSSPropertyGrid, autoColumnsValue, important);
-    addProperty(CSSPropertyGridAutoRows, CSSPropertyGrid, autoRowsValue, important);
-    addProperty(CSSPropertyGridColumnGap, CSSPropertyGrid, CSSInitialValue::createLegacyImplicit(), important);
-    addProperty(CSSPropertyGridRowGap, CSSPropertyGrid, CSSInitialValue::createLegacyImplicit(), important);
+    addProperty(CSSPropertyGridTemplateColumns, CSSPropertyGrid, *CSSInitialValue::createLegacyImplicit(), important);
+    addProperty(CSSPropertyGridTemplateRows, CSSPropertyGrid, *CSSInitialValue::createLegacyImplicit(), important);
+    addProperty(CSSPropertyGridTemplateAreas, CSSPropertyGrid, *CSSInitialValue::createLegacyImplicit(), important);
+    addProperty(CSSPropertyGridAutoFlow, CSSPropertyGrid, *gridAutoFlow, important);
+    addProperty(CSSPropertyGridAutoColumns, CSSPropertyGrid, *autoColumnsValue, important);
+    addProperty(CSSPropertyGridAutoRows, CSSPropertyGrid, *autoRowsValue, important);
+    addProperty(CSSPropertyGridColumnGap, CSSPropertyGrid, *CSSInitialValue::createLegacyImplicit(), important);
+    addProperty(CSSPropertyGridRowGap, CSSPropertyGrid, *CSSInitialValue::createLegacyImplicit(), important);
     return true;
 }
 
@@ -5004,15 +5004,15 @@
         if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(CSSPropertyWebkitMarginBeforeCollapse, id, m_context.mode()))
             return false;
         CSSValue* beforeCollapse = CSSPrimitiveValue::createIdentifier(id);
-        addProperty(CSSPropertyWebkitMarginBeforeCollapse, CSSPropertyWebkitMarginCollapse, beforeCollapse, important);
+        addProperty(CSSPropertyWebkitMarginBeforeCollapse, CSSPropertyWebkitMarginCollapse, *beforeCollapse, important);
         if (m_range.atEnd()) {
-            addProperty(CSSPropertyWebkitMarginAfterCollapse, CSSPropertyWebkitMarginCollapse, beforeCollapse, important);
+            addProperty(CSSPropertyWebkitMarginAfterCollapse, CSSPropertyWebkitMarginCollapse, *beforeCollapse, important);
             return true;
         }
         id = m_range.consumeIncludingWhitespace().id();
         if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(CSSPropertyWebkitMarginAfterCollapse, id, m_context.mode()))
             return false;
-        addProperty(CSSPropertyWebkitMarginAfterCollapse, CSSPropertyWebkitMarginCollapse, CSSPrimitiveValue::createIdentifier(id), important);
+        addProperty(CSSPropertyWebkitMarginAfterCollapse, CSSPropertyWebkitMarginCollapse, *CSSPrimitiveValue::createIdentifier(id), important);
         return true;
     }
     case CSSPropertyOverflow: {
@@ -5033,8 +5033,8 @@
             overflowXValue = CSSPrimitiveValue::createIdentifier(CSSValueAuto);
         else
             overflowXValue = overflowYValue;
-        addProperty(CSSPropertyOverflowX, CSSPropertyOverflow, overflowXValue, important);
-        addProperty(CSSPropertyOverflowY, CSSPropertyOverflow, overflowYValue, important);
+        addProperty(CSSPropertyOverflowX, CSSPropertyOverflow, *overflowXValue, important);
+        addProperty(CSSPropertyOverflowY, CSSPropertyOverflow, *overflowYValue, important);
         return true;
     }
     case CSSPropertyFont: {
@@ -5080,9 +5080,9 @@
         CSSValue* marker = parseSingleValue(CSSPropertyMarkerStart);
         if (!marker || !m_range.atEnd())
             return false;
-        addProperty(CSSPropertyMarkerStart, CSSPropertyMarker, marker, important);
-        addProperty(CSSPropertyMarkerMid, CSSPropertyMarker, marker, important);
-        addProperty(CSSPropertyMarkerEnd, CSSPropertyMarker, marker, important);
+        addProperty(CSSPropertyMarkerStart, CSSPropertyMarker, *marker, important);
+        addProperty(CSSPropertyMarkerMid, CSSPropertyMarker, *marker, important);
+        addProperty(CSSPropertyMarkerEnd, CSSPropertyMarker, *marker, important);
         return true;
     }
     case CSSPropertyFlex:
@@ -5098,10 +5098,10 @@
         CSSPrimitiveValue* verticalRadii[4] = { 0 };
         if (!consumeRadii(horizontalRadii, verticalRadii, m_range, m_context.mode(), unresolvedProperty == CSSPropertyAliasWebkitBorderRadius))
             return false;
-        addProperty(CSSPropertyBorderTopLeftRadius, CSSPropertyBorderRadius, CSSValuePair::create(horizontalRadii[0], verticalRadii[0], CSSValuePair::DropIdenticalValues), important);
-        addProperty(CSSPropertyBorderTopRightRadius, CSSPropertyBorderRadius, CSSValuePair::create(horizontalRadii[1], verticalRadii[1], CSSValuePair::DropIdenticalValues), important);
-        addProperty(CSSPropertyBorderBottomRightRadius, CSSPropertyBorderRadius, CSSValuePair::create(horizontalRadii[2], verticalRadii[2], CSSValuePair::DropIdenticalValues), important);
-        addProperty(CSSPropertyBorderBottomLeftRadius, CSSPropertyBorderRadius, CSSValuePair::create(horizontalRadii[3], verticalRadii[3], CSSValuePair::DropIdenticalValues), important);
+        addProperty(CSSPropertyBorderTopLeftRadius, CSSPropertyBorderRadius, *CSSValuePair::create(horizontalRadii[0], verticalRadii[0], CSSValuePair::DropIdenticalValues), important);
+        addProperty(CSSPropertyBorderTopRightRadius, CSSPropertyBorderRadius, *CSSValuePair::create(horizontalRadii[1], verticalRadii[1], CSSValuePair::DropIdenticalValues), important);
+        addProperty(CSSPropertyBorderBottomRightRadius, CSSPropertyBorderRadius, *CSSValuePair::create(horizontalRadii[2], verticalRadii[2], CSSValuePair::DropIdenticalValues), important);
+        addProperty(CSSPropertyBorderBottomLeftRadius, CSSPropertyBorderRadius, *CSSValuePair::create(horizontalRadii[3], verticalRadii[3], CSSValuePair::DropIdenticalValues), important);
         return true;
     }
     case CSSPropertyBorderColor:
@@ -5136,8 +5136,8 @@
         CSSValue* resultY = nullptr;
         if (!consumeBackgroundPosition(m_range, m_context, UnitlessQuirk::Allow, resultX, resultY) || !m_range.atEnd())
             return false;
-        addProperty(property == CSSPropertyBackgroundPosition ? CSSPropertyBackgroundPositionX : CSSPropertyWebkitMaskPositionX, property, resultX, important);
-        addProperty(property == CSSPropertyBackgroundPosition ? CSSPropertyBackgroundPositionY : CSSPropertyWebkitMaskPositionY, property, resultY, important);
+        addProperty(property == CSSPropertyBackgroundPosition ? CSSPropertyBackgroundPositionX : CSSPropertyWebkitMaskPositionX, property, *resultX, important);
+        addProperty(property == CSSPropertyBackgroundPosition ? CSSPropertyBackgroundPositionY : CSSPropertyWebkitMaskPositionY, property, *resultY, important);
         return true;
     }
     case CSSPropertyBackgroundRepeat:
@@ -5147,8 +5147,8 @@
         bool implicit = false;
         if (!consumeRepeatStyle(m_range, resultX, resultY, implicit) || !m_range.atEnd())
             return false;
-        addProperty(property == CSSPropertyBackgroundRepeat ? CSSPropertyBackgroundRepeatX : CSSPropertyWebkitMaskRepeatX, property, resultX, important, implicit);
-        addProperty(property == CSSPropertyBackgroundRepeat ? CSSPropertyBackgroundRepeatY : CSSPropertyWebkitMaskRepeatY, property, resultY, important, implicit);
+        addProperty(property == CSSPropertyBackgroundRepeat ? CSSPropertyBackgroundRepeatX : CSSPropertyWebkitMaskRepeatX, property, *resultX, important, implicit);
+        addProperty(property == CSSPropertyBackgroundRepeat ? CSSPropertyBackgroundRepeatY : CSSPropertyWebkitMaskRepeatY, property, *resultY, important, implicit);
         return true;
     }
     case CSSPropertyBackground:
@@ -5163,8 +5163,8 @@
             return false;
         if (!columnGap)
             columnGap = rowGap;
-        addProperty(CSSPropertyGridRowGap, CSSPropertyGridGap, rowGap, important);
-        addProperty(CSSPropertyGridColumnGap, CSSPropertyGridGap, columnGap, important);
+        addProperty(CSSPropertyGridRowGap, CSSPropertyGridGap, *rowGap, important);
+        addProperty(CSSPropertyGridColumnGap, CSSPropertyGridGap, *columnGap, important);
         return true;
     }
     case CSSPropertyGridColumn:
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h
index f2d605ac..ecd2bcb 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h
+++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h
@@ -61,8 +61,8 @@
     bool parseViewportDescriptor(CSSPropertyID propId, bool important);
     bool parseFontFaceDescriptor(CSSPropertyID);
 
-    void addProperty(CSSPropertyID, CSSPropertyID, CSSValue*, bool important, bool implicit = false);
-    void addExpandedPropertyForValue(CSSPropertyID propId, CSSValue*, bool);
+    void addProperty(CSSPropertyID, CSSPropertyID, const CSSValue&, bool important, bool implicit = false);
+    void addExpandedPropertyForValue(CSSPropertyID propId, const CSSValue&, bool);
 
     bool consumeBorder(bool important);
 
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp
index 02cf58a..8ed3874 100644
--- a/third_party/WebKit/Source/core/dom/Document.cpp
+++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -100,6 +100,7 @@
 #include "core/dom/StaticNodeList.h"
 #include "core/dom/StyleChangeReason.h"
 #include "core/dom/StyleEngine.h"
+#include "core/dom/TaskRunnerHelper.h"
 #include "core/dom/TouchList.h"
 #include "core/dom/TransformSource.h"
 #include "core/dom/TreeWalker.h"
@@ -361,7 +362,7 @@
 {
     DCHECK(element.hasEditableStyle());
 
-    return element.document().frame() && element.rootEditableElement();
+    return element.document().frame() && rootEditableElement(element);
 }
 
 uint64_t Document::s_globalTreeVersion = 0;
@@ -445,7 +446,7 @@
     , m_compositorPendingAnimations(new CompositorPendingAnimations())
     , m_templateDocumentHost(nullptr)
     , m_didAssociateFormControlsTimer(this, &Document::didAssociateFormControlsTimerFired)
-    , m_timers(timerTaskRunner()->adoptClone())
+    , m_timers(TaskRunnerHelper::getTimerTaskRunner(this)->adoptClone())
     , m_hasViewportUnits(false)
     , m_parserSyncPolicy(AllowAsynchronousParsing)
     , m_nodeCount(0)
@@ -602,11 +603,6 @@
     return m_rootScrollerController->get();
 }
 
-const Element* Document::effectiveRootScroller() const
-{
-    return m_rootScrollerController->effectiveRootScroller();
-}
-
 bool Document::isViewportScrollCallback(const ScrollStateCallback* callback)
 {
     if (!callback)
@@ -2144,8 +2140,6 @@
     ScriptForbiddenScope forbidScript;
     view()->dispose();
     m_markers->prepareForDestruction();
-    if (LocalDOMWindow* window = this->domWindow())
-        window->willDetachDocumentFromFrame();
 
     m_lifecycle.advanceTo(DocumentLifecycle::Stopping);
 
@@ -3026,7 +3020,7 @@
 
 void Document::didLoadAllScriptBlockingResources()
 {
-    loadingTaskRunner()->postTask(BLINK_FROM_HERE, m_executeScriptsWaitingForResourcesTask->cancelAndCreate());
+    TaskRunnerHelper::getLoadingTaskRunner(this)->postTask(BLINK_FROM_HERE, m_executeScriptsWaitingForResourcesTask->cancelAndCreate());
 
     if (isHTMLDocument() && body()) {
         // For HTML if we have no more stylesheets to load and we're past the body
@@ -3565,7 +3559,7 @@
     if (newFocusedElement)
         updateStyleAndLayoutTreeForNode(newFocusedElement);
     if (newFocusedElement && newFocusedElement->isFocusable()) {
-        if (newFocusedElement->isRootEditableElement() && !acceptsEditingFocus(*newFocusedElement)) {
+        if (isRootEditableElement(*newFocusedElement) && !acceptsEditingFocus(*newFocusedElement)) {
             // delegate blocks focus change
             focusChangeBlocked = true;
             goto SetFocusedElementDone;
@@ -3613,7 +3607,7 @@
             }
         }
 
-        if (m_focusedElement->isRootEditableElement())
+        if (isRootEditableElement(*m_focusedElement))
             frame()->spellChecker().didBeginEditing(m_focusedElement.get());
 
         // eww, I suck. set the qt focus correctly
@@ -4170,10 +4164,15 @@
 
 const KURL Document::firstPartyForCookies() const
 {
+    // TODO(mkwst): This doesn't properly handle HTML Import documents.
+
     // If this is an imported document, grab its master document's first-party:
     if (importsController() && importsController()->master() && importsController()->master() != this)
         return importsController()->master()->firstPartyForCookies();
 
+    if (!frame())
+        return SecurityOrigin::urlWithUniqueSecurityOrigin();
+
     // TODO(mkwst): This doesn't correctly handle sandboxed documents; we want to look at their URL,
     // but we can't because we don't know what it is.
     Frame* top = frame()->tree().top();
@@ -5876,39 +5875,6 @@
     return isSecureContextImpl(privilegeContextCheck);
 }
 
-WebTaskRunner* Document::loadingTaskRunner() const
-{
-    if (frame())
-        return frame()->frameScheduler()->loadingTaskRunner();
-    if (m_importsController)
-        return m_importsController->master()->loadingTaskRunner();
-    if (m_contextDocument)
-        return m_contextDocument->loadingTaskRunner();
-    return Platform::current()->currentThread()->scheduler()->loadingTaskRunner();
-}
-
-WebTaskRunner* Document::timerTaskRunner() const
-{
-    if (frame())
-        return m_frame->frameScheduler()->timerTaskRunner();
-    if (m_importsController)
-        return m_importsController->master()->timerTaskRunner();
-    if (m_contextDocument)
-        return m_contextDocument->timerTaskRunner();
-    return Platform::current()->currentThread()->scheduler()->timerTaskRunner();
-}
-
-WebTaskRunner* Document::unthrottledTaskRunner() const
-{
-    if (frame())
-        return m_frame->frameScheduler()->unthrottledTaskRunner();
-    if (m_importsController)
-        return m_importsController->master()->unthrottledTaskRunner();
-    if (m_contextDocument)
-        return m_contextDocument->unthrottledTaskRunner();
-    return Platform::current()->currentThread()->getWebTaskRunner();
-}
-
 void Document::enforceInsecureRequestPolicy(WebInsecureRequestPolicy policy)
 {
     // Combine the new policy with the existing policy, as a base policy may be
diff --git a/third_party/WebKit/Source/core/dom/Document.h b/third_party/WebKit/Source/core/dom/Document.h
index 27a0cd1..fdfa383 100644
--- a/third_party/WebKit/Source/core/dom/Document.h
+++ b/third_party/WebKit/Source/core/dom/Document.h
@@ -1072,10 +1072,6 @@
 
     SnapCoordinator* snapCoordinator();
 
-    WebTaskRunner* loadingTaskRunner() const;
-    WebTaskRunner* timerTaskRunner() const;
-    WebTaskRunner* unthrottledTaskRunner() const;
-
     void enforceInsecureRequestPolicy(WebInsecureRequestPolicy);
 
     bool mayContainV0Shadow() const { return m_mayContainV0Shadow; }
@@ -1088,7 +1084,7 @@
     void initializeRootScroller(ViewportScrollCallback*);
     Element* rootScroller() const;
     void setRootScroller(Element*, ExceptionState&);
-    const Element* effectiveRootScroller() const;
+    RootScrollerController* rootScrollerController() const { return m_rootScrollerController.get(); }
 
     // TODO(bokan): Temporarily added to allow ScrollCustomization to properly
     // opt out for wheel scrolls. crbug.com/623079.
diff --git a/third_party/WebKit/Source/core/dom/DocumentParserTiming.cpp b/third_party/WebKit/Source/core/dom/DocumentParserTiming.cpp
index 795a22aa..2909028 100644
--- a/third_party/WebKit/Source/core/dom/DocumentParserTiming.cpp
+++ b/third_party/WebKit/Source/core/dom/DocumentParserTiming.cpp
@@ -59,6 +59,7 @@
 DEFINE_TRACE(DocumentParserTiming)
 {
     visitor->trace(m_document);
+    Supplement<Document>::trace(visitor);
 }
 
 DocumentParserTiming::DocumentParserTiming(Document& document)
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp
index 67e29c95..1a0e024 100644
--- a/third_party/WebKit/Source/core/dom/Element.cpp
+++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -121,6 +121,7 @@
 #include "core/page/Page.h"
 #include "core/page/PointerLockController.h"
 #include "core/page/SpatialNavigation.h"
+#include "core/page/scrolling/RootScrollerController.h"
 #include "core/page/scrolling/ScrollCustomizationCallbacks.h"
 #include "core/page/scrolling/ScrollState.h"
 #include "core/page/scrolling/ScrollStateCallback.h"
@@ -565,7 +566,7 @@
 
     // We should only ever scroll the effective root scroller this way when the
     // page removes the default applyScroll (ViewportScrollCallback).
-    if (document().effectiveRootScroller() == this)
+    if (document().rootScrollerController()->effectiveRootScroller() == this)
         boxToScroll = document().layoutView();
     else if (layoutObject())
         boxToScroll = toLayoutBox(layoutObject());
@@ -598,6 +599,10 @@
 
 void Element::callApplyScroll(ScrollState& scrollState)
 {
+    // Hits ASSERTs when trying to determine whether we need to scroll on main
+    // or CC. http://crbug.com/625676.
+    DisableCompositingQueryAsserts disabler;
+
     ScrollStateCallback* callback = scrollCustomizationCallbacks().getApplyScroll(this);
 
     // TODO(bokan): Need to add tests before we allow calling custom callbacks
@@ -2425,7 +2430,7 @@
 {
     if (selectionBehavior == SelectionBehaviorOnFocus::None)
         return;
-    if (isRootEditableElement()) {
+    if (isRootEditableElement(*this)) {
         LocalFrame* frame = document().frame();
         if (!frame)
             return;
@@ -2465,7 +2470,7 @@
     // it won't be focusable. Furthermore, supportsFocus cannot just return true
     // always or else tabIndex() will change for all HTML elements.
     return hasElementFlag(TabIndexWasSetExplicitly)
-        || isRootEditableElement()
+        || isRootEditableElement(*this)
         || (isShadowHost(this) && authorShadowRoot() && authorShadowRoot()->delegatesFocus())
         || supportsSpatialNavigationFocus();
 }
diff --git a/third_party/WebKit/Source/core/dom/Fullscreen.cpp b/third_party/WebKit/Source/core/dom/Fullscreen.cpp
index 030f37b..ca15b5bc 100644
--- a/third_party/WebKit/Source/core/dom/Fullscreen.cpp
+++ b/third_party/WebKit/Source/core/dom/Fullscreen.cpp
@@ -483,7 +483,7 @@
     return fullscreenIsAllowedForAllOwners(document) && fullscreenIsSupported(document);
 }
 
-void Fullscreen::didEnterFullScreenForElement(Element* element)
+void Fullscreen::didEnterFullscreenForElement(Element* element)
 {
     DCHECK(element);
     if (!document()->isActive())
@@ -533,7 +533,7 @@
     m_eventQueueTimer.startOneShot(0, BLINK_FROM_HERE);
 }
 
-void Fullscreen::didExitFullScreenForElement()
+void Fullscreen::didExitFullscreen()
 {
     if (!m_fullScreenElement)
         return;
@@ -610,7 +610,7 @@
         event = createEvent(EventTypeNames::webkitfullscreenchange, *target);
     }
     m_eventQueue.append(event);
-    // NOTE: The timer is started in didEnterFullScreenForElement/didExitFullScreenForElement.
+    // NOTE: The timer is started in didEnterFullscreenForElement/didExitFullscreen.
 }
 
 void Fullscreen::enqueueErrorEvent(Element& element, RequestType requestType)
diff --git a/third_party/WebKit/Source/core/dom/Fullscreen.h b/third_party/WebKit/Source/core/dom/Fullscreen.h
index a624c20..566e697 100644
--- a/third_party/WebKit/Source/core/dom/Fullscreen.h
+++ b/third_party/WebKit/Source/core/dom/Fullscreen.h
@@ -83,8 +83,8 @@
     // for its (local) iframe container and make sure to also set the
     // ContainsFullScreenElement flag on it (so that it gains the
     // -webkit-full-screen-ancestor style).
-    void didEnterFullScreenForElement(Element*);
-    void didExitFullScreenForElement();
+    void didEnterFullscreenForElement(Element*);
+    void didExitFullscreen();
 
     void setFullScreenLayoutObject(LayoutFullScreen*);
     LayoutFullScreen* fullScreenLayoutObject() const { return m_fullScreenLayoutObject; }
diff --git a/third_party/WebKit/Source/core/dom/Node.cpp b/third_party/WebKit/Source/core/dom/Node.cpp
index 84a8cea6..d830fe9 100644
--- a/third_party/WebKit/Source/core/dom/Node.cpp
+++ b/third_party/WebKit/Source/core/dom/Node.cpp
@@ -1107,29 +1107,32 @@
     return parentOrShadowHostNode();
 }
 
-bool Node::isRootEditableElement() const
+// TODO(yoichio): Move to core/editing
+bool isRootEditableElement(const Node& node)
 {
-    return hasEditableStyle() && isElementNode() && (!parentNode() || !parentNode()->hasEditableStyle()
-        || !parentNode()->isElementNode() || this == document().body());
+    return node.hasEditableStyle() && node.isElementNode() && (!node.parentNode() || !node.parentNode()->hasEditableStyle()
+        || !node.parentNode()->isElementNode() || &node == node.document().body());
 }
 
-Element* Node::rootEditableElement(EditableType editableType) const
+// TODO(yoichio): Move to core/editing
+Element* rootEditableElement(const Node& node, EditableType editableType)
 {
     if (editableType == HasEditableAXRole) {
-        if (AXObjectCache* cache = document().existingAXObjectCache())
-            return const_cast<Element*>(cache->rootAXEditableElement(this));
+        if (AXObjectCache* cache = node.document().existingAXObjectCache())
+            return const_cast<Element*>(cache->rootAXEditableElement(&node));
     }
 
-    return rootEditableElement();
+    return rootEditableElement(node);
 }
 
-Element* Node::rootEditableElement() const
+// TODO(yoichio): Move to core/editing
+Element* rootEditableElement(const Node& node)
 {
     const Node* result = nullptr;
-    for (const Node* n = this; n && n->hasEditableStyle(); n = n->parentNode()) {
+    for (const Node* n = &node; n && n->hasEditableStyle(); n = n->parentNode()) {
         if (n->isElementNode())
             result = n;
-        if (document().body() == n)
+        if (node.document().body() == n)
             break;
     }
     return toElement(const_cast<Node*>(result));
diff --git a/third_party/WebKit/Source/core/dom/Node.h b/third_party/WebKit/Source/core/dom/Node.h
index ad8cbb4..a3f8ef6 100644
--- a/third_party/WebKit/Source/core/dom/Node.h
+++ b/third_party/WebKit/Source/core/dom/Node.h
@@ -335,10 +335,6 @@
 
     virtual bool canContainRangeEndPoint() const { return false; }
 
-    bool isRootEditableElement() const;
-    Element* rootEditableElement() const;
-    Element* rootEditableElement(EditableType) const;
-
     // For <link> and <style> elements.
     virtual bool sheetLoaded() { return true; }
     enum LoadedSheetErrorStatus {
@@ -894,6 +890,11 @@
     return node;
 }
 
+// TODO(yoichio): Move to core/editing
+CORE_EXPORT bool isRootEditableElement(const Node&);
+CORE_EXPORT Element* rootEditableElement(const Node&);
+CORE_EXPORT Element* rootEditableElement(const Node&, EditableType);
+
 // Allow equality comparisons of Nodes by reference or pointer, interchangeably.
 DEFINE_COMPARISON_OPERATORS_WITH_REFERENCES_REFCOUNTED(Node)
 
diff --git a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
index a8337a8d..deada62 100644
--- a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
+++ b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
@@ -132,21 +132,20 @@
 
     // FIXME: This function is not HTML5 compliant. These belong in the MIME registry as "text/javascript<version>" entries.
     typedef HashSet<String, CaseFoldingHash> LanguageSet;
-    DEFINE_STATIC_LOCAL(LanguageSet, languages, ());
-    if (languages.isEmpty()) {
-        languages.add("javascript");
-        languages.add("javascript1.0");
-        languages.add("javascript1.1");
-        languages.add("javascript1.2");
-        languages.add("javascript1.3");
-        languages.add("javascript1.4");
-        languages.add("javascript1.5");
-        languages.add("javascript1.6");
-        languages.add("javascript1.7");
-        languages.add("livescript");
-        languages.add("ecmascript");
-        languages.add("jscript");
-    }
+    DEFINE_STATIC_LOCAL(LanguageSet, languages, ({
+        "javascript",
+        "javascript1.0",
+        "javascript1.1",
+        "javascript1.2",
+        "javascript1.3",
+        "javascript1.4",
+        "javascript1.5",
+        "javascript1.6",
+        "javascript1.7",
+        "livescript",
+        "ecmascript",
+        "jscript",
+    }));
 
     return languages.contains(language);
 }
diff --git a/third_party/WebKit/Source/core/dom/SelectorQuery.cpp b/third_party/WebKit/Source/core/dom/SelectorQuery.cpp
index 212d353..c739f889 100644
--- a/third_party/WebKit/Source/core/dom/SelectorQuery.cpp
+++ b/third_party/WebKit/Source/core/dom/SelectorQuery.cpp
@@ -27,6 +27,7 @@
 #include "core/dom/SelectorQuery.h"
 
 #include "bindings/core/v8/ExceptionState.h"
+#include "core/HTMLNames.h"
 #include "core/css/SelectorChecker.h"
 #include "core/css/parser/CSSParser.h"
 #include "core/dom/Document.h"
@@ -41,6 +42,8 @@
 
 namespace blink {
 
+using namespace HTMLNames;
+
 struct SingleElementSelectorQueryTrait {
     typedef Element* OutputType;
     static const bool shouldOnlyMatchFirstElement = true;
@@ -444,11 +447,17 @@
     }
 }
 
-const CSSSelector* SelectorDataList::selectorForIdLookup(const CSSSelector& firstSelector) const
+static const CSSSelector* selectorForIdLookup(const CSSSelector& firstSelector)
 {
     for (const CSSSelector* selector = &firstSelector; selector; selector = selector->tagHistory()) {
         if (selector->match() == CSSSelector::Id)
             return selector;
+        // We only use the fast path when in standards mode where #id selectors
+        // are case sensitive, so we need the same behavior for [id=value].
+        if (selector->match() == CSSSelector::AttributeExact
+            && selector->attribute() == idAttr
+            && selector->attributeMatch() == CSSSelector::CaseSensitive)
+            return selector;
         if (selector->relation() != CSSSelector::SubSelector)
             break;
     }
@@ -473,11 +482,12 @@
     }
 
     DCHECK_EQ(m_selectors.size(), 1u);
+    DCHECK(!rootNode.document().inQuirksMode());
 
     const CSSSelector& selector = *m_selectors[0];
     const CSSSelector& firstSelector = selector;
 
-    // Fast path for querySelector*('#id'), querySelector*('tag#id').
+    // Fast path for querySelector*('#id'), querySelector*('tag#id'), querySelector*('tag[id=example]').
     if (const CSSSelector* idSelector = selectorForIdLookup(firstSelector)) {
         const AtomicString& idToMatch = idSelector->value();
         if (rootNode.treeScope().containsMultipleElementsWithId(idToMatch)) {
diff --git a/third_party/WebKit/Source/core/dom/SelectorQuery.h b/third_party/WebKit/Source/core/dom/SelectorQuery.h
index 2dc05bf4..b5ceaa3f 100644
--- a/third_party/WebKit/Source/core/dom/SelectorQuery.h
+++ b/third_party/WebKit/Source/core/dom/SelectorQuery.h
@@ -79,7 +79,6 @@
     void executeSlowTraversingShadowTree(ContainerNode& rootNode, typename SelectorQueryTrait::OutputType&) const;
     template <typename SelectorQueryTrait>
     void execute(ContainerNode& rootNode, typename SelectorQueryTrait::OutputType&) const;
-    const CSSSelector* selectorForIdLookup(const CSSSelector&) const;
 
     Vector<const CSSSelector*> m_selectors;
     bool m_usesDeepCombinatorOrShadowPseudo : 1;
diff --git a/third_party/WebKit/Source/core/dom/TaskRunnerHelper.cpp b/third_party/WebKit/Source/core/dom/TaskRunnerHelper.cpp
new file mode 100644
index 0000000..48f58f8
--- /dev/null
+++ b/third_party/WebKit/Source/core/dom/TaskRunnerHelper.cpp
@@ -0,0 +1,46 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/dom/TaskRunnerHelper.h"
+
+#include "core/dom/Document.h"
+#include "core/frame/LocalFrame.h"
+#include "public/platform/Platform.h"
+#include "public/platform/WebFrameScheduler.h"
+#include "public/platform/WebTaskRunner.h"
+#include "public/platform/WebThread.h"
+
+namespace blink {
+
+WebTaskRunner* TaskRunnerHelper::getUnthrottledTaskRunner(LocalFrame* frame)
+{
+    return frame ? frame->frameScheduler()->unthrottledTaskRunner() : Platform::current()->currentThread()->getWebTaskRunner();
+}
+
+WebTaskRunner* TaskRunnerHelper::getTimerTaskRunner(LocalFrame* frame)
+{
+    return frame ? frame->frameScheduler()->timerTaskRunner() : Platform::current()->currentThread()->getWebTaskRunner();
+}
+
+WebTaskRunner* TaskRunnerHelper::getLoadingTaskRunner(LocalFrame* frame)
+{
+    return frame ? frame->frameScheduler()->loadingTaskRunner() : Platform::current()->currentThread()->getWebTaskRunner();
+}
+
+WebTaskRunner* TaskRunnerHelper::getUnthrottledTaskRunner(Document* document)
+{
+    return getUnthrottledTaskRunner(document ? document->frame() : nullptr);
+}
+
+WebTaskRunner* TaskRunnerHelper::getTimerTaskRunner(Document* document)
+{
+    return getTimerTaskRunner(document ? document->frame() : nullptr);
+}
+
+WebTaskRunner* TaskRunnerHelper::getLoadingTaskRunner(Document* document)
+{
+    return getLoadingTaskRunner(document ? document->frame() : nullptr);
+}
+
+} // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/TaskRunnerHelper.h b/third_party/WebKit/Source/core/dom/TaskRunnerHelper.h
new file mode 100644
index 0000000..d3a5b19
--- /dev/null
+++ b/third_party/WebKit/Source/core/dom/TaskRunnerHelper.h
@@ -0,0 +1,29 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TaskRunnerHelper_h
+#define TaskRunnerHelper_h
+
+#include "wtf/Allocator.h"
+
+namespace blink {
+
+class Document;
+class LocalFrame;
+class WebTaskRunner;
+
+class TaskRunnerHelper final {
+    STATIC_ONLY(TaskRunnerHelper);
+public:
+    static WebTaskRunner* getUnthrottledTaskRunner(LocalFrame*);
+    static WebTaskRunner* getTimerTaskRunner(LocalFrame*);
+    static WebTaskRunner* getLoadingTaskRunner(LocalFrame*);
+    static WebTaskRunner* getUnthrottledTaskRunner(Document*);
+    static WebTaskRunner* getTimerTaskRunner(Document*);
+    static WebTaskRunner* getLoadingTaskRunner(Document*);
+};
+
+} // namespace blink
+
+#endif
diff --git a/third_party/WebKit/Source/core/dom/custom/CustomElement.cpp b/third_party/WebKit/Source/core/dom/custom/CustomElement.cpp
index bab2bec..16d712fb 100644
--- a/third_party/WebKit/Source/core/dom/custom/CustomElement.cpp
+++ b/third_party/WebKit/Source/core/dom/custom/CustomElement.cpp
@@ -60,18 +60,16 @@
         return false;
 
     // https://html.spec.whatwg.org/multipage/scripting.html#valid-custom-element-name
-    DEFINE_STATIC_LOCAL(HashSet<AtomicString>, hyphenContainingElementNames, ());
-    if (hyphenContainingElementNames.isEmpty()) {
-        hyphenContainingElementNames.add("annotation-xml");
-        hyphenContainingElementNames.add("color-profile");
-        hyphenContainingElementNames.add("font-face");
-        hyphenContainingElementNames.add("font-face-src");
-        hyphenContainingElementNames.add("font-face-uri");
-        hyphenContainingElementNames.add("font-face-format");
-        hyphenContainingElementNames.add("font-face-name");
-        hyphenContainingElementNames.add("missing-glyph");
-    }
-
+    DEFINE_STATIC_LOCAL(HashSet<AtomicString>, hyphenContainingElementNames, ({
+        "annotation-xml",
+        "color-profile",
+        "font-face",
+        "font-face-src",
+        "font-face-uri",
+        "font-face-format",
+        "font-face-name",
+        "missing-glyph",
+    }));
     return !hyphenContainingElementNames.contains(name);
 }
 
diff --git a/third_party/WebKit/Source/core/editing/EditingUtilities.cpp b/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
index b578e7a..7731eb25 100644
--- a/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
+++ b/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
@@ -339,7 +339,7 @@
     if (isDisplayInsideTable(node))
         node = node->parentNode();
 
-    return node->rootEditableElement(editableType);
+    return rootEditableElement(*node, editableType);
 }
 
 Element* rootEditableElementOf(const PositionInFlatTree& p, EditableType editableType)
@@ -351,7 +351,7 @@
 Element* rootEditableElementOf(const VisiblePosition& visiblePosition)
 {
     Node* anchorNode = visiblePosition.deepEquivalent().anchorNode();
-    return anchorNode ? anchorNode->rootEditableElement() : nullptr;
+    return anchorNode ? rootEditableElement(*anchorNode) : nullptr;
 }
 
 // Finds the enclosing element until which the tree can be split.
@@ -913,9 +913,9 @@
 
 static HTMLElement* firstInSpecialElement(const Position& pos)
 {
-    Element* rootEditableElement = pos.computeContainerNode()->rootEditableElement();
+    Element* element = rootEditableElement(*pos.computeContainerNode());
     for (Node& runner : NodeTraversal::inclusiveAncestorsOf(*pos.anchorNode())) {
-        if (runner.rootEditableElement() != rootEditableElement)
+        if (rootEditableElement(runner) != element)
             break;
         if (isSpecialHTMLElement(runner)) {
             HTMLElement* specialElement = toHTMLElement(&runner);
@@ -932,9 +932,9 @@
 
 static HTMLElement* lastInSpecialElement(const Position& pos)
 {
-    Element* rootEditableElement = pos.computeContainerNode()->rootEditableElement();
+    Element* element = rootEditableElement(*pos.computeContainerNode());
     for (Node& runner : NodeTraversal::inclusiveAncestorsOf(*pos.anchorNode())) {
-        if (runner.rootEditableElement() != rootEditableElement)
+        if (rootEditableElement(runner) != element)
             break;
         if (isSpecialHTMLElement(runner)) {
             HTMLElement* specialElement = toHTMLElement(&runner);
@@ -955,7 +955,7 @@
     if (!n)
         return pos;
     Position result = Position::inParentBeforeNode(*n);
-    if (result.isNull() || result.anchorNode()->rootEditableElement() != pos.anchorNode()->rootEditableElement())
+    if (result.isNull() || rootEditableElement(*result.anchorNode()) != rootEditableElement(*pos.anchorNode()))
         return pos;
     if (containingSpecialElement)
         *containingSpecialElement = n;
@@ -968,7 +968,7 @@
     if (!n)
         return pos;
     Position result = Position::inParentAfterNode(*n);
-    if (result.isNull() || result.anchorNode()->rootEditableElement() != pos.anchorNode()->rootEditableElement())
+    if (result.isNull() || rootEditableElement(*result.anchorNode()) != rootEditableElement(*pos.anchorNode()))
         return pos;
     if (containingSpecialElement)
         *containingSpecialElement = n;
@@ -1175,10 +1175,10 @@
 Node* highestNodeToRemoveInPruning(Node* node, Node* excludeNode)
 {
     Node* previousNode = nullptr;
-    Element* rootEditableElement = node ? node->rootEditableElement() : nullptr;
+    Element* element = node ? rootEditableElement(*node) : nullptr;
     for (; node; node = node->parentNode()) {
         if (LayoutObject* layoutObject = node->layoutObject()) {
-            if (!layoutObject->canHaveChildren() || hasARenderedDescendant(node, previousNode) || rootEditableElement == node || excludeNode == node)
+            if (!layoutObject->canHaveChildren() || hasARenderedDescendant(node, previousNode) || element == node || excludeNode == node)
                 return previousNode;
         }
         previousNode = node;
@@ -1285,7 +1285,7 @@
 
     return firstList->hasTagName(secondList->tagQName()) // make sure the list types match (ol vs. ul)
     && firstList->hasEditableStyle() && secondList->hasEditableStyle() // both lists are editable
-    && firstList->rootEditableElement() == secondList->rootEditableElement() // don't cross editing boundaries
+    && rootEditableElement(*firstList) == rootEditableElement(*secondList) // don't cross editing boundaries
     && isVisiblyAdjacent(Position::inParentAfterNode(*firstList), Position::inParentBeforeNode(*secondList));
     // Make sure there is no visible content between this li and the previous list
 }
@@ -1416,7 +1416,7 @@
     if (position.isNull())
         return Position();
 
-    Element* fromRootEditableElement = position.anchorNode()->rootEditableElement();
+    Element* fromRootEditableElement = rootEditableElement(*position.anchorNode());
 
     bool atStartOfLine = isStartOfLine(createVisiblePosition(position, affinity));
     bool rendered = isVisuallyEquivalentCandidate(position);
@@ -1428,7 +1428,7 @@
         // |CodePoint|.
         currentPos = previousPositionOf(currentPos, PositionMoveType::CodeUnit);
 
-        if (currentPos.anchorNode()->rootEditableElement() != fromRootEditableElement)
+        if (rootEditableElement(*currentPos.anchorNode()) != fromRootEditableElement)
             return position;
 
         if (atStartOfLine || !rendered) {
diff --git a/third_party/WebKit/Source/core/editing/Editor.cpp b/third_party/WebKit/Source/core/editing/Editor.cpp
index 46f0e4e9..34cc660 100644
--- a/third_party/WebKit/Source/core/editing/Editor.cpp
+++ b/third_party/WebKit/Source/core/editing/Editor.cpp
@@ -311,7 +311,7 @@
         VisiblePosition start = createVisiblePosition(range.startPosition());
         VisiblePosition previous = previousPositionOf(start);
         // FIXME: We sometimes allow deletions at the start of editable roots, like when the caret is in an empty list item.
-        if (previous.isNull() || previous.deepEquivalent().anchorNode()->rootEditableElement() != startContainer->rootEditableElement())
+        if (previous.isNull() || rootEditableElement(*previous.deepEquivalent().anchorNode()) != rootEditableElement(*startContainer))
             return false;
     }
     return true;
diff --git a/third_party/WebKit/Source/core/editing/InputMethodController.cpp b/third_party/WebKit/Source/core/editing/InputMethodController.cpp
index 0bd3b86d..695b8c39 100644
--- a/third_party/WebKit/Source/core/editing/InputMethodController.cpp
+++ b/third_party/WebKit/Source/core/editing/InputMethodController.cpp
@@ -399,6 +399,10 @@
     if (!rootEditableElement)
         return;
 
+    // TODO(dglazkov): The use of updateStyleAndLayoutIgnorePendingStylesheets needs to be audited.
+    // see http://crbug.com/590369 for more details.
+    rootEditableElement->document().updateStyleAndLayoutIgnorePendingStylesheets();
+
     // In case of exceeding the right boundary.
     // If both |value1| and |value2| exceed right boundary,
     // PlainTextRange(value1, value2)::createRange() will return a default
@@ -436,6 +440,10 @@
     if (!editable)
         return;
 
+    // TODO(dglazkov): The use of updateStyleAndLayoutIgnorePendingStylesheets needs to be audited.
+    // see http://crbug.com/590369 for more details.
+    editable->document().updateStyleAndLayoutIgnorePendingStylesheets();
+
     const EphemeralRange range = PlainTextRange(compositionStart, compositionEnd).createRange(*editable);
     if (range.isNull())
         return;
@@ -501,6 +509,10 @@
     if (!rootEditableElement)
         return false;
 
+    // TODO(dglazkov): The use of updateStyleAndLayoutIgnorePendingStylesheets needs to be audited.
+    // see http://crbug.com/590369 for more details.
+    rootEditableElement->document().updateStyleAndLayoutIgnorePendingStylesheets();
+
     const EphemeralRange range = selectionOffsets.createRange(*rootEditableElement);
     if (range.isNull())
         return false;
diff --git a/third_party/WebKit/Source/core/editing/PlainTextRange.cpp b/third_party/WebKit/Source/core/editing/PlainTextRange.cpp
index 553978d..adf72eb1 100644
--- a/third_party/WebKit/Source/core/editing/PlainTextRange.cpp
+++ b/third_party/WebKit/Source/core/editing/PlainTextRange.cpp
@@ -83,10 +83,6 @@
         behaviorFlags |= TextIteratorEmitsCharactersBetweenAllVisiblePositions;
     auto range = EphemeralRange::rangeOfContents(scope);
 
-    // TODO(dglazkov): The use of updateStyleAndLayoutIgnorePendingStylesheets needs to be audited.
-    // see http://crbug.com/590369 for more details.
-    scope.document().updateStyleAndLayoutIgnorePendingStylesheets();
-
     TextIterator it(range.startPosition(), range.endPosition(), behaviorFlags);
 
     // FIXME: the atEnd() check shouldn't be necessary, workaround for
diff --git a/third_party/WebKit/Source/core/editing/VisibleSelection.cpp b/third_party/WebKit/Source/core/editing/VisibleSelection.cpp
index 6bc2b81..5684cc4 100644
--- a/third_party/WebKit/Source/core/editing/VisibleSelection.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleSelection.cpp
@@ -588,7 +588,7 @@
 {
     while (node) {
         if (node->hasEditableStyle())
-            return node->rootEditableElement();
+            return rootEditableElement(*node);
         if (isHTMLBodyElement(*node))
             break;
         node = node->parentNode();
diff --git a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
index 797c2e75..ddeb9512 100644
--- a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
@@ -1336,7 +1336,7 @@
     // Could not find a previous line. This means we must already be on the first line.
     // Move to the start of the content in this block, which effectively moves us
     // to the start of the line we're on.
-    Element* rootElement = node->hasEditableStyle(editableType) ? node->rootEditableElement(editableType) : node->document().documentElement();
+    Element* rootElement = node->hasEditableStyle(editableType) ? rootEditableElement(*node, editableType) : node->document().documentElement();
     if (!rootElement)
         return VisiblePosition();
     return VisiblePosition::firstPositionInNode(rootElement);
@@ -1392,7 +1392,7 @@
     // Could not find a next line. This means we must already be on the last line.
     // Move to the end of the content in this block, which effectively moves us
     // to the end of the line we're on.
-    Element* rootElement = node->hasEditableStyle(editableType) ? node->rootEditableElement(editableType) : node->document().documentElement();
+    Element* rootElement = node->hasEditableStyle(editableType) ? rootEditableElement(*node, editableType) : node->document().documentElement();
     if (!rootElement)
         return VisiblePosition();
     return VisiblePosition::lastPositionInNode(rootElement);
diff --git a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp
index a298222..26702c8 100644
--- a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp
@@ -302,6 +302,11 @@
         nextParagraphStart = nextPositionOf(endOfParagraph(paragraphStart));
     }
 
+    // Update style and layout again, since added or removed styles could have
+    // affected the layout. We need clean layout in order to compute
+    // plain-text ranges below.
+    document().updateStyleAndLayoutIgnorePendingStylesheets();
+
     EphemeralRange startEphemeralRange = PlainTextRange(startIndex).createRangeForSelection(toContainerNode(scope));
     if (startEphemeralRange.isNull())
         return;
@@ -763,7 +768,7 @@
     // e.g. When applying font-size: large on <font color="blue">hello</font>, we need to include the font element in our run
     // to generate <font color="blue" size="4">hello</font> instead of <font color="blue"><font size="4">hello</font></font>
     Range* range = Range::create(startNode->document(), start, end);
-    Element* editableRoot = startNode->rootEditableElement();
+    Element* editableRoot = rootEditableElement(*startNode);
     if (startNode != editableRoot) {
         while (editableRoot && startNode->parentNode() != editableRoot && isNodeVisiblyContainedWithin(*startNode->parentNode(), *range))
             startNode = startNode->parentNode();
diff --git a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp
index ae58cce..b074fa8c 100644
--- a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp
@@ -1065,7 +1065,7 @@
     Node* lastNode = nullptr;
     Node* outerNode = passedOuterNode;
 
-    if (outerNode->isRootEditableElement()) {
+    if (isRootEditableElement(*outerNode)) {
         lastNode = blockElement;
     } else {
         lastNode = outerNode->cloneNode(isDisplayInsideTable(outerNode));
@@ -1365,6 +1365,10 @@
     Element* documentElement = document().documentElement();
     if (!documentElement)
         return;
+
+    // We need clean layout in order to compute plain-text ranges below.
+    document().updateStyleAndLayoutIgnorePendingStylesheets();
+
     // Fragment creation (using createMarkup) incorrectly uses regular spaces
     // instead of nbsps for some spaces that were rendered (11475), which causes
     // spaces to be collapsed during the move operation. This results in a call
@@ -1394,7 +1398,7 @@
     if (!listNode
         || (!isHTMLUListElement(*listNode) && !isHTMLOListElement(*listNode))
         || !listNode->hasEditableStyle()
-        || listNode == emptyListItem->rootEditableElement())
+        || listNode == rootEditableElement(*emptyListItem))
         return false;
 
     HTMLElement* newBlock = nullptr;
diff --git a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp
index 075873b..f632afe 100644
--- a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp
@@ -369,7 +369,7 @@
         }
     }
 
-    if (isTableStructureNode(node) || node->isRootEditableElement()) {
+    if (isTableStructureNode(node) || isRootEditableElement(*node)) {
         // Do not remove an element of table structure; remove its contents.
         // Likewise for the root editable element.
         Node* child = node->firstChild();
@@ -441,12 +441,12 @@
         Node* nextNode = NodeTraversal::next(*node);
         if (isHTMLStyleElement(*node) || isHTMLLinkElement(*node)) {
             nextNode = NodeTraversal::nextSkippingChildren(*node);
-            Element* rootEditableElement = node->rootEditableElement();
-            if (rootEditableElement) {
+            Element* element = rootEditableElement(*node);
+            if (element) {
                 removeNode(node, editingState);
                 if (editingState->isAborted())
                     return;
-                appendNode(node, rootEditableElement, editingState);
+                appendNode(node, element, editingState);
                 if (editingState->isAborted())
                     return;
             }
@@ -809,7 +809,7 @@
 void DeleteSelectionCommand::removeRedundantBlocks(EditingState* editingState)
 {
     Node* node = m_endingPosition.computeContainerNode();
-    Element* rootElement = node->rootEditableElement();
+    Element* rootElement = rootEditableElement(*node);
 
     while (node != rootElement) {
         if (isRemovableBlock(node)) {
@@ -840,8 +840,8 @@
     TextAffinity affinity = m_selectionToDelete.affinity();
 
     Position downstreamEnd = mostForwardCaretPosition(m_selectionToDelete.end());
-    bool rootWillStayOpenWithoutPlaceholder = downstreamEnd.computeContainerNode() == downstreamEnd.computeContainerNode()->rootEditableElement()
-        || (downstreamEnd.computeContainerNode()->isTextNode() && downstreamEnd.computeContainerNode()->parentNode() == downstreamEnd.computeContainerNode()->rootEditableElement());
+    bool rootWillStayOpenWithoutPlaceholder = downstreamEnd.computeContainerNode() == rootEditableElement(*downstreamEnd.computeContainerNode())
+        || (downstreamEnd.computeContainerNode()->isTextNode() && downstreamEnd.computeContainerNode()->parentNode() == rootEditableElement(*downstreamEnd.computeContainerNode()));
     bool lineBreakAtEndOfSelectionToDelete = lineBreakExistsAtVisiblePosition(m_selectionToDelete.visibleEnd());
     m_needPlaceholder = !rootWillStayOpenWithoutPlaceholder
         && isStartOfParagraph(m_selectionToDelete.visibleStart(), CanCrossEditingBoundary)
diff --git a/third_party/WebKit/Source/core/editing/commands/FormatBlockCommand.cpp b/third_party/WebKit/Source/core/editing/commands/FormatBlockCommand.cpp
index 131dbf6..44442099 100644
--- a/third_party/WebKit/Source/core/editing/commands/FormatBlockCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/FormatBlockCommand.cpp
@@ -124,8 +124,8 @@
     if (!commonAncestor)
         return 0;
 
-    Element* rootEditableElement = range->startContainer()->rootEditableElement();
-    if (!rootEditableElement || commonAncestor->contains(rootEditableElement))
+    Element* element = rootEditableElement(*range->startContainer());
+    if (!element || commonAncestor->contains(element))
         return 0;
 
     return commonAncestor->isElementNode() ? toElement(commonAncestor) : 0;
@@ -133,31 +133,30 @@
 
 bool isElementForFormatBlock(const QualifiedName& tagName)
 {
-    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, blockTags, ());
-    if (blockTags.isEmpty()) {
-        blockTags.add(addressTag);
-        blockTags.add(articleTag);
-        blockTags.add(asideTag);
-        blockTags.add(blockquoteTag);
-        blockTags.add(ddTag);
-        blockTags.add(divTag);
-        blockTags.add(dlTag);
-        blockTags.add(dtTag);
-        blockTags.add(footerTag);
-        blockTags.add(h1Tag);
-        blockTags.add(h2Tag);
-        blockTags.add(h3Tag);
-        blockTags.add(h4Tag);
-        blockTags.add(h5Tag);
-        blockTags.add(h6Tag);
-        blockTags.add(headerTag);
-        blockTags.add(hgroupTag);
-        blockTags.add(mainTag);
-        blockTags.add(navTag);
-        blockTags.add(pTag);
-        blockTags.add(preTag);
-        blockTags.add(sectionTag);
-    }
+    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, blockTags, ({
+        addressTag,
+        articleTag,
+        asideTag,
+        blockquoteTag,
+        ddTag,
+        divTag,
+        dlTag,
+        dtTag,
+        footerTag,
+        h1Tag,
+        h2Tag,
+        h3Tag,
+        h4Tag,
+        h5Tag,
+        h6Tag,
+        headerTag,
+        hgroupTag,
+        mainTag,
+        navTag,
+        pTag,
+        preTag,
+        sectionTag,
+    }));
     return blockTags.contains(tagName);
 }
 
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp b/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp
index 9797b95..d9dc694 100644
--- a/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp
@@ -187,6 +187,11 @@
                 if (!singleParagraphResult)
                     break;
                 if (endOfSelection.isNull() || endOfSelection.isOrphan() || startOfLastParagraph.isNull() || startOfLastParagraph.isOrphan()) {
+
+                    // TODO(dglazkov): The use of updateStyleAndLayoutIgnorePendingStylesheets needs to be audited.
+                    // see http://crbug.com/590369 for more details.
+                    document().updateStyleAndLayoutIgnorePendingStylesheets();
+
                     endOfSelection = visiblePositionForIndex(indexForEndOfSelection, scopeForEndOfSelection);
                     // If endOfSelection is null, then some contents have been deleted from the document.
                     // This should never happen and if it did, exit early immediately because we've lost the loop invariant.
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp b/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp
index ea6d016..01099906 100644
--- a/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp
@@ -218,7 +218,7 @@
 
     // Create block to be inserted.
     Element* blockToInsert = nullptr;
-    if (startBlock->isRootEditableElement()) {
+    if (isRootEditableElement(*startBlock)) {
         blockToInsert = createDefaultParagraphElement(document());
         nestNewBlock = true;
     } else if (shouldUseDefaultParagraphElement(startBlock)) {
diff --git a/third_party/WebKit/Source/core/editing/commands/RemoveFormatCommand.cpp b/third_party/WebKit/Source/core/editing/commands/RemoveFormatCommand.cpp
index a86ae4e..fb81be6 100644
--- a/third_party/WebKit/Source/core/editing/commands/RemoveFormatCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/RemoveFormatCommand.cpp
@@ -47,33 +47,32 @@
 
 static bool isElementForRemoveFormatCommand(const Element* element)
 {
-    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, elements, ());
-    if (elements.isEmpty()) {
-        elements.add(acronymTag);
-        elements.add(bTag);
-        elements.add(bdoTag);
-        elements.add(bigTag);
-        elements.add(citeTag);
-        elements.add(codeTag);
-        elements.add(dfnTag);
-        elements.add(emTag);
-        elements.add(fontTag);
-        elements.add(iTag);
-        elements.add(insTag);
-        elements.add(kbdTag);
-        elements.add(nobrTag);
-        elements.add(qTag);
-        elements.add(sTag);
-        elements.add(sampTag);
-        elements.add(smallTag);
-        elements.add(strikeTag);
-        elements.add(strongTag);
-        elements.add(subTag);
-        elements.add(supTag);
-        elements.add(ttTag);
-        elements.add(uTag);
-        elements.add(varTag);
-    }
+    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, elements, ({
+        acronymTag,
+        bTag,
+        bdoTag,
+        bigTag,
+        citeTag,
+        codeTag,
+        dfnTag,
+        emTag,
+        fontTag,
+        iTag,
+        insTag,
+        kbdTag,
+        nobrTag,
+        qTag,
+        sTag,
+        sampTag,
+        smallTag,
+        strikeTag,
+        strongTag,
+        subTag,
+        supTag,
+        ttTag,
+        uTag,
+        varTag,
+    }));
     return elements.contains(element->tagQName());
 }
 
diff --git a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp
index 2e6cbfa2..73649d9d 100644
--- a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp
@@ -613,57 +613,56 @@
 static bool isProhibitedParagraphChild(const AtomicString& name)
 {
     // https://dvcs.w3.org/hg/editing/raw-file/57abe6d3cb60/editing.html#prohibited-paragraph-child
-    DEFINE_STATIC_LOCAL(HashSet<AtomicString>, elements, ());
-    if (elements.isEmpty()) {
-        elements.add(addressTag.localName());
-        elements.add(articleTag.localName());
-        elements.add(asideTag.localName());
-        elements.add(blockquoteTag.localName());
-        elements.add(captionTag.localName());
-        elements.add(centerTag.localName());
-        elements.add(colTag.localName());
-        elements.add(colgroupTag.localName());
-        elements.add(ddTag.localName());
-        elements.add(detailsTag.localName());
-        elements.add(dirTag.localName());
-        elements.add(divTag.localName());
-        elements.add(dlTag.localName());
-        elements.add(dtTag.localName());
-        elements.add(fieldsetTag.localName());
-        elements.add(figcaptionTag.localName());
-        elements.add(figureTag.localName());
-        elements.add(footerTag.localName());
-        elements.add(formTag.localName());
-        elements.add(h1Tag.localName());
-        elements.add(h2Tag.localName());
-        elements.add(h3Tag.localName());
-        elements.add(h4Tag.localName());
-        elements.add(h5Tag.localName());
-        elements.add(h6Tag.localName());
-        elements.add(headerTag.localName());
-        elements.add(hgroupTag.localName());
-        elements.add(hrTag.localName());
-        elements.add(liTag.localName());
-        elements.add(listingTag.localName());
-        elements.add(mainTag.localName()); // Missing in the specification.
-        elements.add(menuTag.localName());
-        elements.add(navTag.localName());
-        elements.add(olTag.localName());
-        elements.add(pTag.localName());
-        elements.add(plaintextTag.localName());
-        elements.add(preTag.localName());
-        elements.add(sectionTag.localName());
-        elements.add(summaryTag.localName());
-        elements.add(tableTag.localName());
-        elements.add(tbodyTag.localName());
-        elements.add(tdTag.localName());
-        elements.add(tfootTag.localName());
-        elements.add(thTag.localName());
-        elements.add(theadTag.localName());
-        elements.add(trTag.localName());
-        elements.add(ulTag.localName());
-        elements.add(xmpTag.localName());
-    }
+    DEFINE_STATIC_LOCAL(HashSet<AtomicString>, elements, ({
+        addressTag.localName(),
+        articleTag.localName(),
+        asideTag.localName(),
+        blockquoteTag.localName(),
+        captionTag.localName(),
+        centerTag.localName(),
+        colTag.localName(),
+        colgroupTag.localName(),
+        ddTag.localName(),
+        detailsTag.localName(),
+        dirTag.localName(),
+        divTag.localName(),
+        dlTag.localName(),
+        dtTag.localName(),
+        fieldsetTag.localName(),
+        figcaptionTag.localName(),
+        figureTag.localName(),
+        footerTag.localName(),
+        formTag.localName(),
+        h1Tag.localName(),
+        h2Tag.localName(),
+        h3Tag.localName(),
+        h4Tag.localName(),
+        h5Tag.localName(),
+        h6Tag.localName(),
+        headerTag.localName(),
+        hgroupTag.localName(),
+        hrTag.localName(),
+        liTag.localName(),
+        listingTag.localName(),
+        mainTag.localName(), // Missing in the specification.
+        menuTag.localName(),
+        navTag.localName(),
+        olTag.localName(),
+        pTag.localName(),
+        plaintextTag.localName(),
+        preTag.localName(),
+        sectionTag.localName(),
+        summaryTag.localName(),
+        tableTag.localName(),
+        tbodyTag.localName(),
+        tdTag.localName(),
+        tfootTag.localName(),
+        thTag.localName(),
+        theadTag.localName(),
+        trTag.localName(),
+        ulTag.localName(),
+        xmpTag.localName(),
+    }));
     return elements.contains(name);
 }
 
diff --git a/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp b/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp
index 8e56bf043..fbd532e7 100644
--- a/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp
@@ -147,10 +147,10 @@
 
     String newText = text;
     if (Node* startNode = selectionForInsertion.start().computeContainerNode()) {
-        if (startNode->rootEditableElement()) {
+        if (rootEditableElement(*startNode)) {
             // Send BeforeTextInsertedEvent. The event handler will update text if necessary.
             BeforeTextInsertedEvent* evt = BeforeTextInsertedEvent::create(text);
-            startNode->rootEditableElement()->dispatchEvent(evt);
+            rootEditableElement(*startNode)->dispatchEvent(evt);
             newText = evt->text();
         }
     }
diff --git a/third_party/WebKit/Source/core/editing/spellcheck/SpellCheckRequester.cpp b/third_party/WebKit/Source/core/editing/spellcheck/SpellCheckRequester.cpp
index 0efee04..0bf8481 100644
--- a/third_party/WebKit/Source/core/editing/spellcheck/SpellCheckRequester.cpp
+++ b/third_party/WebKit/Source/core/editing/spellcheck/SpellCheckRequester.cpp
@@ -47,7 +47,7 @@
     : m_requester(nullptr)
     , m_checkingRange(checkingRange)
     , m_paragraphRange(paragraphRange)
-    , m_rootEditableElement(m_checkingRange->startContainer()->rootEditableElement())
+    , m_rootEditableElement(blink::rootEditableElement(*m_checkingRange->startContainer()))
     , m_requestData(unrequestedTextCheckingSequence, text, mask, processType, documentMarkersInRange, documentMarkerOffsets)
     , m_requestNumber(requestNumber)
 {
@@ -84,7 +84,7 @@
 {
     if (checkingRange.isNull())
         return nullptr;
-    if (!checkingRange.startPosition().computeContainerNode()->rootEditableElement())
+    if (!blink::rootEditableElement(*checkingRange.startPosition().computeContainerNode()))
         return nullptr;
 
     String text = plainText(checkingRange, TextIteratorEmitsObjectReplacementCharacter);
diff --git a/third_party/WebKit/Source/core/events/EventAliases.in b/third_party/WebKit/Source/core/events/EventAliases.in
index 7e9078b..6b7c454 100644
--- a/third_party/WebKit/Source/core/events/EventAliases.in
+++ b/third_party/WebKit/Source/core/events/EventAliases.in
@@ -7,7 +7,6 @@
 MutationEvents ImplementedAs=MutationEvent
 OrientationEvent ImplementedAs=Event, RuntimeEnabled=OrientationEventEnabled
 SVGEvents ImplementedAs=Event
-SVGZoomEvents ImplementedAs=SVGZoomEvent
 UIEvents ImplementedAs=UIEvent
 WebKitTransitionEvent ImplementedAs=TransitionEvent
 
diff --git a/third_party/WebKit/Source/core/fetch/CrossOriginAccessControl.cpp b/third_party/WebKit/Source/core/fetch/CrossOriginAccessControl.cpp
index dcb52929..77f5867 100644
--- a/third_party/WebKit/Source/core/fetch/CrossOriginAccessControl.cpp
+++ b/third_party/WebKit/Source/core/fetch/CrossOriginAccessControl.cpp
@@ -43,24 +43,16 @@
 
 namespace blink {
 
-static std::unique_ptr<HTTPHeaderSet> createAllowedCrossOriginResponseHeadersSet()
-{
-    std::unique_ptr<HTTPHeaderSet> headerSet = wrapUnique(new HashSet<String, CaseFoldingHash>);
-
-    headerSet->add("cache-control");
-    headerSet->add("content-language");
-    headerSet->add("content-type");
-    headerSet->add("expires");
-    headerSet->add("last-modified");
-    headerSet->add("pragma");
-
-    return headerSet;
-}
-
 bool isOnAccessControlResponseHeaderWhitelist(const String& name)
 {
-    DEFINE_THREAD_SAFE_STATIC_LOCAL(HTTPHeaderSet, allowedCrossOriginResponseHeaders, (createAllowedCrossOriginResponseHeadersSet().release()));
-
+    DEFINE_THREAD_SAFE_STATIC_LOCAL(HTTPHeaderSet, allowedCrossOriginResponseHeaders, (new HTTPHeaderSet({
+        "cache-control",
+        "content-language",
+        "content-type",
+        "expires",
+        "last-modified",
+        "pragma",
+    })));
     return allowedCrossOriginResponseHeaders.contains(name);
 }
 
diff --git a/third_party/WebKit/Source/core/fetch/FetchUtils.cpp b/third_party/WebKit/Source/core/fetch/FetchUtils.cpp
index ef2c8848..d199685 100644
--- a/third_party/WebKit/Source/core/fetch/FetchUtils.cpp
+++ b/third_party/WebKit/Source/core/fetch/FetchUtils.cpp
@@ -45,27 +45,29 @@
     : m_proxyHeaderPrefix("proxy-")
     , m_secHeaderPrefix("sec-")
 {
-    m_fixedNames.add("accept-charset");
-    m_fixedNames.add("accept-encoding");
-    m_fixedNames.add("access-control-request-headers");
-    m_fixedNames.add("access-control-request-method");
-    m_fixedNames.add("connection");
-    m_fixedNames.add("content-length");
-    m_fixedNames.add("cookie");
-    m_fixedNames.add("cookie2");
-    m_fixedNames.add("date");
-    m_fixedNames.add("dnt");
-    m_fixedNames.add("expect");
-    m_fixedNames.add("host");
-    m_fixedNames.add("keep-alive");
-    m_fixedNames.add("origin");
-    m_fixedNames.add("referer");
-    m_fixedNames.add("te");
-    m_fixedNames.add("trailer");
-    m_fixedNames.add("transfer-encoding");
-    m_fixedNames.add("upgrade");
-    m_fixedNames.add("user-agent");
-    m_fixedNames.add("via");
+    m_fixedNames = {
+        "accept-charset",
+        "accept-encoding",
+        "access-control-request-headers",
+        "access-control-request-method",
+        "connection",
+        "content-length",
+        "cookie",
+        "cookie2",
+        "date",
+        "dnt",
+        "expect",
+        "host",
+        "keep-alive",
+        "origin",
+        "referer",
+        "te",
+        "trailer",
+        "transfer-encoding",
+        "upgrade",
+        "user-agent",
+        "via",
+    };
 }
 
 const ForbiddenHeaderNames& ForbiddenHeaderNames::get()
diff --git a/third_party/WebKit/Source/core/fetch/ImageResource.cpp b/third_party/WebKit/Source/core/fetch/ImageResource.cpp
index c10b9a96..18de9a4 100644
--- a/third_party/WebKit/Source/core/fetch/ImageResource.cpp
+++ b/third_party/WebKit/Source/core/fetch/ImageResource.cpp
@@ -115,6 +115,20 @@
     Resource::markClientsAndObserversFinished();
 }
 
+void ImageResource::ensureImage()
+{
+    if (m_data && !m_image && !errorOccurred()) {
+        createImage();
+        m_image->setData(m_data, true);
+    }
+}
+
+void ImageResource::didAddClient(ResourceClient* client)
+{
+    ensureImage();
+    Resource::didAddClient(client);
+}
+
 void ImageResource::addObserver(ImageResourceObserver* observer)
 {
     willAddClientOrObserver();
@@ -124,10 +138,7 @@
     if (isCacheValidator())
         return;
 
-    if (m_data && !m_image && !errorOccurred()) {
-        createImage();
-        m_image->setData(m_data, true);
-    }
+    ensureImage();
 
     if (m_image && !m_image->isNull()) {
         observer->imageChanged(this);
diff --git a/third_party/WebKit/Source/core/fetch/ImageResource.h b/third_party/WebKit/Source/core/fetch/ImageResource.h
index da0995f..55e869f 100644
--- a/third_party/WebKit/Source/core/fetch/ImageResource.h
+++ b/third_party/WebKit/Source/core/fetch/ImageResource.h
@@ -91,6 +91,8 @@
     // the Lo-Fi state set to off and bypassing the cache.
     void reloadIfLoFi(ResourceFetcher*);
 
+    void didAddClient(ResourceClient*) override;
+
     void addObserver(ImageResourceObserver*);
     void removeObserver(ImageResourceObserver*);
     bool hasClientsOrObservers() const override { return Resource::hasClientsOrObservers() || !m_observers.isEmpty() || !m_finishedObservers.isEmpty(); }
@@ -158,6 +160,8 @@
     // If not null, changeRect is the changed part of the image.
     void notifyObservers(const IntRect* changeRect = nullptr);
 
+    void ensureImage();
+
     void checkNotify() override;
     void markClientsAndObserversFinished() override;
 
diff --git a/third_party/WebKit/Source/core/fetch/ImageResourceTest.cpp b/third_party/WebKit/Source/core/fetch/ImageResourceTest.cpp
index daf35bd..239564a9 100644
--- a/third_party/WebKit/Source/core/fetch/ImageResourceTest.cpp
+++ b/third_party/WebKit/Source/core/fetch/ImageResourceTest.cpp
@@ -574,4 +574,41 @@
     EXPECT_EQ(300, imageResource->getImage()->height());
 }
 
+// Tests for pruning.
+
+TEST(ImageResourceTest, AddClientAfterPrune)
+{
+    KURL url(ParsedURLString, "http://127.0.0.1:8000/foo");
+    ImageResource* imageResource = ImageResource::create(ResourceRequest(url));
+
+    // Adds a ResourceClient but not ImageResourceObserver.
+    Persistent<MockResourceClient> client1 = new MockResourceClient(imageResource);
+
+    receiveResponse(imageResource, url, "image/jpeg", jpegImage());
+
+    EXPECT_FALSE(imageResource->errorOccurred());
+    ASSERT_TRUE(imageResource->hasImage());
+    EXPECT_FALSE(imageResource->getImage()->isNull());
+    EXPECT_EQ(1, imageResource->getImage()->width());
+    EXPECT_EQ(1, imageResource->getImage()->height());
+    EXPECT_TRUE(client1->notifyFinishedCalled());
+
+    client1->removeAsClient();
+
+    EXPECT_FALSE(imageResource->hasClientsOrObservers());
+
+    imageResource->prune();
+
+    EXPECT_FALSE(imageResource->hasImage());
+
+    // Re-adds a ResourceClient but not ImageResourceObserver.
+    Persistent<MockResourceClient> client2 = new MockResourceClient(imageResource);
+
+    ASSERT_TRUE(imageResource->hasImage());
+    EXPECT_FALSE(imageResource->getImage()->isNull());
+    EXPECT_EQ(1, imageResource->getImage()->width());
+    EXPECT_EQ(1, imageResource->getImage()->height());
+    EXPECT_TRUE(client2->notifyFinishedCalled());
+}
+
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/fetch/RawResource.cpp b/third_party/WebKit/Source/core/fetch/RawResource.cpp
index d6cfe576..94989229 100644
--- a/third_party/WebKit/Source/core/fetch/RawResource.cpp
+++ b/third_party/WebKit/Source/core/fetch/RawResource.cpp
@@ -205,19 +205,18 @@
 static bool shouldIgnoreHeaderForCacheReuse(AtomicString headerName)
 {
     // FIXME: This list of headers that don't affect cache policy almost certainly isn't complete.
-    DEFINE_STATIC_LOCAL(HashSet<AtomicString>, m_headers, ());
-    if (m_headers.isEmpty()) {
-        m_headers.add("Cache-Control");
-        m_headers.add("If-Modified-Since");
-        m_headers.add("If-None-Match");
-        m_headers.add("Origin");
-        m_headers.add("Pragma");
-        m_headers.add("Purpose");
-        m_headers.add("Referer");
-        m_headers.add("User-Agent");
-        m_headers.add(HTTPNames::X_DevTools_Emulate_Network_Conditions_Client_Id);
-    }
-    return m_headers.contains(headerName);
+    DEFINE_STATIC_LOCAL(HashSet<AtomicString>, headers, ({
+        "Cache-Control",
+        "If-Modified-Since",
+        "If-None-Match",
+        "Origin",
+        "Pragma",
+        "Purpose",
+        "Referer",
+        "User-Agent",
+        HTTPNames::X_DevTools_Emulate_Network_Conditions_Client_Id,
+    }));
+    return headers.contains(headerName);
 }
 
 static bool isCacheableHTTPMethod(const AtomicString& method)
diff --git a/third_party/WebKit/Source/core/fetch/Resource.cpp b/third_party/WebKit/Source/core/fetch/Resource.cpp
index 20b69e38..4a0065a8 100644
--- a/third_party/WebKit/Source/core/fetch/Resource.cpp
+++ b/third_party/WebKit/Source/core/fetch/Resource.cpp
@@ -618,7 +618,7 @@
             builder.append(", Finished=");
             builder.appendNumber(m_finishedClients.size());
         }
-        builder.append(")");
+        builder.append(')');
     }
     if (m_loader) {
         if (!builder.isEmpty())
@@ -630,7 +630,7 @@
             builder.append(' ');
         builder.append("m_preloadCount(");
         builder.appendNumber(m_preloadCount);
-        builder.append(")");
+        builder.append(')');
     }
     if (memoryCache()->contains(this)) {
         if (!builder.isEmpty())
diff --git a/third_party/WebKit/Source/core/frame/DOMWindowProperty.cpp b/third_party/WebKit/Source/core/frame/DOMWindowProperty.cpp
index 6fc921d..9133780 100644
--- a/third_party/WebKit/Source/core/frame/DOMWindowProperty.cpp
+++ b/third_party/WebKit/Source/core/frame/DOMWindowProperty.cpp
@@ -52,13 +52,6 @@
     m_frame = nullptr;
 }
 
-void DOMWindowProperty::willDetachGlobalObjectFromFrame()
-{
-    // If the property is getting this callback it must have been
-    // created with a LocalFrame and it should still have it.
-    ASSERT(m_frame);
-}
-
 DEFINE_TRACE(DOMWindowProperty)
 {
     visitor->trace(m_frame);
diff --git a/third_party/WebKit/Source/core/frame/DOMWindowProperty.h b/third_party/WebKit/Source/core/frame/DOMWindowProperty.h
index e7e71459..b24b51d 100644
--- a/third_party/WebKit/Source/core/frame/DOMWindowProperty.h
+++ b/third_party/WebKit/Source/core/frame/DOMWindowProperty.h
@@ -39,7 +39,6 @@
     explicit DOMWindowProperty(LocalFrame*);
 
     virtual void willDestroyGlobalObjectInFrame();
-    virtual void willDetachGlobalObjectFromFrame();
 
     LocalFrame* frame() const { return m_frame; }
 
diff --git a/third_party/WebKit/Source/core/frame/Deprecation.cpp b/third_party/WebKit/Source/core/frame/Deprecation.cpp
index 424639e..aef7cdb 100644
--- a/third_party/WebKit/Source/core/frame/Deprecation.cpp
+++ b/third_party/WebKit/Source/core/frame/Deprecation.cpp
@@ -343,12 +343,6 @@
     case UseCounter::V8TouchEvent_InitTouchEvent_Method:
         return replacedWillBeRemoved("'TouchEvent.initTouchEvent'", "the TouchEvent constructor", 53, "5730982598541312");
 
-    case UseCounter::ObjectObserve:
-        return willBeRemoved("'Object.observe'", 50, "6147094632988672");
-
-    case UseCounter::SVGZoomEvent:
-        return willBeRemoved("'SVGZoomEvent'", 52, "5760883808534528");
-
     case UseCounter::WebAnimationHyphenatedProperty:
         return "Hyphenated property names in Web Animations keyframes are invalid and therefore ignored. Please use camelCase instead.";
 
diff --git a/third_party/WebKit/Source/core/frame/Frame.cpp b/third_party/WebKit/Source/core/frame/Frame.cpp
index 4a92e16..1c763fe 100644
--- a/third_party/WebKit/Source/core/frame/Frame.cpp
+++ b/third_party/WebKit/Source/core/frame/Frame.cpp
@@ -78,17 +78,6 @@
     m_host = nullptr;
 }
 
-void Frame::detachChildren()
-{
-    typedef HeapVector<Member<Frame>> FrameVector;
-    FrameVector childrenToDetach;
-    childrenToDetach.reserveCapacity(tree().childCount());
-    for (Frame* child = tree().firstChild(); child; child = child->tree().nextSibling())
-        childrenToDetach.append(child);
-    for (const auto& child : childrenToDetach)
-        child->detach(FrameDetachType::Remove);
-}
-
 void Frame::disconnectOwnerElement()
 {
     if (m_owner) {
diff --git a/third_party/WebKit/Source/core/frame/Frame.h b/third_party/WebKit/Source/core/frame/Frame.h
index 423e882..2fe7895 100644
--- a/third_party/WebKit/Source/core/frame/Frame.h
+++ b/third_party/WebKit/Source/core/frame/Frame.h
@@ -81,7 +81,6 @@
     virtual void reload(FrameLoadType, ClientRedirectPolicy) = 0;
 
     virtual void detach(FrameDetachType);
-    void detachChildren();
     void disconnectOwnerElement();
     virtual bool shouldClose() = 0;
 
diff --git a/third_party/WebKit/Source/core/frame/FrameConsole.cpp b/third_party/WebKit/Source/core/frame/FrameConsole.cpp
index 99f33fe..a27fb0c8 100644
--- a/third_party/WebKit/Source/core/frame/FrameConsole.cpp
+++ b/third_party/WebKit/Source/core/frame/FrameConsole.cpp
@@ -69,7 +69,8 @@
         consoleMessage->location()->columnNumber(),
         consoleMessage->location()->cloneStackTrace(),
         consoleMessage->location()->scriptId(),
-        IdentifiersFactory::requestId(consoleMessage->requestIdentifier()));
+        IdentifiersFactory::requestId(consoleMessage->requestIdentifier()),
+        consoleMessage->workerId());
 }
 
 void FrameConsole::reportMessageToClient(ConsoleMessage* consoleMessage)
@@ -95,14 +96,10 @@
     frame().chromeClient().addMessageToConsole(m_frame, consoleMessage->source(), consoleMessage->level(), consoleMessage->message(), consoleMessage->location()->lineNumber(), url, stackTrace);
 }
 
-void FrameConsole::reportWorkerMessage(ConsoleMessage* consoleMessage)
+void FrameConsole::addMessageFromWorker(ConsoleMessage* consoleMessage, const String& workerId)
 {
     reportMessageToClient(consoleMessage);
-}
-
-void FrameConsole::adoptWorkerMessage(ConsoleMessage* consoleMessage)
-{
-    addMessageToStorage(consoleMessage);
+    addMessageToStorage(ConsoleMessage::createFromWorker(consoleMessage->level(), consoleMessage->message(), consoleMessage->location() ? consoleMessage->location()->clone() : nullptr, workerId));
 }
 
 void FrameConsole::reportResourceResponseReceived(DocumentLoader* loader, unsigned long requestIdentifier, const ResourceResponse& response)
diff --git a/third_party/WebKit/Source/core/frame/FrameConsole.h b/third_party/WebKit/Source/core/frame/FrameConsole.h
index b345c332..7f305e4 100644
--- a/third_party/WebKit/Source/core/frame/FrameConsole.h
+++ b/third_party/WebKit/Source/core/frame/FrameConsole.h
@@ -51,12 +51,11 @@
     }
 
     void addMessage(ConsoleMessage*);
+    void addMessageFromWorker(ConsoleMessage*, const String& workerId);
+
     bool addMessageToStorage(ConsoleMessage*);
     void reportMessageToClient(ConsoleMessage*);
 
-    void reportWorkerMessage(ConsoleMessage*);
-    void adoptWorkerMessage(ConsoleMessage*);
-
     void reportResourceResponseReceived(DocumentLoader*, unsigned long requestIdentifier, const ResourceResponse&);
 
     void clearMessages();
diff --git a/third_party/WebKit/Source/core/frame/FrameView.cpp b/third_party/WebKit/Source/core/frame/FrameView.cpp
index e00f514..ca48f4a 100644
--- a/third_party/WebKit/Source/core/frame/FrameView.cpp
+++ b/third_party/WebKit/Source/core/frame/FrameView.cpp
@@ -79,6 +79,7 @@
 #include "core/page/FrameTree.h"
 #include "core/page/Page.h"
 #include "core/page/scrolling/ChildViewportScrollCallback.h"
+#include "core/page/scrolling/RootScrollerController.h"
 #include "core/page/scrolling/RootViewportScrollCallback.h"
 #include "core/page/scrolling/ScrollingCoordinator.h"
 #include "core/paint/FramePainter.h"
@@ -2556,6 +2557,7 @@
                 if (view.compositor()->inCompositingMode())
                     scrollingCoordinator()->updateAfterCompositingChangeIfNeeded();
 
+                m_frame->document()->rootScrollerController()->didUpdateCompositing();
                 updateCompositedSelectionIfNeeded();
             }
         }
@@ -2634,8 +2636,21 @@
 
 void FrameView::synchronizedPaintRecursively(GraphicsLayer* graphicsLayer)
 {
-    if (graphicsLayer->drawsContent())
+    if (graphicsLayer->drawsContent()) {
+        // Usually this is not needed because the PaintLayer will setup the chunk properties
+        // altogether. However in debug builds the GraphicsLayer could paint debug background before
+        // we ever reach the PaintLayer.
+        if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
+            PaintChunkProperties properties;
+            properties.transform = m_rootTransform;
+            properties.clip = m_rootClip;
+            properties.effect = m_rootEffect;
+            graphicsLayer->getPaintController().updateCurrentPaintChunkProperties(properties);
+        }
         graphicsLayer->paint(nullptr);
+        if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
+            graphicsLayer->getPaintController().updateCurrentPaintChunkProperties(PaintChunkProperties());
+    }
 
     if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
         if (GraphicsLayer* maskLayer = graphicsLayer->maskLayer())
@@ -4264,10 +4279,4 @@
     return m_subtreeThrottled || (m_hiddenForThrottling && m_crossOriginForThrottling);
 }
 
-LayoutBox& FrameView::boxForScrollControlPaintInvalidation() const
-{
-    ASSERT(!layoutViewItem().isNull());
-    return *layoutView();
-}
-
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/FrameView.h b/third_party/WebKit/Source/core/frame/FrameView.h
index e9c1059..0969307 100644
--- a/third_party/WebKit/Source/core/frame/FrameView.h
+++ b/third_party/WebKit/Source/core/frame/FrameView.h
@@ -40,6 +40,7 @@
 #include "platform/geometry/LayoutRect.h"
 #include "platform/graphics/Color.h"
 #include "platform/graphics/paint/ClipPaintPropertyNode.h"
+#include "platform/graphics/paint/EffectPaintPropertyNode.h"
 #include "platform/graphics/paint/TransformPaintPropertyNode.h"
 #include "platform/scroll/ScrollTypes.h"
 #include "platform/scroll/Scrollbar.h"
@@ -377,7 +378,6 @@
     IntPoint maximumScrollPosition() const override;
 
     // ScrollableArea interface
-    void scrollControlWasSetNeedsPaintInvalidation() override { }
     void getTickmarks(Vector<IntRect>&) const override;
     IntRect scrollableAreaBoundingBox() const override;
     bool scrollAnimatorEnabled() const override;
@@ -600,6 +600,15 @@
     void setContentClip(PassRefPtr<ClipPaintPropertyNode> contentClip) { m_contentClip = contentClip; }
     ClipPaintPropertyNode* contentClip() const { return m_contentClip.get(); }
 
+    void setRootTransform(PassRefPtr<TransformPaintPropertyNode> rootTransform) { m_rootTransform = rootTransform; }
+    TransformPaintPropertyNode* rootTransform() const { return m_rootTransform.get(); }
+
+    void setRootClip(PassRefPtr<ClipPaintPropertyNode> rootClip) { m_rootClip = rootClip; }
+    ClipPaintPropertyNode* rootClip() const { return m_rootClip.get(); }
+
+    void setRootEffect(PassRefPtr<EffectPaintPropertyNode> rootEffect) { m_rootEffect = rootEffect; }
+    EffectPaintPropertyNode* rootEffect() const { return m_rootEffect.get(); }
+
     // TODO(ojan): Merge this with IntersectionObserver once it lands.
     IntRect computeVisibleArea();
 
@@ -770,7 +779,6 @@
     void updateThrottlingStatus();
 
     // PaintInvalidationCapableScrollableArea
-    LayoutBox& boxForScrollControlPaintInvalidation() const override;
     LayoutScrollbarPart* resizer() const override { return nullptr; }
 
     void checkLayoutInvalidationIsAllowed() const;
@@ -910,6 +918,12 @@
     // TODO(trchen): This will not be needed once settings->rootLayerScrolls() is enabled.
     RefPtr<ClipPaintPropertyNode> m_contentClip;
 
+    // These nodes represent the root nodes of each property tree.
+    // Only the root frame should create them and they will be no-op.
+    RefPtr<TransformPaintPropertyNode> m_rootTransform;
+    RefPtr<ClipPaintPropertyNode> m_rootClip;
+    RefPtr<EffectPaintPropertyNode> m_rootEffect;
+
     // This is set on the local root frame view only.
     DocumentLifecycle::LifecycleState m_currentUpdateLifecyclePhasesTargetState;
 
diff --git a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
index a0980bf9..19537c9 100644
--- a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
@@ -104,11 +104,6 @@
     }
 
     // LocalFrameLifecycleObserver overrides:
-    void willDetachFrameHost() override
-    {
-        m_window->willDetachFrameHost();
-    }
-
     void contextDestroyed() override
     {
         m_window->frameDestroyed();
@@ -495,11 +490,6 @@
     return document() ? document()->mediaQueryMatcher().matchMedia(media) : nullptr;
 }
 
-void LocalDOMWindow::willDetachFrameHost()
-{
-    frame()->host()->eventHandlerRegistry().didRemoveAllEventHandlers(*this);
-}
-
 void LocalDOMWindow::frameDestroyed()
 {
     willDestroyDocumentInFrame();
@@ -514,12 +504,6 @@
         domWindowProperty->willDestroyGlobalObjectInFrame();
 }
 
-void LocalDOMWindow::willDetachDocumentFromFrame()
-{
-    for (const auto& domWindowProperty : m_properties)
-        domWindowProperty->willDetachGlobalObjectFromFrame();
-}
-
 void LocalDOMWindow::registerProperty(DOMWindowProperty* property)
 {
     m_properties.add(property);
diff --git a/third_party/WebKit/Source/core/frame/LocalDOMWindow.h b/third_party/WebKit/Source/core/frame/LocalDOMWindow.h
index 663e29e..d1db19f 100644
--- a/third_party/WebKit/Source/core/frame/LocalDOMWindow.h
+++ b/third_party/WebKit/Source/core/frame/LocalDOMWindow.h
@@ -193,8 +193,6 @@
     // recurse on its child frames.
     void sendOrientationChangeEvent();
 
-    void willDetachDocumentFromFrame();
-
     EventQueue* getEventQueue() const;
     void enqueueWindowEvent(Event*);
     void enqueueDocumentEvent(Event*);
diff --git a/third_party/WebKit/Source/core/frame/LocalFrame.cpp b/third_party/WebKit/Source/core/frame/LocalFrame.cpp
index ebf4ce703..8c9fb0d 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrame.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalFrame.cpp
@@ -31,6 +31,7 @@
 
 #include "bindings/core/v8/ScriptController.h"
 #include "core/InstrumentingAgents.h"
+#include "core/dom/ChildFrameDisconnector.h"
 #include "core/dom/DocumentType.h"
 #include "core/dom/StyleChangeReason.h"
 #include "core/editing/EditingUtilities.h"
@@ -239,6 +240,8 @@
 
 } // namespace
 
+template class CORE_TEMPLATE_EXPORT Supplement<LocalFrame>;
+
 LocalFrame* LocalFrame::create(FrameLoaderClient* client, FrameHost* host, FrameOwner* owner, ServiceRegistry* serviceRegistry)
 {
     LocalFrame* frame = new LocalFrame(client, host, owner, serviceRegistry ? serviceRegistry : ServiceRegistry::getEmptyServiceRegistry());
@@ -404,13 +407,25 @@
     // back to FrameLoaderClient via WindowProxy.
     script().clearForClose();
     setView(nullptr);
-    willDetachFrameHost();
-    InspectorInstrumentation::frameDetachedFromParent(this);
-    Frame::detach(type);
+
+    m_host->eventHandlerRegistry().didRemoveAllEventHandlers(*localDOMWindow());
 
     // Signal frame destruction here rather than in the destructor.
     // Main motivation is to avoid being dependent on its exact timing (Oilpan.)
     LocalFrameLifecycleNotifier::notifyContextDestroyed();
+
+    // TODO: Page should take care of updating focus/scrolling instead of Frame.
+    // TODO: It's unclear as to why this is called more than once, but it is,
+    // so page() could be null.
+    if (page() && page()->focusController().focusedFrame() == this)
+        page()->focusController().setFocusedFrame(nullptr);
+
+    if (page() && page()->scrollingCoordinator() && m_view)
+        page()->scrollingCoordinator()->willDestroyScrollableArea(m_view.get());
+
+    InspectorInstrumentation::frameDetachedFromParent(this);
+    Frame::detach(type);
+
     m_supplements.clear();
     WeakIdentifierMap<LocalFrame>::notifyObjectDestroyed(this);
 }
@@ -447,18 +462,12 @@
     return m_loader.shouldClose();
 }
 
-void LocalFrame::willDetachFrameHost()
+void LocalFrame::detachChildren()
 {
-    LocalFrameLifecycleNotifier::notifyWillDetachFrameHost();
+    DCHECK(m_loader.stateMachine()->creatingInitialEmptyDocument() || document());
 
-    // FIXME: Page should take care of updating focus/scrolling instead of Frame.
-    // FIXME: It's unclear as to why this is called more than once, but it is,
-    // so page() could be null.
-    if (page() && page()->focusController().focusedFrame() == this)
-        page()->focusController().setFocusedFrame(nullptr);
-
-    if (page() && page()->scrollingCoordinator() && m_view)
-        page()->scrollingCoordinator()->willDestroyScrollableArea(m_view.get());
+    if (Document* document = this->document())
+        ChildFrameDisconnector(*document).disconnect();
 }
 
 void LocalFrame::setDOMWindow(LocalDOMWindow* domWindow)
diff --git a/third_party/WebKit/Source/core/frame/LocalFrame.h b/third_party/WebKit/Source/core/frame/LocalFrame.h
index 2165cca6..5e22840 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrame.h
+++ b/third_party/WebKit/Source/core/frame/LocalFrame.h
@@ -78,7 +78,9 @@
 class WebFrameHostScheduler;
 class WebFrameScheduler;
 
-class CORE_EXPORT LocalFrame : public Frame, public LocalFrameLifecycleNotifier, public Supplementable<LocalFrame> {
+extern template class CORE_EXTERN_TEMPLATE_EXPORT Supplement<LocalFrame>;
+
+class CORE_EXPORT LocalFrame final : public Frame, public LocalFrameLifecycleNotifier, public Supplementable<LocalFrame> {
     USING_GARBAGE_COLLECTED_MIXIN(LocalFrame);
 public:
     static LocalFrame* create(FrameLoaderClient*, FrameHost*, FrameOwner*, ServiceRegistry* = nullptr);
@@ -104,7 +106,7 @@
     bool prepareForCommit() override;
     void didChangeVisibilityState() override;
 
-    void willDetachFrameHost();
+    void detachChildren();
 
     LocalDOMWindow* localDOMWindow() const;
     void setDOMWindow(LocalDOMWindow*);
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameLifecycleNotifier.cpp b/third_party/WebKit/Source/core/frame/LocalFrameLifecycleNotifier.cpp
deleted file mode 100644
index 1c741bc..0000000
--- a/third_party/WebKit/Source/core/frame/LocalFrameLifecycleNotifier.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "core/frame/LocalFrameLifecycleNotifier.h"
-
-#include "core/frame/LocalFrameLifecycleObserver.h"
-
-namespace blink {
-
-void LocalFrameLifecycleNotifier::notifyWillDetachFrameHost()
-{
-    TemporaryChange<IterationState> scope(m_iterationState, AllowingNone);
-    for (LocalFrameLifecycleObserver* observer : m_observers)
-        observer->willDetachFrameHost();
-}
-
-} // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameLifecycleNotifier.h b/third_party/WebKit/Source/core/frame/LocalFrameLifecycleNotifier.h
index e2a18cd0..0a9c8343 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrameLifecycleNotifier.h
+++ b/third_party/WebKit/Source/core/frame/LocalFrameLifecycleNotifier.h
@@ -15,8 +15,6 @@
 class LocalFrame;
 
 class CORE_EXPORT LocalFrameLifecycleNotifier : public LifecycleNotifier<LocalFrame, LocalFrameLifecycleObserver> {
-public:
-    void notifyWillDetachFrameHost();
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameLifecycleObserver.h b/third_party/WebKit/Source/core/frame/LocalFrameLifecycleObserver.h
index 7fa60acf..7dbe92d 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrameLifecycleObserver.h
+++ b/third_party/WebKit/Source/core/frame/LocalFrameLifecycleObserver.h
@@ -37,7 +37,6 @@
 
 class CORE_EXPORT LocalFrameLifecycleObserver : public LifecycleObserver<LocalFrame, LocalFrameLifecycleObserver> {
 public:
-    virtual void willDetachFrameHost() { }
     virtual void contextDestroyed()
     {
         setContext(nullptr);
diff --git a/third_party/WebKit/Source/core/frame/RemoteFrame.cpp b/third_party/WebKit/Source/core/frame/RemoteFrame.cpp
index f7eb7a0..0c3c253a 100644
--- a/third_party/WebKit/Source/core/frame/RemoteFrame.cpp
+++ b/third_party/WebKit/Source/core/frame/RemoteFrame.cpp
@@ -196,4 +196,15 @@
     client()->advanceFocus(type, source);
 }
 
+void RemoteFrame::detachChildren()
+{
+    using FrameVector = HeapVector<Member<Frame>>;
+    FrameVector childrenToDetach;
+    childrenToDetach.reserveCapacity(tree().childCount());
+    for (Frame* child = tree().firstChild(); child; child = child->tree().nextSibling())
+        childrenToDetach.append(child);
+    for (const auto& child : childrenToDetach)
+        child->detach(FrameDetachType::Remove);
+}
+
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/RemoteFrame.h b/third_party/WebKit/Source/core/frame/RemoteFrame.h
index ebd1fe4..dbdcdd6 100644
--- a/third_party/WebKit/Source/core/frame/RemoteFrame.h
+++ b/third_party/WebKit/Source/core/frame/RemoteFrame.h
@@ -22,7 +22,7 @@
 class WindowProxyManager;
 struct FrameLoadRequest;
 
-class CORE_EXPORT RemoteFrame: public Frame {
+class CORE_EXPORT RemoteFrame final : public Frame {
 public:
     static RemoteFrame* create(RemoteFrameClient*, FrameHost*, FrameOwner*);
 
@@ -71,6 +71,8 @@
     bool isLocalFrame() const override { return false; }
     bool isRemoteFrame() const override { return true; }
 
+    void detachChildren();
+
     Member<RemoteFrameView> m_view;
     Member<RemoteSecurityContext> m_securityContext;
     Member<RemoteDOMWindow> m_domWindow;
diff --git a/third_party/WebKit/Source/core/frame/Settings.in b/third_party/WebKit/Source/core/frame/Settings.in
index 02251c7..79630435 100644
--- a/third_party/WebKit/Source/core/frame/Settings.in
+++ b/third_party/WebKit/Source/core/frame/Settings.in
@@ -411,3 +411,7 @@
 # Use default interpolation quality to scale bitmap images if quality is not determined
 # in other ways. This can help us writing reftests containing scaled images.
 useDefaultImageInterpolationQuality initial=false
+
+# Variant of the ParseHTMLOnMainThread experiment. One experiment immediately
+# tokenizes input bytes. The default is to tokenize with a post task.
+parseHTMLOnMainThreadSyncTokenize initial=false
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.h b/third_party/WebKit/Source/core/frame/UseCounter.h
index 5708f12..8c1202cd 100644
--- a/third_party/WebKit/Source/core/frame/UseCounter.h
+++ b/third_party/WebKit/Source/core/frame/UseCounter.h
@@ -625,7 +625,6 @@
         CSSKeyframesRuleAnonymousIndexedGetter = 785,
         V8Screen_AvailLeft_AttributeGetter = 786,
         V8Screen_AvailTop_AttributeGetter = 787,
-        ObjectObserve = 788,
         V8SVGFEConvolveMatrixElement_PreserveAlpha_AttributeGetter = 791,
         V8SVGStyleElement_Disabled_AttributeGetter = 798,
         V8SVGStyleElement_Disabled_AttributeSetter = 799,
@@ -1034,7 +1033,6 @@
         HTMLMediaElement = 1229,
         HTMLMediaElementInDocument = 1230,
         HTMLMediaElementControlsAttribute = 1231,
-        SVGZoomEvent = 1232,
         V8Animation_Oncancel_AttributeGetter = 1233,
         V8Animation_Oncancel_AttributeSetter = 1234,
         V8HTMLCommentInExternalScript = 1235,
diff --git a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
index 4dede477..ca1f5ac6 100644
--- a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
@@ -36,6 +36,7 @@
 #include "core/dom/Element.h"
 #include "core/dom/ElementTraversal.h"
 #include "core/dom/ExceptionCode.h"
+#include "core/dom/TaskRunnerHelper.h"
 #include "core/fileapi/File.h"
 #include "core/frame/ImageBitmap.h"
 #include "core/frame/LocalFrame.h"
@@ -680,7 +681,7 @@
 
     if (!isPaintable()) {
         // If the canvas element's bitmap has no pixels
-        document().unthrottledTaskRunner()->postTask(BLINK_FROM_HERE, WTF::bind(&BlobCallback::handleEvent, wrapPersistent(callback), nullptr));
+        TaskRunnerHelper::getUnthrottledTaskRunner(&document())->postTask(BLINK_FROM_HERE, WTF::bind(&BlobCallback::handleEvent, wrapPersistent(callback), nullptr));
         return;
     }
 
diff --git a/third_party/WebKit/Source/core/html/HTMLElement.cpp b/third_party/WebKit/Source/core/html/HTMLElement.cpp
index 5160f599..c65115f 100644
--- a/third_party/WebKit/Source/core/html/HTMLElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLElement.cpp
@@ -737,7 +737,8 @@
     while (node) {
         // Skip bdi, script, style and text form controls.
         if (equalIgnoringCase(node->nodeName(), "bdi") || isHTMLScriptElement(*node) || isHTMLStyleElement(*node)
-            || (node->isElementNode() && toElement(node)->isTextFormControl())) {
+            || (node->isElementNode() && toElement(node)->isTextFormControl())
+            || (node->isElementNode() && toElement(node)->shadowPseudoId() == "-webkit-input-placeholder")) {
             node = FlatTreeTraversal::nextSkippingChildren(*node, this);
             continue;
         }
diff --git a/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp b/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp
index 02edf50..c39608b 100644
--- a/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp
@@ -123,13 +123,13 @@
     return m_multiple ? selectMultiple : selectOne;
 }
 
-void HTMLSelectElement::optionSelectedByUser(int optionIndex, bool fireOnChangeNow, bool allowMultipleSelection)
+void HTMLSelectElement::optionSelectedByUser(int optionIndex, bool fireOnChangeNow)
 {
     // User interaction such as mousedown events can cause list box select
     // elements to send change events.  This produces that same behavior for
     // changes triggered by other code running on behalf of the user.
     if (!usesMenuList()) {
-        updateSelectedState(item(optionIndex), allowMultipleSelection, false);
+        updateSelectedState(item(optionIndex), false, false);
         setNeedsValidityCheck();
         if (fireOnChangeNow)
             listBoxOnChange();
@@ -208,14 +208,14 @@
     return validationMessage();
 }
 
-void HTMLSelectElement::listBoxSelectItem(int listIndex, bool allowMultiplySelections, bool shift, bool fireOnChangeNow)
+void HTMLSelectElement::listBoxSelectItem(int listIndex, bool allowMultiplySelections, bool fireOnChangeNow)
 {
     if (!multiple()) {
-        optionSelectedByUser(listToOptionIndex(listIndex), fireOnChangeNow, false);
+        optionSelectedByUser(listToOptionIndex(listIndex), fireOnChangeNow);
     } else {
         HTMLElement* element = listItems()[listIndex];
         if (isHTMLOptionElement(element))
-            updateSelectedState(toHTMLOptionElement(element), allowMultiplySelections, shift);
+            updateSelectedState(toHTMLOptionElement(element), allowMultiplySelections, false);
         setNeedsValidityCheck();
         if (fireOnChangeNow)
             listBoxOnChange();
diff --git a/third_party/WebKit/Source/core/html/HTMLSelectElement.h b/third_party/WebKit/Source/core/html/HTMLSelectElement.h
index 37055b45..ae02da4 100644
--- a/third_party/WebKit/Source/core/html/HTMLSelectElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLSelectElement.h
@@ -56,8 +56,6 @@
     int selectedIndex() const;
     void setSelectedIndex(int);
 
-    void optionSelectedByUser(int index, bool dispatchChangeEvent, bool allowMultipleSelection = false);
-
     // For ValidityState
     String validationMessage() const override;
     bool valueMissing() const override;
@@ -114,8 +112,6 @@
     void scrollToSelection();
     void scrollToOption(HTMLOptionElement*);
 
-    void listBoxSelectItem(int listIndex, bool allowMultiplySelections, bool shift, bool fireOnChangeNow = true);
-
     bool canSelectAll() const;
     void selectAll();
     int listToOptionIndex(int listIndex) const;
@@ -154,6 +150,9 @@
     // Text starting offset in RTL.
     LayoutUnit clientPaddingRight() const;
     void valueChanged(unsigned listIndex);
+    // TODO(tkent): Rename this. This is used only for multiple-selection
+    // menulist.
+    void listBoxSelectItem(int listIndex, bool allowMultiplySelections, bool fireOnChangeNow);
     // A popup is canceled when the popup was hidden without selecting an item.
     void popupDidCancel();
     // Provisional selection is a selection made using arrow keys or type ahead.
@@ -222,6 +221,7 @@
 
     bool hasPlaceholderLabelOption() const;
 
+    void optionSelectedByUser(int optionIndex, bool dispatchChangeEvent);
     enum SelectOptionFlag {
         DeselectOtherOptions = 1 << 0,
         DispatchInputAndChangeEvent = 1 << 1,
diff --git a/third_party/WebKit/Source/core/html/RelList.cpp b/third_party/WebKit/Source/core/html/RelList.cpp
index 3b4bd7d..a05e349 100644
--- a/third_party/WebKit/Source/core/html/RelList.cpp
+++ b/third_party/WebKit/Source/core/html/RelList.cpp
@@ -37,28 +37,31 @@
     m_relValues.set(value, SpaceSplitString::ShouldNotFoldCase);
 }
 
-static RelList::SupportedTokens& supportedTokens()
+static HashSet<AtomicString>& supportedTokens()
 {
-    DEFINE_STATIC_LOCAL(RelList::SupportedTokens, supportedValuesMap, ());
-    if (supportedValuesMap.isEmpty()) {
-        supportedValuesMap.add("preload");
-        supportedValuesMap.add("preconnect");
-        supportedValuesMap.add("dns-prefetch");
-        supportedValuesMap.add("stylesheet");
-        supportedValuesMap.add("import");
-        supportedValuesMap.add("icon");
-        supportedValuesMap.add("alternate");
-        supportedValuesMap.add("prefetch");
-        supportedValuesMap.add("prerender");
-        supportedValuesMap.add("next");
-        supportedValuesMap.add("manifest");
-        supportedValuesMap.add("apple-touch-icon");
-        supportedValuesMap.add("apple-touch-icon-precomposed");
+    DEFINE_STATIC_LOCAL(HashSet<AtomicString>, tokens, ());
+
+    if (tokens.isEmpty()) {
+        tokens = {
+            "preload",
+            "preconnect",
+            "dns-prefetch",
+            "stylesheet",
+            "import",
+            "icon",
+            "alternate",
+            "prefetch",
+            "prerender",
+            "next",
+            "manifest",
+            "apple-touch-icon",
+            "apple-touch-icon-precomposed",
+        };
         if (RuntimeEnabledFeatures::linkServiceWorkerEnabled())
-            supportedValuesMap.add("serviceworker");
+            tokens.add("serviceworker");
     }
 
-    return supportedValuesMap;
+    return tokens;
 }
 
 bool RelList::validateTokenValue(const AtomicString& tokenValue, ExceptionState&) const
diff --git a/third_party/WebKit/Source/core/html/RelList.h b/third_party/WebKit/Source/core/html/RelList.h
index 0da3940..3c0a363 100644
--- a/third_party/WebKit/Source/core/html/RelList.h
+++ b/third_party/WebKit/Source/core/html/RelList.h
@@ -27,8 +27,6 @@
 
     DECLARE_VIRTUAL_TRACE();
 
-    using SupportedTokens = HashSet<AtomicString>;
-
 private:
     explicit RelList(Element*);
 
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp b/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp
index 7acad44..33ce143 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp
@@ -32,6 +32,7 @@
 #include "core/dom/DocumentFragment.h"
 #include "core/dom/DocumentType.h"
 #include "core/dom/Element.h"
+#include "core/dom/ElementTraversal.h"
 #include "core/dom/ScriptLoader.h"
 #include "core/dom/TemplateContentDocumentFragment.h"
 #include "core/dom/Text.h"
@@ -324,14 +325,19 @@
     ASSERT(m_document->isHTMLDocument() || m_document->isXHTMLDocument());
 }
 
-void HTMLConstructionSite::initFragmentParsing(DocumentFragment* fragment)
+void HTMLConstructionSite::initFragmentParsing(DocumentFragment* fragment, Element* contextElement)
 {
+    DCHECK(contextElement);
     DCHECK_EQ(m_document, &fragment->document());
     DCHECK_EQ(m_inQuirksMode, fragment->document().inQuirksMode());
     DCHECK(!m_isParsingFragment);
+    DCHECK(!m_form);
 
     m_attachmentRoot = fragment;
     m_isParsingFragment = true;
+
+    if (!contextElement->document().isTemplateDocument())
+        m_form = Traversal<HTMLFormElement>::firstAncestorOrSelf(*contextElement);
 }
 
 HTMLConstructionSite::~HTMLConstructionSite()
@@ -366,13 +372,6 @@
     m_attachmentRoot = nullptr;
 }
 
-void HTMLConstructionSite::setForm(HTMLFormElement* form)
-{
-    // This method should only be needed for HTMLTreeBuilder in the fragment case.
-    ASSERT(!m_form);
-    m_form = form;
-}
-
 HTMLFormElement* HTMLConstructionSite::takeForm()
 {
     return m_form.release();
@@ -600,10 +599,12 @@
 {
     HTMLElement* element = createHTMLElement(token);
     ASSERT(isHTMLFormElement(element));
-    m_form = toHTMLFormElement(element);
-    m_form->setDemoted(isDemoted);
-    attachLater(currentNode(), m_form.get());
-    m_openElements.push(HTMLStackItem::create(m_form.get(), token));
+    HTMLFormElement* formElement = toHTMLFormElement(element);
+    if (!ownerDocumentForCurrentNode().isTemplateDocument())
+        m_form = formElement;
+    formElement->setDemoted(isDemoted);
+    attachLater(currentNode(), formElement);
+    m_openElements.push(HTMLStackItem::create(formElement, token));
 }
 
 void HTMLConstructionSite::insertHTMLElement(AtomicHTMLToken* token)
@@ -751,7 +752,7 @@
     Document& document = ownerDocumentForCurrentNode();
     // Only associate the element with the current form if we're creating the new element
     // in a document with a browsing context (rather than in <template> contents).
-    HTMLFormElement* form = document.frame() ? m_form.get() : 0;
+    HTMLFormElement* form = document.frame() ? m_form.get() : nullptr;
     // FIXME: This can't use HTMLConstructionSite::createElement because we
     // have to pass the current form element.  We should rework form association
     // to occur after construction to allow better code sharing here.
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.h b/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.h
index ea9952d..3d661623 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.h
+++ b/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.h
@@ -113,7 +113,7 @@
     ~HTMLConstructionSite();
     DECLARE_TRACE();
 
-    void initFragmentParsing(DocumentFragment*);
+    void initFragmentParsing(DocumentFragment*, Element* contextElement);
 
     void detach();
 
@@ -196,8 +196,7 @@
     Element* head() const { return m_head->element(); }
     HTMLStackItem* headStackItem() const { return m_head.get(); }
 
-    void setForm(HTMLFormElement*);
-    HTMLFormElement* form() const { return m_form.get(); }
+    bool isFormElementPointerNonNull() const { return m_form; }
     HTMLFormElement* takeForm();
 
     ParserContentPolicy getParserContentPolicy() { return m_parserContentPolicy; }
@@ -251,7 +250,9 @@
     // and a Document in all other cases.
     Member<ContainerNode> m_attachmentRoot;
 
+    // https://html.spec.whatwg.org/multipage/syntax.html#head-element-pointer
     Member<HTMLStackItem> m_head;
+    // https://html.spec.whatwg.org/multipage/syntax.html#form-element-pointer
     Member<HTMLFormElement> m_form;
     mutable HTMLElementStack m_openElements;
     mutable HTMLFormattingElementList m_activeFormattingElements;
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp
index d2552b0..18f5934 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp
@@ -30,6 +30,7 @@
 #include "core/css/resolver/StyleResolver.h"
 #include "core/dom/DocumentFragment.h"
 #include "core/dom/Element.h"
+#include "core/dom/TaskRunnerHelper.h"
 #include "core/fetch/ResourceFetcher.h"
 #include "core/frame/LocalFrame.h"
 #include "core/frame/Settings.h"
@@ -111,7 +112,7 @@
     , m_options(&document)
     , m_token(syncPolicy == ForceSynchronousParsing ? wrapUnique(new HTMLToken) : nullptr)
     , m_tokenizer(syncPolicy == ForceSynchronousParsing ? HTMLTokenizer::create(m_options) : nullptr)
-    , m_loadingTaskRunner(wrapUnique(document.loadingTaskRunner()->clone()))
+    , m_loadingTaskRunner(wrapUnique(TaskRunnerHelper::getLoadingTaskRunner(&document)->clone()))
     , m_parserScheduler(syncPolicy == AllowAsynchronousParsing ? HTMLParserScheduler::create(this, m_loadingTaskRunner.get()) : nullptr)
     , m_xssAuditorDelegate(&document)
     , m_weakFactory(this)
@@ -314,13 +315,19 @@
         // after the document element is created in documentElementAvailable().
         ASSERT(m_queuedPreloads.isEmpty());
         ASSERT(m_queuedDocumentWriteScripts.isEmpty());
+        // Loop through the chunks to generate preloads before any
+        // document.write script evaluation takes place. Preloading these
+        // scripts is valuable and comparably cheap, while evaluating JS can be
+        // expensive.
+        for (auto& chunk : pendingChunks) {
+            m_preloader->takeAndPreload(chunk->preloads);
+        }
         for (auto& chunk : pendingChunks) {
             for (auto& index : chunk->likelyDocumentWriteScriptIndices) {
                 const CompactHTMLToken& token = chunk->tokens->at(index);
                 ASSERT(token.type() == HTMLToken::TokenType::Character);
                 evaluateAndPreloadScriptForDocumentWrite(token.data());
             }
-            m_preloader->takeAndPreload(chunk->preloads);
         }
     }
 
@@ -1025,7 +1032,8 @@
         memcpy(buffer->data(), data, length);
         TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.debug"), "HTMLDocumentParser::appendBytes", "size", (unsigned)length);
 
-        postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::appendRawBytesFromMainThread, m_backgroundParser, passed(std::move(buffer)), bytesReceivedTime));
+        LookaheadParserTaskSynchrony policy = document()->settings() && document()->settings()->parseHTMLOnMainThreadSyncTokenize() ? Synchronous : Asynchronous;
+        postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::appendRawBytesFromMainThread, m_backgroundParser, passed(std::move(buffer)), bytesReceivedTime), policy);
         return;
     }
 
@@ -1068,13 +1076,14 @@
 {
     TRACE_EVENT0("blink,loader", "HTMLDocumentParser::documentElementAvailable");
     DCHECK(document()->documentElement());
+    if (!m_queuedPreloads.isEmpty())
+        m_preloader->takeAndPreload(m_queuedPreloads);
+
     for (const String& scriptSource : m_queuedDocumentWriteScripts) {
         evaluateAndPreloadScriptForDocumentWrite(scriptSource);
     }
 
     m_queuedDocumentWriteScripts.clear();
-    if (!m_queuedPreloads.isEmpty())
-        m_preloader->takeAndPreload(m_queuedPreloads);
 }
 
 std::unique_ptr<HTMLPreloadScanner> HTMLDocumentParser::createPreloadScanner()
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.cpp b/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.cpp
index f5839e7..01c77ad 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.cpp
@@ -32,6 +32,7 @@
 #include "core/dom/Element.h"
 #include "core/dom/IgnoreDestructiveWriteCountIncrementer.h"
 #include "core/dom/ScriptLoader.h"
+#include "core/dom/TaskRunnerHelper.h"
 #include "core/events/Event.h"
 #include "core/fetch/ScriptResource.h"
 #include "core/frame/LocalFrame.h"
@@ -358,7 +359,7 @@
         if (m_document->frame()) {
             ScriptState* scriptState = ScriptState::forMainWorld(m_document->frame());
             if (scriptState)
-                ScriptStreamer::startStreaming(m_parserBlockingScript.get(), ScriptStreamer::ParsingBlocking, m_document->frame()->settings(), scriptState, m_document->loadingTaskRunner());
+                ScriptStreamer::startStreaming(m_parserBlockingScript.get(), ScriptStreamer::ParsingBlocking, m_document->frame()->settings(), scriptState, TaskRunnerHelper::getLoadingTaskRunner(m_document));
         }
 
         m_parserBlockingScript->watchForLoad(this);
@@ -374,7 +375,7 @@
     if (m_document->frame() && !pendingScript->isReady()) {
         ScriptState* scriptState = ScriptState::forMainWorld(m_document->frame());
         if (scriptState)
-            ScriptStreamer::startStreaming(pendingScript, ScriptStreamer::Deferred, m_document->frame()->settings(), scriptState, m_document->loadingTaskRunner());
+            ScriptStreamer::startStreaming(pendingScript, ScriptStreamer::Deferred, m_document->frame()->settings(), scriptState, TaskRunnerHelper::getLoadingTaskRunner(m_document));
     }
 
     ASSERT(pendingScript->resource());
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilder.cpp b/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilder.cpp
index 7e8382c6..7461e3f6 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilder.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilder.cpp
@@ -38,6 +38,7 @@
 #include "core/frame/UseCounter.h"
 #include "core/html/HTMLDocument.h"
 #include "core/html/HTMLFormElement.h"
+#include "core/html/HTMLTemplateElement.h"
 #include "core/html/parser/AtomicHTMLToken.h"
 #include "core/html/parser/HTMLDocumentParser.h"
 #include "core/html/parser/HTMLParserIdioms.h"
@@ -133,12 +134,6 @@
     return tagName == aTag || isNonAnchorFormattingTag(tagName);
 }
 
-static HTMLFormElement* closestFormAncestor(Element& element)
-{
-    ASSERT(isMainThread());
-    return Traversal<HTMLFormElement>::firstAncestorOrSelf(element);
-}
-
 class HTMLTreeBuilder::CharacterTokenBuffer {
     WTF_MAKE_NONCOPYABLE(CharacterTokenBuffer);
 public:
@@ -287,7 +282,7 @@
 {
     ASSERT(isMainThread());
     ASSERT(contextElement);
-    m_tree.initFragmentParsing(fragment);
+    m_tree.initFragmentParsing(fragment, contextElement);
     m_fragmentContext.init(fragment, contextElement);
 
     // Steps 4.2-4.6 of the HTML5 Fragment Case parsing algorithm:
@@ -300,7 +295,6 @@
         m_templateInsertionModes.append(TemplateContentsMode);
 
     resetInsertionModeAppropriately();
-    m_tree.setForm(closestFormAncestor(*contextElement));
 }
 
 HTMLTreeBuilder::~HTMLTreeBuilder()
@@ -674,7 +668,7 @@
         return;
     }
     if (token->name() == formTag) {
-        if (m_tree.form()) {
+        if (m_tree.isFormElementPointerNonNull() && !isParsingTemplateContents()) {
             parseError(token);
             return;
         }
@@ -1039,7 +1033,7 @@
     }
     if (token->name() == formTag) {
         parseError(token);
-        if (m_tree.form())
+        if (m_tree.isFormElementPointerNonNull() && !isParsingTemplateContents())
             return;
         m_tree.insertHTMLFormElement(token, true);
         m_tree.openElements()->pop();
@@ -1791,7 +1785,7 @@
         m_tree.openElements()->popUntilPopped(token->name());
         return;
     }
-    if (token->name() == formTag) {
+    if (token->name() == formTag && !isParsingTemplateContents()) {
         Element* node = m_tree.takeForm();
         if (!node || !m_tree.openElements()->inScope(node)) {
             parseError(token);
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLViewSourceParser.cpp b/third_party/WebKit/Source/core/html/parser/HTMLViewSourceParser.cpp
index b3f5675..525ac2d 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLViewSourceParser.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLViewSourceParser.cpp
@@ -73,7 +73,10 @@
 {
     if (!m_input.haveSeenEndOfFile())
         m_input.markEndOfFile();
-    pumpTokenizer();
+
+    if (!isDetached())
+        pumpTokenizer();
+
     document()->finishedParsing();
 }
 
diff --git a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp
index 6949fe78..4b5f6e5d 100644
--- a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp
+++ b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp
@@ -220,19 +220,19 @@
     if (arrayBuffer->byteLength() >= longTaskByteLengthThreshold)
         taskSize = BackgroundTaskRunner::TaskSizeLongRunningTask;
     WebTaskRunner* taskRunner = Platform::current()->currentThread()->getWebTaskRunner();
-    BackgroundTaskRunner::postOnBackgroundThread(BLINK_FROM_HERE, crossThreadBind(&ImageBitmapFactories::ImageBitmapLoader::decodeImageOnDecoderThread, wrapCrossThreadPersistent(this), crossThreadUnretained(taskRunner), wrapCrossThreadPersistent(arrayBuffer)), taskSize);
+    BackgroundTaskRunner::postOnBackgroundThread(BLINK_FROM_HERE, crossThreadBind(&ImageBitmapFactories::ImageBitmapLoader::decodeImageOnDecoderThread, wrapCrossThreadPersistent(this), crossThreadUnretained(taskRunner), wrapCrossThreadPersistent(arrayBuffer), m_options.premultiplyAlpha(), m_options.colorSpaceConversion()), taskSize);
 }
 
-void ImageBitmapFactories::ImageBitmapLoader::decodeImageOnDecoderThread(WebTaskRunner* taskRunner, DOMArrayBuffer* arrayBuffer)
+void ImageBitmapFactories::ImageBitmapLoader::decodeImageOnDecoderThread(WebTaskRunner* taskRunner, DOMArrayBuffer* arrayBuffer, const String& premultiplyAlphaOption, const String& colorSpaceConversionOption)
 {
     ASSERT(!isMainThread());
     RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(static_cast<char*>(arrayBuffer->data()), static_cast<size_t>(arrayBuffer->byteLength()));
 
     ImageDecoder::AlphaOption alphaOp = ImageDecoder::AlphaPremultiplied;
-    if (m_options.premultiplyAlpha() == "none")
+    if (premultiplyAlphaOption == "none")
         alphaOp = ImageDecoder::AlphaNotPremultiplied;
     ImageDecoder::GammaAndColorProfileOption colorSpaceOp = ImageDecoder::GammaAndColorProfileApplied;
-    if (m_options.colorSpaceConversion() == "none")
+    if (colorSpaceConversionOption == "none")
         colorSpaceOp = ImageDecoder::GammaAndColorProfileIgnored;
     std::unique_ptr<ImageDecoder> decoder(ImageDecoder::create(*sharedBuffer, alphaOp, colorSpaceOp));
     RefPtr<SkImage> frame;
diff --git a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.h b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.h
index d17c2cc..3b309fba 100644
--- a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.h
+++ b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.h
@@ -92,7 +92,7 @@
         void rejectPromise();
 
         void scheduleAsyncImageBitmapDecoding(DOMArrayBuffer*);
-        void decodeImageOnDecoderThread(WebTaskRunner*, DOMArrayBuffer*);
+        void decodeImageOnDecoderThread(WebTaskRunner*, DOMArrayBuffer*, const String& premultiplyAlphaOption, const String& colorSpaceConversionOption);
         void resolvePromiseOnOriginalThread(PassRefPtr<SkImage>);
 
         // FileReaderLoaderClient
diff --git a/third_party/WebKit/Source/core/input/ScrollManager.cpp b/third_party/WebKit/Source/core/input/ScrollManager.cpp
index 4ca7998..33e6f466a 100644
--- a/third_party/WebKit/Source/core/input/ScrollManager.cpp
+++ b/third_party/WebKit/Source/core/input/ScrollManager.cpp
@@ -16,6 +16,7 @@
 #include "core/page/AutoscrollController.h"
 #include "core/page/Page.h"
 #include "core/page/scrolling/OverscrollController.h"
+#include "core/page/scrolling/RootScrollerController.h"
 #include "core/page/scrolling/ScrollState.h"
 #include "core/paint/PaintLayer.h"
 #include "platform/PlatformGestureEvent.h"
@@ -194,10 +195,6 @@
     if (document->layoutViewItem().isNull())
         return WebInputEventResult::NotHandled;
 
-    FrameView* view = m_frame->view();
-    if (!view)
-        return WebInputEventResult::NotHandled;
-
     // If there's no layoutObject on the node, send the event to the nearest ancestor with a layoutObject.
     // Needed for <option> and <optgroup> elements so we can touch scroll <select>s
     while (m_scrollGestureHandlingNode && !m_scrollGestureHandlingNode->layoutObject())
@@ -350,12 +347,15 @@
     if (!node.isElementNode())
         return false;
 
-    return node.isSameNode(m_frame->document()->effectiveRootScroller());
+    return node.isSameNode(m_frame->document()->rootScrollerController()->effectiveRootScroller());
 }
 
 
 WebInputEventResult ScrollManager::handleGestureScrollEvent(const PlatformGestureEvent& gestureEvent)
 {
+    if (!m_frame->view())
+        return WebInputEventResult::NotHandled;
+
     Node* eventTarget = nullptr;
     Scrollbar* scrollbar = nullptr;
     if (gestureEvent.type() != PlatformEvent::GestureScrollBegin) {
diff --git a/third_party/WebKit/Source/core/inspector/ConsoleMessage.cpp b/third_party/WebKit/Source/core/inspector/ConsoleMessage.cpp
index 446c84c..f1584a95 100644
--- a/third_party/WebKit/Source/core/inspector/ConsoleMessage.cpp
+++ b/third_party/WebKit/Source/core/inspector/ConsoleMessage.cpp
@@ -18,6 +18,7 @@
     return consoleMessage;
 }
 
+// static
 ConsoleMessage* ConsoleMessage::create(MessageSource source, MessageLevel level, const String& message, std::unique_ptr<SourceLocation> location)
 {
     return new ConsoleMessage(source, level, message, std::move(location));
@@ -29,6 +30,14 @@
     return ConsoleMessage::create(source, level, message, SourceLocation::capture());
 }
 
+// static
+ConsoleMessage* ConsoleMessage::createFromWorker(MessageLevel level, const String& message, std::unique_ptr<SourceLocation> location, const String& workerId)
+{
+    ConsoleMessage* consoleMessage = ConsoleMessage::create(WorkerMessageSource, level, message, std::move(location));
+    consoleMessage->m_workerId = workerId;
+    return consoleMessage;
+}
+
 ConsoleMessage::ConsoleMessage(MessageSource source,
     MessageLevel level,
     const String& message,
@@ -76,6 +85,11 @@
     return m_message;
 }
 
+const String& ConsoleMessage::workerId() const
+{
+    return m_workerId;
+}
+
 DEFINE_TRACE(ConsoleMessage)
 {
 }
diff --git a/third_party/WebKit/Source/core/inspector/ConsoleMessage.h b/third_party/WebKit/Source/core/inspector/ConsoleMessage.h
index 4d0b11f..d6e316d9 100644
--- a/third_party/WebKit/Source/core/inspector/ConsoleMessage.h
+++ b/third_party/WebKit/Source/core/inspector/ConsoleMessage.h
@@ -29,6 +29,9 @@
     // This method captures current location.
     static ConsoleMessage* createForRequest(MessageSource, MessageLevel, const String& message, const String& url, unsigned long requestIdentifier);
 
+    // This creates message from WorkerMessageSource.
+    static ConsoleMessage* createFromWorker(MessageLevel, const String& message, std::unique_ptr<SourceLocation>, const String& workerId);
+
     ~ConsoleMessage();
 
     SourceLocation* location() const;
@@ -37,6 +40,7 @@
     MessageSource source() const;
     MessageLevel level() const;
     const String& message() const;
+    const String& workerId() const;
 
     DECLARE_TRACE();
 
@@ -49,6 +53,7 @@
     std::unique_ptr<SourceLocation> m_location;
     unsigned long m_requestIdentifier;
     double m_timestamp;
+    String m_workerId;
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/inspector/InspectorAnimationAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorAnimationAgent.cpp
index 8ffa771b..526f632 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorAnimationAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorAnimationAgent.cpp
@@ -129,7 +129,7 @@
 {
     Decimal decimal = Decimal::fromDouble(keyframe->offset() * 100);
     String offset = decimal.toString();
-    offset.append("%");
+    offset.append('%');
 
     std::unique_ptr<protocol::Animation::KeyframeStyle> keyframeObject = protocol::Animation::KeyframeStyle::create()
         .setOffset(offset)
diff --git a/third_party/WebKit/Source/core/inspector/InspectorSession.cpp b/third_party/WebKit/Source/core/inspector/InspectorSession.cpp
index b83ad56..5044d5c 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorSession.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorSession.cpp
@@ -163,11 +163,6 @@
     m_client->profilingStopped();
 }
 
-void InspectorSession::consoleEnabled()
-{
-    m_client->consoleEnabled();
-}
-
 void InspectorSession::consoleCleared()
 {
     m_client->consoleCleared();
diff --git a/third_party/WebKit/Source/core/inspector/InspectorSession.h b/third_party/WebKit/Source/core/inspector/InspectorSession.h
index 3f31c00..8a9abbe 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorSession.h
+++ b/third_party/WebKit/Source/core/inspector/InspectorSession.h
@@ -37,7 +37,6 @@
         virtual void resumeStartup() { }
         virtual void profilingStarted() { }
         virtual void profilingStopped() { }
-        virtual void consoleEnabled() { }
         virtual void consoleCleared() { }
         virtual ~Client() {}
     };
@@ -68,7 +67,6 @@
     bool canExecuteScripts() override;
     void profilingStarted() override;
     void profilingStopped() override;
-    void consoleEnabled() override;
     void consoleCleared() override;
 
     Client* m_client;
diff --git a/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.cpp b/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.cpp
index 0698b14..1fdc7f4 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.cpp
@@ -646,20 +646,20 @@
 
     StringBuilder builder;
     builder.append(styleRule->selectorText());
-    builder.append("{");
+    builder.append('{');
     for (unsigned i = 0; i < propertyNames.size(); ++i) {
         String name = propertyNames.at(i);
-        builder.append(" ");
+        builder.append(' ');
         builder.append(name);
-        builder.append(":");
+        builder.append(':');
         builder.append(style->getPropertyValue(name));
         if (!style->getPropertyPriority(name).isEmpty()) {
-            builder.append(" ");
+            builder.append(' ');
             builder.append(style->getPropertyPriority(name));
         }
-        builder.append(";");
+        builder.append(';');
     }
-    builder.append("}");
+    builder.append('}');
 
     return builder.toString();
 }
diff --git a/third_party/WebKit/Source/core/inspector/WorkerInspectorController.cpp b/third_party/WebKit/Source/core/inspector/WorkerInspectorController.cpp
index dcd248a..fcd952fa0 100644
--- a/third_party/WebKit/Source/core/inspector/WorkerInspectorController.cpp
+++ b/third_party/WebKit/Source/core/inspector/WorkerInspectorController.cpp
@@ -96,11 +96,6 @@
     m_workerGlobalScope->thread()->stopRunningDebuggerTasksOnPauseOnWorkerThread();
 }
 
-void WorkerInspectorController::consoleEnabled()
-{
-    m_workerGlobalScope->thread()->workerReportingProxy().postWorkerConsoleAgentEnabled();
-}
-
 void WorkerInspectorController::sendProtocolMessage(int sessionId, int callId, const String& response, const String& state)
 {
     // Worker messages are wrapped, no need to handle callId or state.
diff --git a/third_party/WebKit/Source/core/inspector/WorkerInspectorController.h b/third_party/WebKit/Source/core/inspector/WorkerInspectorController.h
index db6969b9..3e0fcb3 100644
--- a/third_party/WebKit/Source/core/inspector/WorkerInspectorController.h
+++ b/third_party/WebKit/Source/core/inspector/WorkerInspectorController.h
@@ -71,7 +71,6 @@
     // InspectorSession::Client implementation.
     void sendProtocolMessage(int sessionId, int callId, const String& response, const String& state) override;
     void resumeStartup() override;
-    void consoleEnabled() override;
 
     WorkerThreadDebugger* m_debugger;
     Member<WorkerGlobalScope> m_workerGlobalScope;
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlock.cpp b/third_party/WebKit/Source/core/layout/LayoutBlock.cpp
index 04c701c37..a1946e9 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBlock.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBlock.cpp
@@ -790,7 +790,7 @@
 
     if (view() && view()->selectionStart()) {
         Node* startElement = view()->selectionStart()->node();
-        if (startElement && startElement->rootEditableElement() == node())
+        if (startElement && rootEditableElement(*startElement) == node())
             return true;
     }
 
@@ -1409,7 +1409,7 @@
     if (!node())
         return false;
 
-    if (node()->isRootEditableElement())
+    if (isRootEditableElement(*node()))
         return true;
 
     if (node()->isShadowRoot() && isHTMLInputElement(toShadowRoot(node())->host()))
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlowLine.cpp b/third_party/WebKit/Source/core/layout/LayoutBlockFlowLine.cpp
index f8daa687..dba4a46e 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBlockFlowLine.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlowLine.cpp
@@ -1878,7 +1878,7 @@
 {
     LayoutUnit endPadding = hasOverflowClip() ? paddingEnd() : LayoutUnit();
     // FIXME: Need to find another way to do this, since scrollbars could show when we don't want them to.
-    if (hasOverflowClip() && !endPadding && node() && node()->isRootEditableElement() && style()->isLeftToRightDirection())
+    if (hasOverflowClip() && !endPadding && node() && isRootEditableElement(*node()) && style()->isLeftToRightDirection())
         endPadding = LayoutUnit(1);
     for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
         addLayoutOverflow(curr->paddedLayoutOverflowRect(endPadding));
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
index 4fc4b88d..bd3dd55b 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -991,15 +991,11 @@
         return true;
 
     LayoutSize offset = LayoutSize(-scrolledContentOffset());
-    if (UNLIKELY(hasFlippedBlocksWritingMode()))
-        offset.setWidth(-offset.width());
     rect.move(offset);
 
     if (applyOverflowClip == ApplyNonScrollOverflowClip && scrollsOverflow())
         return true;
 
-    flipForWritingMode(rect);
-
     LayoutRect clipRect = overflowClipRect(LayoutPoint());
 
     bool doesIntersect;
@@ -1009,8 +1005,6 @@
         rect.intersect(clipRect);
         doesIntersect = !rect.isEmpty();
     }
-    if (doesIntersect)
-        flipForWritingMode(rect);
     return doesIntersect;
 }
 
@@ -2043,34 +2037,25 @@
 {
     inflateVisualRectForReflectionAndFilter(rect);
 
-    if (ancestor == this) {
-        // The final rect returned is always in the physical coordinate space of the ancestor.
-        flipForWritingMode(rect);
+    if (ancestor == this)
         return true;
-    }
 
     bool ancestorSkipped;
     bool filterOrReflectionSkipped;
     LayoutObject* container = this->container(ancestor, &ancestorSkipped, &filterOrReflectionSkipped);
+    LayoutBox* localContainingBlock = containingBlock();
+    // Skip table row because cells and rows are in the same coordinate space.
+    if (container->isTableRow()) {
+        DCHECK(isTableCell());
+        localContainingBlock = toLayoutBox(container->parent());
+        container = container->parent();
+    }
     if (!container)
         return true;
 
     if (filterOrReflectionSkipped)
         inflateVisualRectForReflectionAndFilterUnderContainer(rect, *container, ancestor);
 
-    // The rect we compute at each step is shifted by our x/y offset in the parent container's coordinate space.
-    // Only when we cross a writing mode boundary will we have to possibly flipForWritingMode (to convert into a more
-    // appropriate offset corner for the enclosing container).
-    if (isWritingModeRoot()) {
-        flipForWritingMode(rect);
-        // Then flip rect currently in physical direction to container's block direction.
-        if (container->styleRef().isFlippedBlocksWritingMode())
-            rect.setX(m_frameRect.width() - rect.maxX());
-    }
-
-    LayoutPoint topLeft = rect.location();
-    topLeft.move(locationOffset());
-
     // We are now in our parent container's coordinate space.  Apply our transform to obtain a bounding box
     // in the parent's coordinate space that encloses us.
     if (hasLayer() && layer()->transform()) {
@@ -2078,9 +2063,12 @@
         // the transform since we don't know the desired subpixel accumulation at this point, and the transform may
         // include a scale.
         rect = LayoutRect(layer()->transform()->mapRect(enclosingIntRect(rect)));
-        topLeft = rect.location();
-        topLeft.move(locationOffset());
     }
+    LayoutPoint topLeft = rect.location();
+    // TODO(wkorman): Look into and document why this conditional is needed.
+    // Currently present following logic in PaintLayer::updateLayerPosition.
+    if (!(isInline() && isLayoutInline()))
+        topLeft.moveBy(topLeftLocation(localContainingBlock));
 
     const ComputedStyle& styleToUse = styleRef();
     EPosition position = styleToUse.position();
@@ -2102,7 +2090,7 @@
         return false;
 
     if (ancestorSkipped) {
-        // If the ancestor is below o, then we need to map the rect into ancestor's coordinates.
+        // If the ancestor is below the container, then we need to map the rect into ancestor's coordinates.
         LayoutSize containerOffset = ancestor->offsetFromAncestorContainer(container);
         rect.move(-containerOffset);
         // If the ancestor is fixed, then the rect is already in its coordinates so doesn't need viewport-adjusting.
@@ -2916,13 +2904,14 @@
         LayoutObject* cb = isOutOfFlowPositioned() ? container() : containingBlock();
         while (cb->isAnonymous())
             cb = cb->containingBlock();
-        LayoutUnit stretchedFlexHeight(-1);
+        LayoutUnit stretchedHeight(-1);
         if (cb->isLayoutBlock()) {
             LayoutBlock* block = toLayoutBlock(cb);
             block->addPercentHeightDescendant(const_cast<LayoutBox*>(this));
             if (block->isFlexItem())
-                stretchedFlexHeight = toLayoutFlexibleBox(block->parent())->childLogicalHeightForPercentageResolution(*block);
-
+                stretchedHeight = toLayoutFlexibleBox(block->parent())->childLogicalHeightForPercentageResolution(*block);
+            else if (block->isGridItem() && block->hasOverrideLogicalContentHeight())
+                stretchedHeight = block->overrideLogicalContentHeight();
         }
 
         if (cb->isOutOfFlowPositioned() && cb->style()->height().isAuto() && !(cb->style()->top().isAuto() || cb->style()->bottom().isAuto())) {
@@ -2941,8 +2930,10 @@
         LayoutUnit availableHeight;
         if (isOutOfFlowPositioned()) {
             availableHeight = containingBlockLogicalHeightForPositioned(toLayoutBoxModelObject(cb));
-        } else if (stretchedFlexHeight != -1) {
-            availableHeight = stretchedFlexHeight;
+        } else if (stretchedHeight != -1) {
+            availableHeight = stretchedHeight;
+        } else if (isGridItem() && hasOverrideContainingBlockLogicalHeight()) {
+            availableHeight = overrideContainingBlockContentLogicalHeight();
         } else {
             availableHeight = containingBlockLogicalHeightForContent(IncludeMarginBorderPadding);
             // It is necessary to use the border-box to match WinIE's broken
@@ -4475,12 +4466,12 @@
     return LayoutPoint(point.x() + size().width() - child->size().width() - (2 * child->location().x()), point.y());
 }
 
-LayoutPoint LayoutBox::topLeftLocation() const
+LayoutPoint LayoutBox::topLeftLocation(const LayoutBox* flippedBlocksContainer) const
 {
-    LayoutBlock* containerBlock = containingBlock();
-    if (!containerBlock || containerBlock == this)
+    const LayoutBox* containerBox = flippedBlocksContainer ? flippedBlocksContainer : containingBlock();
+    if (!containerBox || containerBox == this)
         return location();
-    return containerBlock->flipForWritingModeForChild(this, location());
+    return containerBox->flipForWritingModeForChild(this, location());
 }
 
 bool LayoutBox::hasRelativeLogicalWidth() const
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.h b/third_party/WebKit/Source/core/layout/LayoutBox.h
index ca52d25..631a6a1 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.h
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.h
@@ -873,9 +873,11 @@
             return;
         rect.setX(m_frameRect.width() - rect.maxX());
     }
-    // These represent your location relative to your container as a physical offset.
-    // In layout related methods you almost always want the logical location (e.g. x() and y()).
-    LayoutPoint topLeftLocation() const;
+    // These represent your location relative to your container as a physical
+    // offset. In layout related methods you almost always want the logical
+    // location (e.g. x() and y()). Passing |container| causes flipped-block
+    // flipping w.r.t. that container, or containingBlock() otherwise.
+    LayoutPoint topLeftLocation(const LayoutBox* flippedBlocksContainer = nullptr) const;
     LayoutSize topLeftLocationOffset() const { return toLayoutSize(topLeftLocation()); }
 
     LayoutRect logicalVisualOverflowRectForPropagation(const ComputedStyle&) const;
diff --git a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp
index 3f70ca65..5390b736 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp
@@ -555,7 +555,7 @@
     return cb;
 }
 
-bool LayoutBoxModelObject::hasAutoHeightOrContainingBlockWithAutoHeight() const
+bool LayoutBoxModelObject::hasAutoHeightOrContainingBlockWithAutoHeight(bool checkingContainingBlock) const
 {
     const LayoutBox* thisBox = isBox() ? toLayoutBox(this) : nullptr;
     Length logicalHeightLength = style()->logicalHeight();
@@ -567,6 +567,12 @@
         if (flexBox.childLogicalHeightForPercentageResolution(*thisBox) != LayoutUnit(-1))
             return false;
     }
+    if (thisBox && thisBox->isGridItem()) {
+        if (checkingContainingBlock && thisBox->hasOverrideLogicalContentHeight())
+            return false;
+        if (!checkingContainingBlock && thisBox->hasOverrideContainingBlockLogicalHeight())
+            return false;
+    }
     if (logicalHeightLength.isAuto())
         return true;
 
@@ -575,10 +581,15 @@
 
     // If the height of the containing block computes to 'auto', then it hasn't been 'specified explicitly'.
     if (cb)
-        return cb->hasAutoHeightOrContainingBlockWithAutoHeight();
+        return cb->hasAutoHeightOrContainingBlockWithAutoHeight(true);
     return false;
 }
 
+bool LayoutBoxModelObject::hasAutoHeightOrContainingBlockWithAutoHeight() const
+{
+    return hasAutoHeightOrContainingBlockWithAutoHeight(false);
+}
+
 LayoutSize LayoutBoxModelObject::relativePositionOffset() const
 {
     LayoutSize offset = accumulateInFlowPositionOffsets();
diff --git a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.h b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.h
index 95b027df..be67ec6 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.h
+++ b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.h
@@ -376,6 +376,8 @@
         return *m_rareData.get();
     }
 
+    bool hasAutoHeightOrContainingBlockWithAutoHeight(bool checkingContainingBlock) const;
+
     // The PaintLayer associated with this object.
     // |m_layer| can be nullptr depending on the return value of layerTypeRequired().
     std::unique_ptr<PaintLayer> m_layer;
diff --git a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
index 7bdedffe..bed1c2f 100644
--- a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
@@ -90,6 +90,7 @@
     : LayoutBlock(element)
     , m_orderIterator(this)
     , m_numberOfInFlowChildrenOnFirstLine(-1)
+    , m_hasDefiniteHeight(SizeDefiniteness::Unknown)
 {
     ASSERT(!childrenInline());
 }
@@ -380,6 +381,10 @@
     updateAfterLayout();
 
     clearNeedsLayout();
+
+    // We have to reset this, because changes to our ancestors' style
+    // can affect this value.
+    m_hasDefiniteHeight = SizeDefiniteness::Unknown;
 }
 
 void LayoutFlexibleBox::paintChildren(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) const
@@ -769,9 +774,13 @@
     if (flexBasis.isAuto())
         return false;
     if (flexBasis.hasPercent()) {
-        return isColumnFlow() ?
-            child.computePercentageLogicalHeight(flexBasis) != -1 :
-            true;
+        if (!isColumnFlow() || m_hasDefiniteHeight == SizeDefiniteness::Definite)
+            return true;
+        if (m_hasDefiniteHeight == SizeDefiniteness::Indefinite)
+            return false;
+        bool definite = child.computePercentageLogicalHeight(flexBasis) != -1;
+        m_hasDefiniteHeight = definite ? SizeDefiniteness::Definite : SizeDefiniteness::Indefinite;
+        return definite;
     }
     return true;
 }
@@ -781,9 +790,13 @@
     if (length.isAuto())
         return false;
     if (length.hasPercent()) {
-        return hasOrthogonalFlow(child) ?
-            true :
-            child.computePercentageLogicalHeight(length) != -1;
+        if (hasOrthogonalFlow(child) || m_hasDefiniteHeight == SizeDefiniteness::Definite)
+            return true;
+        if (m_hasDefiniteHeight == SizeDefiniteness::Indefinite)
+            return false;
+        bool definite = child.computePercentageLogicalHeight(length) != -1;
+        m_hasDefiniteHeight = definite ? SizeDefiniteness::Definite : SizeDefiniteness::Indefinite;
+        return definite;
     }
     // TODO(cbiesinger): Eventually we should support other types of sizes here. Requires updating
     // computeMainSizeFromAspectRatioUsing.
@@ -1147,7 +1160,6 @@
         // If flex basis had a percentage, our size is guaranteed to be definite or the flex item's
         // size could not be definite.
         // Otherwise, we make up a percentage to check whether we have a definite size.
-        // TODO(cbiesinger): cache this somewhere
         if (!mainAxisLengthIsDefinite(child, Length(0, Percent)))
             return LayoutUnit(-1);
     }
diff --git a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h
index 905efe6..9ea7c01 100644
--- a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h
+++ b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h
@@ -99,6 +99,10 @@
         TopToBottomWritingMode, RightToLeftWritingMode, LeftToRightWritingMode, BottomToTopWritingMode
     };
 
+    enum class SizeDefiniteness {
+        Definite, Indefinite, Unknown
+    };
+
     struct FlexItem;
     struct LineContext;
 
@@ -200,6 +204,9 @@
 
     mutable OrderIterator m_orderIterator;
     int m_numberOfInFlowChildrenOnFirstLine;
+
+    // This is SizeIsUnknown outside of layoutBlock()
+    mutable SizeDefiniteness m_hasDefiniteHeight;
 };
 
 DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutFlexibleBox, isFlexibleBox());
diff --git a/third_party/WebKit/Source/core/layout/LayoutFlowThread.cpp b/third_party/WebKit/Source/core/layout/LayoutFlowThread.cpp
index a95a49a71..a27ce47 100644
--- a/third_party/WebKit/Source/core/layout/LayoutFlowThread.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutFlowThread.cpp
@@ -102,9 +102,7 @@
     // |rect| is a layout rectangle, where the block direction coordinate is flipped for writing
     // mode. fragmentsBoundingBox(), on the other hand, works on physical rectangles, so we need to
     // flip the rectangle before and after calling it.
-    flipForWritingMode(rect);
     rect = fragmentsBoundingBox(rect);
-    flipForWritingMode(rect);
     return LayoutBlockFlow::mapToVisualRectInAncestorSpace(ancestor, rect, visualRectFlags);
 }
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutFrame.cpp b/third_party/WebKit/Source/core/layout/LayoutFrame.cpp
index 7f019f2..768bd03 100644
--- a/third_party/WebKit/Source/core/layout/LayoutFrame.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutFrame.cpp
@@ -24,7 +24,10 @@
 #include "core/layout/LayoutFrame.h"
 
 #include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
 #include "core/html/HTMLFrameElement.h"
+#include "core/input/EventHandler.h"
+#include "core/style/CursorData.h"
 
 namespace blink {
 
@@ -40,6 +43,23 @@
     return FrameEdgeInfo(element->noResize(), element->hasFrameBorder());
 }
 
+void LayoutFrame::imageChanged(WrappedImagePtr image, const IntRect*)
+{
+    if (const CursorList* cursors = style()->cursors()) {
+        for (const CursorData& cursor : *cursors) {
+            if (cursor.image() && cursor.image()->cachedImage() == image) {
+                if (LocalFrame* frame = this->frame()) {
+                    // Cursor update scheduling is done by the local root, which is the main frame if there
+                    // are no RemoteFrame ancestors in the frame tree. Use of localFrameRoot() is
+                    // discouraged but will change when cursor update scheduling is moved from EventHandler
+                    // to PageEventHandler.
+                    frame->localFrameRoot()->eventHandler().scheduleCursorUpdate();
+                }
+            }
+        }
+    }
+}
+
 void LayoutFrame::updateFromElement()
 {
     if (parent() && parent()->isFrameSet())
diff --git a/third_party/WebKit/Source/core/layout/LayoutFrame.h b/third_party/WebKit/Source/core/layout/LayoutFrame.h
index 8753c6c..8f0b728 100644
--- a/third_party/WebKit/Source/core/layout/LayoutFrame.h
+++ b/third_party/WebKit/Source/core/layout/LayoutFrame.h
@@ -36,6 +36,8 @@
 
     FrameEdgeInfo edgeInfo() const;
 
+    void imageChanged(WrappedImagePtr, const IntRect* = nullptr) override;
+
     const char* name() const override { return "LayoutFrame"; }
 
 private:
diff --git a/third_party/WebKit/Source/core/layout/LayoutInline.cpp b/third_party/WebKit/Source/core/layout/LayoutInline.cpp
index 5d11e8f..d46577ff 100644
--- a/third_party/WebKit/Source/core/layout/LayoutInline.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutInline.cpp
@@ -1104,9 +1104,12 @@
     // its controlClipRect will be wrong. For overflow clip we use the values cached by the layer.
     rect.setLocation(topLeft);
 
-    if (container->isBox() && !toLayoutBox(container)->mapScrollingContentsRectToBoxSpace(rect, container == ancestor ? ApplyNonScrollOverflowClip : ApplyOverflowClip, visualRectFlags))
+    LayoutBox* containerBox = container->isBox() ? toLayoutBox(container) : nullptr;
+    if (containerBox && !containerBox->mapScrollingContentsRectToBoxSpace(rect, container == ancestor ? ApplyNonScrollOverflowClip : ApplyOverflowClip, visualRectFlags))
         return false;
 
+    if (containerBox)
+        containerBox->flipForWritingMode(rect);
     return container->mapToVisualRectInAncestorSpace(ancestor, rect, visualRectFlags);
 }
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutMenuList.cpp b/third_party/WebKit/Source/core/layout/LayoutMenuList.cpp
index af5a325..842318f 100644
--- a/third_party/WebKit/Source/core/layout/LayoutMenuList.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutMenuList.cpp
@@ -263,7 +263,8 @@
 void LayoutMenuList::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop,
     LogicalExtentComputedValues& computedValues) const
 {
-    logicalHeight = m_innerBlockHeight + borderAndPaddingHeight();
+    if (style()->hasAppearance())
+        logicalHeight = m_innerBlockHeight + borderAndPaddingHeight();
     LayoutBox::computeLogicalHeight(logicalHeight, logicalTop, computedValues);
 }
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.cpp b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
index c258042..08e8b52 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObject.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
@@ -1567,15 +1567,20 @@
 bool LayoutObject::mapToVisualRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect& rect, VisualRectFlags visualRectFlags) const
 {
     // For any layout object that doesn't override this method (the main example is LayoutText),
-    // the rect is assumed to be in the coordinate space of the object's parent.
+    // the rect is assumed to be in the parent's coordinate space, except for container flip.
 
     if (ancestor == this)
         return true;
 
     if (LayoutObject* parent = this->parent()) {
-        if (parent->isBox() && !toLayoutBox(parent)->mapScrollingContentsRectToBoxSpace(rect, parent == ancestor ? ApplyNonScrollOverflowClip : ApplyOverflowClip, visualRectFlags))
-            return false;
-
+        if (parent->isBox()) {
+            LayoutBox* parentBox = toLayoutBox(parent);
+            if (!parentBox->mapScrollingContentsRectToBoxSpace(rect, parent == ancestor ? ApplyNonScrollOverflowClip : ApplyOverflowClip, visualRectFlags))
+                return false;
+            // Never flip for SVG as it handles writing modes itself.
+            if (!isSVG())
+                parentBox->flipForWritingMode(rect);
+        }
         return parent->mapToVisualRectInAncestorSpace(ancestor, rect, visualRectFlags);
     }
     return true;
@@ -1893,6 +1898,7 @@
     updateImage(oldBoxReflectMaskImage, newBoxReflectMaskImage);
 
     updateShapeImage(oldStyle ? oldStyle->shapeOutside() : 0, m_style->shapeOutside());
+    updateCursorImages(oldStyle ? oldStyle->cursors() : nullptr, m_style->cursors());
 
     bool doesNotNeedLayoutOrPaintInvalidation = !m_parent;
 
@@ -2117,6 +2123,20 @@
     }
 }
 
+void LayoutObject::updateCursorImages(const CursorList* oldCursors, const CursorList* newCursors)
+{
+    if (oldCursors && newCursors && *oldCursors == *newCursors)
+        return;
+
+    if (newCursors) {
+        for (const CursorData& cursorNew : *newCursors) {
+            if (cursorNew.image())
+                cursorNew.image()->addClient(this);
+        }
+    }
+    removeCursorImageClient(oldCursors);
+}
+
 void LayoutObject::updateImage(StyleImage* oldImage, StyleImage* newImage)
 {
     if (oldImage != newImage) {
@@ -2646,6 +2666,7 @@
             m_style->boxReflect()->mask().image()->removeClient(this);
 
         removeShapeImageClient(m_style->shapeOutside());
+        removeCursorImageClient(m_style->cursors());
     }
 
     if (frameView())
@@ -2831,6 +2852,16 @@
         shapeImage->removeClient(this);
 }
 
+void LayoutObject::removeCursorImageClient(const CursorList* cursorList)
+{
+    if (!cursorList)
+        return;
+    for (const CursorData& cursor : *cursorList) {
+        if (cursor.image())
+            cursor.image()->removeClient(this);
+    }
+}
+
 PositionWithAffinity LayoutObject::positionForPoint(const LayoutPoint&)
 {
     return createPositionWithAffinity(caretMinOffset());
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.h b/third_party/WebKit/Source/core/layout/LayoutObject.h
index cee1ba1..33277e6 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObject.h
+++ b/third_party/WebKit/Source/core/layout/LayoutObject.h
@@ -1617,6 +1617,7 @@
 
     void updateShapeImage(const ShapeValue*, const ShapeValue*);
     void updateFillImages(const FillLayer* oldLayers, const FillLayer& newLayers);
+    void updateCursorImages(const CursorList* oldCursors, const CursorList* newCursors);
 
     void setNeedsOverflowRecalcAfterStyleChange();
 
@@ -1651,6 +1652,7 @@
     Color selectionColor(int colorProperty, const GlobalPaintFlags) const;
 
     void removeShapeImageClient(ShapeValue*);
+    void removeCursorImageClient(const CursorList*);
 
 #if ENABLE(ASSERT)
     void checkBlockPositionedObjectsNeedLayout();
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableCell.cpp b/third_party/WebKit/Source/core/layout/LayoutTableCell.cpp
index e6fa743..1aba914 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableCell.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTableCell.cpp
@@ -360,15 +360,6 @@
     return LayoutRect(-location.x(), -location.y(), location.x() + std::max(size().width() + right, selfVisualOverflowRect.maxX()), location.y() + std::max(size().height() + bottom, selfVisualOverflowRect.maxY()));
 }
 
-bool LayoutTableCell::mapToVisualRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect& r, VisualRectFlags visualRectFlags) const
-{
-    if (ancestor == this)
-        return true;
-    if (parent())
-        r.moveBy(-parentBox()->location()); // Rows are in the same coordinate space, so don't add their offset in.
-    return LayoutBlockFlow::mapToVisualRectInAncestorSpace(ancestor, r, visualRectFlags);
-}
-
 int LayoutTableCell::cellBaselinePosition() const
 {
     // <http://www.w3.org/TR/2007/CR-CSS21-20070719/tables.html#height-layout>: The baseline of a cell is the baseline of
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableCell.h b/third_party/WebKit/Source/core/layout/LayoutTableCell.h
index dba89847..0eccd0c 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableCell.h
+++ b/third_party/WebKit/Source/core/layout/LayoutTableCell.h
@@ -301,7 +301,6 @@
 
     LayoutSize offsetFromContainer(const LayoutObject*) const override;
     LayoutRect localOverflowRectForPaintInvalidation() const override;
-    bool mapToVisualRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect&, VisualRectFlags = DefaultVisualRectFlags) const override;
 
     int borderHalfLeft(bool outer) const;
     int borderHalfRight(bool outer) const;
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableRow.cpp b/third_party/WebKit/Source/core/layout/LayoutTableRow.cpp
index 160e3ebc..2d726bc 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableRow.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTableRow.cpp
@@ -53,14 +53,6 @@
     section()->setNeedsCellRecalc();
 }
 
-static bool borderWidthChanged(const ComputedStyle* oldStyle, const ComputedStyle* newStyle)
-{
-    return oldStyle->borderLeftWidth() != newStyle->borderLeftWidth()
-        || oldStyle->borderTopWidth() != newStyle->borderTopWidth()
-        || oldStyle->borderRightWidth() != newStyle->borderRightWidth()
-        || oldStyle->borderBottomWidth() != newStyle->borderBottomWidth();
-}
-
 void LayoutTableRow::styleDidChange(StyleDifference diff, const ComputedStyle* oldStyle)
 {
     ASSERT(style()->display() == TABLE_ROW);
@@ -77,13 +69,14 @@
         if (table && !table->selfNeedsLayout() && !table->normalChildNeedsLayout() && oldStyle && oldStyle->border() != style()->border())
             table->invalidateCollapsedBorders();
 
-        if (table && oldStyle && diff.needsFullLayout() && needsLayout() && table->collapseBorders() && borderWidthChanged(oldStyle, style())) {
+        if (table && oldStyle && diff.needsFullLayout() && needsLayout() && table->collapseBorders() && oldStyle->border().sizeEquals(style()->border())) {
             // If the border width changes on a row, we need to make sure the cells in the row know to lay out again.
             // This only happens when borders are collapsed, since they end up affecting the border sides of the cell
             // itself.
             for (LayoutBox* childBox = firstChildBox(); childBox; childBox = childBox->nextSiblingBox()) {
                 if (!childBox->isTableCell())
                     continue;
+                // TODO(dgrogan) Add a layout test showing that setChildNeedsLayout is needed instead of setNeedsLayout.
                 childBox->setChildNeedsLayout();
                 childBox->setPreferredLogicalWidthsDirty(MarkOnlyThis);
             }
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp b/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp
index 0ae4fb469..ff50a66c 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp
@@ -126,6 +126,10 @@
     LayoutTable* table = this->table();
     if (table && !table->selfNeedsLayout() && !table->normalChildNeedsLayout() && oldStyle && oldStyle->border() != style()->border())
         table->invalidateCollapsedBorders();
+
+    if (table && oldStyle && diff.needsFullLayout() && needsLayout() && table->collapseBorders() && oldStyle->border() != style()->border()) {
+        markAllCellsWidthsDirtyAndOrNeedsLayout(MarkDirtyAndNeedsLayout);
+    }
 }
 
 void LayoutTableSection::willBeRemovedFromTree()
@@ -1221,6 +1225,20 @@
     return childrenOverflowChanged;
 }
 
+void LayoutTableSection::markAllCellsWidthsDirtyAndOrNeedsLayout(WhatToMarkAllCells whatToMark)
+{
+    for (unsigned i = 0; i < numRows(); i++) {
+        LayoutTableRow* row = rowLayoutObjectAt(i);
+        if (!row)
+            continue;
+        for (LayoutTableCell* cell = row->firstCell(); cell; cell = cell->nextCell()) {
+            cell->setPreferredLogicalWidthsDirty();
+            if (whatToMark == MarkDirtyAndNeedsLayout)
+                cell->setChildNeedsLayout();
+        }
+    }
+}
+
 int LayoutTableSection::calcBlockDirectionOuterBorder(BlockBorderSide side) const
 {
     unsigned totalCols = table()->numEffectiveColumns();
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableSection.h b/third_party/WebKit/Source/core/layout/LayoutTableSection.h
index 549a253..edd70aa 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableSection.h
+++ b/third_party/WebKit/Source/core/layout/LayoutTableSection.h
@@ -115,6 +115,8 @@
     void layoutRows();
     void computeOverflowFromCells();
     bool recalcChildOverflowAfterStyleChange();
+    enum WhatToMarkAllCells { MarkDirtyOnly, MarkDirtyAndNeedsLayout };
+    void markAllCellsWidthsDirtyAndOrNeedsLayout(WhatToMarkAllCells);
 
     LayoutTable* table() const { return toLayoutTable(parent()); }
 
@@ -226,6 +228,7 @@
     }
     const LayoutTableCell* primaryCellAt(unsigned row, unsigned effectiveColumn) const { return const_cast<LayoutTableSection*>(this)->primaryCellAt(row, effectiveColumn); }
 
+    // Returns null for cells with a rowspan that exceed the last row. Possibly others.
     LayoutTableRow* rowLayoutObjectAt(unsigned row) { return m_grid[row].rowLayoutObject; }
     const LayoutTableRow* rowLayoutObjectAt(unsigned row) const { return m_grid[row].rowLayoutObject; }
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutTextControl.cpp b/third_party/WebKit/Source/core/layout/LayoutTextControl.cpp
index 0b87e69..e8ee104 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTextControl.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTextControl.cpp
@@ -189,8 +189,15 @@
 // from the width of a '0'. This only seems to apply to a fixed number of Mac fonts,
 // but, in order to get similar rendering across platforms, we do this check for
 // all platforms.
-bool LayoutTextControl::hasValidAvgCharWidth(const AtomicString& family)
+bool LayoutTextControl::hasValidAvgCharWidth(const SimpleFontData* font, const AtomicString& family)
 {
+    // Some fonts match avgCharWidth to CJK full-width characters.
+    // Heuristic check to avoid such fonts.
+    DCHECK(font);
+    const FontMetrics& metrics = font->getFontMetrics();
+    if (metrics.hasZeroWidth() && font->avgCharWidth() > metrics.zeroWidth() * 1.7)
+        return false;
+
     static HashSet<AtomicString>* fontFamiliesWithInvalidCharWidthMap = nullptr;
 
     if (family.isEmpty())
@@ -209,10 +216,9 @@
 float LayoutTextControl::getAvgCharWidth(const AtomicString& family) const
 {
     const Font& font = style()->font();
-    if (hasValidAvgCharWidth(family)) {
-        ASSERT(font.primaryFont());
-        return roundf(font.primaryFont()->avgCharWidth());
-    }
+    const SimpleFontData* primaryFont = font.primaryFont();
+    if (hasValidAvgCharWidth(primaryFont, family))
+        return roundf(primaryFont->avgCharWidth());
 
     const UChar ch = '0';
     const String str = String(&ch, 1);
diff --git a/third_party/WebKit/Source/core/layout/LayoutTextControl.h b/third_party/WebKit/Source/core/layout/LayoutTextControl.h
index 221d2d7..002c6cd 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTextControl.h
+++ b/third_party/WebKit/Source/core/layout/LayoutTextControl.h
@@ -58,7 +58,7 @@
 
     float scaleEmToUnits(int x) const;
 
-    static bool hasValidAvgCharWidth(const AtomicString& family);
+    static bool hasValidAvgCharWidth(const SimpleFontData*, const AtomicString& family);
     virtual float getAvgCharWidth(const AtomicString& family) const;
     virtual LayoutUnit preferredContentLogicalWidth(float charWidth) const = 0;
     virtual LayoutUnit computeControlLogicalHeight(LayoutUnit lineHeight, LayoutUnit nonContentHeight) const = 0;
diff --git a/third_party/WebKit/Source/core/layout/LayoutTextControlSingleLine.cpp b/third_party/WebKit/Source/core/layout/LayoutTextControlSingleLine.cpp
index 47e6e63..138efd02 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTextControlSingleLine.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTextControlSingleLine.cpp
@@ -231,15 +231,16 @@
     LayoutUnit result = LayoutUnit::fromFloatCeil(charWidth * factor);
 
     float maxCharWidth = 0.f;
-    AtomicString family = styleRef().font().getFontDescription().family().family();
+    const Font& font = style()->font();
+    AtomicString family = font.getFontDescription().family().family();
     // Match the default system font to the width of MS Shell Dlg, the default
     // font for textareas in Firefox, Safari Win and IE for some encodings (in
     // IE, the default font is encoding specific). 4027 is the (xMax - xMin)
     // value in the "head" font table for MS Shell Dlg.
     if (LayoutTheme::theme().needsHackForTextControlWithFontFamily(family))
         maxCharWidth = scaleEmToUnits(4027);
-    else if (hasValidAvgCharWidth(family))
-        maxCharWidth = roundf(styleRef().font().primaryFont()->maxCharWidth());
+    else if (hasValidAvgCharWidth(font.primaryFont(), family))
+        maxCharWidth = roundf(font.primaryFont()->maxCharWidth());
 
     // For text inputs, IE adds some extra width.
     if (maxCharWidth > 0.f)
diff --git a/third_party/WebKit/Source/core/layout/LayoutView.cpp b/third_party/WebKit/Source/core/layout/LayoutView.cpp
index 0fc2e451..0496404 100644
--- a/third_party/WebKit/Source/core/layout/LayoutView.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutView.cpp
@@ -448,9 +448,6 @@
 
 bool LayoutView::mapToVisualRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect& rect, MapCoordinatesFlags mode, VisualRectFlags visualRectFlags) const
 {
-    // Convert the rect into the physical coordinates space of this LayoutView.
-    flipForWritingMode(rect);
-
     if (mode & IsFixed)
         adjustOffsetForFixedPosition(rect);
 
diff --git a/third_party/WebKit/Source/core/layout/PaintInvalidationState.cpp b/third_party/WebKit/Source/core/layout/PaintInvalidationState.cpp
index c3076c4..14c00546 100644
--- a/third_party/WebKit/Source/core/layout/PaintInvalidationState.cpp
+++ b/third_party/WebKit/Source/core/layout/PaintInvalidationState.cpp
@@ -389,6 +389,13 @@
 
 static void slowMapToVisualRectInAncestorSpace(const LayoutObject& object, const LayoutBoxModelObject& ancestor, LayoutRect& rect)
 {
+    // TODO(wkorman): The flip below is required because visual rects are
+    // currently in "physical coordinates with flipped block-flow direction"
+    // (see LayoutBoxModelObject.h) but we need them to be in physical
+    // coordinates.
+    if (object.isBox())
+        toLayoutBox(&object)->flipForWritingMode(rect);
+
     if (object.isLayoutView())
         toLayoutView(object).mapToVisualRectInAncestorSpace(&ancestor, rect, InputIsInFrameCoordinates, DefaultVisualRectFlags);
     else
diff --git a/third_party/WebKit/Source/core/layout/README.md b/third_party/WebKit/Source/core/layout/README.md
index 61cbadac..d6943942 100644
--- a/third_party/WebKit/Source/core/layout/README.md
+++ b/third_party/WebKit/Source/core/layout/README.md
@@ -77,3 +77,7 @@
                     
                           overflow rect
                     |<--------------------->|
+
+## Coordinate Spaces
+
+TODO(wkorman): Document writing mode, particularly flipped blocks.
diff --git a/third_party/WebKit/Source/core/layout/TableLayoutAlgorithmFixed.cpp b/third_party/WebKit/Source/core/layout/TableLayoutAlgorithmFixed.cpp
index 9fc6eb4..caa76258 100644
--- a/third_party/WebKit/Source/core/layout/TableLayoutAlgorithmFixed.cpp
+++ b/third_party/WebKit/Source/core/layout/TableLayoutAlgorithmFixed.cpp
@@ -326,15 +326,8 @@
     // (see calcWidthArray above.) This optimization is preferred to always
     // computing the logical widths we never intended to use.
     m_table->recalcSectionsIfNeeded();
-    for (LayoutTableSection* section = m_table->topNonEmptySection(); section; section = m_table->sectionBelow(section)) {
-        for (unsigned i = 0; i < section->numRows(); i++) {
-            LayoutTableRow* row = section->rowLayoutObjectAt(i);
-            if (!row)
-                continue;
-            for (LayoutTableCell* cell = row->firstCell(); cell; cell = cell->nextCell())
-                cell->setPreferredLogicalWidthsDirty();
-        }
-    }
+    for (LayoutTableSection* section = m_table->topNonEmptySection(); section; section = m_table->sectionBelow(section))
+        section->markAllCellsWidthsDirtyAndOrNeedsLayout(LayoutTableSection::MarkDirtyOnly);
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/VisualRectMappingTest.cpp b/third_party/WebKit/Source/core/layout/VisualRectMappingTest.cpp
index 416f838..1436b16 100644
--- a/third_party/WebKit/Source/core/layout/VisualRectMappingTest.cpp
+++ b/third_party/WebKit/Source/core/layout/VisualRectMappingTest.cpp
@@ -171,11 +171,18 @@
     EXPECT_EQ(LayoutRect(-40, 0, 140, 70), overflowRect);
 
     LayoutRect rect = overflowRect;
+    // TODO(wkorman): The calls to flipForWritingMode() here and in other test
+    // cases below are necessary because mapToVisualRectInAncestorSpace()
+    // currently expects the input rect to be in "physical coordinates" (*not*
+    // "physical coordinates with flipped block-flow direction"), see
+    // LayoutBoxModelObject.h.
+    target->flipForWritingMode(rect);
     EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(target, rect));
     // This rect is in physical coordinates of target.
     EXPECT_EQ(LayoutRect(0, 0, 140, 70), rect);
 
     rect = overflowRect;
+    target->flipForWritingMode(rect);
     EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(&layoutView(), rect));
     EXPECT_EQ(LayoutRect(222, 111, 140, 70), rect);
     checkPaintInvalidationStateRectMapping(rect, overflowRect, *target, layoutView(), layoutView());
@@ -197,16 +204,19 @@
     EXPECT_EQ(LayoutRect(-40, 0, 140, 110), targetOverflowRect);
 
     LayoutRect rect = targetOverflowRect;
+    target->flipForWritingMode(rect);
     EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(target, rect));
     // This rect is in physical coordinates of target.
     EXPECT_EQ(LayoutRect(0, 0, 140, 110), rect);
 
     LayoutBlock* container = toLayoutBlock(getLayoutObjectByElementId("container"));
     rect = targetOverflowRect;
+    target->flipForWritingMode(rect);
     EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(container, rect));
     // 100 is the physical x location of target in container.
     EXPECT_EQ(LayoutRect(100, 0, 140, 110), rect);
     rect = targetOverflowRect;
+    target->flipForWritingMode(rect);
     EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(&layoutView(), rect));
     EXPECT_EQ(LayoutRect(322, 111, 140, 110), rect);
     checkPaintInvalidationStateRectMapping(rect, targetOverflowRect, *target, layoutView(), layoutView());
@@ -214,9 +224,11 @@
     LayoutRect containerOverflowRect = container->localOverflowRectForPaintInvalidation();
     EXPECT_EQ(LayoutRect(0, 0, 200, 100), containerOverflowRect);
     rect = containerOverflowRect;
+    container->flipForWritingMode(rect);
     EXPECT_TRUE(container->mapToVisualRectInAncestorSpace(container, rect));
     EXPECT_EQ(LayoutRect(0, 0, 200, 100), rect);
     rect = containerOverflowRect;
+    container->flipForWritingMode(rect);
     EXPECT_TRUE(container->mapToVisualRectInAncestorSpace(&layoutView(), rect));
     EXPECT_EQ(LayoutRect(222, 111, 200, 100), rect);
     checkPaintInvalidationStateRectMapping(rect, containerOverflowRect, *container, layoutView(), layoutView());
@@ -303,11 +315,13 @@
     EXPECT_EQ(LayoutRect(-40, 0, 140, 110), targetOverflowRect);
 
     LayoutRect rect = targetOverflowRect;
+    target->flipForWritingMode(rect);
     EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(target, rect));
     // This rect is in physical coordinates of target.
     EXPECT_EQ(LayoutRect(0, 0, 140, 110), rect);
 
     rect = targetOverflowRect;
+    target->flipForWritingMode(rect);
     EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(container, rect));
     // -2 = target_physical_x(100) + container_border_left(40) - scroll_left(142)
     // 3 = target_y(0) + container_border_top(10) - scroll_top(7)
@@ -315,6 +329,7 @@
     EXPECT_EQ(LayoutRect(-2, 3, 140, 110), rect);
 
     rect = targetOverflowRect;
+    target->flipForWritingMode(rect);
     EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(&layoutView(), rect));
     // (-2, 3, 140, 100) is first clipped by container's overflow clip, to (40, 10, 50, 80),
     // then is added by container's offset in LayoutView (111, 222).
@@ -330,10 +345,12 @@
     EXPECT_EQ(LayoutRect(0, 0, 110, 120), containerOverflowRect);
 
     rect = containerOverflowRect;
+    container->flipForWritingMode(rect);
     EXPECT_TRUE(container->mapToVisualRectInAncestorSpace(container, rect));
     EXPECT_EQ(LayoutRect(0, 0, 110, 120), rect);
 
     rect = containerOverflowRect;
+    container->flipForWritingMode(rect);
     EXPECT_TRUE(container->mapToVisualRectInAncestorSpace(&layoutView(), rect));
     // TODO(crbug.com/600039): rect.x() should be 222 (left), but is offset by extra horizontal
     // border-widths because of layout error.
@@ -398,11 +415,13 @@
     EXPECT_EQ(LayoutRect(-40, 0, 140, 110), targetOverflowRect);
 
     LayoutRect rect = targetOverflowRect;
+    target->flipForWritingMode(rect);
     EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(target, rect));
     // This rect is in physical coordinates of target.
     EXPECT_EQ(LayoutRect(0, 0, 140, 110), rect);
 
     rect = targetOverflowRect;
+    target->flipForWritingMode(rect);
     EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(container, rect));
     // 58 = target_physical_x(100) + container_border_left(40) - scroll_left(58)
     // The other sides of the rect are clipped by container's overflow clip.
diff --git a/third_party/WebKit/Source/core/layout/api/LayoutItem.h b/third_party/WebKit/Source/core/layout/api/LayoutItem.h
index 83d85a99..50f24bd8 100644
--- a/third_party/WebKit/Source/core/layout/api/LayoutItem.h
+++ b/third_party/WebKit/Source/core/layout/api/LayoutItem.h
@@ -32,12 +32,13 @@
 
     LayoutItem() : m_layoutObject(0) { }
 
-    // TODO(leviw): This should be an UnspecifiedBoolType, but
+    // TODO(leviw): This should be "explicit operator bool", but
     // using this operator allows the API to be landed in pieces.
     // https://crbug.com/499321
     operator LayoutObject*() const { return m_layoutObject; }
 
-    // TODO(pilgrim): Remove this when we replace the operator above with UnspecifiedBoolType.
+    // TODO(pilgrim): Remove this when we replace the operator above with
+    // operator bool.
     bool isNull() const
     {
         return !m_layoutObject;
diff --git a/third_party/WebKit/Source/core/layout/api/LineLayoutItem.h b/third_party/WebKit/Source/core/layout/api/LineLayoutItem.h
index 46c7fe7..70fed8d 100644
--- a/third_party/WebKit/Source/core/layout/api/LineLayoutItem.h
+++ b/third_party/WebKit/Source/core/layout/api/LineLayoutItem.h
@@ -47,8 +47,7 @@
 
     LineLayoutItem() : m_layoutObject(0) { }
 
-    typedef LayoutObject* LineLayoutItem::*UnspecifiedBoolType;
-    operator UnspecifiedBoolType() const { return m_layoutObject ? &LineLayoutItem::m_layoutObject : nullptr; }
+    explicit operator bool() const { return m_layoutObject; }
 
     bool isEqual(const LayoutObject* layoutObject) const
     {
diff --git a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp
index 4dc1e45..dd5482a 100644
--- a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp
+++ b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp
@@ -229,7 +229,7 @@
 
     graphicsLayer->setCompositingReasons(reasons);
     graphicsLayer->setSquashingDisallowedReasons(squashingDisallowedReasons);
-    if (Node* owningNode = m_owningLayer.layoutObject()->generatingNode())
+    if (Node* owningNode = m_owningLayer.layoutObject()->node())
         graphicsLayer->setOwnerNodeId(DOMNodeIds::idForNode(owningNode));
 
     return graphicsLayer;
@@ -1547,7 +1547,7 @@
     uint32_t primaryMutableProperties = CompositorMutableProperty::kNone;
     uint32_t scrollMutableProperties = CompositorMutableProperty::kNone;
 
-    Node* owningNode = m_owningLayer.layoutObject()->generatingNode();
+    Node* owningNode = m_owningLayer.layoutObject()->node();
     Element* owningElement = nullptr;
     if (owningNode && owningNode->isElementNode())
         owningElement = toElement(owningNode);
@@ -1661,7 +1661,7 @@
             // Inner layer which renders the content that scrolls.
             m_scrollingContentsLayer = createGraphicsLayer(CompositingReasonLayerForScrollingContents);
 
-            if (Node* owningNode = m_owningLayer.layoutObject()->generatingNode()) {
+            if (Node* owningNode = m_owningLayer.layoutObject()->node()) {
                 m_scrollingContentsLayer->setElementId(createCompositorElementId(DOMNodeIds::idForNode(owningNode), CompositorSubElementId::Scroll));
                 m_scrollingContentsLayer->setCompositorMutableProperties(CompositorMutableProperty::kScrollLeft | CompositorMutableProperty::kScrollTop);
             }
@@ -2298,9 +2298,6 @@
     // Start with the bounds of the graphics layer in the space of the anchor LayoutObject.
     FloatRect graphicsLayerBoundsInObjectSpace(graphicsLayerBounds);
     graphicsLayerBoundsInObjectSpace.move(offsetFromAnchorLayoutObject);
-    // The object space means including writing mode flip.
-    if (anchorLayoutObject->isBox())
-        toLayoutBox(anchorLayoutObject)->flipForWritingMode(graphicsLayerBoundsInObjectSpace);
 
     // Now map the bounds to its visible content rect in screen space, including applying clips along the way.
     LayoutRect visibleContentRect(graphicsLayerBoundsInObjectSpace);
diff --git a/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.cpp b/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.cpp
index c08de88..b44a02c 100644
--- a/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.cpp
+++ b/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.cpp
@@ -1018,7 +1018,7 @@
         IntRect overflowRect = m_layoutView.pixelSnappedLayoutOverflowRect();
         m_rootContentLayer->setSize(FloatSize(overflowRect.maxX(), overflowRect.maxY()));
         m_rootContentLayer->setPosition(FloatPoint());
-        m_rootContentLayer->setOwnerNodeId(DOMNodeIds::idForNode(m_layoutView.generatingNode()));
+        m_rootContentLayer->setOwnerNodeId(DOMNodeIds::idForNode(m_layoutView.node()));
 
         // FIXME: with rootLayerScrolls, we probably don't even need m_rootContentLayer?
         if (!(settings && settings->rootLayerScrolls())) {
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGResources.cpp b/third_party/WebKit/Source/core/layout/svg/SVGResources.cpp
index c668bdb..1332771 100644
--- a/third_party/WebKit/Source/core/layout/svg/SVGResources.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/SVGResources.cpp
@@ -48,91 +48,79 @@
 
 static HashSet<AtomicString>& clipperFilterMaskerTags()
 {
-    DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ());
-    if (s_tagList.isEmpty()) {
+    DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ({
         // "container elements": http://www.w3.org/TR/SVG11/intro.html#TermContainerElement
         // "graphics elements" : http://www.w3.org/TR/SVG11/intro.html#TermGraphicsElement
-        s_tagList.add(aTag.localName());
-        s_tagList.add(circleTag.localName());
-        s_tagList.add(ellipseTag.localName());
-        s_tagList.add(gTag.localName());
-        s_tagList.add(imageTag.localName());
-        s_tagList.add(lineTag.localName());
-        s_tagList.add(markerTag.localName());
-        s_tagList.add(maskTag.localName());
-        s_tagList.add(pathTag.localName());
-        s_tagList.add(polygonTag.localName());
-        s_tagList.add(polylineTag.localName());
-        s_tagList.add(rectTag.localName());
-        s_tagList.add(svgTag.localName());
-        s_tagList.add(textTag.localName());
-        s_tagList.add(useTag.localName());
-
+        aTag.localName(),
+        circleTag.localName(),
+        ellipseTag.localName(),
+        gTag.localName(),
+        imageTag.localName(),
+        lineTag.localName(),
+        markerTag.localName(),
+        maskTag.localName(),
+        pathTag.localName(),
+        polygonTag.localName(),
+        polylineTag.localName(),
+        rectTag.localName(),
+        svgTag.localName(),
+        textTag.localName(),
+        useTag.localName(),
         // Not listed in the definitions is the clipPath element, the SVG spec says though:
         // The "clipPath" element or any of its children can specify property "clip-path".
         // So we have to add clipPathTag here, otherwhise clip-path on clipPath will fail.
         // (Already mailed SVG WG, waiting for a solution)
-        s_tagList.add(clipPathTag.localName());
-
+        clipPathTag.localName(),
         // Not listed in the definitions are the text content elements, though filter/clipper/masker on tspan/text/.. is allowed.
         // (Already mailed SVG WG, waiting for a solution)
-        s_tagList.add(textPathTag.localName());
-        s_tagList.add(tspanTag.localName());
-
+        textPathTag.localName(),
+        tspanTag.localName(),
         // Not listed in the definitions is the foreignObject element, but clip-path
         // is a supported attribute.
-        s_tagList.add(foreignObjectTag.localName());
-
+        foreignObjectTag.localName(),
         // Elements that we ignore, as it doesn't make any sense.
         // defs, pattern, switch (FIXME: Mail SVG WG about these)
         // symbol (is converted to a svg element, when referenced by use, we can safely ignore it.)
-    }
-
+    }));
     return s_tagList;
 }
 
 bool SVGResources::supportsMarkers(const SVGElement& element)
 {
-    DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ());
-    if (s_tagList.isEmpty()) {
-        s_tagList.add(lineTag.localName());
-        s_tagList.add(pathTag.localName());
-        s_tagList.add(polygonTag.localName());
-        s_tagList.add(polylineTag.localName());
-    }
-
+    DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ({
+        lineTag.localName(),
+        pathTag.localName(),
+        polygonTag.localName(),
+        polylineTag.localName(),
+    }));
     return s_tagList.contains(element.localName());
 }
 
 static HashSet<AtomicString>& fillAndStrokeTags()
 {
-    DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ());
-    if (s_tagList.isEmpty()) {
-        s_tagList.add(circleTag.localName());
-        s_tagList.add(ellipseTag.localName());
-        s_tagList.add(lineTag.localName());
-        s_tagList.add(pathTag.localName());
-        s_tagList.add(polygonTag.localName());
-        s_tagList.add(polylineTag.localName());
-        s_tagList.add(rectTag.localName());
-        s_tagList.add(textTag.localName());
-        s_tagList.add(textPathTag.localName());
-        s_tagList.add(tspanTag.localName());
-    }
-
+    DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ({
+        circleTag.localName(),
+        ellipseTag.localName(),
+        lineTag.localName(),
+        pathTag.localName(),
+        polygonTag.localName(),
+        polylineTag.localName(),
+        rectTag.localName(),
+        textTag.localName(),
+        textPathTag.localName(),
+        tspanTag.localName(),
+    }));
     return s_tagList;
 }
 
 static HashSet<AtomicString>& chainableResourceTags()
 {
-    DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ());
-    if (s_tagList.isEmpty()) {
-        s_tagList.add(linearGradientTag.localName());
-        s_tagList.add(filterTag.localName());
-        s_tagList.add(patternTag.localName());
-        s_tagList.add(radialGradientTag.localName());
-    }
-
+    DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ({
+        linearGradientTag.localName(),
+        filterTag.localName(),
+        patternTag.localName(),
+        radialGradientTag.localName(),
+    }));
     return s_tagList;
 }
 
diff --git a/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.cpp b/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.cpp
index aafc6c9..446036a 100644
--- a/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.cpp
+++ b/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.cpp
@@ -388,6 +388,7 @@
 DEFINE_TRACE(OriginTrialContext)
 {
     visitor->trace(m_host);
+    Supplement<ExecutionContext>::trace(visitor);
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/page/FocusController.cpp b/third_party/WebKit/Source/core/page/FocusController.cpp
index f0388e2a..c7d11a22 100644
--- a/third_party/WebKit/Source/core/page/FocusController.cpp
+++ b/third_party/WebKit/Source/core/page/FocusController.cpp
@@ -1021,7 +1021,7 @@
 static bool relinquishesEditingFocus(const Element& element)
 {
     DCHECK(element.hasEditableStyle());
-    return element.document().frame() && element.rootEditableElement();
+    return element.document().frame() && rootEditableElement(element);
 }
 
 static void clearSelectionIfNeeded(LocalFrame* oldFocusedFrame, LocalFrame* newFocusedFrame, Element* newFocusedElement)
@@ -1068,7 +1068,7 @@
         return true;
 
     // FIXME: Might want to disable this check for caretBrowsing
-    if (oldFocusedElement && oldFocusedElement->isRootEditableElement() && !relinquishesEditingFocus(*oldFocusedElement))
+    if (oldFocusedElement && isRootEditableElement(*oldFocusedElement) && !relinquishesEditingFocus(*oldFocusedElement))
         return false;
 
     m_page->chromeClient().willSetInputMethodState();
diff --git a/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.cpp b/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.cpp
index 9bac01d..4d4f495f 100644
--- a/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.cpp
+++ b/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.cpp
@@ -9,11 +9,14 @@
 #include "core/frame/FrameHost.h"
 #include "core/frame/FrameView.h"
 #include "core/frame/TopControls.h"
+#include "core/frame/VisualViewport.h"
 #include "core/layout/LayoutBox.h"
+#include "core/page/ChromeClient.h"
 #include "core/page/Page.h"
 #include "core/page/scrolling/OverscrollController.h"
 #include "core/page/scrolling/ViewportScrollCallback.h"
 #include "core/paint/PaintLayerScrollableArea.h"
+#include "platform/graphics/GraphicsLayer.h"
 #include "platform/scroll/ScrollableArea.h"
 
 namespace blink {
@@ -160,6 +163,34 @@
     return true;
 }
 
+void RootScrollerController::didUpdateCompositing()
+{
+    FrameHost& frameHost = *m_document->frameHost();
+
+    // Let the compositor-side counterpart know about this change.
+    if (m_document->isInMainFrame())
+        frameHost.chromeClient().registerViewportLayers();
+}
+
+GraphicsLayer* RootScrollerController::rootScrollerLayer()
+{
+    if (!m_effectiveRootScroller)
+        return nullptr;
+
+    ScrollableArea* area = scrollableAreaFor(*m_effectiveRootScroller);
+
+    if (!area)
+        return nullptr;
+
+    GraphicsLayer* graphicsLayer = area->layerForScrolling();
+
+    // TODO(bokan): We should assert graphicsLayer here and
+    // RootScrollerController should do whatever needs to happen to ensure
+    // the root scroller gets composited.
+
+    return graphicsLayer;
+}
+
 Element* RootScrollerController::defaultEffectiveRootScroller()
 {
     DCHECK(m_document);
diff --git a/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.h b/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.h
index dd497226..557102b 100644
--- a/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.h
+++ b/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.h
@@ -12,6 +12,7 @@
 
 class Document;
 class Element;
+class GraphicsLayer;
 class ViewportScrollCallback;
 
 // Manages the root scroller associated with a given document. The root scroller
@@ -70,6 +71,12 @@
     // replaced by the defualt root scroller.
     void didUpdateLayout();
 
+    // This class needs to be informed of changes to compositing so that it can
+    // update the compositor when the effective root scroller changes.
+    void didUpdateCompositing();
+
+    GraphicsLayer* rootScrollerLayer();
+
     // TODO(bokan): Temporarily exposed to allow ScrollCustomization to
     // differentiate between real custom callback and the built-in viewport
     // apply scroll.
diff --git a/third_party/WebKit/Source/core/paint/ImagePainter.cpp b/third_party/WebKit/Source/core/paint/ImagePainter.cpp
index 203c6880..ad19b3f 100644
--- a/third_party/WebKit/Source/core/paint/ImagePainter.cpp
+++ b/third_party/WebKit/Source/core/paint/ImagePainter.cpp
@@ -19,7 +19,6 @@
 #include "core/paint/PaintInfo.h"
 #include "platform/geometry/LayoutPoint.h"
 #include "platform/graphics/Path.h"
-#include "platform/graphics/paint/ClipRecorder.h"
 
 namespace blink {
 
@@ -102,46 +101,51 @@
             context.drawRect(paintRect);
         }
     } else if (cWidth > 0 && cHeight > 0) {
+        if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(context, m_layoutImage, paintInfo.phase))
+            return;
+
         LayoutRect contentRect = m_layoutImage.contentBoxRect();
         contentRect.moveBy(paintOffset);
         LayoutRect paintRect = m_layoutImage.replacedContentRect();
         paintRect.moveBy(paintOffset);
 
-        Optional<ClipRecorder> clipRecorder;
-        if (!contentRect.contains(paintRect)) {
-            // TODO(fmalita): can we get rid of this clip and adjust the image src/dst rect instead?
-            clipRecorder.emplace(context, m_layoutImage, paintInfo.displayItemTypeForClipping(), pixelSnappedIntRect(contentRect));
-        }
-
-        if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(context, m_layoutImage, paintInfo.phase))
-            return;
-
         LayoutObjectDrawingRecorder drawingRecorder(context, m_layoutImage, paintInfo.phase, contentRect);
-        paintIntoRect(context, paintRect);
+        paintIntoRect(context, paintRect, contentRect);
     }
 }
 
-void ImagePainter::paintIntoRect(GraphicsContext& context, const LayoutRect& rect)
+void ImagePainter::paintIntoRect(GraphicsContext& context, const LayoutRect& destRect, const LayoutRect& contentRect)
 {
     if (!m_layoutImage.imageResource()->hasImage() || m_layoutImage.imageResource()->errorOccurred())
         return; // FIXME: should we just ASSERT these conditions? (audit all callers).
 
-    IntRect alignedRect = pixelSnappedIntRect(rect);
-    if (alignedRect.width() <= 0 || alignedRect.height() <= 0)
+    IntRect pixelSnappedDestRect = pixelSnappedIntRect(destRect);
+    if (pixelSnappedDestRect.isEmpty())
         return;
 
-    RefPtr<Image> image = m_layoutImage.imageResource()->image(alignedRect.size(), m_layoutImage.style()->effectiveZoom());
+    RefPtr<Image> image = m_layoutImage.imageResource()->image(pixelSnappedDestRect.size(), m_layoutImage.style()->effectiveZoom());
     if (!image || image->isNull())
         return;
 
     // FIXME: why is interpolation quality selection not included in the Instrumentation reported cost of drawing an image?
-    InterpolationQuality interpolationQuality = BoxPainter::chooseInterpolationQuality(m_layoutImage, image.get(), image.get(), LayoutSize(alignedRect.size()));
+    InterpolationQuality interpolationQuality = BoxPainter::chooseInterpolationQuality(m_layoutImage, image.get(), image.get(), LayoutSize(pixelSnappedDestRect.size()));
+
+    FloatRect srcRect = image->rect();
+    // If the content rect requires clipping, adjust |srcRect| and |pixelSnappedDestRect| over using a clip.
+    if (!contentRect.contains(destRect)) {
+        IntRect pixelSnappedContentRect = pixelSnappedIntRect(contentRect);
+        pixelSnappedContentRect.intersect(pixelSnappedDestRect);
+        if (pixelSnappedContentRect.isEmpty())
+            return;
+        srcRect = mapRect(pixelSnappedContentRect, pixelSnappedDestRect, srcRect);
+        pixelSnappedDestRect = pixelSnappedContentRect;
+    }
 
     TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage", "data", InspectorPaintImageEvent::data(m_layoutImage));
 
     InterpolationQuality previousInterpolationQuality = context.imageInterpolationQuality();
     context.setImageInterpolationQuality(interpolationQuality);
-    context.drawImage(image.get(), alignedRect, nullptr, SkXfermode::kSrcOver_Mode,
+    context.drawImage(image.get(), pixelSnappedDestRect, &srcRect, SkXfermode::kSrcOver_Mode,
         LayoutObject::shouldRespectImageOrientation(&m_layoutImage));
     context.setImageInterpolationQuality(previousInterpolationQuality);
 }
diff --git a/third_party/WebKit/Source/core/paint/ImagePainter.h b/third_party/WebKit/Source/core/paint/ImagePainter.h
index fce4d61..287dc59e 100644
--- a/third_party/WebKit/Source/core/paint/ImagePainter.h
+++ b/third_party/WebKit/Source/core/paint/ImagePainter.h
@@ -22,7 +22,10 @@
 
     void paint(const PaintInfo&, const LayoutPoint& paintOffset);
     void paintReplaced(const PaintInfo&, const LayoutPoint& paintOffset);
-    void paintIntoRect(GraphicsContext&, const LayoutRect&);
+
+    // Paint the image into |destRect|, after clipping by |contentRect|. Both |destRect| and
+    // |contentRect| should be in local coordinates plus the paint offset.
+    void paintIntoRect(GraphicsContext&, const LayoutRect& destRect, const LayoutRect& contentRect);
 
 private:
     void paintAreaElementFocusRing(const PaintInfo&, const LayoutPoint& paintOffset);
diff --git a/third_party/WebKit/Source/core/paint/LayoutObjectDrawingRecorderTest.cpp b/third_party/WebKit/Source/core/paint/LayoutObjectDrawingRecorderTest.cpp
index c0eb0e53..abc9a5a 100644
--- a/third_party/WebKit/Source/core/paint/LayoutObjectDrawingRecorderTest.cpp
+++ b/third_party/WebKit/Source/core/paint/LayoutObjectDrawingRecorderTest.cpp
@@ -76,9 +76,7 @@
     drawNothing(context, layoutView(), PaintPhaseSelfBlockBackgroundOnly, bound);
     drawRect(context, layoutView(), PaintPhaseForeground, bound);
 
-    EXPECT_DISPLAY_LIST(rootPaintController().newDisplayItemList(), 2,
-        TestDisplayItem(layoutView(), DisplayItem::drawingTypeToCachedDrawingType(DisplayItem::paintPhaseToDrawingType(PaintPhaseSelfBlockBackgroundOnly))),
-        TestDisplayItem(layoutView(), DisplayItem::drawingTypeToCachedDrawingType(DisplayItem::paintPhaseToDrawingType(PaintPhaseForeground))));
+    EXPECT_EQ(2, numCachedNewItems());
 
     rootPaintController().commitNewDisplayItems();
 
diff --git a/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.h b/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.h
index 83a1cf4..db2c9b1 100644
--- a/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.h
+++ b/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.h
@@ -75,6 +75,8 @@
         return false;
     }
 
+    int numCachedNewItems() { return rootPaintController().m_numCachedNewItems; }
+
 private:
     bool m_originalSlimmingPaintInvalidationEnabled;
     bool m_originalSlimmingPaintV2Enabled;
@@ -129,11 +131,8 @@
 
 // Shorter names for frequently used display item types in tests.
 const DisplayItem::Type backgroundType = DisplayItem::BoxDecorationBackground;
-const DisplayItem::Type cachedBackgroundType = DisplayItem::drawingTypeToCachedDrawingType(backgroundType);
 const DisplayItem::Type foregroundType = DisplayItem::paintPhaseToDrawingType(PaintPhaseForeground);
-const DisplayItem::Type cachedForegroundType = DisplayItem::drawingTypeToCachedDrawingType(foregroundType);
 const DisplayItem::Type documentBackgroundType = DisplayItem::DocumentBackground;
-const DisplayItem::Type cachedDocumentBackgroundType = DisplayItem::drawingTypeToCachedDrawingType(DisplayItem::DocumentBackground);
 
 } // namespace blink
 
diff --git a/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp b/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp
index f89da6ef..e552529 100644
--- a/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp
@@ -19,7 +19,7 @@
 {
     if (!scrollbar.isCustomScrollbar()
         && !(orientation == HorizontalScrollbar ? layerForHorizontalScrollbar() : layerForVerticalScrollbar()))
-        boxForScrollControlPaintInvalidation().slowSetPaintingLayerNeedsRepaintAndInvalidateDisplayItemClient(scrollbar, PaintInvalidationScroll);
+        layoutBox()->slowSetPaintingLayerNeedsRepaintAndInvalidateDisplayItemClient(scrollbar, PaintInvalidationScroll);
 
     ScrollableArea::willRemoveScrollbar(scrollbar, orientation);
 }
@@ -42,7 +42,6 @@
     }
     if (shouldInvalidateNewRect) {
         box.invalidatePaintUsingContainer(paintInvalidationContainer, newPaintInvalidationRect, PaintInvalidationScroll);
-        box.enclosingLayer()->setNeedsRepaint();
         return true;
     }
     return false;
@@ -99,7 +98,7 @@
 
 void PaintInvalidationCapableScrollableArea::invalidatePaintOfScrollControlsIfNeeded(const PaintInvalidationState& paintInvalidationState)
 {
-    LayoutBox& box = boxForScrollControlPaintInvalidation();
+    LayoutBox& box = *layoutBox();
     invalidatePaintOfScrollbarIfNeeded(horizontalScrollbar(), layerForHorizontalScrollbar(), m_horizontalScrollbarPreviouslyWasOverlay, m_horizontalScrollbarPreviousPaintInvalidationRect, horizontalScrollbarNeedsPaintInvalidation(), box, paintInvalidationState);
     invalidatePaintOfScrollbarIfNeeded(verticalScrollbar(), layerForVerticalScrollbar(), m_verticalScrollbarPreviouslyWasOverlay, m_verticalScrollbarPreviousPaintInvalidationRect, verticalScrollbarNeedsPaintInvalidation(), box, paintInvalidationState);
 
@@ -131,4 +130,9 @@
     return fullBounds;
 }
 
+void PaintInvalidationCapableScrollableArea::scrollControlWasSetNeedsPaintInvalidation()
+{
+    layoutBox()->setMayNeedPaintInvalidation();
+}
+
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.h b/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.h
index d58342ef..4ef4a25 100644
--- a/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.h
+++ b/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.h
@@ -37,10 +37,11 @@
     LayoutRect visualRectForScrollbarParts() const override;
 
 private:
-    virtual LayoutBox& boxForScrollControlPaintInvalidation() const = 0;
     virtual LayoutScrollbarPart* scrollCorner() const = 0;
     virtual LayoutScrollbarPart* resizer() const = 0;
 
+    void scrollControlWasSetNeedsPaintInvalidation() override;
+
     bool m_horizontalScrollbarPreviouslyWasOverlay;
     bool m_verticalScrollbarPreviouslyWasOverlay;
     LayoutRect m_horizontalScrollbarPreviousPaintInvalidationRect;
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerPainterTest.cpp b/third_party/WebKit/Source/core/paint/PaintLayerPainterTest.cpp
index a7789d7..5e9c5922 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerPainterTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerPainterTest.cpp
@@ -56,20 +56,11 @@
 
     toHTMLElement(content1.node())->setAttribute(HTMLNames::styleAttr, "position: absolute; width: 100px; height: 100px; background-color: green");
     document().view()->updateAllLifecyclePhasesExceptPaint();
-    bool needsCommit = paintWithoutCommit();
+    EXPECT_TRUE(paintWithoutCommit());
 
-    EXPECT_DISPLAY_LIST(rootPaintController().newDisplayItemList(), 8,
-        TestDisplayItem(layoutView(), cachedDocumentBackgroundType),
-        TestDisplayItem(htmlLayer, DisplayItem::Subsequence),
-        TestDisplayItem(container1Layer, DisplayItem::Subsequence),
-        TestDisplayItem(container1, cachedBackgroundType),
-        TestDisplayItem(content1, backgroundType),
-        TestDisplayItem(container1Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(container2Layer, DisplayItem::CachedSubsequence),
-        TestDisplayItem(htmlLayer, DisplayItem::EndSubsequence));
+    EXPECT_EQ(6, numCachedNewItems());
 
-    if (needsCommit)
-        commit();
+    commit();
 
     EXPECT_DISPLAY_LIST(rootPaintController().getDisplayItemList(), 11,
         TestDisplayItem(layoutView(), documentBackgroundType),
@@ -139,28 +130,16 @@
 
     document().view()->updateAllLifecyclePhasesExceptPaint();
     IntRect newInterestRect(0, 100, 300, 1000);
-    bool needsCommit = paintWithoutCommit(&newInterestRect);
+    EXPECT_TRUE(paintWithoutCommit(&newInterestRect));
 
     // Container1 becomes partly in the interest rect, but uses cached subsequence
     // because it was fully painted before;
     // Container2's intersection with the interest rect changes;
     // Content2b is out of the interest rect and outputs nothing;
     // Container3 becomes out of the interest rect and outputs empty subsequence pair..
-    EXPECT_DISPLAY_LIST(rootPaintController().newDisplayItemList(), 11,
-        TestDisplayItem(layoutView(), cachedDocumentBackgroundType),
-        TestDisplayItem(htmlLayer, DisplayItem::Subsequence),
-        TestDisplayItem(container1Layer, DisplayItem::CachedSubsequence),
-        TestDisplayItem(container2Layer, DisplayItem::Subsequence),
-        TestDisplayItem(container2, cachedBackgroundType),
-        TestDisplayItem(content2a, cachedBackgroundType),
-        TestDisplayItem(content2b, backgroundType),
-        TestDisplayItem(container2Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(container3Layer, DisplayItem::Subsequence),
-        TestDisplayItem(container3Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(htmlLayer, DisplayItem::EndSubsequence));
+    EXPECT_EQ(7, numCachedNewItems());
 
-    if (needsCommit)
-        commit();
+    commit();
 
     EXPECT_DISPLAY_LIST(rootPaintController().getDisplayItemList(), 14,
         TestDisplayItem(layoutView(), documentBackgroundType),
@@ -215,20 +194,11 @@
 
     toHTMLElement(content1.node())->setAttribute(HTMLNames::styleAttr, "position: absolute; width: 100px; height: 100px; background-color: green");
     document().view()->updateAllLifecyclePhasesExceptPaint();
-    bool needsCommit = paintWithoutCommit(&interestRect);
+    EXPECT_TRUE(paintWithoutCommit(&interestRect));
 
-    EXPECT_DISPLAY_LIST(rootPaintController().newDisplayItemList(), 8,
-        TestDisplayItem(layoutView(), cachedDocumentBackgroundType),
-        TestDisplayItem(htmlLayer, DisplayItem::Subsequence),
-        TestDisplayItem(container1Layer, DisplayItem::Subsequence),
-        TestDisplayItem(container1, cachedBackgroundType),
-        TestDisplayItem(content1, backgroundType),
-        TestDisplayItem(container1Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(container2Layer, DisplayItem::CachedSubsequence),
-        TestDisplayItem(htmlLayer, DisplayItem::EndSubsequence));
+    EXPECT_EQ(6, numCachedNewItems());
 
-    if (needsCommit)
-        commit();
+    commit();
 
     EXPECT_DISPLAY_LIST(rootPaintController().getDisplayItemList(), 11,
         TestDisplayItem(layoutView(), documentBackgroundType),
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
index 209a6ca..52b9388e 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
@@ -219,11 +219,6 @@
     return layer()->hasCompositedLayerMapping() ? layer()->compositedLayerMapping()->layerForScrollCorner() : 0;
 }
 
-void PaintLayerScrollableArea::scrollControlWasSetNeedsPaintInvalidation()
-{
-    box().setMayNeedPaintInvalidation();
-}
-
 bool PaintLayerScrollableArea::shouldUseIntegerScrollOffset() const
 {
     Frame* frame = box().frame();
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h
index 2aa1d6a..dd957916 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h
+++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h
@@ -258,7 +258,6 @@
 
     bool usesCompositedScrolling() const override;
     bool shouldScrollOnMainThread() const override;
-    void scrollControlWasSetNeedsPaintInvalidation() override;
     bool shouldUseIntegerScrollOffset() const override;
     bool isActive() const override;
     bool isScrollCornerVisible() const override;
@@ -489,9 +488,6 @@
         return *m_rareData.get();
     }
 
-    // PaintInvalidationCapableScrollableArea
-    LayoutBox& boxForScrollControlPaintInvalidation() const { return box(); }
-
     PaintLayer& m_layer;
 
     PaintLayer* m_nextTopmostScrollChild;
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
index d0860a4..07abff8 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
@@ -21,19 +21,17 @@
 
 void PaintPropertyTreeBuilder::buildTreeRootNodes(FrameView& rootFrame, PaintPropertyTreeBuilderContext& context)
 {
-    // Only create extra root clip and transform nodes when RLS is enabled, because the main frame
-    // unconditionally create frame translation / clip nodes otherwise.
-    if (rootFrame.frame().settings() && rootFrame.frame().settings()->rootLayerScrolls()) {
-        transformRoot = TransformPaintPropertyNode::create(TransformationMatrix(), FloatPoint3D(), nullptr);
-        context.currentTransform = context.transformForAbsolutePosition = context.transformForFixedPosition = transformRoot.get();
+    RefPtr<TransformPaintPropertyNode> transformRoot = TransformPaintPropertyNode::create(TransformationMatrix(), FloatPoint3D(), nullptr);
+    context.currentTransform = context.transformForAbsolutePosition = context.transformForFixedPosition = transformRoot.get();
+    rootFrame.setRootTransform(std::move(transformRoot));
 
-        clipRoot = ClipPaintPropertyNode::create(transformRoot, FloatRoundedRect(LayoutRect::infiniteIntRect()), nullptr);
-        context.currentClip = context.clipForAbsolutePosition = context.clipForFixedPosition = clipRoot.get();
-    }
+    RefPtr<ClipPaintPropertyNode> clipRoot = ClipPaintPropertyNode::create(transformRoot, FloatRoundedRect(LayoutRect::infiniteIntRect()), nullptr);
+    context.currentClip = context.clipForAbsolutePosition = context.clipForFixedPosition = clipRoot.get();
+    rootFrame.setRootClip(std::move(clipRoot));
 
-    // The root frame never creates effect node so we unconditionally create a root node here.
-    effectRoot = EffectPaintPropertyNode::create(1.0, nullptr);
+    RefPtr<EffectPaintPropertyNode> effectRoot = EffectPaintPropertyNode::create(1.0, nullptr);
     context.currentEffect = effectRoot.get();
+    rootFrame.setRootEffect(std::move(effectRoot));
 }
 
 void PaintPropertyTreeBuilder::buildTreeNodes(FrameView& frameView, PaintPropertyTreeBuilderContext& context)
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h
index 0234bbe..118763f 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h
@@ -86,11 +86,6 @@
     static void updateSvgLocalToBorderBoxTransform(const LayoutObject&, PaintPropertyTreeBuilderContext&);
     static void updateScrollTranslation(const LayoutObject&, PaintPropertyTreeBuilderContext&);
     static void updateOutOfFlowContext(const LayoutObject&, PaintPropertyTreeBuilderContext&);
-
-    // Holds references to root property nodes to keep them alive during tree walk.
-    RefPtr<TransformPaintPropertyNode> transformRoot;
-    RefPtr<ClipPaintPropertyNode> clipRoot;
-    RefPtr<EffectPaintPropertyNode> effectRoot;
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
index 466906e..0bd39b2 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
@@ -145,12 +145,14 @@
     FrameView* frameView = document().view();
     frameView->updateAllLifecyclePhases();
     EXPECT_EQ(TransformationMatrix(), frameView->preTranslation()->matrix());
-    EXPECT_EQ(nullptr, frameView->preTranslation()->parent());
+    EXPECT_EQ(frameView->rootTransform(), frameView->preTranslation()->parent());
+    EXPECT_EQ(nullptr, frameView->rootTransform()->parent());
     EXPECT_EQ(TransformationMatrix().translate(0, -100), frameView->scrollTranslation()->matrix());
     EXPECT_EQ(frameView->preTranslation(), frameView->scrollTranslation()->parent());
     EXPECT_EQ(frameView->preTranslation(), frameView->contentClip()->localTransformSpace());
     EXPECT_EQ(FloatRoundedRect(0, 0, 800, 600), frameView->contentClip()->clipRect());
-    EXPECT_EQ(nullptr, frameView->contentClip()->parent());
+    EXPECT_EQ(frameView->rootClip(), frameView->contentClip()->parent());
+    EXPECT_EQ(nullptr, frameView->rootClip()->parent());
 
     LayoutViewItem layoutViewItem = document().layoutViewItem();
     ObjectPaintProperties* layoutViewProperties = layoutViewItem.objectPaintProperties();
diff --git a/third_party/WebKit/Source/core/paint/PaintTiming.cpp b/third_party/WebKit/Source/core/paint/PaintTiming.cpp
index 7ff505a..87fc0e0 100644
--- a/third_party/WebKit/Source/core/paint/PaintTiming.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintTiming.cpp
@@ -68,6 +68,7 @@
 DEFINE_TRACE(PaintTiming)
 {
     visitor->trace(m_document);
+    Supplement<Document>::trace(visitor);
 }
 
 PaintTiming::PaintTiming(Document& document)
diff --git a/third_party/WebKit/Source/core/paint/README.md b/third_party/WebKit/Source/core/paint/README.md
index 1972dea..c391268 100644
--- a/third_party/WebKit/Source/core/paint/README.md
+++ b/third_party/WebKit/Source/core/paint/README.md
@@ -215,9 +215,8 @@
 
 ### Display item caching
 
-We'll create a `CachedDisplayItem` when a painter would create a `DrawingDisplayItem` exactly
-the same as the display item created in the previous painting. After painting, `PaintController`
-will replace `CachedDisplayItem` with the corresponding display item from the cache.
+When a painter would create a `DrawingDisplayItem` exactly the same as the display item
+created in the previous painting, we'll reuse the previous one instead of repainting it.
 
 ### Subsequence caching
 
@@ -225,10 +224,8 @@
 (including display items generated by sublayers) in a pair of `BeginSubsequence/EndSubsequence`
 display items.
 
-In a subsequence paint, if the layer would generate exactly the same display items, we'll simply
-output a `CachedSubsequence` display item in place of the display items, and skip all paintings
-of the layer and its descendants in painting order. After painting, `PaintController` will
-replace `CacheSubsequence` with cached display items created in previous paintings.
+In a subsequence paint, if the layer would generate exactly the same display items, we'll get
+the whole subsequence from the cache instead of repainting them.
 
 There are many conditions affecting
 *   whether we need to generate subsequence for a PaintLayer;
diff --git a/third_party/WebKit/Source/core/paint/VideoPainter.cpp b/third_party/WebKit/Source/core/paint/VideoPainter.cpp
index 49ea54a..07b42bd 100644
--- a/third_party/WebKit/Source/core/paint/VideoPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/VideoPainter.cpp
@@ -12,7 +12,6 @@
 #include "core/paint/LayoutObjectDrawingRecorder.h"
 #include "core/paint/PaintInfo.h"
 #include "platform/geometry/LayoutPoint.h"
-#include "platform/graphics/paint/ClipRecorder.h"
 #include "platform/graphics/paint/ForeignLayerDisplayItem.h"
 
 namespace blink {
@@ -29,18 +28,13 @@
         return;
     rect.moveBy(paintOffset);
 
+    if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(paintInfo.context, m_layoutVideo, paintInfo.phase))
+        return;
+
     GraphicsContext& context = paintInfo.context;
     LayoutRect contentRect = m_layoutVideo.contentBoxRect();
     contentRect.moveBy(paintOffset);
 
-    Optional<ClipRecorder> clipRecorder;
-    if (!contentRect.contains(rect))
-        clipRecorder.emplace(context, m_layoutVideo, paintInfo.displayItemTypeForClipping(), pixelSnappedIntRect(contentRect));
-
-    if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(context, m_layoutVideo, paintInfo.phase))
-        return;
-
-
     // Video frames are only painted in software for printing or capturing node images via web APIs.
     bool forceSoftwareVideoPaint = paintInfo.getGlobalPaintFlags() & GlobalPaintFlattenCompositingLayers;
 
@@ -61,7 +55,7 @@
 
     if (displayingPoster || !forceSoftwareVideoPaint) {
         // This will display the poster image, if one is present, and otherwise paint nothing.
-        ImagePainter(m_layoutVideo).paintIntoRect(context, rect);
+        ImagePainter(m_layoutVideo).paintIntoRect(context, rect, contentRect);
     } else {
         SkPaint videoPaint = context.fillPaint();
         videoPaint.setColor(SK_ColorBLACK);
diff --git a/third_party/WebKit/Source/core/style/BorderData.h b/third_party/WebKit/Source/core/style/BorderData.h
index eedc12a8..7bdb4d3 100644
--- a/third_party/WebKit/Source/core/style/BorderData.h
+++ b/third_party/WebKit/Source/core/style/BorderData.h
@@ -124,6 +124,14 @@
         return !(*this == o);
     }
 
+    bool sizeEquals(const BorderData& o) const
+    {
+        return borderLeftWidth() != o.borderLeftWidth()
+            || borderTopWidth() != o.borderTopWidth()
+            || borderRightWidth() != o.borderRightWidth()
+            || borderBottomWidth() != o.borderBottomWidth();
+    }
+
     const BorderValue& left() const { return m_left; }
     const BorderValue& right() const { return m_right; }
     const BorderValue& top() const { return m_top; }
diff --git a/third_party/WebKit/Source/core/style/StyleGeneratedImage.cpp b/third_party/WebKit/Source/core/style/StyleGeneratedImage.cpp
index 1e63714f..e03e8ec 100644
--- a/third_party/WebKit/Source/core/style/StyleGeneratedImage.cpp
+++ b/third_party/WebKit/Source/core/style/StyleGeneratedImage.cpp
@@ -68,9 +68,9 @@
     m_imageGeneratorValue->removeClient(layoutObject);
 }
 
-PassRefPtr<Image> StyleGeneratedImage::image(const LayoutObject& layoutObject, const IntSize& size, float) const
+PassRefPtr<Image> StyleGeneratedImage::image(const LayoutObject& layoutObject, const IntSize& size, float zoom) const
 {
-    return m_imageGeneratorValue->image(layoutObject, size);
+    return m_imageGeneratorValue->image(layoutObject, size, zoom);
 }
 
 bool StyleGeneratedImage::knownToBeOpaque(const LayoutObject& layoutObject) const
diff --git a/third_party/WebKit/Source/core/svg/SVGAttributeNames.in b/third_party/WebKit/Source/core/svg/SVGAttributeNames.in
index 8b2d5e1b..0d63f39 100644
--- a/third_party/WebKit/Source/core/svg/SVGAttributeNames.in
+++ b/third_party/WebKit/Source/core/svg/SVGAttributeNames.in
@@ -127,7 +127,6 @@
 onfocusin
 onfocusout
 onrepeat
-onzoom
 opacity
 operator
 order
diff --git a/third_party/WebKit/Source/core/svg/SVGElement.cpp b/third_party/WebKit/Source/core/svg/SVGElement.cpp
index 28f432c..9f3bfab 100644
--- a/third_party/WebKit/Source/core/svg/SVGElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGElement.cpp
@@ -999,105 +999,99 @@
 {
     // This static is atomically initialized to dodge a warning about
     // a race when dumping debug data for a layer.
-    DEFINE_THREAD_SAFE_STATIC_LOCAL(HashSet<QualifiedName>, animatableAttributes, new HashSet<QualifiedName>());
-
-    if (animatableAttributes.isEmpty()) {
-        const QualifiedName* const animatableAttrs[] = {
-            &SVGNames::amplitudeAttr,
-            &SVGNames::azimuthAttr,
-            &SVGNames::baseFrequencyAttr,
-            &SVGNames::biasAttr,
-            &SVGNames::clipPathUnitsAttr,
-            &SVGNames::cxAttr,
-            &SVGNames::cyAttr,
-            &SVGNames::diffuseConstantAttr,
-            &SVGNames::divisorAttr,
-            &SVGNames::dxAttr,
-            &SVGNames::dyAttr,
-            &SVGNames::edgeModeAttr,
-            &SVGNames::elevationAttr,
-            &SVGNames::exponentAttr,
-            &SVGNames::filterUnitsAttr,
-            &SVGNames::fxAttr,
-            &SVGNames::fyAttr,
-            &SVGNames::gradientTransformAttr,
-            &SVGNames::gradientUnitsAttr,
-            &SVGNames::heightAttr,
-            &SVGNames::hrefAttr,
-            &SVGNames::in2Attr,
-            &SVGNames::inAttr,
-            &SVGNames::interceptAttr,
-            &SVGNames::k1Attr,
-            &SVGNames::k2Attr,
-            &SVGNames::k3Attr,
-            &SVGNames::k4Attr,
-            &SVGNames::kernelMatrixAttr,
-            &SVGNames::kernelUnitLengthAttr,
-            &SVGNames::lengthAdjustAttr,
-            &SVGNames::limitingConeAngleAttr,
-            &SVGNames::markerHeightAttr,
-            &SVGNames::markerUnitsAttr,
-            &SVGNames::markerWidthAttr,
-            &SVGNames::maskContentUnitsAttr,
-            &SVGNames::maskUnitsAttr,
-            &SVGNames::methodAttr,
-            &SVGNames::modeAttr,
-            &SVGNames::numOctavesAttr,
-            &SVGNames::offsetAttr,
-            &SVGNames::operatorAttr,
-            &SVGNames::orderAttr,
-            &SVGNames::orientAttr,
-            &SVGNames::pathLengthAttr,
-            &SVGNames::patternContentUnitsAttr,
-            &SVGNames::patternTransformAttr,
-            &SVGNames::patternUnitsAttr,
-            &SVGNames::pointsAtXAttr,
-            &SVGNames::pointsAtYAttr,
-            &SVGNames::pointsAtZAttr,
-            &SVGNames::preserveAlphaAttr,
-            &SVGNames::preserveAspectRatioAttr,
-            &SVGNames::primitiveUnitsAttr,
-            &SVGNames::radiusAttr,
-            &SVGNames::rAttr,
-            &SVGNames::refXAttr,
-            &SVGNames::refYAttr,
-            &SVGNames::resultAttr,
-            &SVGNames::rotateAttr,
-            &SVGNames::rxAttr,
-            &SVGNames::ryAttr,
-            &SVGNames::scaleAttr,
-            &SVGNames::seedAttr,
-            &SVGNames::slopeAttr,
-            &SVGNames::spacingAttr,
-            &SVGNames::specularConstantAttr,
-            &SVGNames::specularExponentAttr,
-            &SVGNames::spreadMethodAttr,
-            &SVGNames::startOffsetAttr,
-            &SVGNames::stdDeviationAttr,
-            &SVGNames::stitchTilesAttr,
-            &SVGNames::surfaceScaleAttr,
-            &SVGNames::tableValuesAttr,
-            &SVGNames::targetAttr,
-            &SVGNames::targetXAttr,
-            &SVGNames::targetYAttr,
-            &SVGNames::transformAttr,
-            &SVGNames::typeAttr,
-            &SVGNames::valuesAttr,
-            &SVGNames::viewBoxAttr,
-            &SVGNames::widthAttr,
-            &SVGNames::x1Attr,
-            &SVGNames::x2Attr,
-            &SVGNames::xAttr,
-            &SVGNames::xChannelSelectorAttr,
-            &SVGNames::y1Attr,
-            &SVGNames::y2Attr,
-            &SVGNames::yAttr,
-            &SVGNames::yChannelSelectorAttr,
-            &SVGNames::zAttr,
-        };
-        for (size_t i = 0; i < WTF_ARRAY_LENGTH(animatableAttrs); i++)
-            animatableAttributes.add(*animatableAttrs[i]);
-    }
+    DEFINE_THREAD_SAFE_STATIC_LOCAL(HashSet<QualifiedName>, animatableAttributes, new HashSet<QualifiedName>({
+        SVGNames::amplitudeAttr,
+        SVGNames::azimuthAttr,
+        SVGNames::baseFrequencyAttr,
+        SVGNames::biasAttr,
+        SVGNames::clipPathUnitsAttr,
+        SVGNames::cxAttr,
+        SVGNames::cyAttr,
+        SVGNames::diffuseConstantAttr,
+        SVGNames::divisorAttr,
+        SVGNames::dxAttr,
+        SVGNames::dyAttr,
+        SVGNames::edgeModeAttr,
+        SVGNames::elevationAttr,
+        SVGNames::exponentAttr,
+        SVGNames::filterUnitsAttr,
+        SVGNames::fxAttr,
+        SVGNames::fyAttr,
+        SVGNames::gradientTransformAttr,
+        SVGNames::gradientUnitsAttr,
+        SVGNames::heightAttr,
+        SVGNames::hrefAttr,
+        SVGNames::in2Attr,
+        SVGNames::inAttr,
+        SVGNames::interceptAttr,
+        SVGNames::k1Attr,
+        SVGNames::k2Attr,
+        SVGNames::k3Attr,
+        SVGNames::k4Attr,
+        SVGNames::kernelMatrixAttr,
+        SVGNames::kernelUnitLengthAttr,
+        SVGNames::lengthAdjustAttr,
+        SVGNames::limitingConeAngleAttr,
+        SVGNames::markerHeightAttr,
+        SVGNames::markerUnitsAttr,
+        SVGNames::markerWidthAttr,
+        SVGNames::maskContentUnitsAttr,
+        SVGNames::maskUnitsAttr,
+        SVGNames::methodAttr,
+        SVGNames::modeAttr,
+        SVGNames::numOctavesAttr,
+        SVGNames::offsetAttr,
+        SVGNames::operatorAttr,
+        SVGNames::orderAttr,
+        SVGNames::orientAttr,
+        SVGNames::pathLengthAttr,
+        SVGNames::patternContentUnitsAttr,
+        SVGNames::patternTransformAttr,
+        SVGNames::patternUnitsAttr,
+        SVGNames::pointsAtXAttr,
+        SVGNames::pointsAtYAttr,
+        SVGNames::pointsAtZAttr,
+        SVGNames::preserveAlphaAttr,
+        SVGNames::preserveAspectRatioAttr,
+        SVGNames::primitiveUnitsAttr,
+        SVGNames::radiusAttr,
+        SVGNames::rAttr,
+        SVGNames::refXAttr,
+        SVGNames::refYAttr,
+        SVGNames::resultAttr,
+        SVGNames::rotateAttr,
+        SVGNames::rxAttr,
+        SVGNames::ryAttr,
+        SVGNames::scaleAttr,
+        SVGNames::seedAttr,
+        SVGNames::slopeAttr,
+        SVGNames::spacingAttr,
+        SVGNames::specularConstantAttr,
+        SVGNames::specularExponentAttr,
+        SVGNames::spreadMethodAttr,
+        SVGNames::startOffsetAttr,
+        SVGNames::stdDeviationAttr,
+        SVGNames::stitchTilesAttr,
+        SVGNames::surfaceScaleAttr,
+        SVGNames::tableValuesAttr,
+        SVGNames::targetAttr,
+        SVGNames::targetXAttr,
+        SVGNames::targetYAttr,
+        SVGNames::transformAttr,
+        SVGNames::typeAttr,
+        SVGNames::valuesAttr,
+        SVGNames::viewBoxAttr,
+        SVGNames::widthAttr,
+        SVGNames::x1Attr,
+        SVGNames::x2Attr,
+        SVGNames::xAttr,
+        SVGNames::xChannelSelectorAttr,
+        SVGNames::y1Attr,
+        SVGNames::y2Attr,
+        SVGNames::yAttr,
+        SVGNames::yChannelSelectorAttr,
+        SVGNames::zAttr,
+    }));
 
     if (name == classAttr)
         return true;
diff --git a/third_party/WebKit/Source/core/svg/SVGLength.cpp b/third_party/WebKit/Source/core/svg/SVGLength.cpp
index c5fe9da..f8000e9 100644
--- a/third_party/WebKit/Source/core/svg/SVGLength.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGLength.cpp
@@ -212,21 +212,18 @@
 
 bool SVGLength::negativeValuesForbiddenForAnimatedLengthAttribute(const QualifiedName& attrName)
 {
-    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, s_noNegativeValuesSet, ());
-
-    if (s_noNegativeValuesSet.isEmpty()) {
-        s_noNegativeValuesSet.add(SVGNames::frAttr);
-        s_noNegativeValuesSet.add(SVGNames::rAttr);
-        s_noNegativeValuesSet.add(SVGNames::rxAttr);
-        s_noNegativeValuesSet.add(SVGNames::ryAttr);
-        s_noNegativeValuesSet.add(SVGNames::widthAttr);
-        s_noNegativeValuesSet.add(SVGNames::heightAttr);
-        s_noNegativeValuesSet.add(SVGNames::markerWidthAttr);
-        s_noNegativeValuesSet.add(SVGNames::markerHeightAttr);
-        s_noNegativeValuesSet.add(SVGNames::textLengthAttr);
-    }
-
-    return s_noNegativeValuesSet.contains(attrName);
+    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, noNegativeValuesSet, ({
+        SVGNames::frAttr,
+        SVGNames::rAttr,
+        SVGNames::rxAttr,
+        SVGNames::ryAttr,
+        SVGNames::widthAttr,
+        SVGNames::heightAttr,
+        SVGNames::markerWidthAttr,
+        SVGNames::markerHeightAttr,
+        SVGNames::textLengthAttr,
+    }));
+    return noNegativeValuesSet.contains(attrName);
 }
 
 void SVGLength::add(SVGPropertyBase* other, SVGElement* contextElement)
diff --git a/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp b/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp
index eb3e57ad7..73bddfc0 100644
--- a/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp
@@ -177,9 +177,6 @@
             document().setWindowAttributeEventListener(EventTypeNames::resize, createAttributeEventListener(document().frame(), name, value, eventParameterName()));
         } else if (name == HTMLNames::onscrollAttr) {
             document().setWindowAttributeEventListener(EventTypeNames::scroll, createAttributeEventListener(document().frame(), name, value, eventParameterName()));
-        } else if (name == SVGNames::onzoomAttr) {
-            Deprecation::countDeprecation(document(), UseCounter::SVGZoomEvent);
-            document().setWindowAttributeEventListener(EventTypeNames::zoom, createAttributeEventListener(document().frame(), name, value, eventParameterName()));
         } else {
             setListener = false;
         }
diff --git a/third_party/WebKit/Source/core/svg/SVGUseElement.cpp b/third_party/WebKit/Source/core/svg/SVGUseElement.cpp
index e6d6b6eb..d2249021f 100644
--- a/third_party/WebKit/Source/core/svg/SVGUseElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGUseElement.cpp
@@ -249,29 +249,28 @@
     if (!element.isSVGElement())
         return true;
 
-    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, allowedElementTags, ());
-    if (allowedElementTags.isEmpty()) {
-        allowedElementTags.add(SVGNames::aTag);
-        allowedElementTags.add(SVGNames::circleTag);
-        allowedElementTags.add(SVGNames::descTag);
-        allowedElementTags.add(SVGNames::ellipseTag);
-        allowedElementTags.add(SVGNames::gTag);
-        allowedElementTags.add(SVGNames::imageTag);
-        allowedElementTags.add(SVGNames::lineTag);
-        allowedElementTags.add(SVGNames::metadataTag);
-        allowedElementTags.add(SVGNames::pathTag);
-        allowedElementTags.add(SVGNames::polygonTag);
-        allowedElementTags.add(SVGNames::polylineTag);
-        allowedElementTags.add(SVGNames::rectTag);
-        allowedElementTags.add(SVGNames::svgTag);
-        allowedElementTags.add(SVGNames::switchTag);
-        allowedElementTags.add(SVGNames::symbolTag);
-        allowedElementTags.add(SVGNames::textTag);
-        allowedElementTags.add(SVGNames::textPathTag);
-        allowedElementTags.add(SVGNames::titleTag);
-        allowedElementTags.add(SVGNames::tspanTag);
-        allowedElementTags.add(SVGNames::useTag);
-    }
+    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, allowedElementTags, ({
+        SVGNames::aTag,
+        SVGNames::circleTag,
+        SVGNames::descTag,
+        SVGNames::ellipseTag,
+        SVGNames::gTag,
+        SVGNames::imageTag,
+        SVGNames::lineTag,
+        SVGNames::metadataTag,
+        SVGNames::pathTag,
+        SVGNames::polygonTag,
+        SVGNames::polylineTag,
+        SVGNames::rectTag,
+        SVGNames::svgTag,
+        SVGNames::switchTag,
+        SVGNames::symbolTag,
+        SVGNames::textTag,
+        SVGNames::textPathTag,
+        SVGNames::titleTag,
+        SVGNames::tspanTag,
+        SVGNames::useTag,
+    }));
     return !allowedElementTags.contains<SVGAttributeHashTranslator>(element.tagQName());
 }
 
diff --git a/third_party/WebKit/Source/core/svg/SVGZoomEvent.cpp b/third_party/WebKit/Source/core/svg/SVGZoomEvent.cpp
deleted file mode 100644
index f9f7d1c3..0000000
--- a/third_party/WebKit/Source/core/svg/SVGZoomEvent.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2004, 2005 Nikolas Zimmermann <zimmermann@kde.org>
- * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
- * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "core/svg/SVGZoomEvent.h"
-
-#include "core/svg/SVGElement.h"
-#include "core/svg/SVGPointTearOff.h"
-#include "core/svg/SVGRectTearOff.h"
-
-namespace blink {
-
-SVGZoomEvent::SVGZoomEvent()
-    : m_newScale(0.0f)
-    , m_previousScale(0.0f)
-{
-}
-
-SVGRectTearOff* SVGZoomEvent::zoomRectScreen() const
-{
-    SVGRectTearOff* rectTearOff = SVGRectTearOff::create(SVGRect::create(), 0, PropertyIsNotAnimVal);
-    rectTearOff->setIsReadOnlyProperty();
-    return rectTearOff;
-}
-
-float SVGZoomEvent::previousScale() const
-{
-    return m_previousScale;
-}
-
-SVGPointTearOff* SVGZoomEvent::previousTranslate() const
-{
-    SVGPointTearOff* pointTearOff = SVGPointTearOff::create(SVGPoint::create(m_previousTranslate), 0, PropertyIsNotAnimVal);
-    pointTearOff->setIsReadOnlyProperty();
-    return pointTearOff;
-}
-
-float SVGZoomEvent::newScale() const
-{
-    return m_newScale;
-}
-
-SVGPointTearOff* SVGZoomEvent::newTranslate() const
-{
-    SVGPointTearOff* pointTearOff = SVGPointTearOff::create(SVGPoint::create(m_newTranslate), 0, PropertyIsNotAnimVal);
-    pointTearOff->setIsReadOnlyProperty();
-    return pointTearOff;
-}
-
-const AtomicString& SVGZoomEvent::interfaceName() const
-{
-    return EventNames::SVGZoomEvent;
-}
-
-DEFINE_TRACE(SVGZoomEvent)
-{
-    UIEvent::trace(visitor);
-}
-
-} // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGZoomEvent.h b/third_party/WebKit/Source/core/svg/SVGZoomEvent.h
deleted file mode 100644
index 0cbdc12..0000000
--- a/third_party/WebKit/Source/core/svg/SVGZoomEvent.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2004, 2005 Nikolas Zimmermann <zimmermann@kde.org>
- * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
- * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef SVGZoomEvent_h
-#define SVGZoomEvent_h
-
-#include "core/events/UIEvent.h"
-#include "core/svg/SVGPoint.h"
-#include "core/svg/SVGRect.h"
-#include "platform/heap/Handle.h"
-
-namespace blink {
-
-class SVGZoomEvent final : public UIEvent {
-    DEFINE_WRAPPERTYPEINFO();
-public:
-    static SVGZoomEvent* create()
-    {
-        return new SVGZoomEvent;
-    }
-
-    // 'SVGZoomEvent' functions
-    SVGRectTearOff* zoomRectScreen() const;
-
-    float previousScale() const;
-
-    SVGPointTearOff* previousTranslate() const;
-
-    float newScale() const;
-
-    SVGPointTearOff* newTranslate() const;
-
-    const AtomicString& interfaceName() const override;
-
-    DECLARE_VIRTUAL_TRACE();
-
-private:
-    SVGZoomEvent();
-
-    float m_newScale;
-    float m_previousScale;
-
-    FloatPoint m_newTranslate;
-    FloatPoint m_previousTranslate;
-};
-
-} // namespace blink
-
-#endif // SVGZoomEvent_h
diff --git a/third_party/WebKit/Source/core/svg/SVGZoomEvent.idl b/third_party/WebKit/Source/core/svg/SVGZoomEvent.idl
deleted file mode 100644
index 85fa751..0000000
--- a/third_party/WebKit/Source/core/svg/SVGZoomEvent.idl
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2006 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. 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.
- */
-
-// http://www.w3.org/TR/SVG2/script.html#InterfaceSVGZoomEvent
-
-[
-    DependentLifetime,
-] interface SVGZoomEvent : UIEvent {
-    // TODO(foolip): SVGRect/SVGPoint should be DOMRectReadOnly/DOMPointReadOnly.
-    readonly attribute SVGRect zoomRectScreen;
-    readonly attribute float previousScale;
-    readonly attribute SVGPoint previousTranslate;
-    readonly attribute float newScale;
-    readonly attribute SVGPoint newTranslate;
-};
diff --git a/third_party/WebKit/Source/core/testing/DictionaryTest.cpp b/third_party/WebKit/Source/core/testing/DictionaryTest.cpp
index e862f1f..4d99353 100644
--- a/third_party/WebKit/Source/core/testing/DictionaryTest.cpp
+++ b/third_party/WebKit/Source/core/testing/DictionaryTest.cpp
@@ -163,7 +163,7 @@
         if (firstLoop)
             firstLoop = false;
         else
-            result.append(",");
+            result.append(',');
 
         v8::Local<v8::Value> value;
         if (v8Call(iterator.value(), value))
diff --git a/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.cpp b/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.cpp
index 1b1074d..3b19195 100644
--- a/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.cpp
+++ b/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.cpp
@@ -268,13 +268,6 @@
         m_workerInspectorProxy->dispatchMessageFromWorker(message);
 }
 
-void InProcessWorkerMessagingProxy::postWorkerConsoleAgentEnabled()
-{
-    DCHECK(isParentContextThread());
-    if (m_workerInspectorProxy)
-        m_workerInspectorProxy->workerConsoleAgentEnabled();
-}
-
 void InProcessWorkerMessagingProxy::confirmMessageFromWorkerObject(bool hasPendingActivity)
 {
     DCHECK(isParentContextThread());
diff --git a/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.h b/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.h
index 27722da..42c1eeb 100644
--- a/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.h
+++ b/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.h
@@ -70,7 +70,6 @@
     void reportException(const String& errorMessage, std::unique_ptr<SourceLocation>);
     void reportConsoleMessage(MessageSource, MessageLevel, const String& message, std::unique_ptr<SourceLocation>);
     void postMessageToPageInspector(const String&);
-    void postWorkerConsoleAgentEnabled();
     void confirmMessageFromWorkerObject(bool hasPendingActivity);
     void reportPendingActivity(bool hasPendingActivity);
     void workerThreadTerminated();
diff --git a/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.cpp b/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.cpp
index b68dc72..402ca48 100644
--- a/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.cpp
+++ b/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.cpp
@@ -85,13 +85,6 @@
         toDocument(context)->postInspectorTask(BLINK_FROM_HERE, createCrossThreadTask(&InProcessWorkerMessagingProxy::postMessageToPageInspector, crossThreadUnretained(m_messagingProxy), message));
 }
 
-void InProcessWorkerObjectProxy::postWorkerConsoleAgentEnabled()
-{
-    ExecutionContext* context = getExecutionContext();
-    if (context->isDocument())
-        toDocument(context)->postInspectorTask(BLINK_FROM_HERE, createCrossThreadTask(&InProcessWorkerMessagingProxy::postWorkerConsoleAgentEnabled, crossThreadUnretained(m_messagingProxy)));
-}
-
 void InProcessWorkerObjectProxy::workerGlobalScopeClosed()
 {
     getExecutionContext()->postTask(BLINK_FROM_HERE, createCrossThreadTask(&InProcessWorkerMessagingProxy::terminateWorkerGlobalScope, crossThreadUnretained(m_messagingProxy)));
diff --git a/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.h b/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.h
index 1bfe52a..ed8386c 100644
--- a/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.h
+++ b/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.h
@@ -67,7 +67,6 @@
     void reportException(const String& errorMessage, std::unique_ptr<SourceLocation>) override;
     void reportConsoleMessage(ConsoleMessage*) override;
     void postMessageToPageInspector(const String&) override;
-    void postWorkerConsoleAgentEnabled() override;
     void didEvaluateWorkerScript(bool success) override { }
     void workerGlobalScopeStarted(WorkerGlobalScope*) override { }
     void workerGlobalScopeClosed() override;
diff --git a/third_party/WebKit/Source/core/workers/WorkerClients.cpp b/third_party/WebKit/Source/core/workers/WorkerClients.cpp
new file mode 100644
index 0000000..d3dc043
--- /dev/null
+++ b/third_party/WebKit/Source/core/workers/WorkerClients.cpp
@@ -0,0 +1,11 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/workers/WorkerClients.h"
+
+namespace blink {
+
+template class CORE_TEMPLATE_EXPORT Supplement<WorkerClients>;
+
+} // namespace blink
diff --git a/third_party/WebKit/Source/core/workers/WorkerClients.h b/third_party/WebKit/Source/core/workers/WorkerClients.h
index 70d5661e..f46c455 100644
--- a/third_party/WebKit/Source/core/workers/WorkerClients.h
+++ b/third_party/WebKit/Source/core/workers/WorkerClients.h
@@ -31,11 +31,14 @@
 #ifndef WorkerClients_h
 #define WorkerClients_h
 
+#include "core/CoreExport.h"
 #include "platform/Supplementable.h"
 #include "wtf/Forward.h"
 
 namespace blink {
 
+class WorkerClients;
+
 // This is created on the main thread, passed to the worker thread and
 // attached to WorkerGlobalScope when it is created.
 // This class can be used to provide "client" implementations to Workers.
@@ -57,6 +60,8 @@
     WorkerClients() { }
 };
 
+extern template class CORE_EXTERN_TEMPLATE_EXPORT Supplement<WorkerClients>;
+
 } // namespace blink
 
 #endif // WorkerClients_h
diff --git a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
index 0770e90d..d10cff0 100644
--- a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
@@ -295,7 +295,8 @@
         consoleMessage->location()->columnNumber(),
         consoleMessage->location()->cloneStackTrace(),
         consoleMessage->location()->scriptId(),
-        IdentifiersFactory::requestId(consoleMessage->requestIdentifier()));
+        IdentifiersFactory::requestId(consoleMessage->requestIdentifier()),
+        consoleMessage->workerId());
 }
 
 bool WorkerGlobalScope::isContextThread() const
diff --git a/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.cpp b/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.cpp
index d21c83a..2cc2908 100644
--- a/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.cpp
@@ -20,8 +20,6 @@
 
 namespace {
 
-static const unsigned maxConsoleMessageCount = 1000;
-
 static WorkerInspectorProxy::WorkerInspectorProxySet& inspectorProxies()
 {
     DEFINE_STATIC_LOCAL(WorkerInspectorProxy::WorkerInspectorProxySet, proxies, ());
@@ -39,7 +37,6 @@
     : m_workerThread(nullptr)
     , m_document(nullptr)
     , m_pageInspector(nullptr)
-    , m_ignoreConsoleMessages(false)
 {
 }
 
@@ -85,13 +82,6 @@
         InspectorInstrumentation::workerTerminated(m_document, this);
     }
 
-    LocalFrame* frame = m_document ? m_document->frame() : nullptr;
-    if (frame) {
-        for (ConsoleMessage* message : m_consoleMessages)
-            frame->console().adoptWorkerMessage(message);
-        m_consoleMessages.clear();
-    }
-
     m_workerThread = nullptr;
     m_pageInspector = nullptr;
     m_document = nullptr;
@@ -103,22 +93,10 @@
         m_pageInspector->dispatchMessageFromWorker(this, message);
 }
 
-void WorkerInspectorProxy::workerConsoleAgentEnabled()
-{
-    m_ignoreConsoleMessages = true;
-    m_consoleMessages.clear();
-}
-
 void WorkerInspectorProxy::addConsoleMessageFromWorker(ConsoleMessage* consoleMessage)
 {
-    if (!m_ignoreConsoleMessages) {
-        DCHECK(m_consoleMessages.size() <= maxConsoleMessageCount);
-        if (m_consoleMessages.size() == maxConsoleMessageCount)
-            m_consoleMessages.removeFirst();
-        m_consoleMessages.append(consoleMessage);
-    }
     if (LocalFrame* frame = m_document->frame())
-        frame->console().reportWorkerMessage(consoleMessage);
+        frame->console().addMessageFromWorker(consoleMessage, m_inspectorId);
 }
 
 static void connectToWorkerGlobalScopeInspectorTask(WorkerThread* workerThread)
@@ -172,7 +150,6 @@
 DEFINE_TRACE(WorkerInspectorProxy)
 {
     visitor->trace(m_document);
-    visitor->trace(m_consoleMessages);
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.h b/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.h
index 7ce7e37..af5e7a44 100644
--- a/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.h
+++ b/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.h
@@ -37,7 +37,6 @@
     void workerThreadCreated(Document*, WorkerThread*, const KURL&);
     void workerThreadTerminated();
     void dispatchMessageFromWorker(const String&);
-    void workerConsoleAgentEnabled();
     void addConsoleMessageFromWorker(ConsoleMessage*);
 
     void connectToInspector(PageInspector*);
@@ -60,8 +59,6 @@
     PageInspector* m_pageInspector;
     String m_url;
     String m_inspectorId;
-    HeapDeque<Member<ConsoleMessage>> m_consoleMessages;
-    bool m_ignoreConsoleMessages;
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/workers/WorkerReportingProxy.h b/third_party/WebKit/Source/core/workers/WorkerReportingProxy.h
index 7e9d343..5d1f77a 100644
--- a/third_party/WebKit/Source/core/workers/WorkerReportingProxy.h
+++ b/third_party/WebKit/Source/core/workers/WorkerReportingProxy.h
@@ -50,7 +50,6 @@
     virtual void reportException(const String& errorMessage, std::unique_ptr<SourceLocation>) = 0;
     virtual void reportConsoleMessage(ConsoleMessage*) = 0;
     virtual void postMessageToPageInspector(const String&) = 0;
-    virtual void postWorkerConsoleAgentEnabled() = 0;
 
     // Invoked when the worker script is evaluated. |success| is true if the
     // evaluation completed with no uncaught exception.
diff --git a/third_party/WebKit/Source/core/workers/WorkerThreadTestHelper.h b/third_party/WebKit/Source/core/workers/WorkerThreadTestHelper.h
index 5ceb933..3b48da6 100644
--- a/third_party/WebKit/Source/core/workers/WorkerThreadTestHelper.h
+++ b/third_party/WebKit/Source/core/workers/WorkerThreadTestHelper.h
@@ -61,7 +61,6 @@
     }
     MOCK_METHOD1(reportConsoleMessage, void(ConsoleMessage*));
     MOCK_METHOD1(postMessageToPageInspector, void(const String&));
-    MOCK_METHOD0(postWorkerConsoleAgentEnabled, void());
     MOCK_METHOD1(didEvaluateWorkerScript, void(bool success));
     MOCK_METHOD1(workerGlobalScopeStarted, void(WorkerGlobalScope*));
     MOCK_METHOD0(workerGlobalScopeClosed, void());
diff --git a/third_party/WebKit/Source/core/xml/XPathParser.cpp b/third_party/WebKit/Source/core/xml/XPathParser.cpp
index 3d2a055c..c44cbba1 100644
--- a/third_party/WebKit/Source/core/xml/XPathParser.cpp
+++ b/third_party/WebKit/Source/core/xml/XPathParser.cpp
@@ -106,13 +106,12 @@
 
 static bool isNodeTypeName(const String& name)
 {
-    DEFINE_STATIC_LOCAL(HashSet<String>, nodeTypeNames, ());
-    if (nodeTypeNames.isEmpty()) {
-        nodeTypeNames.add("comment");
-        nodeTypeNames.add("text");
-        nodeTypeNames.add("processing-instruction");
-        nodeTypeNames.add("node");
-    }
+    DEFINE_STATIC_LOCAL(HashSet<String>, nodeTypeNames, ({
+        "comment",
+        "text",
+        "processing-instruction",
+        "node",
+    }));
     return nodeTypeNames.contains(name);
 }
 
diff --git a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp
index 941a9f3..5868ce54 100644
--- a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp
+++ b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp
@@ -837,7 +837,7 @@
 
     String message = "Failed to load '" + m_url.elidedString() + "'";
     if (reason.isNull()) {
-        message.append(".");
+        message.append('.');
     } else {
         message.append(": ");
         message.append(reason);
@@ -1716,4 +1716,12 @@
     ActiveDOMObject::trace(visitor);
 }
 
+DEFINE_TRACE_WRAPPERS(XMLHttpRequest)
+{
+    visitor->traceWrappers(m_responseBlob);
+    visitor->traceWrappers(m_responseLegacyStream);
+    visitor->traceWrappers(m_responseDocument);
+    visitor->traceWrappers(m_responseArrayBuffer);
+}
+
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.h b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.h
index 453404e..ea79344 100644
--- a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.h
+++ b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.h
@@ -147,6 +147,7 @@
     // progress event throttle.
     EAGERLY_FINALIZE();
     DECLARE_VIRTUAL_TRACE();
+    DECLARE_TRACE_WRAPPERS();
 
 private:
     class BlobLoader;
diff --git a/third_party/WebKit/Source/devtools/front_end/Tests.js b/third_party/WebKit/Source/devtools/front_end/Tests.js
index 268f62c..ad125f1e 100644
--- a/third_party/WebKit/Source/devtools/front_end/Tests.js
+++ b/third_party/WebKit/Source/devtools/front_end/Tests.js
@@ -717,6 +717,20 @@
     step1();
 };
 
+TestSuite.prototype.testDispatchKeyEventDoesNotCrash = function()
+{
+    WebInspector.targetManager.mainTarget().inputAgent().invoke_dispatchKeyEvent({
+        type: "rawKeyDown",
+        windowsVirtualKeyCode: 0x23,
+        key: "End"
+    });
+    WebInspector.targetManager.mainTarget().inputAgent().invoke_dispatchKeyEvent({
+        type: "keyUp",
+        windowsVirtualKeyCode: 0x23,
+        key: "End"
+    });
+};
+
 TestSuite.prototype.testEmulateNetworkConditions = function()
 {
     var test = this;
diff --git a/third_party/WebKit/Source/devtools/front_end/bindings/PresentationConsoleMessageHelper.js b/third_party/WebKit/Source/devtools/front_end/bindings/PresentationConsoleMessageHelper.js
index 77f57d9..4be67638 100644
--- a/third_party/WebKit/Source/devtools/front_end/bindings/PresentationConsoleMessageHelper.js
+++ b/third_party/WebKit/Source/devtools/front_end/bindings/PresentationConsoleMessageHelper.js
@@ -88,10 +88,10 @@
             return null;
         var callFrame = message.stackTrace && message.stackTrace.callFrames ? message.stackTrace.callFrames[0] : null;
         // FIXME(62725): stack trace line/column numbers are one-based.
-        var lineNumber = callFrame ? callFrame.lineNumber - 1 : message.line - 1;
+        var lineNumber = callFrame ? callFrame.lineNumber : message.line - 1;
         var columnNumber = message.column ? message.column - 1 : 0;
-        if (callFrame && callFrame.columnNumber)
-            columnNumber = callFrame.columnNumber - 1;
+        if (callFrame)
+            columnNumber = callFrame.columnNumber;
         if (message.scriptId)
             return debuggerModel.createRawLocationByScriptId(message.scriptId, lineNumber, columnNumber);
         return debuggerModel.createRawLocationByURL(message.url || "", lineNumber, columnNumber);
diff --git a/third_party/WebKit/Source/devtools/front_end/components/EventListenersUtils.js b/third_party/WebKit/Source/devtools/front_end/components/EventListenersUtils.js
index 8942f42..1948a65 100644
--- a/third_party/WebKit/Source/devtools/front_end/components/EventListenersUtils.js
+++ b/third_party/WebKit/Source/devtools/front_end/components/EventListenersUtils.js
@@ -137,7 +137,7 @@
             function storeFunctionWithDetails(functionObject)
             {
                 handler = functionObject;
-                return /** @type {!Promise<undefined>} */(functionObject.functionDetailsPromise().then(storeFunctionDetails));
+                return /** @type {!Promise<undefined>} */(functionObject.debuggerModel().functionDetailsPromise(functionObject).then(storeFunctionDetails));
             }
 
             /**
diff --git a/third_party/WebKit/Source/devtools/front_end/components/Linkifier.js b/third_party/WebKit/Source/devtools/front_end/components/Linkifier.js
index fc3b6b1c..07b04cf3 100644
--- a/third_party/WebKit/Source/devtools/front_end/components/Linkifier.js
+++ b/third_party/WebKit/Source/devtools/front_end/components/Linkifier.js
@@ -204,7 +204,19 @@
      */
     linkifyConsoleCallFrame: function(target, callFrame, classes)
     {
-        return this.linkifyScriptLocation(target, callFrame.scriptId, callFrame.url, WebInspector.DebuggerModel.fromOneBased(callFrame.lineNumber), WebInspector.DebuggerModel.fromOneBased(callFrame.columnNumber), classes);
+        return this.linkifyScriptLocation(target, callFrame.scriptId, callFrame.url, callFrame.lineNumber, callFrame.columnNumber, classes);
+    },
+
+    /**
+     * @param {?WebInspector.Target} target
+     * @param {!RuntimeAgent.CallFrame} callFrame
+     * @param {string=} classes
+     * @return {!Element}
+     */
+    linkifyConsoleCallFrameForTimeline: function(target, callFrame, classes)
+    {
+        // TODO(kozyatinskiy): remove this when Profilers will migrate to 0-based lineNumber and columnNumber.
+        return this.linkifyScriptLocation(target, callFrame.scriptId, callFrame.url, callFrame.lineNumber - 1, callFrame.columnNumber - 1, classes);
     },
 
     /**
@@ -218,7 +230,7 @@
         console.assert(stackTrace.callFrames && stackTrace.callFrames.length);
 
         var topFrame = stackTrace.callFrames[0];
-        var fallbackAnchor = WebInspector.linkifyResourceAsNode(topFrame.url, WebInspector.DebuggerModel.fromOneBased(topFrame.lineNumber), WebInspector.DebuggerModel.fromOneBased(topFrame.columnNumber), classes);
+        var fallbackAnchor = WebInspector.linkifyResourceAsNode(topFrame.url, topFrame.lineNumber, topFrame.columnNumber, classes);
         if (target.isDetached())
             return fallbackAnchor;
 
diff --git a/third_party/WebKit/Source/devtools/front_end/components/ObjectPopoverHelper.js b/third_party/WebKit/Source/devtools/front_end/components/ObjectPopoverHelper.js
index 4b9b2fe..e06236f 100644
--- a/third_party/WebKit/Source/devtools/front_end/components/ObjectPopoverHelper.js
+++ b/third_party/WebKit/Source/devtools/front_end/components/ObjectPopoverHelper.js
@@ -75,7 +75,7 @@
                 }
             }
             WebInspector.ObjectPropertiesSection.formatObjectAsFunction(funcObject, popoverValueElement, true);
-            funcObject.functionDetails(didGetFunctionDetails.bind(this, popoverContentElement, anchorElement));
+            funcObject.debuggerModel().functionDetailsPromise(funcObject).then(didGetFunctionDetails.bind(this, popoverContentElement, anchorElement));
         }
 
         /**
@@ -95,7 +95,6 @@
             functionName.textContent = WebInspector.beautifyFunctionName(response.functionName);
 
             var rawLocation = response.location;
-            var sourceURL = response.sourceURL;
             var linkContainer = title.createChild("div", "function-title-link-container");
             if (rawLocation && Runtime.experiments.isEnabled("continueToFirstInvocation")) {
                 var sectionToolbar = new WebInspector.Toolbar("function-location-step-into", linkContainer);
@@ -103,6 +102,7 @@
                 stepInto.addEventListener("click", () => rawLocation.continueToLocation());
                 sectionToolbar.appendToolbarItem(stepInto);
             }
+            var sourceURL = rawLocation.script() ? rawLocation.script().sourceURL : null;
             if (rawLocation && sourceURL) {
                 var link = this._lazyLinkifier().linkifyRawLocation(rawLocation, sourceURL);
                 linkContainer.appendChild(link);
diff --git a/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js b/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js
index 8a90167..6a5813db 100644
--- a/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js
+++ b/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js
@@ -591,23 +591,6 @@
             treeNode.appendChild(treeElement);
         }
     }
-    if (value && value.type === "function") {
-        // Whether function has TargetFunction internal property.
-        // This is a simple way to tell that the function is actually a bound function (we are not told).
-        // Bound function never has inner scope and doesn't need corresponding UI node.
-        var hasTargetFunction = false;
-
-        if (internalProperties) {
-            for (var i = 0; i < internalProperties.length; i++) {
-                if (internalProperties[i].name === "[[TargetFunction]]") {
-                    hasTargetFunction = true;
-                    break;
-                }
-            }
-        }
-        if (!hasTargetFunction)
-            treeNode.appendChild(new WebInspector.FunctionScopeMainTreeElement(value, linkifier));
-    }
     WebInspector.ObjectPropertyTreeElement._appendEmptyPlaceholderIfNeeded(treeNode, emptyPlaceholder);
 }
 
@@ -654,117 +637,6 @@
 /**
  * @constructor
  * @extends {TreeElement}
- * @param {!WebInspector.RemoteObject} remoteObject
- * @param {!WebInspector.Linkifier=} linkifier
- */
-WebInspector.FunctionScopeMainTreeElement = function(remoteObject, linkifier)
-{
-    TreeElement.call(this, "<function scope>", true);
-    this.toggleOnClick = true;
-    this.selectable = false;
-    this._remoteObject = remoteObject;
-    this._linkifier = linkifier;
-}
-
-WebInspector.FunctionScopeMainTreeElement.prototype = {
-    onpopulate: function()
-    {
-        /**
-         * @param {?WebInspector.DebuggerModel.FunctionDetails} response
-         * @this {WebInspector.FunctionScopeMainTreeElement}
-         */
-        function didGetDetails(response)
-        {
-            if (!response)
-                return;
-            this.removeChildren();
-
-            var scopeChain = response.scopeChain || [];
-            for (var i = 0; i < scopeChain.length; ++i) {
-                var scope = scopeChain[i];
-                var title = null;
-                var isTrueObject = false;
-
-                switch (scope.type) {
-                case DebuggerAgent.ScopeType.Local:
-                    // Not really expecting this scope type here.
-                    title = WebInspector.UIString("Local");
-                    break;
-                case DebuggerAgent.ScopeType.Closure:
-                    title = WebInspector.UIString("Closure");
-                    break;
-                case DebuggerAgent.ScopeType.Catch:
-                    title = WebInspector.UIString("Catch");
-                    break;
-                case DebuggerAgent.ScopeType.Block:
-                    title = WebInspector.UIString("Block");
-                    break;
-                case DebuggerAgent.ScopeType.Script:
-                    title = WebInspector.UIString("Script");
-                    break;
-                case DebuggerAgent.ScopeType.With:
-                    title = WebInspector.UIString("With Block");
-                    isTrueObject = true;
-                    break;
-                case DebuggerAgent.ScopeType.Global:
-                    title = WebInspector.UIString("Global");
-                    isTrueObject = true;
-                    break;
-                default:
-                    console.error("Unknown scope type: " + scope.type);
-                    continue;
-                }
-
-                var runtimeModel = this._remoteObject.target().runtimeModel;
-                if (isTrueObject) {
-                    var remoteObject = runtimeModel.createRemoteObject(scope.object);
-                    var property = new WebInspector.RemoteObjectProperty(title, remoteObject);
-                    property.writable = false;
-                    property.parentObject = null;
-                    this.appendChild(new WebInspector.ObjectPropertyTreeElement(property, this._linkifier));
-                } else {
-                    var scopeRef = new WebInspector.ScopeRef(i, undefined);
-                    var remoteObject = runtimeModel.createScopeRemoteObject(scope.object, scopeRef);
-                    var scopeTreeElement = new WebInspector.ScopeTreeElement(title, remoteObject);
-                    this.appendChild(scopeTreeElement);
-                }
-            }
-
-            WebInspector.ObjectPropertyTreeElement._appendEmptyPlaceholderIfNeeded(this, WebInspector.UIString("No Scopes"));
-        }
-
-        this._remoteObject.functionDetails(didGetDetails.bind(this));
-    },
-
-    __proto__: TreeElement.prototype
-}
-
-/**
- * @constructor
- * @extends {TreeElement}
- * @param {string} title
- * @param {!WebInspector.RemoteObject} remoteObject
- */
-WebInspector.ScopeTreeElement = function(title, remoteObject)
-{
-    TreeElement.call(this, title, true);
-    this.toggleOnClick = true;
-    this.selectable = false;
-    this._remoteObject = remoteObject;
-}
-
-WebInspector.ScopeTreeElement.prototype = {
-    onpopulate: function()
-    {
-        WebInspector.ObjectPropertyTreeElement._populate(this, this._remoteObject, false);
-    },
-
-    __proto__: TreeElement.prototype
-}
-
-/**
- * @constructor
- * @extends {TreeElement}
  * @param {!WebInspector.RemoteObject} object
  * @param {number} fromIndex
  * @param {number} toIndex
@@ -1192,8 +1064,13 @@
         valueElement.title = description || "";
     }
 
-    if (type === "object" && subtype === "internal#location" && linkifier)
-        return linkifier.linkifyScriptLocation(value.target(), value.value.scriptId, "", value.value.lineNumber, value.value.columnNumber);
+    if (type === "object" && subtype === "internal#location") {
+        var rawLocation = value.debuggerModel().createRawLocationByScriptId(value.value.scriptId, value.value.lineNumber, value.value.columnNumber);
+        if (rawLocation && linkifier)
+            return linkifier.linkifyRawLocation(rawLocation, "");
+        else
+            valueElement.textContent = "<unknown>";
+    }
 
     function mouseMove()
     {
@@ -1225,7 +1102,7 @@
  */
 WebInspector.ObjectPropertiesSection.formatObjectAsFunction = function(func, element, linkify, includePreview)
 {
-    func.functionDetails(didGetDetails);
+    func.debuggerModel().functionDetailsPromise(func).then(didGetDetails);
 
     /**
      * @param {?WebInspector.DebuggerModel.FunctionDetails} response
diff --git a/third_party/WebKit/Source/devtools/front_end/console/ConsoleContextSelector.js b/third_party/WebKit/Source/devtools/front_end/console/ConsoleContextSelector.js
index e9fc42f..1da29b93 100644
--- a/third_party/WebKit/Source/devtools/front_end/console/ConsoleContextSelector.js
+++ b/third_party/WebKit/Source/devtools/front_end/console/ConsoleContextSelector.js
@@ -63,7 +63,7 @@
         this._optionByExecutionContext.set(executionContext, newOption);
         var options = this._selectElement.options;
         var contexts = Array.prototype.map.call(options, mapping);
-        var index = contexts.lowerBound(executionContext, WebInspector.ExecutionContext.comparator)
+        var index = contexts.lowerBound(executionContext, executionContext.runtimeModel.executionContextComparator())
         this._selectElement.insertBefore(newOption, options[index]);
 
         if (executionContext === WebInspector.context.flavor(WebInspector.ExecutionContext))
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
index bc5f4de..4b9023d 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
@@ -89,8 +89,6 @@
 
     /** @type {!Array.<!WebInspector.ElementsTreeOutline>} */
     this._treeOutlines = [];
-    /** @type {!Map.<!WebInspector.DOMModel, !WebInspector.ElementsTreeOutline>} */
-    this._modelToTreeOutline = new Map();
     WebInspector.targetManager.observeTargets(this);
     WebInspector.moduleSetting("showUAShadowDOM").addChangeListener(this._showUAShadowDOMChanged.bind(this));
     WebInspector.targetManager.addModelListener(WebInspector.DOMModel, WebInspector.DOMModel.Events.DocumentUpdated, this._documentUpdatedEvent, this);
@@ -123,7 +121,6 @@
         var filterInput = WebInspector.StylesSidebarPane.createPropertyFilterElement(WebInspector.UIString("Filter"), hbox, ssp.onFilterChanged.bind(ssp));
         filterContainerElement.appendChild(filterInput);
         var toolbar = new WebInspector.ExtensibleToolbar("styles-sidebarpane-toolbar", hbox);
-        toolbar.onLoad().then(() => toolbar.appendToolbarItem(WebInspector.StylesSidebarPane.createAddNewRuleButton(ssp)));
         toolbar.element.classList.add("styles-pane-toolbar");
         toolbar.makeToggledGray();
         var toolbarPaneContainer = container.createChild("div", "styles-sidebar-toolbar-pane-container");
@@ -203,24 +200,6 @@
         }
     },
 
-    _toggleHideElement: function()
-    {
-        var node = this.selectedDOMNode();
-        var treeOutline = this._treeOutlineForNode(node);
-        if (!node || !treeOutline)
-            return;
-        treeOutline.toggleHideElement(node);
-    },
-
-    _toggleEditAsHTML: function()
-    {
-        var node = this.selectedDOMNode();
-        var treeOutline = this._treeOutlineForNode(node);
-        if (!node || !treeOutline)
-            return;
-        treeOutline.toggleEditAsHTML(node);
-    },
-
     _loadSidebarViews: function()
     {
         var extensions = self.runtime.extensions("@WebInspector.Widget");
@@ -266,7 +245,6 @@
         treeOutline.addEventListener(WebInspector.ElementsTreeOutline.Events.ElementsTreeUpdated, this._updateBreadcrumbIfNeeded, this);
         new WebInspector.ElementsTreeElementHighlighter(treeOutline);
         this._treeOutlines.push(treeOutline);
-        this._modelToTreeOutline.set(domModel, treeOutline);
 
         // Perform attach if necessary.
         if (this.isShowing())
@@ -283,7 +261,7 @@
         var domModel = WebInspector.DOMModel.fromTarget(target);
         if (!domModel)
             return;
-        var treeOutline = this._modelToTreeOutline.remove(domModel);
+        var treeOutline = WebInspector.ElementsTreeOutline.forDOMModel(domModel);
         treeOutline.unwireFromDOMModel();
         this._treeOutlines.remove(treeOutline);
         treeOutline.element.remove();
@@ -429,7 +407,7 @@
         this._reset();
         this.searchCanceled();
 
-        var treeOutline = this._modelToTreeOutline.get(domModel);
+        var treeOutline = WebInspector.ElementsTreeOutline.forDOMModel(domModel);
         treeOutline.rootDOMNode = inspectedRootDocument;
 
         if (!inspectedRootDocument) {
@@ -694,7 +672,7 @@
         var searchResult = this._searchResults[this._currentSearchResultIndex];
         if (!searchResult.node)
             return;
-        var treeOutline = this._modelToTreeOutline.get(searchResult.node.domModel());
+        var treeOutline = WebInspector.ElementsTreeOutline.forDOMModel(searchResult.node.domModel());
         var treeElement = treeOutline.findTreeElement(searchResult.node);
         if (treeElement)
             treeElement.hideSearchHighlights();
@@ -805,7 +783,7 @@
     {
         if (!node)
             return null;
-        return this._modelToTreeOutline.get(node.domModel()) || null;
+        return WebInspector.ElementsTreeOutline.forDOMModel(node.domModel());
     },
 
     /**
@@ -896,33 +874,6 @@
         this._notFirstInspectElement = true;
     },
 
-    /**
-     * @param {!Event} event
-     * @param {!WebInspector.ContextMenu} contextMenu
-     * @param {!Object} object
-     */
-    appendApplicableItems: function(event, contextMenu, object)
-    {
-        if (!(object instanceof WebInspector.RemoteObject && (/** @type {!WebInspector.RemoteObject} */ (object)).isNode())
-            && !(object instanceof WebInspector.DOMNode)
-            && !(object instanceof WebInspector.DeferredDOMNode)) {
-            return;
-        }
-
-        // Add debbuging-related actions
-        if (object instanceof WebInspector.DOMNode) {
-            contextMenu.appendSeparator();
-            WebInspector.domBreakpointsSidebarPane.populateNodeContextMenu(object, contextMenu, true);
-        }
-
-        // Skip adding "Reveal..." menu item for our own tree outline.
-        if (this.element.isAncestor(/** @type {!Node} */ (event.target)))
-            return;
-        var commandCallback = WebInspector.Revealer.reveal.bind(WebInspector.Revealer, object);
-
-        contextMenu.appendItem(WebInspector.UIString.capitalize("Reveal in Elements ^panel"), commandCallback);
-    },
-
     _sidebarContextMenuEventFired: function(event)
     {
         var contextMenu = new WebInspector.ContextMenu(event);
@@ -1094,11 +1045,27 @@
      * @override
      * @param {!Event} event
      * @param {!WebInspector.ContextMenu} contextMenu
-     * @param {!Object} target
+     * @param {!Object} object
      */
-    appendApplicableItems: function(event, contextMenu, target)
+    appendApplicableItems: function(event, contextMenu, object)
     {
-        WebInspector.ElementsPanel.instance().appendApplicableItems(event, contextMenu, target);
+        if (!(object instanceof WebInspector.RemoteObject && (/** @type {!WebInspector.RemoteObject} */ (object)).isNode())
+            && !(object instanceof WebInspector.DOMNode)
+            && !(object instanceof WebInspector.DeferredDOMNode)) {
+            return;
+        }
+
+        // Add debbuging-related actions
+        if (object instanceof WebInspector.DOMNode) {
+            contextMenu.appendSeparator();
+            WebInspector.domBreakpointsSidebarPane.populateNodeContextMenu(object, contextMenu, true);
+        }
+
+        // Skip adding "Reveal..." menu item for our own tree outline.
+        if (WebInspector.ElementsPanel.instance().element.isAncestor(/** @type {!Node} */ (event.target)))
+            return;
+        var commandCallback = WebInspector.Revealer.reveal.bind(WebInspector.Revealer, object);
+        contextMenu.appendItem(WebInspector.UIString.capitalize("Reveal in Elements ^panel"), commandCallback);
     }
 }
 
@@ -1211,12 +1178,19 @@
      */
     handleAction: function(context, actionId)
     {
+        var node = WebInspector.context.flavor(WebInspector.DOMNode);
+        if (!node)
+            return true;
+        var treeOutline = WebInspector.ElementsTreeOutline.forDOMModel(node.domModel());
+        if (!treeOutline)
+            return true;
+
         switch (actionId) {
         case "elements.hide-element":
-            WebInspector.ElementsPanel.instance()._toggleHideElement();
+            treeOutline.toggleHideElement(node);
             return true;
         case "elements.edit-as-html":
-            WebInspector.ElementsPanel.instance()._toggleEditAsHTML();
+            treeOutline.toggleEditAsHTML(node);
             return true;
         }
         return false;
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js
index 4b56b65..8c058f8 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js
@@ -81,6 +81,17 @@
     this._domModel.addEventListener(WebInspector.DOMModel.Events.MarkersChanged, this._markersChanged, this);
 }
 
+WebInspector.ElementsTreeOutline._treeOutlineSymbol = Symbol("treeOutline");
+
+/**
+ * @param {!WebInspector.DOMModel} domModel
+ * @return {?WebInspector.ElementsTreeOutline}
+ */
+WebInspector.ElementsTreeOutline.forDOMModel = function(domModel)
+{
+    return domModel[WebInspector.ElementsTreeOutline._treeOutlineSymbol] || null;
+}
+
 /** @typedef {{node: !WebInspector.DOMNode, isCut: boolean}} */
 WebInspector.ElementsTreeOutline.ClipboardData;
 
@@ -1056,6 +1067,7 @@
 
     wireToDOMModel: function()
     {
+        this._domModel[WebInspector.ElementsTreeOutline._treeOutlineSymbol] = this;
         this._domModel.addEventListener(WebInspector.DOMModel.Events.NodeInserted, this._nodeInserted, this);
         this._domModel.addEventListener(WebInspector.DOMModel.Events.NodeRemoved, this._nodeRemoved, this);
         this._domModel.addEventListener(WebInspector.DOMModel.Events.AttrModified, this._attributeModified, this);
@@ -1076,6 +1088,7 @@
         this._domModel.removeEventListener(WebInspector.DOMModel.Events.DocumentUpdated, this._documentUpdated, this);
         this._domModel.removeEventListener(WebInspector.DOMModel.Events.ChildNodeCountUpdated, this._childNodeCountUpdated, this);
         this._domModel.removeEventListener(WebInspector.DOMModel.Events.DistributedNodesChanged, this._distributedNodesChanged, this);
+        delete this._domModel[WebInspector.ElementsTreeOutline._treeOutlineSymbol];
     },
 
     /**
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
index 4304ea0..8530344 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
@@ -50,6 +50,7 @@
 
      /** @type {!Array<!WebInspector.SectionBlock>} */
     this._sectionBlocks = [];
+    WebInspector.StylesSidebarPane._instance = this;
 
     WebInspector.targetManager.addModelListener(WebInspector.CSSModel, WebInspector.CSSModel.Events.LayoutEditorChange, this._onLayoutEditorChange, this);
 }
@@ -3124,23 +3125,50 @@
     }
 }
 
-
 /**
- * @return {!WebInspector.ToolbarItem}
+ * @constructor
+ * @implements {WebInspector.ToolbarItem.Provider}
  */
-WebInspector.StylesSidebarPane.createAddNewRuleButton = function(stylesSidebarPane)
+WebInspector.StylesSidebarPane.ButtonProvider = function()
 {
-    var button = new WebInspector.ToolbarButton(WebInspector.UIString("New Style Rule"), "add-toolbar-item");
-    button.addEventListener("click", stylesSidebarPane._createNewRuleInViaInspectorStyleSheet, stylesSidebarPane);
-    button.element.createChild("div", "long-click-glyph toolbar-button-theme");
-    new WebInspector.LongClickController(button.element, stylesSidebarPane._onAddButtonLongClick.bind(stylesSidebarPane));
-    WebInspector.context.addFlavorChangeListener(WebInspector.DOMNode, onNodeChanged);
-    onNodeChanged();
-    return button;
+    this._button = new WebInspector.ToolbarButton(WebInspector.UIString("New Style Rule"), "add-toolbar-item");
+    this._button.addEventListener("click", this._clicked, this);
+    this._button.element.createChild("div", "long-click-glyph toolbar-button-theme");
+    new WebInspector.LongClickController(this._button.element, this._longClicked.bind(this));
+    WebInspector.context.addFlavorChangeListener(WebInspector.DOMNode, onNodeChanged.bind(this));
+    onNodeChanged.call(this);
 
+    /**
+     * @this {WebInspector.StylesSidebarPane.ButtonProvider}
+     */
     function onNodeChanged()
     {
         var node = WebInspector.context.flavor(WebInspector.DOMNode);
-        button.setEnabled(!!node);
+        node = node ? node.enclosingElementOrSelf() : null;
+        this._button.setEnabled(!!node);
+    }
+}
+
+WebInspector.StylesSidebarPane.ButtonProvider.prototype = {
+    _clicked: function()
+    {
+        WebInspector.StylesSidebarPane._instance._createNewRuleInViaInspectorStyleSheet();
+    },
+
+    /**
+     * @param {!Event} e
+     */
+    _longClicked: function(e)
+    {
+        WebInspector.StylesSidebarPane._instance._onAddButtonLongClick(e);
+    },
+
+    /**
+     * @override
+     * @return {!WebInspector.ToolbarItem}
+     */
+    item: function()
+    {
+        return this._button;
     }
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/module.json b/third_party/WebKit/Source/devtools/front_end/elements/module.json
index f0cb659..439d955 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/elements/module.json
@@ -81,6 +81,12 @@
             "location": "styles-sidebarpane-toolbar"
         },
         {
+            "type": "@WebInspector.ToolbarItem.Provider",
+            "className": "WebInspector.StylesSidebarPane.ButtonProvider",
+            "order": 100,
+            "location": "styles-sidebarpane-toolbar"
+        },
+        {
             "type": "@WebInspector.ActionDelegate",
             "actionId": "elements.hide-element",
             "contextTypes": ["WebInspector.ElementsPanel"],
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/CPUProfileView.js b/third_party/WebKit/Source/devtools/front_end/profiler/CPUProfileView.js
index 4fd2517b..8f42a3b 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/CPUProfileView.js
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/CPUProfileView.js
@@ -349,8 +349,7 @@
      */
     linkifyNode: function(node)
     {
-        var callFrame = node.profileNode.frame;
-        return this._profileView.linkifier().linkifyConsoleCallFrame(this._profileView.target(), callFrame, "profile-node-file");
+        return this._profileView.linkifier().linkifyConsoleCallFrameForTimeline(this._profileView.target(), node.profileNode.frame, "profile-node-file");
     }
 }
 
@@ -478,9 +477,8 @@
         var totalTime = millisecondsToString(timelineData.entryTotalTimes[entryIndex]);
         pushEntryInfoRow(WebInspector.UIString("Self time"), selfTime);
         pushEntryInfoRow(WebInspector.UIString("Total time"), totalTime);
-        var callFrame = /** @type {!RuntimeAgent.CallFrame} */ (node);
         var linkifier = new WebInspector.Linkifier();
-        var text = linkifier.linkifyConsoleCallFrame(this._target, callFrame).textContent;
+        var text = linkifier.linkifyConsoleCallFrameForTimeline(this._target, node).textContent;
         linkifier.dispose();
         pushEntryInfoRow(WebInspector.UIString("URL"), text);
         pushEntryInfoRow(WebInspector.UIString("Aggregated self time"), Number.secondsToString(node.selfTime / 1000, true));
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/HeapProfileView.js b/third_party/WebKit/Source/devtools/front_end/profiler/HeapProfileView.js
index ef44c98..24404a6 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/HeapProfileView.js
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/HeapProfileView.js
@@ -302,8 +302,7 @@
      */
     linkifyNode: function(node)
     {
-        var callFrame = node.profileNode.frame;
-        return this._profileView.linkifier().linkifyConsoleCallFrame(this._profileView.target(), callFrame, "profile-node-file");
+        return this._profileView.linkifier().linkifyConsoleCallFrameForTimeline(this._profileView.target(), node.profileNode.frame, "profile-node-file");
     }
 }
 
@@ -423,7 +422,7 @@
         pushEntryInfoRow(WebInspector.UIString("Self size"), Number.bytesToString(node.self));
         pushEntryInfoRow(WebInspector.UIString("Total size"), Number.bytesToString(node.total));
         var linkifier = new WebInspector.Linkifier();
-        var text = (new WebInspector.Linkifier()).linkifyConsoleCallFrame(this._target, node.frame).textContent;
+        var text = (new WebInspector.Linkifier()).linkifyConsoleCallFrameForTimeline(this._target, node.frame).textContent;
         linkifier.dispose();
         pushEntryInfoRow(WebInspector.UIString("URL"), text);
         return entryInfo;
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/ConsoleModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/ConsoleModel.js
index 03e46ff..485b8889 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/ConsoleModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/ConsoleModel.js
@@ -79,6 +79,9 @@
         if (this._isBlacklisted(msg))
             return;
 
+        if (msg.source === WebInspector.ConsoleMessage.MessageSource.Worker && msg.target().workerManager && msg.target().workerManager.targetByWorkerId(msg.workerId))
+            return;
+
         if (msg.level === WebInspector.ConsoleMessage.MessageLevel.RevokedError && msg._revokedExceptionId) {
             var exceptionMessage = this._messageByExceptionId.get(msg._revokedExceptionId);
             if (!exceptionMessage)
@@ -269,8 +272,9 @@
  * @param {number=} timestamp
  * @param {!RuntimeAgent.ExecutionContextId=} executionContextId
  * @param {?string=} scriptId
+ * @param {?string=} workerId
  */
-WebInspector.ConsoleMessage = function(target, source, level, messageText, type, url, line, column, requestId, parameters, stackTrace, timestamp, executionContextId, scriptId)
+WebInspector.ConsoleMessage = function(target, source, level, messageText, type, url, line, column, requestId, parameters, stackTrace, timestamp, executionContextId, scriptId, workerId)
 {
     this._target = target;
     this.source = source;
@@ -289,6 +293,7 @@
     this.timestamp = timestamp || Date.now();
     this.executionContextId = executionContextId || 0;
     this.scriptId = scriptId || null;
+    this.workerId = workerId || null;
 
     var networkLog = target && WebInspector.NetworkLog.fromTarget(target);
     this.request = (requestId && networkLog) ? networkLog.requestForId(requestId) : null;
@@ -463,7 +468,8 @@
     CSS: "css",
     Security: "security",
     Other: "other",
-    Deprecation: "deprecation"
+    Deprecation: "deprecation",
+    Worker: "worker"
 }
 
 /**
@@ -539,7 +545,8 @@
             payload.stack,
             payload.timestamp * 1000, // Convert to ms.
             payload.executionContextId,
-            payload.scriptId);
+            payload.scriptId,
+            payload.workerId);
         this._console.addMessage(consoleMessage);
     },
 
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js
index 67fe2cd..70899b5c 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js
@@ -58,7 +58,7 @@
     this.enableDebugger();
 }
 
-/** @typedef {{location: ?WebInspector.DebuggerModel.Location, sourceURL: ?string, functionName: string, scopeChain: (Array.<!DebuggerAgent.Scope>|null)}} */
+/** @typedef {{location: ?WebInspector.DebuggerModel.Location, functionName: string}} */
 WebInspector.DebuggerModel.FunctionDetails;
 
 /**
@@ -98,16 +98,6 @@
     Other: "other"
 }
 
-/**
- * @param {number=} value
- * @return {number}
- */
-WebInspector.DebuggerModel.fromOneBased = function(value)
-{
-    // FIXME(webkit:62725): console stack trace line/column numbers are one-based.
-    return value ? value - 1 : 0;
-}
-
 WebInspector.DebuggerModel.prototype = {
     /**
      * @return {boolean}
@@ -581,7 +571,7 @@
 
         var rawLocations = [];
         for (var frame of frames) {
-            var rawLocation = this.createRawLocationByScriptId(frame.scriptId, WebInspector.DebuggerModel.fromOneBased(frame.lineNumber), WebInspector.DebuggerModel.fromOneBased(frame.columnNumber));
+            var rawLocation = this.createRawLocationByScriptId(frame.scriptId, frame.lineNumber, frame.columnNumber);
             if (rawLocation)
                 rawLocations.push(rawLocation);
         }
@@ -659,28 +649,41 @@
 
     /**
      * @param {!WebInspector.RemoteObject} remoteObject
-     * @param {function(?WebInspector.DebuggerModel.FunctionDetails)} callback
+     * @return {!Promise<?WebInspector.DebuggerModel.FunctionDetails>}
      */
-    functionDetails: function(remoteObject, callback)
+    functionDetailsPromise: function(remoteObject)
     {
-        this._agent.getFunctionDetails(remoteObject.objectId, didGetDetails.bind(this));
+        return remoteObject.getAllPropertiesPromise(/* accessorPropertiesOnly */false).then(buildDetails.bind(this));
 
         /**
-         * @param {?Protocol.Error} error
-         * @param {!DebuggerAgent.FunctionDetails} response
-         * @this {WebInspector.DebuggerModel}
+         * @param {!{properties: ?Array.<!WebInspector.RemoteObjectProperty>, internalProperties: ?Array.<!WebInspector.RemoteObjectProperty>}} response
+         * @return {?WebInspector.DebuggerModel.FunctionDetails}
+         * @this {!WebInspector.DebuggerModel}
          */
-        function didGetDetails(error, response)
+        function buildDetails(response)
         {
-            if (error) {
-                callback(null);
-                return;
+            if (!response || !response.internalProperties)
+                return null;
+            var location = null;
+            for (var prop of response.internalProperties) {
+                if (prop.name === "[[FunctionLocation]]")
+                    location = prop.value;
             }
-            var location = response.location;
-            var script = this.scriptForId(location.scriptId);
-            var rawLocation = script ? this.createRawLocation(script, location.lineNumber, location.columnNumber || 0) : null;
-            var sourceURL = script ? script.contentURL() : null;
-            callback({location: rawLocation, sourceURL: sourceURL, functionName: response.functionName, scopeChain: response.scopeChain || null});
+            var functionName = null;
+            if (response.properties) {
+                for (var prop of response.properties) {
+                    if (prop.name === "name" && prop.value && prop.value.type === "string")
+                        functionName = prop.value;
+                    if (prop.name === "displayName" && prop.value && prop.value.type === "string") {
+                        functionName = prop.value;
+                        break;
+                    }
+                }
+            }
+            var debuggerLocation = null;
+            if (location)
+                debuggerLocation = this.createRawLocationByScriptId(location.value.scriptId, location.value.lineNumber, location.value.columnNumber);
+            return { location: debuggerLocation, functionName: functionName ? functionName.value : "" };
         }
     },
 
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js b/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js
index f59a6b0d..a1dd129 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js
@@ -281,31 +281,6 @@
     isNode: function()
     {
         return false;
-    },
-
-    /**
-     * @param {function(?WebInspector.DebuggerModel.FunctionDetails)} callback
-     */
-    functionDetails: function(callback)
-    {
-        callback(null);
-    },
-
-    /**
-     * @return {!Promise<?WebInspector.DebuggerModel.FunctionDetails>}
-     */
-    functionDetailsPromise: function()
-    {
-        return new Promise(promiseConstructor.bind(this));
-
-        /**
-         * @param {function(?WebInspector.DebuggerModel.FunctionDetails)} success
-         * @this {WebInspector.RemoteObject}
-         */
-        function promiseConstructor(success)
-        {
-            this.functionDetails(success);
-        }
     }
 }
 
@@ -860,15 +835,6 @@
         return !!this._objectId && this.type === "object" && this.subtype === "node";
     },
 
-    /**
-     * @override
-     * @param {function(?WebInspector.DebuggerModel.FunctionDetails)} callback
-     */
-    functionDetails: function(callback)
-    {
-        this._debuggerModel.functionDetails(this, callback);
-    },
-
     __proto__: WebInspector.RemoteObject.prototype
 };
 
@@ -1526,7 +1492,7 @@
         function functionDetails(targetFunction)
         {
             var boundReleaseFunctionDetails = releaseTargetFunction.bind(null, this._object !== targetFunction ? targetFunction : null);
-            return targetFunction.functionDetailsPromise().then(boundReleaseFunctionDetails);
+            return targetFunction.debuggerModel().functionDetailsPromise(targetFunction).then(boundReleaseFunctionDetails);
         }
 
         /**
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/ResourceTreeModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/ResourceTreeModel.js
index 8f5b5c55..035b4ac 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/ResourceTreeModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/ResourceTreeModel.js
@@ -55,6 +55,8 @@
     this._inspectedPageURL = "";
     this._pendingReloadOptions = null;
     this._reloadSuspensionCount = 0;
+
+    target.runtimeModel.setExecutionContextComparator(this._executionContextComparator.bind(this));
 }
 
 WebInspector.ResourceTreeModel.EventTypes = {
@@ -486,6 +488,49 @@
             callback(url, data || null, errors);
         }
     },
+    /**
+     * @param {!WebInspector.ExecutionContext} a
+     * @param {!WebInspector.ExecutionContext} b
+     * @return {number}
+     */
+    _executionContextComparator: function(a,b)
+    {
+        /**
+         * @param {!WebInspector.ResourceTreeFrame} frame
+         */
+        function framePath(frame)
+        {
+            var currentFrame = frame;
+            var parents = [];
+            while (currentFrame) {
+                parents.push(currentFrame);
+                currentFrame = currentFrame.parentFrame;
+            }
+            return parents.reverse();
+        }
+
+        var framesA = a.frameId ? framePath(this.frameForId(a.frameId)) : [];
+        var framesB = b.frameId ? framePath(this.frameForId(b.frameId)) : [];
+        var frameA;
+        var frameB;
+        for (var i = 0; ; i++) {
+            if (!framesA[i] || !framesB[i] || (framesA[i] !== framesB[i])) {
+                frameA = framesA[i];
+                frameB = framesB[i];
+                break;
+            }
+        }
+        if (!frameA && frameB)
+            return -1;
+
+        if (!frameB && frameA)
+            return 1;
+
+        if (frameA && frameB) {
+            return frameA.id.localeCompare(frameB.id);
+        }
+        return WebInspector.ExecutionContext.comparator(a,b);
+    },
 
     __proto__: WebInspector.SDKModel.prototype
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js
index 4013efa2..291d0d90 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js
@@ -45,6 +45,7 @@
      * @type {!Object.<number, !WebInspector.ExecutionContext>}
      */
     this._executionContextById = {};
+    this._executionContextComparator = WebInspector.ExecutionContext.comparator;
 
     if (WebInspector.moduleSetting("customFormatters").get())
         this._agent.setCustomObjectFormatterEnabled(true);
@@ -67,7 +68,23 @@
      */
     executionContexts: function()
     {
-        return Object.values(this._executionContextById);
+        return Object.values(this._executionContextById).sort(this.executionContextComparator());
+    },
+
+    /**
+     * @param {function(!WebInspector.ExecutionContext,!WebInspector.ExecutionContext)} comparator
+     */
+    setExecutionContextComparator: function(comparator)
+    {
+        this._executionContextComparator = comparator;
+    },
+
+    /**
+     * @return {function(!WebInspector.ExecutionContext,!WebInspector.ExecutionContext)} comparator
+     */
+    executionContextComparator: function()
+    {
+        return this._executionContextComparator;
     },
 
     /**
@@ -453,10 +470,6 @@
     if (weightDiff)
         return -weightDiff;
 
-    var frameIdDiff = String.hashCode(a.frameId) - String.hashCode(b.frameId);
-    if (frameIdDiff)
-        return frameIdDiff;
-
     // Main world context should always go first.
     if (a.isDefault)
         return -1;
@@ -869,11 +882,11 @@
         if (!this._removeFunction)
             return Promise.resolve();
         return this._removeFunction.callFunctionPromise(callCustomRemove, [
-                WebInspector.RemoteObject.toCallArgument(this._type),
-                WebInspector.RemoteObject.toCallArgument(this._originalHandler),
-                WebInspector.RemoteObject.toCallArgument(this._useCapture),
-                WebInspector.RemoteObject.toCallArgument(this._passive),
-            ]).then(() => undefined);
+            WebInspector.RemoteObject.toCallArgument(this._type),
+            WebInspector.RemoteObject.toCallArgument(this._originalHandler),
+            WebInspector.RemoteObject.toCallArgument(this._useCapture),
+            WebInspector.RemoteObject.toCallArgument(this._passive),
+        ]).then(() => undefined);
 
         /**
          * @param {string} type
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/TargetManager.js b/third_party/WebKit/Source/devtools/front_end/sdk/TargetManager.js
index 7e09dff..8af0433 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/TargetManager.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/TargetManager.js
@@ -196,6 +196,8 @@
 
         /** @type {!WebInspector.ConsoleModel} */
         target.consoleModel = new WebInspector.ConsoleModel(target);
+        /** @type {!WebInspector.RuntimeModel} */
+        target.runtimeModel = new WebInspector.RuntimeModel(target);
 
         var networkManager = null;
         if (!target.isJSInspector())
@@ -207,8 +209,6 @@
         if (networkManager)
             new WebInspector.NetworkLog(target, networkManager);
 
-        /** @type {!WebInspector.RuntimeModel} */
-        target.runtimeModel = new WebInspector.RuntimeModel(target);
         if (target.hasJSContext())
             new WebInspector.DebuggerModel(target);
 
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/SourceMapNamesResolver.js b/third_party/WebKit/Source/devtools/front_end/sources/SourceMapNamesResolver.js
index 955d19d3..4816c9f 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/SourceMapNamesResolver.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/SourceMapNamesResolver.js
@@ -573,15 +573,6 @@
         return this._object.isNode();
     },
 
-    /**
-     * @override
-     * @param {function(?WebInspector.DebuggerModel.FunctionDetails)} callback
-     */
-    functionDetails: function(callback)
-    {
-        this._object.functionDetails(callback);
-    },
-
     __proto__: WebInspector.RemoteObject.prototype
 }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js b/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js
index 80306fd..1105848 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js
@@ -1038,7 +1038,7 @@
      */
     _showFunctionDefinition: function(remoteObject)
     {
-        remoteObject.debuggerModel().functionDetails(remoteObject, this._didGetFunctionDetails.bind(this));
+        remoteObject.debuggerModel().functionDetailsPromise(remoteObject).then(this._didGetFunctionDetails.bind(this));
     },
 
     /**
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js
index 025a36c..21471d7 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js
@@ -86,7 +86,7 @@
      */
     linkifyLocation: function(frame)
     {
-        return this._linkifier.linkifyConsoleCallFrame(this._model.target(), frame);
+        return this._linkifier.linkifyConsoleCallFrameForTimeline(this._model.target(), frame);
     },
 
     /**
@@ -618,10 +618,10 @@
      */
     _createAggregator: function()
     {
-         return new WebInspector.TimelineAggregator(
-             event => WebInspector.TimelineUIUtils.eventStyle(event).title,
-             event => WebInspector.TimelineUIUtils.eventStyle(event).category.name
-         );
+        return new WebInspector.TimelineAggregator(
+            event => WebInspector.TimelineUIUtils.eventStyle(event).title,
+            event => WebInspector.TimelineUIUtils.eventStyle(event).category.name
+        );
     },
 
     __proto__: WebInspector.TimelineTreeView.prototype,
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
index d374d3c..b8a51e4b 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
@@ -619,7 +619,7 @@
     function linkifyTopCallFrame()
     {
         var frame = WebInspector.TimelineUIUtils.topStackFrame(event);
-        return frame ? linkifier.linkifyConsoleCallFrame(target, frame, "timeline-details") : null;
+        return frame ? linkifier.linkifyConsoleCallFrameForTimeline(target, frame, "timeline-details") : null;
     }
 }
 
@@ -996,7 +996,7 @@
     var sendRequest = request.children[0];
     var topFrame = WebInspector.TimelineUIUtils.topStackFrame(sendRequest);
     if (topFrame) {
-        contentHelper.appendElementRow(title, linkifier.linkifyConsoleCallFrame(target, topFrame));
+        contentHelper.appendElementRow(title, linkifier.linkifyConsoleCallFrameForTimeline(target, topFrame));
     } else if (sendRequest.initiator) {
         var initiatorURL = WebInspector.TimelineUIUtils.eventURL(sendRequest.initiator);
         if (initiatorURL)
@@ -1241,7 +1241,7 @@
             var stack = title.createChild("span", "monospace");
             stack.createChild("span").textContent = WebInspector.beautifyFunctionName(topFrame.functionName);
             stack.createChild("span").textContent = " @ ";
-            stack.createChild("span").appendChild(this._contentHelper.linkifier().linkifyConsoleCallFrame(target, topFrame));
+            stack.createChild("span").appendChild(this._contentHelper.linkifier().linkifyConsoleCallFrameForTimeline(target, topFrame));
         }
 
         return title;
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/Toolbar.js b/third_party/WebKit/Source/devtools/front_end/ui/Toolbar.js
index 711d4837..6a000d9 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/Toolbar.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/Toolbar.js
@@ -945,7 +945,7 @@
             if (extensions[i].descriptor()["location"] === location)
                 promises.push(resolveItem(extensions[i]));
         }
-        this._promise = Promise.all(promises).then(appendItemsInOrder.bind(this));
+        Promise.all(promises).then(appendItemsInOrder.bind(this));
 
         /**
          * @param {!Runtime.Extension} extension
@@ -985,13 +985,5 @@
         }
     },
 
-    /**
-     * @return {!Promise}
-     */
-    onLoad: function()
-    {
-        return this._promise;
-    },
-
     __proto__: WebInspector.Toolbar.prototype
 }
diff --git a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
index cf28e55..109ce6a 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
@@ -2029,6 +2029,11 @@
     if (!frame)
         return;
 
+    // TODO(dglazkov): The use of updateStyleAndLayoutIgnorePendingStylesheets needs to be audited.
+    // see http://crbug.com/590369 for more details.
+    // This callsite should probably move up the stack.
+    frame->document()->updateStyleAndLayoutIgnorePendingStylesheets();
+
     // Set the selection based on visible positions, because the offsets in accessibility nodes
     // are based on visible indexes, which often skips redundant whitespace, for example.
     VisiblePosition anchorVisiblePosition = anchorNode->isTextNode()
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
index 93d5da6..cbb0e6d 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
@@ -865,7 +865,7 @@
             localRelatedObjects.append(new NameSourceRelatedObject(axElement, result));
             if (!result.isEmpty()) {
                 if (!accumulatedText.isEmpty())
-                    accumulatedText.append(" ");
+                    accumulatedText.append(' ');
                 accumulatedText.append(result);
             }
         }
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObjectCacheImpl.cpp b/third_party/WebKit/Source/modules/accessibility/AXObjectCacheImpl.cpp
index 0aff29dd..b10b14c 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXObjectCacheImpl.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXObjectCacheImpl.cpp
@@ -1075,7 +1075,7 @@
 
 const Element* AXObjectCacheImpl::rootAXEditableElement(const Node* node)
 {
-    const Element* result = node->rootEditableElement();
+    const Element* result = rootEditableElement(*node);
     const Element* element = node->isElementNode() ? toElement(node) : node->parentElement();
 
     for (; element; element = element->parentElement()) {
diff --git a/third_party/WebKit/Source/modules/audio_output_devices/AudioOutputDeviceClient.cpp b/third_party/WebKit/Source/modules/audio_output_devices/AudioOutputDeviceClient.cpp
index 2bda77e..31fa813 100644
--- a/third_party/WebKit/Source/modules/audio_output_devices/AudioOutputDeviceClient.cpp
+++ b/third_party/WebKit/Source/modules/audio_output_devices/AudioOutputDeviceClient.cpp
@@ -32,4 +32,9 @@
     frame.provideSupplement(AudioOutputDeviceClient::supplementName(), client);
 }
 
+DEFINE_TRACE(AudioOutputDeviceClient)
+{
+    Supplement<LocalFrame>::trace(visitor);
+}
+
 } // namespace blink
diff --git a/third_party/WebKit/Source/modules/audio_output_devices/AudioOutputDeviceClient.h b/third_party/WebKit/Source/modules/audio_output_devices/AudioOutputDeviceClient.h
index 7d824bd..363c4ae 100644
--- a/third_party/WebKit/Source/modules/audio_output_devices/AudioOutputDeviceClient.h
+++ b/third_party/WebKit/Source/modules/audio_output_devices/AudioOutputDeviceClient.h
@@ -5,6 +5,7 @@
 #ifndef AudioOutputDeviceClient_h
 #define AudioOutputDeviceClient_h
 
+#include "core/frame/LocalFrame.h"
 #include "modules/ModulesExport.h"
 #include "platform/Supplementable.h"
 #include "public/platform/WebSetSinkIdCallbacks.h"
@@ -13,17 +14,18 @@
 namespace blink {
 
 class ExecutionContext;
-class LocalFrame;
 class WebString;
 class ScriptState;
 
-class AudioOutputDeviceClient : public Supplement<LocalFrame> {
+class MODULES_EXPORT AudioOutputDeviceClient : public Supplement<LocalFrame> {
 public:
     virtual ~AudioOutputDeviceClient() {}
 
     // Checks that a given sink exists and has permissions to be used from the origin of the current frame.
     virtual void checkIfAudioSinkExistsAndIsAuthorized(ExecutionContext*, const WebString& sinkId, std::unique_ptr<WebSetSinkIdCallbacks>) = 0;
 
+    DECLARE_VIRTUAL_TRACE();
+
     // Supplement requirements.
     static AudioOutputDeviceClient* from(ExecutionContext*);
     static const char* supplementName();
diff --git a/third_party/WebKit/Source/modules/cachestorage/InspectorCacheStorageAgent.cpp b/third_party/WebKit/Source/modules/cachestorage/InspectorCacheStorageAgent.cpp
index a509375..232b7e3 100644
--- a/third_party/WebKit/Source/modules/cachestorage/InspectorCacheStorageAgent.cpp
+++ b/third_party/WebKit/Source/modules/cachestorage/InspectorCacheStorageAgent.cpp
@@ -46,7 +46,7 @@
 String buildCacheId(const String& securityOrigin, const String& cacheName)
 {
     String id(securityOrigin);
-    id.append("|");
+    id.append('|');
     id.append(cacheName);
     return id;
 }
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
index 1a0c7ffd..9a0fc75 100644
--- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
+++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
@@ -783,9 +783,15 @@
     context2d()->getImageData(0, 0, 1, 1, exceptionState);
 
     EXPECT_FALSE(exceptionState.hadException());
-    EXPECT_FALSE(bridge->isAccelerated());
-    EXPECT_EQ(0u, getGlobalAcceleratedImageBufferCount());
-    EXPECT_EQ(0, getGlobalGPUMemoryUsage());
+    if (ExpensiveCanvasHeuristicParameters::GetImageDataForcesNoAcceleration) {
+        EXPECT_FALSE(bridge->isAccelerated());
+        EXPECT_EQ(0u, getGlobalAcceleratedImageBufferCount());
+        EXPECT_EQ(0, getGlobalGPUMemoryUsage());
+    } else {
+        EXPECT_TRUE(bridge->isAccelerated());
+        EXPECT_EQ(1u, getGlobalAcceleratedImageBufferCount());
+        EXPECT_EQ(720000, getGlobalGPUMemoryUsage());
+    }
 
     // Restore global state to prevent side-effects on other tests
     RuntimeEnabledFeatures::setCanvas2dFixedRenderingModeEnabled(savedFixedRenderingMode);
diff --git a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThreadTest.cpp b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThreadTest.cpp
index bc13d96..43d24aa 100644
--- a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThreadTest.cpp
+++ b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThreadTest.cpp
@@ -41,7 +41,6 @@
     virtual void reportException(const String& errorMessage, std::unique_ptr<SourceLocation>) {}
     void reportConsoleMessage(ConsoleMessage*) override {}
     void postMessageToPageInspector(const String&) override {}
-    void postWorkerConsoleAgentEnabled() override {}
 
     void didEvaluateWorkerScript(bool success) override {}
     void workerGlobalScopeStarted(WorkerGlobalScope*) override {}
diff --git a/third_party/WebKit/Source/modules/crypto/CryptoResultImpl.cpp b/third_party/WebKit/Source/modules/crypto/CryptoResultImpl.cpp
index ff04f11b..7db6844 100644
--- a/third_party/WebKit/Source/modules/crypto/CryptoResultImpl.cpp
+++ b/third_party/WebKit/Source/modules/crypto/CryptoResultImpl.cpp
@@ -192,7 +192,7 @@
     ScriptState* scriptState = m_resolver->getScriptState();
     ScriptState::Scope scope(scriptState);
 
-    v8::Local<v8::String> jsonString = v8AtomicString(scriptState->isolate(), utf8Data, length);
+    v8::Local<v8::String> jsonString = v8StringFromUtf8(scriptState->isolate(), utf8Data, length);
 
     v8::TryCatch exceptionCatcher(scriptState->isolate());
     v8::Local<v8::Value> jsonDictionary;
diff --git a/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.cpp b/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.cpp
index ba9e7486..963a504 100644
--- a/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.cpp
+++ b/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.cpp
@@ -21,6 +21,19 @@
 
 namespace blink {
 
+namespace {
+
+IntSize getSpecifiedSize(const IntSize& size, float zoom)
+{
+    float unZoomFactor = 1 / zoom;
+    auto unZoomFn = [unZoomFactor](int a) -> int {
+        return round(a * unZoomFactor);
+    };
+    return IntSize(unZoomFn(size.width()), unZoomFn(size.height()));
+}
+
+} // namespace
+
 CSSPaintDefinition* CSSPaintDefinition::create(ScriptState* scriptState, v8::Local<v8::Function> constructor, v8::Local<v8::Function> paint, Vector<CSSPropertyID>& nativeInvalidationProperties, Vector<AtomicString>& customInvalidationProperties, bool hasAlpha)
 {
     return new CSSPaintDefinition(scriptState, constructor, paint, nativeInvalidationProperties, customInvalidationProperties, hasAlpha);
@@ -41,8 +54,10 @@
 {
 }
 
-PassRefPtr<Image> CSSPaintDefinition::paint(const LayoutObject& layoutObject, const IntSize& size)
+PassRefPtr<Image> CSSPaintDefinition::paint(const LayoutObject& layoutObject, const IntSize& size, float zoom)
 {
+    const IntSize specifiedSize = getSpecifiedSize(size, zoom);
+
     ScriptState::Scope scope(m_scriptState.get());
 
     maybeCreatePaintInstance();
@@ -58,8 +73,8 @@
     DCHECK(layoutObject.node());
 
     PaintRenderingContext2D* renderingContext = PaintRenderingContext2D::create(
-        ImageBuffer::create(wrapUnique(new RecordingImageBufferSurface(size, nullptr /* fallbackFactory */, m_hasAlpha ? NonOpaque : Opaque))),  m_hasAlpha);
-    PaintSize* paintSize = PaintSize::create(size);
+        ImageBuffer::create(wrapUnique(new RecordingImageBufferSurface(size, nullptr /* fallbackFactory */, m_hasAlpha ? NonOpaque : Opaque))),  m_hasAlpha, zoom);
+    PaintSize* paintSize = PaintSize::create(specifiedSize);
     StylePropertyMap* styleMap = FilteredComputedStylePropertyMap::create(
         CSSComputedStyleDeclaration::create(layoutObject.node()),
         m_nativeInvalidationProperties, m_customInvalidationProperties);
@@ -83,7 +98,7 @@
         return nullptr;
     }
 
-    return PaintGeneratedImage::create(renderingContext->imageBuffer()->getPicture(), size);
+    return PaintGeneratedImage::create(renderingContext->imageBuffer()->getPicture(), specifiedSize);
 }
 
 void CSSPaintDefinition::maybeCreatePaintInstance()
diff --git a/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.h b/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.h
index 7e0df358b..b4b720a 100644
--- a/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.h
+++ b/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.h
@@ -30,7 +30,7 @@
     //
     // This may return a nullptr (representing an invalid image) if javascript
     // throws an error.
-    PassRefPtr<Image> paint(const LayoutObject&, const IntSize&);
+    PassRefPtr<Image> paint(const LayoutObject&, const IntSize&, float zoom);
     const Vector<CSSPropertyID>& nativeInvalidationProperties() const { return m_nativeInvalidationProperties; }
     const Vector<AtomicString>& customInvalidationProperties() const { return m_customInvalidationProperties; }
     bool hasAlpha() const { return m_hasAlpha; }
diff --git a/third_party/WebKit/Source/modules/csspaint/CSSPaintImageGeneratorImpl.cpp b/third_party/WebKit/Source/modules/csspaint/CSSPaintImageGeneratorImpl.cpp
index 416c0a8..733767a4 100644
--- a/third_party/WebKit/Source/modules/csspaint/CSSPaintImageGeneratorImpl.cpp
+++ b/third_party/WebKit/Source/modules/csspaint/CSSPaintImageGeneratorImpl.cpp
@@ -53,9 +53,9 @@
     m_observer->paintImageGeneratorReady();
 }
 
-PassRefPtr<Image> CSSPaintImageGeneratorImpl::paint(const LayoutObject& layoutObject, const IntSize& size)
+PassRefPtr<Image> CSSPaintImageGeneratorImpl::paint(const LayoutObject& layoutObject, const IntSize& size, float zoom)
 {
-    return m_definition ? m_definition->paint(layoutObject, size) : nullptr;
+    return m_definition ? m_definition->paint(layoutObject, size, zoom) : nullptr;
 }
 
 const Vector<CSSPropertyID>& CSSPaintImageGeneratorImpl::nativeInvalidationProperties() const
diff --git a/third_party/WebKit/Source/modules/csspaint/CSSPaintImageGeneratorImpl.h b/third_party/WebKit/Source/modules/csspaint/CSSPaintImageGeneratorImpl.h
index a4c8f3e..561b2eb6 100644
--- a/third_party/WebKit/Source/modules/csspaint/CSSPaintImageGeneratorImpl.h
+++ b/third_party/WebKit/Source/modules/csspaint/CSSPaintImageGeneratorImpl.h
@@ -22,7 +22,7 @@
     static CSSPaintImageGenerator* create(const String& name, Document&, Observer*);
     ~CSSPaintImageGeneratorImpl() override;
 
-    PassRefPtr<Image> paint(const LayoutObject&, const IntSize&) final;
+    PassRefPtr<Image> paint(const LayoutObject&, const IntSize&, float zoom) final;
     const Vector<CSSPropertyID>& nativeInvalidationProperties() const final;
     const Vector<AtomicString>& customInvalidationProperties() const final;
     bool hasAlpha() const final;
diff --git a/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2D.cpp b/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2D.cpp
index 19884e3..28f6a81 100644
--- a/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2D.cpp
+++ b/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2D.cpp
@@ -9,17 +9,18 @@
 
 namespace blink {
 
-PaintRenderingContext2D::PaintRenderingContext2D(std::unique_ptr<ImageBuffer> imageBuffer, bool hasAlpha)
+PaintRenderingContext2D::PaintRenderingContext2D(std::unique_ptr<ImageBuffer> imageBuffer, bool hasAlpha, float zoom)
     : m_imageBuffer(std::move(imageBuffer)), m_hasAlpha(hasAlpha)
 {
     m_clipAntialiasing = AntiAliased;
     modifiableState().setShouldAntialias(true);
 
-
     // RecordingImageBufferSurface doesn't call ImageBufferSurface::clear explicitly.
     DCHECK(m_imageBuffer);
     m_imageBuffer->canvas()->clear(hasAlpha ? SK_ColorTRANSPARENT : SK_ColorBLACK);
     m_imageBuffer->didDraw(FloatRect(0, 0, width(), height()));
+
+    m_imageBuffer->canvas()->scale(zoom, zoom);
 }
 
 int PaintRenderingContext2D::width() const
diff --git a/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2D.h b/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2D.h
index 9ce602f..9c98aea4 100644
--- a/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2D.h
+++ b/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2D.h
@@ -23,9 +23,9 @@
     USING_GARBAGE_COLLECTED_MIXIN(PaintRenderingContext2D);
     WTF_MAKE_NONCOPYABLE(PaintRenderingContext2D);
 public:
-    static PaintRenderingContext2D* create(std::unique_ptr<ImageBuffer> imageBuffer, bool hasAlpha)
+    static PaintRenderingContext2D* create(std::unique_ptr<ImageBuffer> imageBuffer, bool hasAlpha, float zoom)
     {
-        return new PaintRenderingContext2D(std::move(imageBuffer), hasAlpha);
+        return new PaintRenderingContext2D(std::move(imageBuffer), hasAlpha, zoom);
     }
 
     // BaseRenderingContext2D
@@ -68,7 +68,7 @@
     bool isContextLost() const final { return false; }
 
 private:
-    PaintRenderingContext2D(std::unique_ptr<ImageBuffer>, bool hasAlpha);
+    PaintRenderingContext2D(std::unique_ptr<ImageBuffer>, bool hasAlpha, float zoom);
 
     std::unique_ptr<ImageBuffer> m_imageBuffer;
     bool m_hasAlpha;
diff --git a/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2DTest.cpp b/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2DTest.cpp
index acf37dd..891ef2f 100644
--- a/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2DTest.cpp
+++ b/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2DTest.cpp
@@ -12,6 +12,7 @@
 
 static const int s_width = 50;
 static const int s_height = 75;
+static const float s_zoom = 1.0;
 
 class PaintRenderingContext2DTest : public ::testing::Test {
 protected:
@@ -22,7 +23,7 @@
 
 void PaintRenderingContext2DTest::SetUp()
 {
-    m_ctx = PaintRenderingContext2D::create(ImageBuffer::create(IntSize(s_width, s_height)), false /* hasAlpha */);
+    m_ctx = PaintRenderingContext2D::create(ImageBuffer::create(IntSize(s_width, s_height)), false /* hasAlpha */, s_zoom);
 }
 
 void trySettingStrokeStyle(PaintRenderingContext2D* ctx, const String& expected, const String& value)
diff --git a/third_party/WebKit/Source/modules/filesystem/LocalFileSystem.cpp b/third_party/WebKit/Source/modules/filesystem/LocalFileSystem.cpp
index 8585373..0489559 100644
--- a/third_party/WebKit/Source/modules/filesystem/LocalFileSystem.cpp
+++ b/third_party/WebKit/Source/modules/filesystem/LocalFileSystem.cpp
@@ -195,6 +195,12 @@
 {
 }
 
+DEFINE_TRACE(LocalFileSystem)
+{
+    Supplement<LocalFrame>::trace(visitor);
+    Supplement<WorkerClients>::trace(visitor);
+}
+
 const char* LocalFileSystem::supplementName()
 {
     return "LocalFileSystem";
diff --git a/third_party/WebKit/Source/modules/filesystem/LocalFileSystem.h b/third_party/WebKit/Source/modules/filesystem/LocalFileSystem.h
index 75baffe..1c06b5a 100644
--- a/third_party/WebKit/Source/modules/filesystem/LocalFileSystem.h
+++ b/third_party/WebKit/Source/modules/filesystem/LocalFileSystem.h
@@ -31,6 +31,7 @@
 #ifndef LocalFileSystem_h
 #define LocalFileSystem_h
 
+#include "core/frame/LocalFrame.h"
 #include "core/workers/WorkerClients.h"
 #include "platform/FileSystemType.h"
 #include "platform/Supplementable.h"
@@ -46,7 +47,6 @@
 class FileSystemClient;
 class ExecutionContext;
 class KURL;
-class LocalFrame;
 class WebFileSystem;
 
 class LocalFileSystem final : public GarbageCollectedFinalized<LocalFileSystem>, public Supplement<LocalFrame>, public Supplement<WorkerClients> {
@@ -65,11 +65,7 @@
     static const char* supplementName();
     static LocalFileSystem* from(ExecutionContext&);
 
-    DEFINE_INLINE_VIRTUAL_TRACE()
-    {
-        Supplement<LocalFrame>::trace(visitor);
-        Supplement<WorkerClients>::trace(visitor);
-    }
+    DECLARE_VIRTUAL_TRACE();
 
 private:
     explicit LocalFileSystem(std::unique_ptr<FileSystemClient>);
diff --git a/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.cpp b/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.cpp
index a5b7404..5735dc4 100644
--- a/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.cpp
+++ b/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.cpp
@@ -106,14 +106,15 @@
     visitor->trace(m_pendingEvents);
     visitor->trace(m_dispatchOneEventRunner);
     Supplement<Navigator>::trace(visitor);
-    DOMWindowProperty::trace(visitor);
+    ContextLifecycleObserver::trace(visitor);
     PlatformEventController::trace(visitor);
 }
 
 bool NavigatorGamepad::startUpdatingIfAttached()
 {
+    Document* document = static_cast<Document*>(getExecutionContext());
     // The frame must be attached to start updating.
-    if (frame() && frame()->host()) {
+    if (document && document->frame()) {
         startUpdating();
         return true;
     }
@@ -123,14 +124,14 @@
 void NavigatorGamepad::didUpdateData()
 {
     // We should stop listening once we detached.
-    ASSERT(frame());
-    ASSERT(frame()->domWindow());
+    Document* document = static_cast<Document*>(getExecutionContext());
+    DCHECK(document->frame());
+    DCHECK(document->frame()->domWindow());
 
     // We register to the dispatcher before sampling gamepads so we need to check if we actually have an event listener.
     if (!m_hasEventListener)
         return;
 
-    Document* document = frame()->domWindow()->document();
     if (document->activeDOMObjectsAreStopped() || document->activeDOMObjectsAreSuspended())
         return;
 
@@ -151,20 +152,21 @@
 
 void NavigatorGamepad::dispatchOneEvent()
 {
-    ASSERT(frame());
-    ASSERT(frame()->domWindow());
-    ASSERT(!m_pendingEvents.isEmpty());
+    Document* document = static_cast<Document*>(getExecutionContext());
+    DCHECK(document->frame());
+    DCHECK(document->frame()->domWindow());
+    DCHECK(!m_pendingEvents.isEmpty());
 
     Gamepad* gamepad = m_pendingEvents.takeFirst();
     const AtomicString& eventName = gamepad->connected() ? EventTypeNames::gamepadconnected : EventTypeNames::gamepaddisconnected;
-    frame()->domWindow()->dispatchEvent(GamepadEvent::create(eventName, false, true, gamepad));
+    document->frame()->domWindow()->dispatchEvent(GamepadEvent::create(eventName, false, true, gamepad));
 
     if (!m_pendingEvents.isEmpty())
         m_dispatchOneEventRunner->runAsync();
 }
 
 NavigatorGamepad::NavigatorGamepad(LocalFrame* frame)
-    : DOMWindowProperty(frame)
+    : ContextLifecycleObserver(frame->document())
     , PlatformEventController(frame ? frame->page() : 0)
     , m_dispatchOneEventRunner(AsyncMethodRunner<NavigatorGamepad>::create(this, &NavigatorGamepad::dispatchOneEvent))
 {
@@ -181,16 +183,9 @@
     return "NavigatorGamepad";
 }
 
-void NavigatorGamepad::willDestroyGlobalObjectInFrame()
+void NavigatorGamepad::contextDestroyed()
 {
     stopUpdating();
-    DOMWindowProperty::willDestroyGlobalObjectInFrame();
-}
-
-void NavigatorGamepad::willDetachGlobalObjectFromFrame()
-{
-    stopUpdating();
-    DOMWindowProperty::willDetachGlobalObjectFromFrame();
 }
 
 void NavigatorGamepad::registerWithDispatcher()
@@ -263,7 +258,7 @@
     GamepadList* oldGamepads = m_gamepads.release();
     gamepads();
     GamepadList* newGamepads = m_gamepads.get();
-    ASSERT(newGamepads);
+    DCHECK(newGamepads);
 
     for (unsigned i = 0; i < WebGamepads::itemsLengthCap; ++i) {
         Gamepad* oldGamepad = oldGamepads ? oldGamepads->item(i) : 0;
diff --git a/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.h b/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.h
index a170945..a0febcc 100644
--- a/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.h
+++ b/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.h
@@ -26,7 +26,7 @@
 #ifndef NavigatorGamepad_h
 #define NavigatorGamepad_h
 
-#include "core/frame/DOMWindowProperty.h"
+#include "core/dom/ContextLifecycleObserver.h"
 #include "core/frame/LocalDOMWindow.h"
 #include "core/frame/PlatformEventController.h"
 #include "modules/ModulesExport.h"
@@ -42,7 +42,7 @@
 class GamepadList;
 class Navigator;
 
-class MODULES_EXPORT NavigatorGamepad final : public GarbageCollectedFinalized<NavigatorGamepad>, public Supplement<Navigator>, public DOMWindowProperty, public PlatformEventController, public LocalDOMWindow::EventListenerObserver {
+class MODULES_EXPORT NavigatorGamepad final : public GarbageCollectedFinalized<NavigatorGamepad>, public Supplement<Navigator>, public ContextLifecycleObserver, public PlatformEventController, public LocalDOMWindow::EventListenerObserver {
     USING_GARBAGE_COLLECTED_MIXIN(NavigatorGamepad);
 public:
     static NavigatorGamepad* from(Document&);
@@ -65,9 +65,8 @@
     void didRemoveGamepadEventListeners();
     bool startUpdatingIfAttached();
 
-    // DOMWindowProperty
-    void willDestroyGlobalObjectInFrame() override;
-    void willDetachGlobalObjectFromFrame() override;
+    // ContextLifecycleObserver
+    void contextDestroyed() override;
 
     // PlatformEventController
     void registerWithDispatcher() override;
diff --git a/third_party/WebKit/Source/modules/indexeddb/IndexedDBClient.cpp b/third_party/WebKit/Source/modules/indexeddb/IndexedDBClient.cpp
index f8ddc1a..8c17873 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IndexedDBClient.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IndexedDBClient.cpp
@@ -31,6 +31,12 @@
     return "IndexedDBClient";
 }
 
+DEFINE_TRACE(IndexedDBClient)
+{
+    Supplement<LocalFrame>::trace(visitor);
+    Supplement<WorkerClients>::trace(visitor);
+}
+
 void provideIndexedDBClientTo(LocalFrame& frame, IndexedDBClient* client)
 {
     frame.provideSupplement(IndexedDBClient::supplementName(), client);
diff --git a/third_party/WebKit/Source/modules/indexeddb/IndexedDBClient.h b/third_party/WebKit/Source/modules/indexeddb/IndexedDBClient.h
index 3c65ee9..ac1a739 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IndexedDBClient.h
+++ b/third_party/WebKit/Source/modules/indexeddb/IndexedDBClient.h
@@ -28,6 +28,8 @@
 #ifndef IndexedDBClient_h
 #define IndexedDBClient_h
 
+#include "core/frame/LocalFrame.h"
+#include "core/workers/WorkerClients.h"
 #include "modules/ModulesExport.h"
 #include "platform/Supplementable.h"
 #include "platform/heap/Handle.h"
@@ -46,7 +48,7 @@
     IndexedDBClient();
     virtual ~IndexedDBClient() {}
 
-    DEFINE_INLINE_VIRTUAL_TRACE() { }
+    DECLARE_VIRTUAL_TRACE();
 
     virtual bool allowIndexedDB(ExecutionContext*, const String& name) = 0;
 
diff --git a/third_party/WebKit/Source/modules/installedapp/InstalledAppController.cpp b/third_party/WebKit/Source/modules/installedapp/InstalledAppController.cpp
index 4f0c188..1b97479 100644
--- a/third_party/WebKit/Source/modules/installedapp/InstalledAppController.cpp
+++ b/third_party/WebKit/Source/modules/installedapp/InstalledAppController.cpp
@@ -54,7 +54,7 @@
     m_client->getInstalledRelatedApps(url, std::move(callback));
 }
 
-void InstalledAppController::willDetachFrameHost()
+void InstalledAppController::contextDestroyed()
 {
     m_client = nullptr;
 }
diff --git a/third_party/WebKit/Source/modules/installedapp/InstalledAppController.h b/third_party/WebKit/Source/modules/installedapp/InstalledAppController.h
index c1496a4..571071c9 100644
--- a/third_party/WebKit/Source/modules/installedapp/InstalledAppController.h
+++ b/third_party/WebKit/Source/modules/installedapp/InstalledAppController.h
@@ -33,7 +33,7 @@
     InstalledAppController(LocalFrame&, WebInstalledAppClient*);
 
     // Inherited from LocalFrameLifecycleObserver.
-    void willDetachFrameHost() override;
+    void contextDestroyed() override;
 
     WebInstalledAppClient* m_client;
 };
diff --git a/third_party/WebKit/Source/modules/mediasource/SourceBuffer.cpp b/third_party/WebKit/Source/modules/mediasource/SourceBuffer.cpp
index fe119e1d..573f455 100644
--- a/third_party/WebKit/Source/modules/mediasource/SourceBuffer.cpp
+++ b/third_party/WebKit/Source/modules/mediasource/SourceBuffer.cpp
@@ -85,13 +85,13 @@
 WTF::String webTimeRangesToString(const WebTimeRanges& ranges)
 {
     StringBuilder stringBuilder;
-    stringBuilder.append("{");
+    stringBuilder.append('{');
     for (auto& r : ranges) {
         stringBuilder.append(" [");
         stringBuilder.appendNumber(r.start);
-        stringBuilder.append(";");
+        stringBuilder.append(';');
         stringBuilder.appendNumber(r.end);
-        stringBuilder.append("]");
+        stringBuilder.append(']');
     }
     stringBuilder.append(" }");
     return stringBuilder.toString();
diff --git a/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.cpp b/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.cpp
index ccb2d8fc..3032706 100644
--- a/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.cpp
+++ b/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.cpp
@@ -226,6 +226,12 @@
     NavigatorContentUtils::from(*navigator.frame())->client()->unregisterProtocolHandler(scheme, document->completeURL(url));
 }
 
+DEFINE_TRACE(NavigatorContentUtils)
+{
+    visitor->trace(m_client);
+    Supplement<LocalFrame>::trace(visitor);
+}
+
 const char* NavigatorContentUtils::supplementName()
 {
     return "NavigatorContentUtils";
diff --git a/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.h b/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.h
index d510d47e..323b00c4 100644
--- a/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.h
+++ b/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.h
@@ -27,6 +27,7 @@
 #ifndef NavigatorContentUtils_h
 #define NavigatorContentUtils_h
 
+#include "core/frame/LocalFrame.h"
 #include "modules/ModulesExport.h"
 #include "modules/navigatorcontentutils/NavigatorContentUtilsClient.h"
 #include "platform/Supplementable.h"
@@ -53,11 +54,7 @@
 
     static NavigatorContentUtils* create(NavigatorContentUtilsClient*);
 
-    DEFINE_INLINE_VIRTUAL_TRACE()
-    {
-        visitor->trace(m_client);
-        Supplement<LocalFrame>::trace(visitor);
-    }
+    DECLARE_VIRTUAL_TRACE();
 
     void setClientForTest(NavigatorContentUtilsClient* client) { m_client = client; }
 
diff --git a/third_party/WebKit/Source/modules/payments/PaymentAddress.cpp b/third_party/WebKit/Source/modules/payments/PaymentAddress.cpp
index 10fc779105..fea61124 100644
--- a/third_party/WebKit/Source/modules/payments/PaymentAddress.cpp
+++ b/third_party/WebKit/Source/modules/payments/PaymentAddress.cpp
@@ -4,6 +4,8 @@
 
 #include "modules/payments/PaymentAddress.h"
 
+#include "wtf/text/StringBuilder.h"
+
 namespace blink {
 
 PaymentAddress::PaymentAddress(mojom::blink::PaymentAddressPtr address)
@@ -21,8 +23,11 @@
     , m_phone(address->phone)
 {
     if (!m_languageCode.isEmpty() && !address->script_code.isEmpty()) {
-        m_languageCode.append("-");
-        m_languageCode.append(address->script_code);
+        StringBuilder builder;
+        builder.append(m_languageCode);
+        builder.append('-');
+        builder.append(address->script_code);
+        m_languageCode = builder.toString();
     }
 }
 
diff --git a/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp b/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp
index 386f6308..c24a730f 100644
--- a/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp
+++ b/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp
@@ -206,12 +206,19 @@
 
 void validateShippingOptions(const HeapVector<PaymentShippingOption>& options, ExceptionState& exceptionState)
 {
+    HashSet<String> uniqueIds;
     for (const auto& option : options) {
         if (!option.hasId() || option.id().isEmpty()) {
             exceptionState.throwTypeError("ShippingOption id required");
             return;
         }
 
+        if (uniqueIds.contains(option.id())) {
+            exceptionState.throwTypeError("Duplicate shipping option identifiers are not allowed");
+            return;
+        }
+        uniqueIds.add(option.id());
+
         validateShippingOptionOrPaymentItem(option, exceptionState);
         if (exceptionState.hadException())
             return;
@@ -231,6 +238,7 @@
             exceptionState.throwTypeError("Must specify at least one payment method identifier");
             return;
         }
+
         for (const auto& method : modifier.supportedMethods()) {
             if (uniqueMethods.contains(method)) {
                 exceptionState.throwTypeError("Duplicate payment method identifiers are not allowed");
@@ -304,6 +312,7 @@
             exceptionState.throwTypeError("Must specify at least one payment method identifier");
             return;
         }
+
         for (const auto& method : pmd.supportedMethods()) {
             if (uniqueMethods.contains(method)) {
                 exceptionState.throwTypeError("Duplicate payment method identifiers are not allowed");
diff --git a/third_party/WebKit/Source/modules/payments/PaymentTestHelper.cpp b/third_party/WebKit/Source/modules/payments/PaymentTestHelper.cpp
index 1d2293ef..5714c8c 100644
--- a/third_party/WebKit/Source/modules/payments/PaymentTestHelper.cpp
+++ b/third_party/WebKit/Source/modules/payments/PaymentTestHelper.cpp
@@ -13,6 +13,7 @@
 namespace blink {
 namespace {
 
+static int gUniqueId = 0;
 // PaymentItem and PaymentShippingOption have identical structure
 // except for the "id" field, which is present only in PaymentShippingOption.
 template <typename PaymentItemOrPaymentShippingOption>
@@ -60,7 +61,7 @@
         if (modificationType == PaymentTestOverwriteValue)
             shippingOption.setId(valueToUse);
     } else {
-        shippingOption.setId("id");
+        shippingOption.setId("id" + String::number(gUniqueId++));
     }
     setValues(shippingOption, data, modificationType, valueToUse);
     return shippingOption;
@@ -116,7 +117,7 @@
     PaymentDetails result;
     result.setTotal(total);
     result.setDisplayItems(HeapVector<PaymentItem>(1, item));
-    result.setShippingOptions(HeapVector<PaymentShippingOption>(2, shippingOption));
+    result.setShippingOptions(HeapVector<PaymentShippingOption>(1, shippingOption));
     result.setModifiers(HeapVector<PaymentDetailsModifier>(1, modifier));
 
     return result;
diff --git a/third_party/WebKit/Source/modules/permissions/PermissionController.cpp b/third_party/WebKit/Source/modules/permissions/PermissionController.cpp
index 96e06c5..f1bfef0 100644
--- a/third_party/WebKit/Source/modules/permissions/PermissionController.cpp
+++ b/third_party/WebKit/Source/modules/permissions/PermissionController.cpp
@@ -43,7 +43,7 @@
     return m_client;
 }
 
-void PermissionController::willDetachFrameHost()
+void PermissionController::contextDestroyed()
 {
     m_client = nullptr;
 }
diff --git a/third_party/WebKit/Source/modules/permissions/PermissionController.h b/third_party/WebKit/Source/modules/permissions/PermissionController.h
index 6c4f7c1..c59228c 100644
--- a/third_party/WebKit/Source/modules/permissions/PermissionController.h
+++ b/third_party/WebKit/Source/modules/permissions/PermissionController.h
@@ -34,7 +34,7 @@
     PermissionController(LocalFrame&, WebPermissionClient*);
 
     // Inherited from LocalFrameLifecycleObserver.
-    void willDetachFrameHost() override;
+    void contextDestroyed() override;
 
     WebPermissionClient* m_client;
 };
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationController.cpp b/third_party/WebKit/Source/modules/presentation/PresentationController.cpp
index 2cc3b32..50c9ffe1 100644
--- a/third_party/WebKit/Source/modules/presentation/PresentationController.cpp
+++ b/third_party/WebKit/Source/modules/presentation/PresentationController.cpp
@@ -131,7 +131,7 @@
     m_connections.add(connection);
 }
 
-void PresentationController::willDetachFrameHost()
+void PresentationController::contextDestroyed()
 {
     if (m_client) {
         m_client->setController(nullptr);
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationController.h b/third_party/WebKit/Source/modules/presentation/PresentationController.h
index ef45351..73cee31 100644
--- a/third_party/WebKit/Source/modules/presentation/PresentationController.h
+++ b/third_party/WebKit/Source/modules/presentation/PresentationController.h
@@ -71,7 +71,7 @@
     PresentationController(LocalFrame&, WebPresentationClient*);
 
     // Implementation of LocalFrameLifecycleObserver.
-    void willDetachFrameHost() override;
+    void contextDestroyed() override;
 
     // Return the connection associated with the given |connectionClient| or
     // null if it doesn't exist.
diff --git a/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationController.cpp b/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationController.cpp
index 87380a3..9dc9f52 100644
--- a/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationController.cpp
+++ b/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationController.cpp
@@ -197,7 +197,7 @@
     return true;
 }
 
-void ScreenOrientationController::willDetachFrameHost()
+void ScreenOrientationController::contextDestroyed()
 {
     m_client = nullptr;
 }
diff --git a/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationController.h b/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationController.h
index 07e7ed6..d06c3c0a 100644
--- a/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationController.h
+++ b/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationController.h
@@ -55,7 +55,7 @@
     void pageVisibilityChanged() override;
 
     // Inherited from LocalFrameLifecycleObserver.
-    void willDetachFrameHost() override;
+    void contextDestroyed() override;
 
     void notifyDispatcher();
 
diff --git a/third_party/WebKit/Source/modules/serviceworkers/NavigatorServiceWorker.cpp b/third_party/WebKit/Source/modules/serviceworkers/NavigatorServiceWorker.cpp
index a7ba1e19..4dd3c93 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/NavigatorServiceWorker.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/NavigatorServiceWorker.cpp
@@ -13,7 +13,7 @@
 namespace blink {
 
 NavigatorServiceWorker::NavigatorServiceWorker(Navigator& navigator)
-    : DOMWindowProperty(navigator.frame())
+    : ContextLifecycleObserver(navigator.frame() ? navigator.frame()->document() : nullptr)
 {
 }
 
@@ -33,7 +33,7 @@
         provideTo(navigator, supplementName(), supplement);
         if (navigator.frame() && navigator.frame()->securityContext()->getSecurityOrigin()->canAccessServiceWorkers()) {
             // Initialize ServiceWorkerContainer too.
-            supplement->serviceWorker(ASSERT_NO_EXCEPTION);
+            supplement->serviceWorker(navigator.frame(), ASSERT_NO_EXCEPTION);
         }
     }
     return *supplement;
@@ -51,27 +51,27 @@
 
 ServiceWorkerContainer* NavigatorServiceWorker::serviceWorker(ExecutionContext* executionContext, Navigator& navigator, ExceptionState& exceptionState)
 {
-    ASSERT(!navigator.frame() || executionContext->getSecurityOrigin()->canAccessCheckSuborigins(navigator.frame()->securityContext()->getSecurityOrigin()));
-    return NavigatorServiceWorker::from(navigator).serviceWorker(exceptionState);
+    DCHECK(!navigator.frame() || executionContext->getSecurityOrigin()->canAccessCheckSuborigins(navigator.frame()->securityContext()->getSecurityOrigin()));
+    return NavigatorServiceWorker::from(navigator).serviceWorker(navigator.frame(), exceptionState);
 }
 
-ServiceWorkerContainer* NavigatorServiceWorker::serviceWorker(ExceptionState& exceptionState)
+ServiceWorkerContainer* NavigatorServiceWorker::serviceWorker(LocalFrame* frame, ExceptionState& exceptionState)
 {
-    if (frame() && !frame()->securityContext()->getSecurityOrigin()->canAccessServiceWorkers()) {
-        if (frame()->securityContext()->isSandboxed(SandboxOrigin))
+    if (frame && !frame->securityContext()->getSecurityOrigin()->canAccessServiceWorkers()) {
+        if (frame->securityContext()->isSandboxed(SandboxOrigin))
             exceptionState.throwSecurityError("Service worker is disabled because the context is sandboxed and lacks the 'allow-same-origin' flag.");
         else
             exceptionState.throwSecurityError("Access to service workers is denied in this document origin.");
         return nullptr;
     }
-    if (!m_serviceWorker && frame()) {
-        ASSERT(frame()->domWindow());
-        m_serviceWorker = ServiceWorkerContainer::create(frame()->domWindow()->getExecutionContext());
+    if (!m_serviceWorker && frame) {
+        DCHECK(frame->domWindow());
+        m_serviceWorker = ServiceWorkerContainer::create(frame->domWindow()->getExecutionContext());
     }
     return m_serviceWorker.get();
 }
 
-void NavigatorServiceWorker::willDetachGlobalObjectFromFrame()
+void NavigatorServiceWorker::contextDestroyed()
 {
     if (m_serviceWorker) {
         m_serviceWorker->willBeDetachedFromFrame();
@@ -83,7 +83,7 @@
 {
     visitor->trace(m_serviceWorker);
     Supplement<Navigator>::trace(visitor);
-    DOMWindowProperty::trace(visitor);
+    ContextLifecycleObserver::trace(visitor);
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/modules/serviceworkers/NavigatorServiceWorker.h b/third_party/WebKit/Source/modules/serviceworkers/NavigatorServiceWorker.h
index ebcb21b..9d8584e 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/NavigatorServiceWorker.h
+++ b/third_party/WebKit/Source/modules/serviceworkers/NavigatorServiceWorker.h
@@ -5,6 +5,7 @@
 #ifndef NavigatorServiceWorker_h
 #define NavigatorServiceWorker_h
 
+#include "core/dom/ContextLifecycleObserver.h"
 #include "core/frame/Navigator.h"
 #include "modules/ModulesExport.h"
 #include "platform/Supplementable.h"
@@ -17,7 +18,7 @@
 class Navigator;
 class ServiceWorkerContainer;
 
-class MODULES_EXPORT NavigatorServiceWorker final : public GarbageCollected<NavigatorServiceWorker>, public Supplement<Navigator>, public DOMWindowProperty {
+class MODULES_EXPORT NavigatorServiceWorker final : public GarbageCollected<NavigatorServiceWorker>, public Supplement<Navigator>, public ContextLifecycleObserver {
     USING_GARBAGE_COLLECTED_MIXIN(NavigatorServiceWorker);
 public:
     static NavigatorServiceWorker* from(Document&);
@@ -29,12 +30,12 @@
 
 private:
     explicit NavigatorServiceWorker(Navigator&);
-    ServiceWorkerContainer* serviceWorker(ExceptionState&);
+    ServiceWorkerContainer* serviceWorker(LocalFrame*, ExceptionState&);
 
     static const char* supplementName();
 
-    // DOMWindowProperty override.
-    void willDetachGlobalObjectFromFrame() override;
+    // ContextLifecycleObserver override.
+    void contextDestroyed() override;
 
     Member<ServiceWorkerContainer> m_serviceWorker;
 };
diff --git a/third_party/WebKit/Source/modules/vibration/NavigatorVibration.cpp b/third_party/WebKit/Source/modules/vibration/NavigatorVibration.cpp
index 0a560cf..9ca5c36c 100644
--- a/third_party/WebKit/Source/modules/vibration/NavigatorVibration.cpp
+++ b/third_party/WebKit/Source/modules/vibration/NavigatorVibration.cpp
@@ -19,6 +19,7 @@
 
 #include "modules/vibration/NavigatorVibration.h"
 
+#include "core/dom/Document.h"
 #include "core/frame/LocalFrame.h"
 #include "core/frame/Navigator.h"
 #include "core/frame/UseCounter.h"
@@ -30,7 +31,7 @@
 namespace blink {
 
 NavigatorVibration::NavigatorVibration(Navigator& navigator)
-    : DOMWindowProperty(navigator.frame())
+    : ContextLifecycleObserver(navigator.frame()->document())
 {
 }
 
@@ -80,7 +81,7 @@
     if (!frame->page()->isPageVisible())
         return false;
 
-    return NavigatorVibration::from(navigator).controller()->vibrate(pattern);
+    return NavigatorVibration::from(navigator).controller(*frame)->vibrate(pattern);
 }
 
 // static
@@ -112,15 +113,15 @@
     NavigatorVibrateHistogram.count(type);
 }
 
-VibrationController* NavigatorVibration::controller()
+VibrationController* NavigatorVibration::controller(const LocalFrame& frame)
 {
-    if (!m_controller && frame())
-        m_controller = new VibrationController(*frame()->document());
+    if (!m_controller)
+        m_controller = new VibrationController(*frame.document());
 
     return m_controller.get();
 }
 
-void NavigatorVibration::willDetachGlobalObjectFromFrame()
+void NavigatorVibration::contextDestroyed()
 {
     if (m_controller) {
         m_controller->cancel();
@@ -132,7 +133,7 @@
 {
     visitor->trace(m_controller);
     Supplement<Navigator>::trace(visitor);
-    DOMWindowProperty::trace(visitor);
+    ContextLifecycleObserver::trace(visitor);
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/modules/vibration/NavigatorVibration.h b/third_party/WebKit/Source/modules/vibration/NavigatorVibration.h
index ec978cff..723cf09 100644
--- a/third_party/WebKit/Source/modules/vibration/NavigatorVibration.h
+++ b/third_party/WebKit/Source/modules/vibration/NavigatorVibration.h
@@ -20,7 +20,7 @@
 #ifndef NavigatorVibration_h
 #define NavigatorVibration_h
 
-#include "core/frame/DOMWindowProperty.h"
+#include "core/dom/ContextLifecycleObserver.h"
 #include "modules/ModulesExport.h"
 #include "platform/Supplementable.h"
 #include "platform/heap/GarbageCollected.h"
@@ -30,6 +30,7 @@
 
 namespace blink {
 
+class LocalFrame;
 class Navigator;
 class VibrationController;
 
@@ -46,7 +47,7 @@
 class MODULES_EXPORT NavigatorVibration final
     : public GarbageCollectedFinalized<NavigatorVibration>
     , public Supplement<Navigator>
-    , public DOMWindowProperty {
+    , public ContextLifecycleObserver {
     USING_GARBAGE_COLLECTED_MIXIN(NavigatorVibration);
     WTF_MAKE_NONCOPYABLE(NavigatorVibration);
 public:
@@ -59,7 +60,7 @@
     static bool vibrate(Navigator&, unsigned time);
     static bool vibrate(Navigator&, const VibrationPattern&);
 
-    VibrationController* controller();
+    VibrationController* controller(const LocalFrame&);
 
     DECLARE_VIRTUAL_TRACE();
 
@@ -68,8 +69,8 @@
 
     explicit NavigatorVibration(Navigator&);
 
-    // Inherited from DOMWindowProperty.
-    void willDetachGlobalObjectFromFrame() override;
+    // Inherited from ContextLifecycleObserver.
+    void contextDestroyed() override;
 
     static void collectHistogramMetrics(const LocalFrame&);
 
diff --git a/third_party/WebKit/Source/modules/vibration/testing/InternalsVibration.cpp b/third_party/WebKit/Source/modules/vibration/testing/InternalsVibration.cpp
index 5c7c679..814c78e 100644
--- a/third_party/WebKit/Source/modules/vibration/testing/InternalsVibration.cpp
+++ b/third_party/WebKit/Source/modules/vibration/testing/InternalsVibration.cpp
@@ -40,13 +40,13 @@
 bool InternalsVibration::isVibrating(Internals&, Navigator* navigator)
 {
     DCHECK(navigator && navigator->frame());
-    return NavigatorVibration::from(*navigator).controller()->isRunning();
+    return NavigatorVibration::from(*navigator).controller(*navigator->frame())->isRunning();
 }
 
 Vector<unsigned> InternalsVibration::pendingVibrationPattern(Internals&, Navigator* navigator)
 {
     DCHECK(navigator && navigator->frame());
-    return NavigatorVibration::from(*navigator).controller()->pattern();
+    return NavigatorVibration::from(*navigator).controller(*navigator->frame())->pattern();
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/modules/vr/VRController.cpp b/third_party/WebKit/Source/modules/vr/VRController.cpp
index 88a2128..455d700 100644
--- a/third_party/WebKit/Source/modules/vr/VRController.cpp
+++ b/third_party/WebKit/Source/modules/vr/VRController.cpp
@@ -28,7 +28,6 @@
 }
 
 VRController::VRController(LocalFrame& frame, ServiceRegistry* registry)
-    : LocalFrameLifecycleObserver(&frame)
 {
     ASSERT(!m_service.is_bound());
     registry->connectToRemoteService(mojo::GetProxy(&m_service));
@@ -67,11 +66,6 @@
     m_service->ResetPose(index);
 }
 
-void VRController::willDetachFrameHost()
-{
-    // TODO(kphanee): Detach from the mojo service connection.
-}
-
 void VRController::onGetDisplays(mojo::WTFArray<device::blink::VRDisplayPtr> displays)
 {
     std::unique_ptr<VRGetDevicesCallback> callback = m_pendingGetDevicesCallbacks.takeFirst();
@@ -84,7 +78,6 @@
 DEFINE_TRACE(VRController)
 {
     Supplement<LocalFrame>::trace(visitor);
-    LocalFrameLifecycleObserver::trace(visitor);
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/modules/vr/VRController.h b/third_party/WebKit/Source/modules/vr/VRController.h
index 32c984cd..3e01a2f 100644
--- a/third_party/WebKit/Source/modules/vr/VRController.h
+++ b/third_party/WebKit/Source/modules/vr/VRController.h
@@ -5,7 +5,7 @@
 #ifndef VRController_h
 #define VRController_h
 
-#include "core/frame/LocalFrameLifecycleObserver.h"
+#include "core/frame/LocalFrame.h"
 #include "device/vr/vr_service.mojom-blink.h"
 #include "modules/ModulesExport.h"
 #include "platform/Supplementable.h"
@@ -20,8 +20,7 @@
 
 class MODULES_EXPORT VRController final
     : public GarbageCollectedFinalized<VRController>
-    , public Supplement<LocalFrame>
-    , public LocalFrameLifecycleObserver {
+    , public Supplement<LocalFrame> {
     USING_GARBAGE_COLLECTED_MIXIN(VRController);
     WTF_MAKE_NONCOPYABLE(VRController);
 public:
@@ -42,9 +41,6 @@
 private:
     VRController(LocalFrame&, ServiceRegistry*);
 
-    // Inherited from LocalFrameLifecycleObserver.
-    void willDetachFrameHost() override;
-
     // Binding callbacks.
     void onGetDisplays(mojo::WTFArray<device::blink::VRDisplayPtr>);
 
diff --git a/third_party/WebKit/Source/modules/webdatabase/DatabaseAuthorizer.cpp b/third_party/WebKit/Source/modules/webdatabase/DatabaseAuthorizer.cpp
index 345d5c6..353d3b02 100644
--- a/third_party/WebKit/Source/modules/webdatabase/DatabaseAuthorizer.cpp
+++ b/third_party/WebKit/Source/modules/webdatabase/DatabaseAuthorizer.cpp
@@ -28,6 +28,10 @@
 
 #include "modules/webdatabase/DatabaseAuthorizer.h"
 
+#include "wtf/HashSet.h"
+#include "wtf/StdLibExtras.h"
+#include "wtf/text/StringHash.h"
+
 namespace blink {
 
 DatabaseAuthorizer* DatabaseAuthorizer::create(const String& databaseInfoTableName)
@@ -42,7 +46,6 @@
     DCHECK(isMainThread());
 
     reset();
-    addWhitelistedFunctions();
 }
 
 void DatabaseAuthorizer::reset()
@@ -57,68 +60,70 @@
     m_hadDeletes = false;
 }
 
-void DatabaseAuthorizer::addWhitelistedFunctions()
+namespace {
+using FunctionNameList = HashSet<String, CaseFoldingHash>;
+
+const FunctionNameList& whitelistedFunctions()
 {
-    // SQLite functions used to help implement some operations
-    // ALTER TABLE helpers
-    m_whitelistedFunctions.add("sqlite_rename_table");
-    m_whitelistedFunctions.add("sqlite_rename_trigger");
-    // GLOB helpers
-    m_whitelistedFunctions.add("glob");
-
-    // SQLite core functions
-    m_whitelistedFunctions.add("abs");
-    m_whitelistedFunctions.add("changes");
-    m_whitelistedFunctions.add("coalesce");
-    m_whitelistedFunctions.add("glob");
-    m_whitelistedFunctions.add("ifnull");
-    m_whitelistedFunctions.add("hex");
-    m_whitelistedFunctions.add("last_insert_rowid");
-    m_whitelistedFunctions.add("length");
-    m_whitelistedFunctions.add("like");
-    m_whitelistedFunctions.add("lower");
-    m_whitelistedFunctions.add("ltrim");
-    m_whitelistedFunctions.add("max");
-    m_whitelistedFunctions.add("min");
-    m_whitelistedFunctions.add("nullif");
-    m_whitelistedFunctions.add("quote");
-    m_whitelistedFunctions.add("replace");
-    m_whitelistedFunctions.add("round");
-    m_whitelistedFunctions.add("rtrim");
-    m_whitelistedFunctions.add("soundex");
-    m_whitelistedFunctions.add("sqlite_source_id");
-    m_whitelistedFunctions.add("sqlite_version");
-    m_whitelistedFunctions.add("substr");
-    m_whitelistedFunctions.add("total_changes");
-    m_whitelistedFunctions.add("trim");
-    m_whitelistedFunctions.add("typeof");
-    m_whitelistedFunctions.add("upper");
-    m_whitelistedFunctions.add("zeroblob");
-
-    // SQLite date and time functions
-    m_whitelistedFunctions.add("date");
-    m_whitelistedFunctions.add("time");
-    m_whitelistedFunctions.add("datetime");
-    m_whitelistedFunctions.add("julianday");
-    m_whitelistedFunctions.add("strftime");
-
-    // SQLite aggregate functions
-    // max() and min() are already in the list
-    m_whitelistedFunctions.add("avg");
-    m_whitelistedFunctions.add("count");
-    m_whitelistedFunctions.add("group_concat");
-    m_whitelistedFunctions.add("sum");
-    m_whitelistedFunctions.add("total");
-
-    // SQLite FTS functions
-    m_whitelistedFunctions.add("match");
-    m_whitelistedFunctions.add("snippet");
-    m_whitelistedFunctions.add("offsets");
-    m_whitelistedFunctions.add("optimize");
-
-    // SQLite ICU functions
-    // like(), lower() and upper() are already in the list
-    m_whitelistedFunctions.add("regexp");
+    DEFINE_STATIC_LOCAL(FunctionNameList, list, ({
+        // SQLite functions used to help implement some operations
+        // ALTER TABLE helpers
+        "sqlite_rename_table",
+        "sqlite_rename_trigger",
+        // GLOB helpers
+        "glob",
+        // SQLite core functions
+        "abs",
+        "changes",
+        "coalesce",
+        "glob",
+        "ifnull",
+        "hex",
+        "last_insert_rowid",
+        "length",
+        "like",
+        "lower",
+        "ltrim",
+        "max",
+        "min",
+        "nullif",
+        "quote",
+        "replace",
+        "round",
+        "rtrim",
+        "soundex",
+        "sqlite_source_id",
+        "sqlite_version",
+        "substr",
+        "total_changes",
+        "trim",
+        "typeof",
+        "upper",
+        "zeroblob",
+        // SQLite date and time functions
+        "date",
+        "time",
+        "datetime",
+        "julianday",
+        "strftime",
+        // SQLite aggregate functions
+        // max() and min() are already in the list
+        "avg",
+        "count",
+        "group_concat",
+        "sum",
+        "total",
+        // SQLite FTS functions
+        "match",
+        "snippet",
+        "offsets",
+        "optimize",
+        // SQLite ICU functions
+        // like(), lower() and upper() are already in the list
+        "regexp",
+    }));
+    return list;
+}
 }
 
 int DatabaseAuthorizer::createTable(const String& tableName)
@@ -373,7 +378,7 @@
 
 int DatabaseAuthorizer::allowFunction(const String& functionName)
 {
-    if (m_securityEnabled && !m_whitelistedFunctions.contains(functionName))
+    if (m_securityEnabled && !whitelistedFunctions().contains(functionName))
         return SQLAuthDeny;
 
     return SQLAuthAllow;
diff --git a/third_party/WebKit/Source/modules/webdatabase/DatabaseAuthorizer.h b/third_party/WebKit/Source/modules/webdatabase/DatabaseAuthorizer.h
index 81bfd4fe..c612528 100644
--- a/third_party/WebKit/Source/modules/webdatabase/DatabaseAuthorizer.h
+++ b/third_party/WebKit/Source/modules/webdatabase/DatabaseAuthorizer.h
@@ -30,8 +30,6 @@
 
 #include "platform/heap/Handle.h"
 #include "wtf/Forward.h"
-#include "wtf/HashSet.h"
-#include "wtf/text/StringHash.h"
 #include "wtf/text/WTFString.h"
 
 namespace blink {
@@ -116,8 +114,6 @@
     bool m_hadDeletes : 1;
 
     const String m_databaseInfoTableName;
-
-    HashSet<String, CaseFoldingHash> m_whitelistedFunctions;
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/modules/webdatabase/DatabaseClient.cpp b/third_party/WebKit/Source/modules/webdatabase/DatabaseClient.cpp
index 88c2fab..3b36126 100644
--- a/third_party/WebKit/Source/modules/webdatabase/DatabaseClient.cpp
+++ b/third_party/WebKit/Source/modules/webdatabase/DatabaseClient.cpp
@@ -44,6 +44,7 @@
 DEFINE_TRACE(DatabaseClient)
 {
     visitor->trace(m_inspectorAgent);
+    Supplement<Page>::trace(visitor);
 }
 
 DatabaseClient* DatabaseClient::fromPage(Page* page)
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
index 382461c7..c7fe240 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
@@ -534,7 +534,7 @@
     formatWebGLStatusString("Reset notification strategy", String::format("0x%04x", info.resetNotificationStrategy).utf8().data(), statusMessage);
     formatWebGLStatusString("GPU process crash count", String::number(info.processCrashCount).utf8().data(), statusMessage);
     formatWebGLStatusString("ErrorMessage", info.errorMessage.utf8().data(), statusMessage);
-    statusMessage.append(".");
+    statusMessage.append('.');
     return statusMessage;
 }
 
diff --git a/third_party/WebKit/Source/modules/websockets/DOMWebSocketTest.cpp b/third_party/WebKit/Source/modules/websockets/DOMWebSocketTest.cpp
index 7669a9c..53b7bc6 100644
--- a/third_party/WebKit/Source/modules/websockets/DOMWebSocketTest.cpp
+++ b/third_party/WebKit/Source/modules/websockets/DOMWebSocketTest.cpp
@@ -20,6 +20,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "wtf/Vector.h"
 #include "wtf/text/CString.h"
+#include "wtf/text/StringBuilder.h"
 #include "wtf/text/WTFString.h"
 #include <memory>
 #include <v8.h>
@@ -358,15 +359,15 @@
         EXPECT_CALL(webSocketScope.channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
         EXPECT_CALL(webSocketScope.channel(), failMock(_, _, _));
     }
-    String reason;
+    StringBuilder reason;
     for (size_t i = 0; i < 123; ++i)
-        reason.append("a");
+        reason.append('a');
     webSocketScope.socket().connect("ws://example.com/", Vector<String>(), scope.getExceptionState());
 
     EXPECT_FALSE(scope.getExceptionState().hadException());
     EXPECT_EQ(DOMWebSocket::CONNECTING, webSocketScope.socket().readyState());
 
-    webSocketScope.socket().close(1000, reason, scope.getExceptionState());
+    webSocketScope.socket().close(1000, reason.toString(), scope.getExceptionState());
 
     EXPECT_FALSE(scope.getExceptionState().hadException());
     EXPECT_EQ(DOMWebSocket::CLOSING, webSocketScope.socket().readyState());
@@ -380,15 +381,15 @@
         InSequence s;
         EXPECT_CALL(webSocketScope.channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true));
     }
-    String reason;
+    StringBuilder reason;
     for (size_t i = 0; i < 124; ++i)
-        reason.append("a");
+        reason.append('a');
     webSocketScope.socket().connect("ws://example.com/", Vector<String>(), scope.getExceptionState());
 
     EXPECT_FALSE(scope.getExceptionState().hadException());
     EXPECT_EQ(DOMWebSocket::CONNECTING, webSocketScope.socket().readyState());
 
-    webSocketScope.socket().close(1000, reason, scope.getExceptionState());
+    webSocketScope.socket().close(1000, reason.toString(), scope.getExceptionState());
 
     EXPECT_TRUE(scope.getExceptionState().hadException());
     EXPECT_EQ(SyntaxError, scope.getExceptionState().code());
diff --git a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp
index 8d4c7b9..456d2711 100644
--- a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp
+++ b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp
@@ -58,8 +58,6 @@
 #include "wtf/PtrUtil.h"
 #include <memory>
 
-using blink::WebSocketHandle;
-
 namespace blink {
 
 class DocumentWebSocketChannel::BlobLoader final : public GarbageCollectedFinalized<DocumentWebSocketChannel::BlobLoader>, public FileReaderLoaderClient {
@@ -184,7 +182,8 @@
 
     if (document()->frame())
         document()->frame()->loader().client()->dispatchWillOpenWebSocket(m_handle.get());
-    m_handle->connect(url, webProtocols, WebSecurityOrigin(getExecutionContext()->getSecurityOrigin()), document()->userAgent(), this);
+    m_handle->connect(url, webProtocols, WebSecurityOrigin(getExecutionContext()->getSecurityOrigin()), document()->firstPartyForCookies(), document()->userAgent(), this);
+
     flowControlIfNecessary();
     TRACE_EVENT_INSTANT1("devtools.timeline", "WebSocketCreate", TRACE_EVENT_SCOPE_THREAD, "data", InspectorWebSocketCreateEvent::data(document(), m_identifier, url, protocol));
     InspectorInstrumentation::didCreateWebSocket(document(), m_identifier, url, protocol);
diff --git a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannelTest.cpp b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannelTest.cpp
index 2b8ce537..56494e6 100644
--- a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannelTest.cpp
+++ b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannelTest.cpp
@@ -30,7 +30,7 @@
 using testing::InSequence;
 using testing::PrintToString;
 using testing::AnyNumber;
-
+using testing::SaveArg;
 
 namespace blink {
 
@@ -80,7 +80,7 @@
 
     ~MockWebSocketHandle() override { }
 
-    MOCK_METHOD5(connect, void(const WebURL&, const WebVector<WebString>&, const WebSecurityOrigin&, const WebString&, WebSocketHandleClient*));
+    MOCK_METHOD6(connect, void(const WebURL&, const WebVector<WebString>&, const WebSecurityOrigin&, const WebURL&, const WebString&, WebSocketHandleClient*));
     MOCK_METHOD4(send, void(bool, WebSocketHandle::MessageType, const char*, size_t));
     MOCK_METHOD1(flowControl, void(int64_t));
     MOCK_METHOD2(close, void(unsigned short, const WebString&));
@@ -132,7 +132,7 @@
     {
         {
             InSequence s;
-            EXPECT_CALL(*handle(), connect(WebURL(KURL(KURL(), "ws://localhost/")), _, _, _, handleClient()));
+            EXPECT_CALL(*handle(), connect(WebURL(KURL(KURL(), "ws://localhost/")), _, _, _, _, handleClient()));
             EXPECT_CALL(*handle(), flowControl(65536));
             EXPECT_CALL(*channelClient(), didConnect(String("a"), String("b")));
         }
@@ -158,18 +158,46 @@
     return memcmp(arg, p, len) == 0;
 }
 
+MATCHER_P(WebURLEq, urlString,
+    std::string(negation ? "doesn't equal" : "equals")
+    + " to \"" + urlString + "\""
+)
+{
+    WebURL url(KURL(KURL(), urlString));
+    *result_listener << "where the url is \"" << arg.string().utf8() << "\"";
+    return arg == url;
+}
+
 TEST_F(DocumentWebSocketChannelTest, connectSuccess)
 {
+    WebVector<WebString> protocols;
+    WebSecurityOrigin origin;
+
     Checkpoint checkpoint;
     {
         InSequence s;
-        EXPECT_CALL(*handle(), connect(WebURL(KURL(KURL(), "ws://localhost/")), _, _, _, handleClient()));
+        EXPECT_CALL(*handle(), connect(WebURLEq("ws://localhost/"), _, _, WebURLEq("http://example.com/"), _, handleClient())).WillOnce(DoAll(
+            SaveArg<1>(&protocols),
+            SaveArg<2>(&origin)));
         EXPECT_CALL(*handle(), flowControl(65536));
         EXPECT_CALL(checkpoint, Call(1));
         EXPECT_CALL(*channelClient(), didConnect(String("a"), String("b")));
     }
 
+    KURL pageUrl(KURL(), "http://example.com/");
+    m_pageHolder->frame().securityContext()->setSecurityOrigin(SecurityOrigin::create(pageUrl));
+    Document& document = m_pageHolder->document();
+    document.setURL(pageUrl);
+    // Make sure that firstPartyForCookies() is set to the given value.
+    EXPECT_STREQ("http://example.com/", document.firstPartyForCookies().getString().utf8().data());
+
     EXPECT_TRUE(channel()->connect(KURL(KURL(), "ws://localhost/"), "x"));
+
+    EXPECT_EQ(1U, protocols.size());
+    EXPECT_STREQ("x", protocols[0].utf8().data());
+
+    EXPECT_STREQ("http://example.com", origin.toString().utf8().data());
+
     checkpoint.Call(1);
     handleClient()->didConnect(handle(), WebString("a"), WebString("b"));
 }
diff --git a/third_party/WebKit/Source/platform/Crypto.cpp b/third_party/WebKit/Source/platform/Crypto.cpp
index 79fa67b..90808a76 100644
--- a/third_party/WebKit/Source/platform/Crypto.cpp
+++ b/third_party/WebKit/Source/platform/Crypto.cpp
@@ -7,7 +7,6 @@
 #include "public/platform/Platform.h"
 #include "public/platform/WebCrypto.h"
 #include "public/platform/WebCryptoAlgorithm.h"
-#include "wtf/PtrUtil.h"
 #include <memory>
 
 namespace blink {
@@ -38,8 +37,9 @@
 
     ASSERT(crypto);
 
-    std::unique_ptr<WebCryptoDigestor> digestor = wrapUnique(crypto->createDigestor(algorithmId));
-    if (!digestor.get() || !digestor->consume(reinterpret_cast<const unsigned char*>(digestable), length) || !digestor->finish(result, resultSize))
+    std::unique_ptr<WebCryptoDigestor> digestor = crypto->createDigestor(algorithmId);
+    DCHECK(digestor);
+    if (!digestor->consume(reinterpret_cast<const unsigned char*>(digestable), length) || !digestor->finish(result, resultSize))
         return false;
 
     digestResult.append(static_cast<uint8_t*>(result), resultSize);
@@ -48,7 +48,7 @@
 
 std::unique_ptr<WebCryptoDigestor> createDigestor(HashAlgorithm algorithm)
 {
-    return wrapUnique(Platform::current()->crypto()->createDigestor(toWebCryptoAlgorithmId(algorithm)));
+    return Platform::current()->crypto()->createDigestor(toWebCryptoAlgorithmId(algorithm));
 }
 
 void finishDigestor(WebCryptoDigestor* digestor, DigestValue& digestResult)
diff --git a/third_party/WebKit/Source/platform/Crypto.h b/third_party/WebKit/Source/platform/Crypto.h
index 388462e..cbe597c 100644
--- a/third_party/WebKit/Source/platform/Crypto.h
+++ b/third_party/WebKit/Source/platform/Crypto.h
@@ -33,6 +33,7 @@
 };
 
 PLATFORM_EXPORT bool computeDigest(HashAlgorithm, const char* digestable, size_t length, DigestValue& digestResult);
+// Note: this will never return null.
 PLATFORM_EXPORT std::unique_ptr<WebCryptoDigestor> createDigestor(HashAlgorithm);
 PLATFORM_EXPORT void finishDigestor(WebCryptoDigestor*, DigestValue& digestResult);
 
diff --git a/third_party/WebKit/Source/platform/Supplementable.h b/third_party/WebKit/Source/platform/Supplementable.h
index f60bc75..4878737 100644
--- a/third_party/WebKit/Source/platform/Supplementable.h
+++ b/third_party/WebKit/Source/platform/Supplementable.h
@@ -107,6 +107,8 @@
     {
         return host ? host->requireSupplement(key) : 0;
     }
+
+    DEFINE_INLINE_VIRTUAL_TRACE() { }
 };
 
 // Supplementable<T> inherits from GarbageCollectedMixin virtually
diff --git a/third_party/WebKit/Source/platform/blink_platform.gypi b/third_party/WebKit/Source/platform/blink_platform.gypi
index 7e6763e..8714aaa 100644
--- a/third_party/WebKit/Source/platform/blink_platform.gypi
+++ b/third_party/WebKit/Source/platform/blink_platform.gypi
@@ -376,7 +376,6 @@
       'exported/WebURLLoaderTestDelegate.cpp',
       'exported/WebURLLoadTiming.cpp',
       'exported/WebURLRequest.cpp',
-      'exported/WebURLRequestPrivate.h',
       'exported/WebURLResponse.cpp',
       'exported/WrappedResourceRequest.h',
       'exported/WrappedResourceResponse.h',
@@ -743,7 +742,6 @@
       'graphics/gpu/Extensions3DUtil.h',
       'graphics/gpu/WebGLImageConversion.cpp',
       'graphics/gpu/WebGLImageConversion.h',
-      'graphics/paint/CachedDisplayItem.h',
       'graphics/paint/ClipDisplayItem.cpp',
       'graphics/paint/ClipDisplayItem.h',
       'graphics/paint/ClipPaintPropertyNode.h',
@@ -1101,6 +1099,8 @@
       'v8_inspector/V8InjectedScriptHost.h',
       'v8_inspector/V8InspectorSessionImpl.cpp',
       'v8_inspector/V8InspectorSessionImpl.h',
+      'v8_inspector/V8InternalValueType.cpp',
+      'v8_inspector/V8InternalValueType.h',
       'v8_inspector/V8ProfilerAgentImpl.cpp',
       'v8_inspector/V8ProfilerAgentImpl.h',
       'v8_inspector/V8Regex.cpp',
@@ -1239,6 +1239,7 @@
       'network/LinkHeaderTest.cpp',
       'network/NetworkUtilsTest.cpp',
       'network/ResourceRequestTest.cpp',
+      'network/ResourceResponseTest.cpp',
       'scheduler/CancellableTaskFactoryTest.cpp',
       'scroll/ScrollableAreaTest.cpp',
       'testing/ArenaTestHelpers.h',
diff --git a/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp b/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp
index 008bb5f..6c5a96c62 100644
--- a/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp
@@ -30,7 +30,6 @@
 
 #include "public/platform/WebURLRequest.h"
 
-#include "platform/exported/WebURLRequestPrivate.h"
 #include "platform/network/ResourceRequest.h"
 #include "public/platform/WebCachePolicy.h"
 #include "public/platform/WebHTTPBody.h"
@@ -65,120 +64,123 @@
 
 } // namespace
 
-// The standard implementation of WebURLRequestPrivate, which maintains
-// ownership of a ResourceRequest instance.
-class WebURLRequestPrivateImpl final : public WebURLRequestPrivate {
-    USING_FAST_MALLOC(WebURLRequestPrivate);
-public:
-    WebURLRequestPrivateImpl()
-    {
-        m_resourceRequest = &m_resourceRequestAllocation;
-    }
+// The purpose of this struct is to permit allocating a ResourceRequest on the
+// heap, which is otherwise disallowed by DISALLOW_NEW_EXCEPT_PLACEMENT_NEW
+// annotation on ResourceRequest.
+struct WebURLRequest::ResourceRequestContainer {
+    ResourceRequestContainer() {}
+    explicit ResourceRequestContainer(const ResourceRequest& r) : resourceRequest(r) {}
 
-    WebURLRequestPrivateImpl(const WebURLRequestPrivate* p)
-        : m_resourceRequestAllocation(*p->m_resourceRequest)
-    {
-        m_resourceRequest = &m_resourceRequestAllocation;
-    }
-
-    virtual void dispose() { delete this; }
-
-private:
-    virtual ~WebURLRequestPrivateImpl() { }
-
-    ResourceRequest m_resourceRequestAllocation;
+    ResourceRequest resourceRequest;
 };
 
-void WebURLRequest::initialize()
+WebURLRequest::~WebURLRequest()
 {
-    assign(new WebURLRequestPrivateImpl());
 }
 
-void WebURLRequest::reset()
+WebURLRequest::WebURLRequest()
+    : m_ownedResourceRequest(new ResourceRequestContainer())
+    , m_resourceRequest(&m_ownedResourceRequest->resourceRequest)
 {
-    assign(0);
 }
 
-void WebURLRequest::assign(const WebURLRequest& r)
+WebURLRequest::WebURLRequest(const WebURLRequest& r)
+    : m_ownedResourceRequest(new ResourceRequestContainer(*r.m_resourceRequest))
+    , m_resourceRequest(&m_ownedResourceRequest->resourceRequest)
 {
+}
+
+WebURLRequest::WebURLRequest(const WebURL& url)
+    : WebURLRequest()
+{
+    setURL(url);
+}
+
+WebURLRequest& WebURLRequest::operator=(const WebURLRequest& r)
+{
+    // Copying subclasses that have different m_resourceRequest ownership
+    // semantics via this operator is just not supported.
+    DCHECK(m_ownedResourceRequest);
+    DCHECK(m_resourceRequest);
     if (&r != this)
-        assign(r.m_private ? new WebURLRequestPrivateImpl(r.m_private) : 0);
+        *m_resourceRequest = *r.m_resourceRequest;
+    return *this;
 }
 
 bool WebURLRequest::isNull() const
 {
-    return !m_private || m_private->m_resourceRequest->isNull();
+    return m_resourceRequest->isNull();
 }
 
 WebURL WebURLRequest::url() const
 {
-    return m_private->m_resourceRequest->url();
+    return m_resourceRequest->url();
 }
 
 void WebURLRequest::setURL(const WebURL& url)
 {
-    m_private->m_resourceRequest->setURL(url);
+    m_resourceRequest->setURL(url);
 }
 
 WebURL WebURLRequest::firstPartyForCookies() const
 {
-    return m_private->m_resourceRequest->firstPartyForCookies();
+    return m_resourceRequest->firstPartyForCookies();
 }
 
 void WebURLRequest::setFirstPartyForCookies(const WebURL& firstPartyForCookies)
 {
-    m_private->m_resourceRequest->setFirstPartyForCookies(firstPartyForCookies);
+    m_resourceRequest->setFirstPartyForCookies(firstPartyForCookies);
 }
 
 WebSecurityOrigin WebURLRequest::requestorOrigin() const
 {
-    return m_private->m_resourceRequest->requestorOrigin();
+    return m_resourceRequest->requestorOrigin();
 }
 
 void WebURLRequest::setRequestorOrigin(const WebSecurityOrigin& requestorOrigin)
 {
-    m_private->m_resourceRequest->setRequestorOrigin(requestorOrigin);
+    m_resourceRequest->setRequestorOrigin(requestorOrigin);
 }
 
 bool WebURLRequest::allowStoredCredentials() const
 {
-    return m_private->m_resourceRequest->allowStoredCredentials();
+    return m_resourceRequest->allowStoredCredentials();
 }
 
 void WebURLRequest::setAllowStoredCredentials(bool allowStoredCredentials)
 {
-    m_private->m_resourceRequest->setAllowStoredCredentials(allowStoredCredentials);
+    m_resourceRequest->setAllowStoredCredentials(allowStoredCredentials);
 }
 
 WebCachePolicy WebURLRequest::getCachePolicy() const
 {
-    return m_private->m_resourceRequest->getCachePolicy();
+    return m_resourceRequest->getCachePolicy();
 }
 
 void WebURLRequest::setCachePolicy(WebCachePolicy cachePolicy)
 {
-    m_private->m_resourceRequest->setCachePolicy(cachePolicy);
+    m_resourceRequest->setCachePolicy(cachePolicy);
 }
 
 WebString WebURLRequest::httpMethod() const
 {
-    return m_private->m_resourceRequest->httpMethod();
+    return m_resourceRequest->httpMethod();
 }
 
 void WebURLRequest::setHTTPMethod(const WebString& httpMethod)
 {
-    m_private->m_resourceRequest->setHTTPMethod(httpMethod);
+    m_resourceRequest->setHTTPMethod(httpMethod);
 }
 
 WebString WebURLRequest::httpHeaderField(const WebString& name) const
 {
-    return m_private->m_resourceRequest->httpHeaderField(name);
+    return m_resourceRequest->httpHeaderField(name);
 }
 
 void WebURLRequest::setHTTPHeaderField(const WebString& name, const WebString& value)
 {
     RELEASE_ASSERT(!equalIgnoringCase(name, "referer"));
-    m_private->m_resourceRequest->setHTTPHeaderField(name, value);
+    m_resourceRequest->setHTTPHeaderField(name, value);
 }
 
 void WebURLRequest::setHTTPReferrer(const WebString& webReferrer, WebReferrerPolicy referrerPolicy)
@@ -187,22 +189,22 @@
     // the null WTFString for referrer.
     ASSERT(Referrer::noReferrer() == String());
     String referrer = webReferrer.isEmpty() ? Referrer::noReferrer() : String(webReferrer);
-    m_private->m_resourceRequest->setHTTPReferrer(Referrer(referrer, static_cast<ReferrerPolicy>(referrerPolicy)));
+    m_resourceRequest->setHTTPReferrer(Referrer(referrer, static_cast<ReferrerPolicy>(referrerPolicy)));
 }
 
 void WebURLRequest::addHTTPHeaderField(const WebString& name, const WebString& value)
 {
-    m_private->m_resourceRequest->addHTTPHeaderField(name, value);
+    m_resourceRequest->addHTTPHeaderField(name, value);
 }
 
 void WebURLRequest::clearHTTPHeaderField(const WebString& name)
 {
-    m_private->m_resourceRequest->clearHTTPHeaderField(name);
+    m_resourceRequest->clearHTTPHeaderField(name);
 }
 
 void WebURLRequest::visitHTTPHeaderFields(WebHTTPHeaderVisitor* visitor) const
 {
-    const HTTPHeaderMap& map = m_private->m_resourceRequest->httpHeaderFields();
+    const HTTPHeaderMap& map = m_resourceRequest->httpHeaderFields();
     for (HTTPHeaderMap::const_iterator it = map.begin(); it != map.end(); ++it)
         visitor->visitHeader(it->key, it->value);
 }
@@ -213,199 +215,199 @@
     // before any ServiceWorker has a chance to operate, which means we're
     // revealing data to the SW that we ought to be hiding. Baby steps.
     // https://crbug.com/599597
-    if (m_private->m_resourceRequest->attachedCredential())
-        return WebHTTPBody(m_private->m_resourceRequest->attachedCredential());
-    return WebHTTPBody(m_private->m_resourceRequest->httpBody());
+    if (m_resourceRequest->attachedCredential())
+        return WebHTTPBody(m_resourceRequest->attachedCredential());
+    return WebHTTPBody(m_resourceRequest->httpBody());
 }
 
 void WebURLRequest::setHTTPBody(const WebHTTPBody& httpBody)
 {
-    m_private->m_resourceRequest->setHTTPBody(httpBody);
+    m_resourceRequest->setHTTPBody(httpBody);
 }
 
 WebHTTPBody WebURLRequest::attachedCredential() const
 {
-    return WebHTTPBody(m_private->m_resourceRequest->attachedCredential());
+    return WebHTTPBody(m_resourceRequest->attachedCredential());
 }
 
 void WebURLRequest::setAttachedCredential(const WebHTTPBody& attachedCredential)
 {
-    m_private->m_resourceRequest->setAttachedCredential(attachedCredential);
+    m_resourceRequest->setAttachedCredential(attachedCredential);
 }
 
 bool WebURLRequest::reportUploadProgress() const
 {
-    return m_private->m_resourceRequest->reportUploadProgress();
+    return m_resourceRequest->reportUploadProgress();
 }
 
 void WebURLRequest::setReportUploadProgress(bool reportUploadProgress)
 {
-    m_private->m_resourceRequest->setReportUploadProgress(reportUploadProgress);
+    m_resourceRequest->setReportUploadProgress(reportUploadProgress);
 }
 
 void WebURLRequest::setReportRawHeaders(bool reportRawHeaders)
 {
-    m_private->m_resourceRequest->setReportRawHeaders(reportRawHeaders);
+    m_resourceRequest->setReportRawHeaders(reportRawHeaders);
 }
 
 bool WebURLRequest::reportRawHeaders() const
 {
-    return m_private->m_resourceRequest->reportRawHeaders();
+    return m_resourceRequest->reportRawHeaders();
 }
 
 WebURLRequest::RequestContext WebURLRequest::getRequestContext() const
 {
-    return m_private->m_resourceRequest->requestContext();
+    return m_resourceRequest->requestContext();
 }
 
 WebURLRequest::FrameType WebURLRequest::getFrameType() const
 {
-    return m_private->m_resourceRequest->frameType();
+    return m_resourceRequest->frameType();
 }
 
 WebReferrerPolicy WebURLRequest::referrerPolicy() const
 {
-    return static_cast<WebReferrerPolicy>(m_private->m_resourceRequest->getReferrerPolicy());
+    return static_cast<WebReferrerPolicy>(m_resourceRequest->getReferrerPolicy());
 }
 
 void WebURLRequest::addHTTPOriginIfNeeded(const WebString& origin)
 {
-    m_private->m_resourceRequest->addHTTPOriginIfNeeded(WebSecurityOrigin::createFromString(origin));
+    m_resourceRequest->addHTTPOriginIfNeeded(WebSecurityOrigin::createFromString(origin));
 }
 
 bool WebURLRequest::hasUserGesture() const
 {
-    return m_private->m_resourceRequest->hasUserGesture();
+    return m_resourceRequest->hasUserGesture();
 }
 
 void WebURLRequest::setHasUserGesture(bool hasUserGesture)
 {
-    m_private->m_resourceRequest->setHasUserGesture(hasUserGesture);
+    m_resourceRequest->setHasUserGesture(hasUserGesture);
 }
 
 void WebURLRequest::setRequestContext(RequestContext requestContext)
 {
-    m_private->m_resourceRequest->setRequestContext(requestContext);
+    m_resourceRequest->setRequestContext(requestContext);
 }
 
 void WebURLRequest::setFrameType(FrameType frameType)
 {
-    m_private->m_resourceRequest->setFrameType(frameType);
+    m_resourceRequest->setFrameType(frameType);
 }
 
 int WebURLRequest::requestorID() const
 {
-    return m_private->m_resourceRequest->requestorID();
+    return m_resourceRequest->requestorID();
 }
 
 void WebURLRequest::setRequestorID(int requestorID)
 {
-    m_private->m_resourceRequest->setRequestorID(requestorID);
+    m_resourceRequest->setRequestorID(requestorID);
 }
 
 int WebURLRequest::requestorProcessID() const
 {
-    return m_private->m_resourceRequest->requestorProcessID();
+    return m_resourceRequest->requestorProcessID();
 }
 
 void WebURLRequest::setRequestorProcessID(int requestorProcessID)
 {
-    m_private->m_resourceRequest->setRequestorProcessID(requestorProcessID);
+    m_resourceRequest->setRequestorProcessID(requestorProcessID);
 }
 
 int WebURLRequest::appCacheHostID() const
 {
-    return m_private->m_resourceRequest->appCacheHostID();
+    return m_resourceRequest->appCacheHostID();
 }
 
 void WebURLRequest::setAppCacheHostID(int appCacheHostID)
 {
-    m_private->m_resourceRequest->setAppCacheHostID(appCacheHostID);
+    m_resourceRequest->setAppCacheHostID(appCacheHostID);
 }
 
 bool WebURLRequest::downloadToFile() const
 {
-    return m_private->m_resourceRequest->downloadToFile();
+    return m_resourceRequest->downloadToFile();
 }
 
 void WebURLRequest::setDownloadToFile(bool downloadToFile)
 {
-    m_private->m_resourceRequest->setDownloadToFile(downloadToFile);
+    m_resourceRequest->setDownloadToFile(downloadToFile);
 }
 
 bool WebURLRequest::useStreamOnResponse() const
 {
-    return m_private->m_resourceRequest->useStreamOnResponse();
+    return m_resourceRequest->useStreamOnResponse();
 }
 
 void WebURLRequest::setUseStreamOnResponse(bool useStreamOnResponse)
 {
-    m_private->m_resourceRequest->setUseStreamOnResponse(useStreamOnResponse);
+    m_resourceRequest->setUseStreamOnResponse(useStreamOnResponse);
 }
 
 WebURLRequest::SkipServiceWorker WebURLRequest::skipServiceWorker() const
 {
-    return m_private->m_resourceRequest->skipServiceWorker();
+    return m_resourceRequest->skipServiceWorker();
 }
 
 void WebURLRequest::setSkipServiceWorker(WebURLRequest::SkipServiceWorker skipServiceWorker)
 {
-    m_private->m_resourceRequest->setSkipServiceWorker(skipServiceWorker);
+    m_resourceRequest->setSkipServiceWorker(skipServiceWorker);
 }
 
 bool WebURLRequest::shouldResetAppCache() const
 {
-    return m_private->m_resourceRequest->shouldResetAppCache();
+    return m_resourceRequest->shouldResetAppCache();
 }
 
 void WebURLRequest::setShouldResetAppCache(bool setShouldResetAppCache)
 {
-    m_private->m_resourceRequest->setShouldResetAppCache(setShouldResetAppCache);
+    m_resourceRequest->setShouldResetAppCache(setShouldResetAppCache);
 }
 
 WebURLRequest::FetchRequestMode WebURLRequest::getFetchRequestMode() const
 {
-    return m_private->m_resourceRequest->fetchRequestMode();
+    return m_resourceRequest->fetchRequestMode();
 }
 
 void WebURLRequest::setFetchRequestMode(WebURLRequest::FetchRequestMode mode)
 {
-    return m_private->m_resourceRequest->setFetchRequestMode(mode);
+    return m_resourceRequest->setFetchRequestMode(mode);
 }
 
 WebURLRequest::FetchCredentialsMode WebURLRequest::getFetchCredentialsMode() const
 {
-    return m_private->m_resourceRequest->fetchCredentialsMode();
+    return m_resourceRequest->fetchCredentialsMode();
 }
 
 void WebURLRequest::setFetchCredentialsMode(WebURLRequest::FetchCredentialsMode mode)
 {
-    return m_private->m_resourceRequest->setFetchCredentialsMode(mode);
+    return m_resourceRequest->setFetchCredentialsMode(mode);
 }
 
 WebURLRequest::FetchRedirectMode WebURLRequest::getFetchRedirectMode() const
 {
-    return m_private->m_resourceRequest->fetchRedirectMode();
+    return m_resourceRequest->fetchRedirectMode();
 }
 
 void WebURLRequest::setFetchRedirectMode(WebURLRequest::FetchRedirectMode redirect)
 {
-    return m_private->m_resourceRequest->setFetchRedirectMode(redirect);
+    return m_resourceRequest->setFetchRedirectMode(redirect);
 }
 
 WebURLRequest::LoFiState WebURLRequest::getLoFiState() const
 {
-    return m_private->m_resourceRequest->loFiState();
+    return m_resourceRequest->loFiState();
 }
 
 void WebURLRequest::setLoFiState(WebURLRequest::LoFiState loFiState)
 {
-    return m_private->m_resourceRequest->setLoFiState(loFiState);
+    return m_resourceRequest->setLoFiState(loFiState);
 }
 
 WebURLRequest::ExtraData* WebURLRequest::getExtraData() const
 {
-    RefPtr<ResourceRequest::ExtraData> data = m_private->m_resourceRequest->getExtraData();
+    RefPtr<ResourceRequest::ExtraData> data = m_resourceRequest->getExtraData();
     if (!data)
         return 0;
     return static_cast<ExtraDataContainer*>(data.get())->getExtraData();
@@ -413,84 +415,74 @@
 
 void WebURLRequest::setExtraData(WebURLRequest::ExtraData* extraData)
 {
-    m_private->m_resourceRequest->setExtraData(ExtraDataContainer::create(extraData));
+    m_resourceRequest->setExtraData(ExtraDataContainer::create(extraData));
 }
 
 ResourceRequest& WebURLRequest::toMutableResourceRequest()
 {
-    ASSERT(m_private);
-    ASSERT(m_private->m_resourceRequest);
-
-    return *m_private->m_resourceRequest;
+    DCHECK(m_resourceRequest);
+    return *m_resourceRequest;
 }
 
 WebURLRequest::Priority WebURLRequest::getPriority() const
 {
     return static_cast<WebURLRequest::Priority>(
-        m_private->m_resourceRequest->priority());
+        m_resourceRequest->priority());
 }
 
 void WebURLRequest::setPriority(WebURLRequest::Priority priority)
 {
-    m_private->m_resourceRequest->setPriority(
+    m_resourceRequest->setPriority(
         static_cast<ResourceLoadPriority>(priority));
 }
 
 bool WebURLRequest::checkForBrowserSideNavigation() const
 {
-    return m_private->m_resourceRequest->checkForBrowserSideNavigation();
+    return m_resourceRequest->checkForBrowserSideNavigation();
 }
 
 void WebURLRequest::setCheckForBrowserSideNavigation(bool check)
 {
-    m_private->m_resourceRequest->setCheckForBrowserSideNavigation(check);
+    m_resourceRequest->setCheckForBrowserSideNavigation(check);
 }
 
 double WebURLRequest::uiStartTime() const
 {
-    return m_private->m_resourceRequest->uiStartTime();
+    return m_resourceRequest->uiStartTime();
 }
 
 void WebURLRequest::setUiStartTime(double time)
 {
-    m_private->m_resourceRequest->setUIStartTime(time);
+    m_resourceRequest->setUIStartTime(time);
 }
 
 bool WebURLRequest::isExternalRequest() const
 {
-    return m_private->m_resourceRequest->isExternalRequest();
+    return m_resourceRequest->isExternalRequest();
 }
 
 WebURLRequest::InputToLoadPerfMetricReportPolicy WebURLRequest::inputPerfMetricReportPolicy() const
 {
     return static_cast<WebURLRequest::InputToLoadPerfMetricReportPolicy>(
-        m_private->m_resourceRequest->inputPerfMetricReportPolicy());
+        m_resourceRequest->inputPerfMetricReportPolicy());
 }
 
 void WebURLRequest::setInputPerfMetricReportPolicy(
     WebURLRequest::InputToLoadPerfMetricReportPolicy policy)
 {
-    m_private->m_resourceRequest->setInputPerfMetricReportPolicy(
+    m_resourceRequest->setInputPerfMetricReportPolicy(
         static_cast<blink::InputToLoadPerfMetricReportPolicy>(policy));
 }
 
 const ResourceRequest& WebURLRequest::toResourceRequest() const
 {
-    ASSERT(m_private);
-    ASSERT(m_private->m_resourceRequest);
-
-    return *m_private->m_resourceRequest;
+    DCHECK(m_resourceRequest);
+    return *m_resourceRequest;
 }
 
-void WebURLRequest::assign(WebURLRequestPrivate* p)
+WebURLRequest::WebURLRequest(ResourceRequest& r)
+    : m_resourceRequest(&r)
 {
-    // Subclasses may call this directly so a self-assignment check is needed
-    // here as well as in the public assign method.
-    if (m_private == p)
-        return;
-    if (m_private)
-        m_private->dispose();
-    m_private = p;
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/platform/exported/WebURLRequestPrivate.h b/third_party/WebKit/Source/platform/exported/WebURLRequestPrivate.h
deleted file mode 100644
index 3163a9b..0000000
--- a/third_party/WebKit/Source/platform/exported/WebURLRequestPrivate.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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 WebURLRequestPrivate_h
-#define WebURLRequestPrivate_h
-
-#include "wtf/Noncopyable.h"
-
-namespace blink {
-
-class ResourceRequest;
-
-class WebURLRequestPrivate {
-    WTF_MAKE_NONCOPYABLE(WebURLRequestPrivate);
-public:
-    WebURLRequestPrivate()
-        : m_resourceRequest(0)
-    {
-    }
-
-    // Called by WebURLRequest when it no longer needs this object.
-    virtual void dispose() = 0;
-
-    ResourceRequest* m_resourceRequest;
-};
-
-} // namespace blink
-
-#endif
diff --git a/third_party/WebKit/Source/platform/exported/WebURLResponse.cpp b/third_party/WebKit/Source/platform/exported/WebURLResponse.cpp
index 0ffcd8b..f329712 100644
--- a/third_party/WebKit/Source/platform/exported/WebURLResponse.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebURLResponse.cpp
@@ -72,7 +72,7 @@
 struct WebURLResponse::ResourceResponseContainer {
     ResourceResponseContainer() {}
 
-    ResourceResponseContainer(const ResourceResponse& r)
+    explicit ResourceResponseContainer(const ResourceResponse& r)
         : resourceResponse(r)
     {
     }
@@ -512,10 +512,9 @@
     m_resourceResponse->setExtraData(ExtraDataContainer::create(extraData));
 }
 
-WebURLResponse::WebURLResponse(ResourceResponse* p)
-    : m_resourceResponse(p)
+WebURLResponse::WebURLResponse(ResourceResponse& r)
+    : m_resourceResponse(&r)
 {
-    DCHECK(p);
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/platform/exported/WrappedResourceRequest.h b/third_party/WebKit/Source/platform/exported/WrappedResourceRequest.h
index a81d5f79..67277e3 100644
--- a/third_party/WebKit/Source/platform/exported/WrappedResourceRequest.h
+++ b/third_party/WebKit/Source/platform/exported/WrappedResourceRequest.h
@@ -31,53 +31,28 @@
 #ifndef WrappedResourceRequest_h
 #define WrappedResourceRequest_h
 
-#include "platform/exported/WebURLRequestPrivate.h"
 #include "public/platform/WebURLRequest.h"
 #include "wtf/Allocator.h"
 #include "wtf/Noncopyable.h"
 
 namespace blink {
 
+// WrappedResourceRequest doesn't take ownership of given ResourceRequest,
+// but just holds a pointer to it. It is not copyable.
 class WrappedResourceRequest : public WebURLRequest {
+    WTF_MAKE_NONCOPYABLE(WrappedResourceRequest);
 public:
-    ~WrappedResourceRequest()
+    ~WrappedResourceRequest() {}
+
+    explicit WrappedResourceRequest(ResourceRequest& resourceRequest)
+        : WebURLRequest(resourceRequest)
     {
-        reset(); // Need to drop reference to m_handle
     }
 
-    WrappedResourceRequest() { }
-
-    WrappedResourceRequest(ResourceRequest& resourceRequest)
+    explicit WrappedResourceRequest(const ResourceRequest& resourceRequest)
+        : WrappedResourceRequest(const_cast<ResourceRequest&>(resourceRequest))
     {
-        bind(resourceRequest);
     }
-
-    WrappedResourceRequest(const ResourceRequest& resourceRequest)
-    {
-        bind(resourceRequest);
-    }
-
-    void bind(ResourceRequest& resourceRequest)
-    {
-        m_handle.m_resourceRequest = &resourceRequest;
-        assign(&m_handle);
-    }
-
-    void bind(const ResourceRequest& resourceRequest)
-    {
-        bind(*const_cast<ResourceRequest*>(&resourceRequest));
-    }
-
-private:
-    class Handle final : public WebURLRequestPrivate {
-        DISALLOW_NEW();
-    public:
-        Handle() { }
-
-        virtual void dispose() { m_resourceRequest = 0; }
-    };
-
-    Handle m_handle;
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/platform/exported/WrappedResourceResponse.h b/third_party/WebKit/Source/platform/exported/WrappedResourceResponse.h
index 493341f5..519e3f0 100644
--- a/third_party/WebKit/Source/platform/exported/WrappedResourceResponse.h
+++ b/third_party/WebKit/Source/platform/exported/WrappedResourceResponse.h
@@ -44,7 +44,7 @@
     ~WrappedResourceResponse() {}
 
     explicit WrappedResourceResponse(ResourceResponse& resourceResponse)
-        : WebURLResponse(&resourceResponse)
+        : WebURLResponse(resourceResponse)
     {
     }
 
diff --git a/third_party/WebKit/Source/platform/graphics/ContiguousContainer.cpp b/third_party/WebKit/Source/platform/graphics/ContiguousContainer.cpp
index cb42fef..73a3929 100644
--- a/third_party/WebKit/Source/platform/graphics/ContiguousContainer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/ContiguousContainer.cpp
@@ -171,6 +171,14 @@
     std::swap(m_maxObjectSize, other.m_maxObjectSize);
 }
 
+void ContiguousContainerBase::shrinkToFit()
+{
+    while (m_endIndex < m_buffers.size() - 1) {
+        DCHECK(m_buffers.last()->isEmpty());
+        m_buffers.removeLast();
+    }
+}
+
 ContiguousContainerBase::Buffer*
 ContiguousContainerBase::allocateNewBufferForNextAllocation(size_t bufferSize, const char* typeName)
 {
diff --git a/third_party/WebKit/Source/platform/graphics/ContiguousContainer.h b/third_party/WebKit/Source/platform/graphics/ContiguousContainer.h
index 95d21b2d..98bce19 100644
--- a/third_party/WebKit/Source/platform/graphics/ContiguousContainer.h
+++ b/third_party/WebKit/Source/platform/graphics/ContiguousContainer.h
@@ -60,6 +60,10 @@
     void clear();
     void swap(ContiguousContainerBase&);
 
+    // Discards excess buffer capacity. Intended for use when no more appending
+    // is anticipated.
+    void shrinkToFit();
+
     Vector<void*> m_elements;
 
 private:
@@ -142,6 +146,7 @@
     using ContiguousContainerBase::capacityInBytes;
     using ContiguousContainerBase::usedCapacityInBytes;
     using ContiguousContainerBase::memoryUsageInBytes;
+    using ContiguousContainerBase::shrinkToFit;
 
     iterator begin() { return iterator(m_elements.begin()); }
     iterator end() { return iterator(m_elements.end()); }
diff --git a/third_party/WebKit/Source/platform/graphics/ExpensiveCanvasHeuristicParameters.h b/third_party/WebKit/Source/platform/graphics/ExpensiveCanvasHeuristicParameters.h
index 67033a1..c69af79a 100644
--- a/third_party/WebKit/Source/platform/graphics/ExpensiveCanvasHeuristicParameters.h
+++ b/third_party/WebKit/Source/platform/graphics/ExpensiveCanvasHeuristicParameters.h
@@ -65,7 +65,7 @@
     // Disable Acceleration heuristic parameters
     //===========================================
 
-    GetImageDataForcesNoAcceleration = 1,
+    GetImageDataForcesNoAcceleration = 0, // Disabled for crbug.com/626188
 
 }; // enum
 
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h
index 3d6f9be..f208a5ea 100644
--- a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h
+++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h
@@ -42,7 +42,6 @@
 #include "platform/graphics/ImageOrientation.h"
 #include "platform/graphics/PaintInvalidationReason.h"
 #include "platform/graphics/filters/FilterOperations.h"
-#include "platform/graphics/paint/CachedDisplayItem.h"
 #include "platform/graphics/paint/DisplayItemClient.h"
 #include "platform/graphics/paint/PaintController.h"
 #include "platform/heap/Handle.h"
diff --git a/third_party/WebKit/Source/platform/graphics/paint/CachedDisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/CachedDisplayItem.h
deleted file mode 100644
index 24b2888..0000000
--- a/third_party/WebKit/Source/platform/graphics/paint/CachedDisplayItem.h
+++ /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.
-
-#ifndef CachedDisplayItem_h
-#define CachedDisplayItem_h
-
-#include "platform/graphics/paint/DisplayItem.h"
-#include "wtf/Assertions.h"
-
-namespace blink {
-
-// A placeholder of a DrawingDisplayItem or a subtree in the new paint DisplayItemList,
-// to indicate that the DrawingDisplayItem/subtree has not been changed and should be replaced with
-// the cached DrawingDisplayItem/subtree when merging new paint list to cached paint list.
-class CachedDisplayItem final : public DisplayItem {
-public:
-    CachedDisplayItem(const DisplayItemClient& client, Type type)
-        : DisplayItem(client, type, sizeof(*this))
-    {
-        ASSERT(isCachedType(type));
-    }
-
-private:
-    // CachedDisplayItem is never replayed or appended to WebDisplayItemList.
-    void replay(GraphicsContext&) const final { ASSERT_NOT_REACHED(); }
-    void appendToWebDisplayItemList(const IntRect&, WebDisplayItemList*) const final { ASSERT_NOT_REACHED(); }
-};
-
-} // namespace blink
-
-#endif // CachedDisplayItem_h
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.cpp b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.cpp
index cb0b833..3f2bee5 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.cpp
@@ -185,8 +185,6 @@
 {
     if (isDrawingType(type))
         return drawingTypeAsDebugString(type);
-    if (isCachedDrawingType(type))
-        return "Cached" + drawingTypeAsDebugString(cachedDrawingTypeToDrawingType(type));
 
     if (isForeignLayerType(type))
         return foreignLayerTypeAsDebugString(type);
@@ -224,7 +222,6 @@
         DEBUG_STRING_CASE(EndClipPath);
         DEBUG_STRING_CASE(Subsequence);
         DEBUG_STRING_CASE(EndSubsequence);
-        DEBUG_STRING_CASE(CachedSubsequence);
         DEBUG_STRING_CASE(UninitializedType);
         DEFAULT_CASE;
     }
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h
index 72c2104f..93ae1bf 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h
@@ -116,9 +116,6 @@
         ReflectionMask,
         DrawingLast = ReflectionMask,
 
-        CachedDrawingFirst,
-        CachedDrawingLast = CachedDrawingFirst + DrawingLast - DrawingFirst,
-
         ForeignLayerFirst,
         ForeignLayerCanvas = ForeignLayerFirst,
         ForeignLayerPlugin,
@@ -184,7 +181,6 @@
 
         Subsequence,
         EndSubsequence,
-        CachedSubsequence,
 
         UninitializedType,
         TypeLast = UninitializedType
@@ -224,33 +220,11 @@
             : client(client)
             , type(type) { }
 
-        bool matches(const DisplayItem& item) const
-        {
-            // We should always convert to non-cached types before matching.
-            ASSERT(!isCachedType(item.m_type));
-            ASSERT(!isCachedType(type));
-            return &client == item.m_client && type == item.m_type;
-        }
-
         const DisplayItemClient& client;
         const Type type;
     };
 
-    // Convert cached type to non-cached type (e.g., Type::CachedSVGImage -> Type::SVGImage).
-    static Type nonCachedType(Type type)
-    {
-        if (isCachedDrawingType(type))
-            return cachedDrawingTypeToDrawingType(type);
-        if (type == CachedSubsequence)
-            return Subsequence;
-        return type;
-    }
-
-    // Return the Id with cached type converted to non-cached type.
-    Id nonCachedId() const
-    {
-        return Id(*m_client, nonCachedType(m_type));
-    }
+    Id getId() const { return Id(*m_client, m_type); }
 
     virtual void replay(GraphicsContext&) const { }
 
@@ -303,8 +277,6 @@
 
     DEFINE_CATEGORY_METHODS(Drawing)
     DEFINE_PAINT_PHASE_CONVERSION_METHOD(Drawing)
-    DEFINE_CATEGORY_METHODS(CachedDrawing)
-    DEFINE_CONVERSION_METHODS(Drawing, drawing, CachedDrawing, cachedDrawing)
 
     DEFINE_CATEGORY_METHODS(ForeignLayer)
 
@@ -321,8 +293,6 @@
 
     DEFINE_PAIRED_CATEGORY_METHODS(Transform3D, transform3D)
 
-    static bool isCachedType(Type type) { return isCachedDrawingType(type) || type == CachedSubsequence; }
-    bool isCached() const { return isCachedType(m_type); }
     static bool isCacheableType(Type type) { return isDrawingType(type) || type == Subsequence; }
     bool isCacheable() const { return !skippedCache() && isCacheableType(m_type); }
 
@@ -383,6 +353,16 @@
 #endif
 };
 
+inline bool operator==(const DisplayItem::Id& a, const DisplayItem::Id& b)
+{
+    return a.client == b.client && a.type == b.type;
+}
+
+inline bool operator!=(const DisplayItem::Id& a, const DisplayItem::Id& b)
+{
+    return !(a == b);
+}
+
 class PLATFORM_EXPORT PairedBeginDisplayItem : public DisplayItem {
 protected:
     PairedBeginDisplayItem(const DisplayItemClient& client, Type type, size_t derivedSize) : DisplayItem(client, type, derivedSize) { }
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp
index d7292ad6..c3f23f1 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp
@@ -14,12 +14,8 @@
 
 namespace blink {
 
-DisplayItem& DisplayItemList::appendByMoving(DisplayItem& item, const IntRect& visualRect, SkPictureGpuAnalyzer& gpuAnalyzer)
+DisplayItem& DisplayItemList::appendByMoving(DisplayItem& item)
 {
-    // No reason to continue the analysis once we have a veto.
-    if (gpuAnalyzer.suitableForGpuRasterization())
-        item.analyzeForGpuRasterization(gpuAnalyzer);
-
 #ifndef NDEBUG
     String originalDebugString = item.asDebugString();
 #endif
@@ -33,7 +29,6 @@
     // Save original debug string in the old item to help debugging.
     item.setClientDebugString(originalDebugString);
 #endif
-    appendVisualRect(visualRect);
     return result;
 }
 
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.h b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.h
index df66a435..166619c 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.h
@@ -43,7 +43,7 @@
         return *this;
     }
 
-    DisplayItem& appendByMoving(DisplayItem&, const IntRect& visualRect, SkPictureGpuAnalyzer&);
+    DisplayItem& appendByMoving(DisplayItem&);
 
     IntRect visualRect(unsigned index) const
     {
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DrawingRecorder.cpp b/third_party/WebKit/Source/platform/graphics/paint/DrawingRecorder.cpp
index d75455f..eefcd8f 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/DrawingRecorder.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/DrawingRecorder.cpp
@@ -7,31 +7,11 @@
 #include "platform/RuntimeEnabledFeatures.h"
 #include "platform/graphics/GraphicsContext.h"
 #include "platform/graphics/GraphicsLayer.h"
-#include "platform/graphics/paint/CachedDisplayItem.h"
 #include "platform/graphics/paint/PaintController.h"
 #include "third_party/skia/include/core/SkPicture.h"
 
 namespace blink {
 
-bool DrawingRecorder::useCachedDrawingIfPossible(GraphicsContext& context, const DisplayItemClient& client, DisplayItem::Type type)
-{
-    ASSERT(DisplayItem::isDrawingType(type));
-
-    if (!context.getPaintController().clientCacheIsValid(client))
-        return false;
-
-    context.getPaintController().createAndAppend<CachedDisplayItem>(client, DisplayItem::drawingTypeToCachedDrawingType(type));
-
-#if ENABLE(ASSERT)
-    // When under-invalidation checking is enabled, we output CachedDrawing display item
-    // followed by the display item containing forced painting.
-    if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled())
-        return false;
-#endif
-
-    return true;
-}
-
 DrawingRecorder::DrawingRecorder(GraphicsContext& context, const DisplayItemClient& displayItemClient, DisplayItem::Type displayItemType, const FloatRect& floatCullRect)
     : m_context(context)
     , m_displayItemClient(displayItemClient)
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DrawingRecorder.h b/third_party/WebKit/Source/platform/graphics/paint/DrawingRecorder.h
index 5816312..29f7184 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/DrawingRecorder.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/DrawingRecorder.h
@@ -8,7 +8,9 @@
 #include "platform/PlatformExport.h"
 
 #include "platform/geometry/FloatRect.h"
+#include "platform/graphics/GraphicsContext.h"
 #include "platform/graphics/paint/DrawingDisplayItem.h"
+#include "platform/graphics/paint/PaintController.h"
 #include "wtf/Allocator.h"
 #include "wtf/Noncopyable.h"
 
@@ -24,7 +26,10 @@
     DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
     WTF_MAKE_NONCOPYABLE(DrawingRecorder);
 public:
-    static bool useCachedDrawingIfPossible(GraphicsContext&, const DisplayItemClient&, DisplayItem::Type);
+    static bool useCachedDrawingIfPossible(GraphicsContext& context, const DisplayItemClient& client, DisplayItem::Type type)
+    {
+        return context.getPaintController().useCachedDrawingIfPossible(client, type);
+    }
 
     DrawingRecorder(GraphicsContext&, const DisplayItemClient&, DisplayItem::Type, const FloatRect& cullRect);
     ~DrawingRecorder();
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp
index 46b1bde..24e041f2 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp
@@ -31,6 +31,81 @@
     return m_currentPaintArtifact;
 }
 
+bool PaintController::useCachedDrawingIfPossible(const DisplayItemClient& client, DisplayItem::Type type)
+{
+    DCHECK(DisplayItem::isDrawingType(type));
+
+    if (displayItemConstructionIsDisabled())
+        return false;
+
+    if (!clientCacheIsValid(client))
+        return false;
+
+#if ENABLE(ASSERT)
+    // When under-invalidation checking is enabled, we output CachedDrawing display item
+    // followed by the display item containing forced painting.
+    if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled())
+        return false;
+#endif
+
+    DisplayItemList::iterator cachedItem = findCachedItem(DisplayItem::Id(client, type));
+    if (cachedItem == m_currentPaintArtifact.getDisplayItemList().end()) {
+        NOTREACHED();
+        return false;
+    }
+
+    ++m_numCachedNewItems;
+    ensureNewDisplayItemListInitialCapacity();
+    processNewItem(m_newDisplayItemList.appendByMoving(*cachedItem));
+
+    m_nextItemToMatch = cachedItem + 1;
+    // Items before m_nextItemToMatch have been copied so we don't need to index them.
+    if (m_nextItemToMatch - m_nextItemToIndex > 0)
+        m_nextItemToIndex = m_nextItemToMatch;
+
+    return true;
+}
+
+bool PaintController::useCachedSubsequenceIfPossible(const DisplayItemClient& client)
+{
+    // TODO(crbug.com/596983): Implement subsequence caching for spv2.
+    // The problem is in copyCachedSubsequence() which fails to handle PaintChunkProperties
+    // of chunks containing cached display items. We need to find the previous
+    // PaintChunkProperties and ensure they are valid in the current paint property tree.
+    if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
+        return false;
+
+    if (displayItemConstructionIsDisabled() || subsequenceCachingIsDisabled())
+        return false;
+
+    if (!clientCacheIsValid(client))
+        return false;
+
+#if ENABLE(ASSERT)
+    // When under-invalidation checking is enabled, we output CachedDrawing display item
+    // followed by the display item containing forced painting.
+    if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled())
+        return false;
+#endif
+
+    DisplayItemList::iterator cachedItem = findCachedItem(DisplayItem::Id(client, DisplayItem::Subsequence));
+    if (cachedItem == m_currentPaintArtifact.getDisplayItemList().end()) {
+        NOTREACHED();
+        return false;
+    }
+
+    // |cachedItem| will point to the first item after the subsequence or end of the current list.
+    ensureNewDisplayItemListInitialCapacity();
+    copyCachedSubsequence(cachedItem);
+
+    m_nextItemToMatch = cachedItem;
+    // Items before |cachedItem| have been copied so we don't need to index them.
+    if (cachedItem - m_nextItemToIndex > 0)
+        m_nextItemToIndex = cachedItem;
+
+    return true;
+}
+
 bool PaintController::lastDisplayItemIsNoopBegin() const
 {
     if (m_newDisplayItemList.isEmpty())
@@ -63,11 +138,10 @@
 void PaintController::processNewItem(DisplayItem& displayItem)
 {
     DCHECK(!m_constructionDisabled);
-    DCHECK(!skippingCache() || !displayItem.isCached());
 
 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS
     if (!skippingCache()) {
-        if (displayItem.isCacheable() || displayItem.isCached()) {
+        if (displayItem.isCacheable()) {
             // Mark the client shouldKeepAlive under this PaintController.
             // The status will end after the new display items are committed.
             displayItem.client().beginShouldKeepAlive(this);
@@ -88,9 +162,6 @@
     }
 #endif
 
-    if (displayItem.isCached())
-        ++m_numCachedNewItems;
-
 #if DCHECK_IS_ON()
     // Verify noop begin/end pairs have been removed.
     if (m_newDisplayItemList.size() >= 2 && displayItem.isEnd()) {
@@ -104,7 +175,7 @@
         displayItem.setSkippedCache();
 
 #if DCHECK_IS_ON()
-    size_t index = findMatchingItemFromIndex(displayItem.nonCachedId(), m_newDisplayItemIndicesByClient, m_newDisplayItemList);
+    size_t index = findMatchingItemFromIndex(displayItem.getId(), m_newDisplayItemIndicesByClient, m_newDisplayItemList);
     if (index != kNotFound) {
 #ifndef NDEBUG
         showDebugData();
@@ -158,7 +229,7 @@
     for (size_t index : indices) {
         const DisplayItem& existingItem = list[index];
         DCHECK(!existingItem.hasValidClient() || existingItem.client() == id.client);
-        if (id.matches(existingItem))
+        if (id == existingItem.getId())
             return index;
     }
 
@@ -176,54 +247,88 @@
     indices.append(index);
 }
 
-struct PaintController::OutOfOrderIndexContext {
-    STACK_ALLOCATED();
-    OutOfOrderIndexContext(DisplayItemList::iterator begin) : nextItemToIndex(begin) { }
-
-    DisplayItemList::iterator nextItemToIndex;
-    DisplayItemIndicesByClientMap displayItemIndicesByClient;
-};
-
-DisplayItemList::iterator PaintController::findOutOfOrderCachedItem(const DisplayItem::Id& id, OutOfOrderIndexContext& context)
+DisplayItemList::iterator PaintController::findCachedItem(const DisplayItem::Id& id)
 {
     DCHECK(clientCacheIsValid(id.client));
 
-    size_t foundIndex = findMatchingItemFromIndex(id, context.displayItemIndicesByClient, m_currentPaintArtifact.getDisplayItemList());
-    if (foundIndex != kNotFound)
-        return m_currentPaintArtifact.getDisplayItemList().begin() + foundIndex;
+    // Try to find the item sequentially first. This is fast if the current list and the new list are in
+    // the same order around the new item. If found, we don't need to update and lookup the index.
+    DisplayItemList::iterator end = m_currentPaintArtifact.getDisplayItemList().end();
+    DisplayItemList::iterator it = m_nextItemToMatch;
+    for (; it != end; ++it) {
+        // We encounter an item that has already been copied which indicates we can't do sequential matching.
+        if (!it->hasValidClient())
+            break;
+        if (id == it->getId()) {
+#if DCHECK_IS_ON()
+            ++m_numSequentialMatches;
+#endif
+            return it;
+        }
+        // We encounter a different cacheable item which also indicates we can't do sequential matching.
+        if (it->isCacheable())
+            break;
+    }
 
-    return findOutOfOrderCachedItemForward(id, context);
+    size_t foundIndex = findMatchingItemFromIndex(id, m_outOfOrderItemIndices, m_currentPaintArtifact.getDisplayItemList());
+    if (foundIndex != kNotFound) {
+#if DCHECK_IS_ON()
+        ++m_numOutOfOrderMatches;
+#endif
+        return m_currentPaintArtifact.getDisplayItemList().begin() + foundIndex;
+    }
+
+    return findOutOfOrderCachedItemForward(id);
 }
 
 // Find forward for the item and index all skipped indexable items.
-DisplayItemList::iterator PaintController::findOutOfOrderCachedItemForward(const DisplayItem::Id& id, OutOfOrderIndexContext& context)
+DisplayItemList::iterator PaintController::findOutOfOrderCachedItemForward(const DisplayItem::Id& id)
 {
-    DisplayItemList::iterator currentEnd = m_currentPaintArtifact.getDisplayItemList().end();
-    for (; context.nextItemToIndex != currentEnd; ++context.nextItemToIndex) {
-        const DisplayItem& item = *context.nextItemToIndex;
+    DisplayItemList::iterator end = m_currentPaintArtifact.getDisplayItemList().end();
+    for (DisplayItemList::iterator it = m_nextItemToIndex; it != end; ++it) {
+        const DisplayItem& item = *it;
         DCHECK(item.hasValidClient());
-        if (id.matches(item))
-            return context.nextItemToIndex++;
-        if (item.isCacheable())
-            addItemToIndexIfNeeded(item, context.nextItemToIndex - m_currentPaintArtifact.getDisplayItemList().begin(), context.displayItemIndicesByClient);
+        if (id == item.getId()) {
+#if DCHECK_IS_ON()
+            ++m_numSequentialMatches;
+#endif
+            return it;
+        }
+        if (item.isCacheable()) {
+#if DCHECK_IS_ON()
+            ++m_numIndexedItems;
+#endif
+            addItemToIndexIfNeeded(item, it - m_currentPaintArtifact.getDisplayItemList().begin(), m_outOfOrderItemIndices);
+        }
     }
-    return currentEnd;
+
+#ifndef NDEBUG
+    showDebugData();
+    LOG(ERROR) << id.client.debugName() << ":" << DisplayItem::typeAsDebugString(id.type) << " not found in current display item list";
+#endif
+    NOTREACHED();
+    // We did not find the cached display item. This should be impossible, but may occur if there is a bug
+    // in the system, such as under-invalidation, incorrect cache checking or duplicate display ids.
+    // In this case, the caller should fall back to repaint the display item.
+    return end;
 }
 
-void PaintController::copyCachedSubsequence(const DisplayItemList& currentList, DisplayItemList::iterator& currentIt, DisplayItemList& updatedList, SkPictureGpuAnalyzer& gpuAnalyzer)
+// On return, |it| points to the item after the EndSubsequence item of the subsequence.
+void PaintController::copyCachedSubsequence(DisplayItemList::iterator& it)
 {
-    DCHECK(currentIt->getType() == DisplayItem::Subsequence);
-    DisplayItem::Id endSubsequenceId(currentIt->client(), DisplayItem::EndSubsequence);
+    DCHECK(it->getType() == DisplayItem::Subsequence);
+    DisplayItem::Id endSubsequenceId(it->client(), DisplayItem::EndSubsequence);
     do {
         // We should always find the EndSubsequence display item.
-        DCHECK(currentIt != m_currentPaintArtifact.getDisplayItemList().end());
-        DCHECK(currentIt->hasValidClient());
+        DCHECK(it != m_currentPaintArtifact.getDisplayItemList().end());
+        DCHECK(it->hasValidClient());
 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS
-        CHECK(currentIt->client().isAlive());
+        CHECK(it->client().isAlive());
 #endif
-        updatedList.appendByMoving(*currentIt, currentList.visualRect(currentIt - m_currentPaintArtifact.getDisplayItemList().begin()), gpuAnalyzer);
-        ++currentIt;
-    } while (!endSubsequenceId.matches(updatedList.last()));
+        ++m_numCachedNewItems;
+        processNewItem(m_newDisplayItemList.appendByMoving(*it));
+        ++it;
+    } while (endSubsequenceId != m_newDisplayItemList.last().getId());
 }
 
 static IntRect visualRectForDisplayItem(const DisplayItem& displayItem, const LayoutSize& offsetFromLayoutObject)
@@ -233,17 +338,12 @@
     return enclosingIntRect(visualRect);
 }
 
-// Update the existing display items by removing invalidated entries, updating
-// repainted ones, and appending new items.
-// - For cached drawing display item, copy the corresponding cached DrawingDisplayItem;
-// - For cached subsequence display item, copy the cached display items between the
-//   corresponding SubsequenceDisplayItem and EndSubsequenceDisplayItem (incl.);
-// - Otherwise, copy the new display item.
-//
-// The algorithm is O(|m_currentDisplayItemList| + |m_newDisplayItemList|).
-// Coefficients are related to the ratio of out-of-order CachedDisplayItems
-// and the average number of (Drawing|Subsequence)DisplayItems per client.
-//
+void PaintController::resetCurrentListIterators()
+{
+    m_nextItemToMatch = m_currentPaintArtifact.getDisplayItemList().begin();
+    m_nextItemToIndex = m_nextItemToMatch;
+}
+
 void PaintController::commitNewDisplayItems(const LayoutSize& offsetFromLayoutObject)
 {
     TRACE_EVENT2("blink,benchmark", "PaintController::commitNewDisplayItems",
@@ -259,99 +359,37 @@
 
     SkPictureGpuAnalyzer gpuAnalyzer;
 
-    if (m_currentPaintArtifact.isEmpty()) {
-#if DCHECK_IS_ON()
-        for (const auto& item : m_newDisplayItemList)
-            DCHECK(!item.isCached());
-#endif
+    m_currentCacheGeneration = DisplayItemClient::CacheGenerationOrInvalidationReason::next();
+    for (const auto& item : m_newDisplayItemList) {
+        // No reason to continue the analysis once we have a veto.
+        if (gpuAnalyzer.suitableForGpuRasterization())
+            item.analyzeForGpuRasterization(gpuAnalyzer);
 
-        for (const auto& item : m_newDisplayItemList) {
-            m_newDisplayItemList.appendVisualRect(visualRectForDisplayItem(item, offsetFromLayoutObject));
-            // No reason to continue the analysis once we have a veto.
-            if (gpuAnalyzer.suitableForGpuRasterization())
-                item.analyzeForGpuRasterization(gpuAnalyzer);
-        }
-        m_currentPaintArtifact = PaintArtifact(std::move(m_newDisplayItemList), m_newPaintChunks.releasePaintChunks(), gpuAnalyzer.suitableForGpuRasterization());
-        m_newDisplayItemList = DisplayItemList(kInitialDisplayItemListCapacityBytes);
-        updateCacheGeneration();
-        return;
+        m_newDisplayItemList.appendVisualRect(visualRectForDisplayItem(item, offsetFromLayoutObject));
+
+        if (item.isCacheable())
+            item.client().setDisplayItemsCached(m_currentCacheGeneration);
     }
 
-    // Stores indices to valid DrawingDisplayItems in m_currentDisplayItems that have not been matched
-    // by CachedDisplayItems during synchronized matching. The indexed items will be matched
-    // by later out-of-order CachedDisplayItems in m_newDisplayItemList. This ensures that when
-    // out-of-order CachedDisplayItems occur, we only traverse at most once over m_currentDisplayItems
-    // looking for potential matches. Thus we can ensure that the algorithm runs in linear time.
-    OutOfOrderIndexContext outOfOrderIndexContext(m_currentPaintArtifact.getDisplayItemList().begin());
+    // The new list will not be appended to again so we can release unused memory.
+    m_newDisplayItemList.shrinkToFit();
+    m_currentPaintArtifact = PaintArtifact(std::move(m_newDisplayItemList), m_newPaintChunks.releasePaintChunks(), gpuAnalyzer.suitableForGpuRasterization());
+    resetCurrentListIterators();
+    m_outOfOrderItemIndices.clear();
 
-    // TODO(jbroman): Consider revisiting this heuristic.
-    DisplayItemList updatedList(std::max(m_currentPaintArtifact.getDisplayItemList().usedCapacityInBytes(), m_newDisplayItemList.usedCapacityInBytes()));
-    Vector<PaintChunk> updatedPaintChunks;
-    DisplayItemList::iterator currentIt = m_currentPaintArtifact.getDisplayItemList().begin();
-    DisplayItemList::iterator currentEnd = m_currentPaintArtifact.getDisplayItemList().end();
-    for (DisplayItemList::iterator newIt = m_newDisplayItemList.begin(); newIt != m_newDisplayItemList.end(); ++newIt) {
-        const DisplayItem& newDisplayItem = *newIt;
-        const DisplayItem::Id newDisplayItemId = newDisplayItem.nonCachedId();
-        bool newDisplayItemHasCachedType = newDisplayItem.getType() != newDisplayItemId.type;
+    // We'll allocate the initial buffer when we start the next paint.
+    m_newDisplayItemList = DisplayItemList(0);
 
-        bool isSynchronized = currentIt != currentEnd && newDisplayItemId.matches(*currentIt);
-
-        if (newDisplayItemHasCachedType) {
-            DCHECK(newDisplayItem.isCached());
 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS
-            CHECK(clientCacheIsValid(newDisplayItem.client()));
+    CHECK(m_currentSubsequenceClients.isEmpty());
+    DisplayItemClient::endShouldKeepAliveAllClients(this);
 #endif
-            if (!isSynchronized) {
-                currentIt = findOutOfOrderCachedItem(newDisplayItemId, outOfOrderIndexContext);
 
-                if (currentIt == currentEnd) {
-#ifndef NDEBUG
-                    showDebugData();
-                    WTFLogAlways("%s not found in m_currentDisplayItemList\n", newDisplayItem.asDebugString().utf8().data());
-#endif
-                    NOTREACHED();
-                    // We did not find the cached display item. This should be impossible, but may occur if there is a bug
-                    // in the system, such as under-invalidation, incorrect cache checking or duplicate display ids.
-                    // In this case, attempt to recover rather than crashing or bailing on display of the rest of the display list.
-                    continue;
-                }
-            }
 #if DCHECK_IS_ON()
-            if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) {
-                DisplayItemList::iterator temp = currentIt;
-                checkUnderInvalidation(newIt, temp);
-            }
+    m_numSequentialMatches = 0;
+    m_numOutOfOrderMatches = 0;
+    m_numIndexedItems = 0;
 #endif
-            if (newDisplayItem.isCachedDrawing()) {
-                updatedList.appendByMoving(*currentIt, m_currentPaintArtifact.getDisplayItemList().visualRect(currentIt - m_currentPaintArtifact.getDisplayItemList().begin()),
-                    gpuAnalyzer);
-                ++currentIt;
-            } else {
-                DCHECK(newDisplayItem.getType() == DisplayItem::CachedSubsequence);
-                copyCachedSubsequence(m_currentPaintArtifact.getDisplayItemList(), currentIt, updatedList, gpuAnalyzer);
-                DCHECK(updatedList.last().getType() == DisplayItem::EndSubsequence);
-            }
-        } else {
-            DCHECK(!newDisplayItem.isDrawing()
-                || newDisplayItem.skippedCache()
-                || !clientCacheIsValid(newDisplayItem.client()));
-
-            updatedList.appendByMoving(*newIt, visualRectForDisplayItem(*newIt, offsetFromLayoutObject), gpuAnalyzer);
-
-            if (isSynchronized)
-                ++currentIt;
-        }
-        // Items before currentIt should have been copied so we don't need to index them.
-        if (currentIt - outOfOrderIndexContext.nextItemToIndex > 0)
-            outOfOrderIndexContext.nextItemToIndex = currentIt;
-    }
-
-    // TODO(jbroman): When subsequence caching applies to SPv2, we'll need to
-    // merge the paint chunks as well.
-    m_currentPaintArtifact = PaintArtifact(std::move(updatedList), m_newPaintChunks.releasePaintChunks(), gpuAnalyzer.suitableForGpuRasterization());
-
-    m_newDisplayItemList = DisplayItemList(kInitialDisplayItemListCapacityBytes);
-    updateCacheGeneration();
 }
 
 size_t PaintController::approximateUnsharedMemoryUsage() const
@@ -379,34 +417,23 @@
     return memoryUsage;
 }
 
-void PaintController::updateCacheGeneration()
-{
-    m_currentCacheGeneration = DisplayItemClient::CacheGenerationOrInvalidationReason::next();
-    for (const DisplayItem& displayItem : m_currentPaintArtifact.getDisplayItemList()) {
-        if (!displayItem.isCacheable())
-            continue;
-        displayItem.client().setDisplayItemsCached(m_currentCacheGeneration);
-    }
-#if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS
-    CHECK(m_currentSubsequenceClients.isEmpty());
-    DisplayItemClient::endShouldKeepAliveAllClients(this);
-#endif
-}
-
 void PaintController::appendDebugDrawingAfterCommit(const DisplayItemClient& displayItemClient, PassRefPtr<SkPicture> picture, const LayoutSize& offsetFromLayoutObject)
 {
     DCHECK(m_newDisplayItemList.isEmpty());
     DrawingDisplayItem& displayItem = m_currentPaintArtifact.getDisplayItemList().allocateAndConstruct<DrawingDisplayItem>(displayItemClient, DisplayItem::DebugDrawing, picture);
     displayItem.setSkippedCache();
     m_currentPaintArtifact.getDisplayItemList().appendVisualRect(visualRectForDisplayItem(displayItem, offsetFromLayoutObject));
+
+    // Need to reset the iterators after mutation of the DisplayItemList.
+    resetCurrentListIterators();
 }
 
-#if DCHECK_IS_ON()
+#if 0 // DCHECK_IS_ON()
+// TODO(wangxianzhu): Fix under-invalidation checking for the new caching method.
 
 void PaintController::checkUnderInvalidation(DisplayItemList::iterator& newIt, DisplayItemList::iterator& currentIt)
 {
     DCHECK(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled());
-    DCHECK(newIt->isCached());
 
     // When under-invalidation-checking is enabled, the forced painting is following the cached display item.
     DisplayItem::Type nextItemType = DisplayItem::nonCachedType(newIt->getType());
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintController.h b/third_party/WebKit/Source/platform/graphics/paint/PaintController.h
index fd1d11f4..28324670 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintController.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintController.h
@@ -75,6 +75,8 @@
 
         if (displayItemConstructionIsDisabled())
             return;
+
+        ensureNewDisplayItemListInitialCapacity();
         DisplayItemClass& displayItem = m_newDisplayItemList.allocateAndConstruct<DisplayItemClass>(std::forward<Args>(args)...);
         processNewItem(displayItem);
     }
@@ -95,6 +97,14 @@
             createAndAppend<DisplayItemClass>(std::forward<Args>(args)...);
     }
 
+    // Tries to find the cached drawing display item corresponding to the given parameters. If found,
+    // appends the cached display item to the new display list and returns true. Otherwise returns false.
+    bool useCachedDrawingIfPossible(const DisplayItemClient&, DisplayItem::Type);
+
+    // Tries to find the cached subsequence corresponding to the given parameters. If found, copies the
+    // cache subsequence to the new display list and returns true. Otherwise returns false.
+    bool useCachedSubsequenceIfPossible(const DisplayItemClient&);
+
     // True if the last display item is a begin that doesn't draw content.
     bool lastDisplayItemIsNoopBegin() const;
     void removeLastDisplayItem();
@@ -148,16 +158,34 @@
 
 protected:
     PaintController()
-        : m_newDisplayItemList(kInitialDisplayItemListCapacityBytes)
+        : m_newDisplayItemList(0)
         , m_constructionDisabled(false)
         , m_subsequenceCachingDisabled(false)
         , m_textPainted(false)
         , m_imagePainted(false)
         , m_skippingCacheCount(0)
         , m_numCachedNewItems(0)
-    { }
+#if DCHECK_IS_ON()
+        , m_numSequentialMatches(0)
+        , m_numOutOfOrderMatches(0)
+        , m_numIndexedItems(0)
+#endif
+    {
+        resetCurrentListIterators();
+    }
 
 private:
+    friend class PaintControllerTest;
+    friend class PaintControllerPaintTestBase;
+
+    void ensureNewDisplayItemListInitialCapacity()
+    {
+        if (m_newDisplayItemList.isEmpty()) {
+            // TODO(wangxianzhu): Consider revisiting this heuristic.
+            m_newDisplayItemList = DisplayItemList(m_currentPaintArtifact.getDisplayItemList().isEmpty() ? kInitialDisplayItemListCapacityBytes : m_currentPaintArtifact.getDisplayItemList().usedCapacityInBytes());
+        }
+    }
+
     // Set new item state (cache skipping, etc) for a new item.
     void processNewItem(DisplayItem&);
 
@@ -172,10 +200,14 @@
     static size_t findMatchingItemFromIndex(const DisplayItem::Id&, const DisplayItemIndicesByClientMap&, const DisplayItemList&);
     static void addItemToIndexIfNeeded(const DisplayItem&, size_t index, DisplayItemIndicesByClientMap&);
 
-    struct OutOfOrderIndexContext;
-    DisplayItemList::iterator findOutOfOrderCachedItem(const DisplayItem::Id&, OutOfOrderIndexContext&);
-    DisplayItemList::iterator findOutOfOrderCachedItemForward(const DisplayItem::Id&, OutOfOrderIndexContext&);
-    void copyCachedSubsequence(const DisplayItemList& currentList, DisplayItemList::iterator& currentIt, DisplayItemList& updatedList, SkPictureGpuAnalyzer&);
+    DisplayItemList::iterator findCachedItem(const DisplayItem::Id&);
+    DisplayItemList::iterator findOutOfOrderCachedItemForward(const DisplayItem::Id&);
+    void copyCachedSubsequence(DisplayItemList::iterator&);
+
+    // Resets the iterators (e.g. m_nextItemToMatch) of m_currentPaintArtifact.getDisplayItemList()
+    // to their initial values. This should be called when the DisplayItemList in m_currentPaintArtifact
+    // is newly created, or is changed causing the previous iterators to be invalid.
+    void resetCurrentListIterators();
 
 #if DCHECK_IS_ON()
     // The following two methods are for checking under-invalidations
@@ -184,8 +216,6 @@
     void checkCachedDisplayItemIsUnchanged(const char* messagePrefix, const DisplayItem& newItem, const DisplayItem& oldItem);
 #endif
 
-    void updateCacheGeneration();
-
     // The last complete paint artifact.
     // In SPv2, this includes paint chunks as well as display items.
     PaintArtifact m_currentPaintArtifact;
@@ -209,15 +239,31 @@
 
     int m_numCachedNewItems;
 
-#if DCHECK_IS_ON()
-    // This is used to check duplicated ids during add(). We could also check
-    // during commitNewDisplayItems(), but checking during add() helps developer
-    // easily find where the duplicated ids are from.
-    DisplayItemIndicesByClientMap m_newDisplayItemIndicesByClient;
-#endif
+    // Stores indices to valid DrawingDisplayItems in current display list that have not been
+    // matched by CachedDisplayItems during sequential matching. The indexed items will be
+    // matched by later out-of-order requests of cached display items. This ensures that when
+    // out-of-order cached display items are requested, we only traverse at most once over
+    // the current display list looking for potential matches. Thus we can ensure that the
+    // algorithm runs in linear time.
+    DisplayItemIndicesByClientMap m_outOfOrderItemIndices;
+
+    // The next item in the current list for sequential match.
+    DisplayItemList::iterator m_nextItemToMatch;
+
+    // The next item in the current list to be indexed for out-of-order cache requests.
+    DisplayItemList::iterator m_nextItemToIndex;
 
     DisplayItemClient::CacheGenerationOrInvalidationReason m_currentCacheGeneration;
 
+#if DCHECK_IS_ON()
+    int m_numSequentialMatches;
+    int m_numOutOfOrderMatches;
+    int m_numIndexedItems;
+
+    // This is used to check duplicated ids during createAndAppend().
+    DisplayItemIndicesByClientMap m_newDisplayItemIndicesByClient;
+#endif
+
 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS
     // A stack recording subsequence clients that are currently painting.
     Vector<const DisplayItemClient*> m_currentSubsequenceClients;
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp
index 826c05d..22798a2 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp
@@ -6,7 +6,6 @@
 
 #include "platform/RuntimeEnabledFeatures.h"
 #include "platform/graphics/GraphicsContext.h"
-#include "platform/graphics/paint/CachedDisplayItem.h"
 #include "platform/graphics/paint/ClipPathDisplayItem.h"
 #include "platform/graphics/paint/ClipPathRecorder.h"
 #include "platform/graphics/paint/ClipRecorder.h"
@@ -33,6 +32,14 @@
 protected:
     PaintController& getPaintController() { return *m_paintController; }
 
+    int numCachedNewItems() const { return m_paintController->m_numCachedNewItems; }
+
+#if DCHECK_IS_ON()
+    int numSequentialMatches() const { return m_paintController->m_numSequentialMatches; }
+    int numOutOfOrderMatches() const { return m_paintController->m_numOutOfOrderMatches; }
+    int numIndexedItems() const { return m_paintController->m_numIndexedItems; }
+#endif
+
 private:
     void TearDown() override
     {
@@ -115,6 +122,9 @@
     drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 300, 300));
     drawRect(context, second, backgroundDrawingType, FloatRect(100, 100, 200, 200));
     drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 300, 300));
+
+    EXPECT_EQ(0, numCachedNewItems());
+
     getPaintController().commitNewDisplayItems();
 
     EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 3,
@@ -125,6 +135,14 @@
     second.setDisplayItemsUncached();
     drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 300, 300));
     drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 300, 300));
+
+    EXPECT_EQ(2, numCachedNewItems());
+#if DCHECK_IS_ON()
+    EXPECT_EQ(2, numSequentialMatches());
+    EXPECT_EQ(0, numOutOfOrderMatches());
+    EXPECT_EQ(1, numIndexedItems());
+#endif
+
     getPaintController().commitNewDisplayItems();
 
     EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 2,
@@ -140,25 +158,93 @@
     GraphicsContext context(getPaintController());
 
     drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 100, 100));
+    drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 100, 100));
     drawRect(context, second, backgroundDrawingType, FloatRect(100, 100, 50, 200));
+    drawRect(context, second, foregroundDrawingType, FloatRect(100, 100, 50, 200));
     drawRect(context, unaffected, backgroundDrawingType, FloatRect(300, 300, 10, 10));
+    drawRect(context, unaffected, foregroundDrawingType, FloatRect(300, 300, 10, 10));
     getPaintController().commitNewDisplayItems();
 
-    EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 3,
+    EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 6,
         TestDisplayItem(first, backgroundDrawingType),
+        TestDisplayItem(first, foregroundDrawingType),
         TestDisplayItem(second, backgroundDrawingType),
-        TestDisplayItem(unaffected, backgroundDrawingType));
+        TestDisplayItem(second, foregroundDrawingType),
+        TestDisplayItem(unaffected, backgroundDrawingType),
+        TestDisplayItem(unaffected, foregroundDrawingType));
 
-    second.setDisplayItemsUncached();
     drawRect(context, second, backgroundDrawingType, FloatRect(100, 100, 50, 200));
+    drawRect(context, second, foregroundDrawingType, FloatRect(100, 100, 50, 200));
     drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 100, 100));
+    drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 100, 100));
     drawRect(context, unaffected, backgroundDrawingType, FloatRect(300, 300, 10, 10));
+    drawRect(context, unaffected, foregroundDrawingType, FloatRect(300, 300, 10, 10));
+
+    EXPECT_EQ(6, numCachedNewItems());
+#if DCHECK_IS_ON()
+    EXPECT_EQ(5, numSequentialMatches()); // second, first foreground, unaffected
+    EXPECT_EQ(1, numOutOfOrderMatches()); // first
+    EXPECT_EQ(2, numIndexedItems()); // first
+#endif
+
     getPaintController().commitNewDisplayItems();
 
-    EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 3,
+    EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 6,
         TestDisplayItem(second, backgroundDrawingType),
+        TestDisplayItem(second, foregroundDrawingType),
         TestDisplayItem(first, backgroundDrawingType),
-        TestDisplayItem(unaffected, backgroundDrawingType));
+        TestDisplayItem(first, foregroundDrawingType),
+        TestDisplayItem(unaffected, backgroundDrawingType),
+        TestDisplayItem(unaffected, foregroundDrawingType));
+}
+
+TEST_F(PaintControllerTest, UpdateSwapOrderWithInvalidation)
+{
+    FakeDisplayItemClient first("first");
+    FakeDisplayItemClient second("second");
+    FakeDisplayItemClient unaffected("unaffected");
+    GraphicsContext context(getPaintController());
+
+    drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 100, 100));
+    drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 100, 100));
+    drawRect(context, second, backgroundDrawingType, FloatRect(100, 100, 50, 200));
+    drawRect(context, second, foregroundDrawingType, FloatRect(100, 100, 50, 200));
+    drawRect(context, unaffected, backgroundDrawingType, FloatRect(300, 300, 10, 10));
+    drawRect(context, unaffected, foregroundDrawingType, FloatRect(300, 300, 10, 10));
+    getPaintController().commitNewDisplayItems();
+
+    EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 6,
+        TestDisplayItem(first, backgroundDrawingType),
+        TestDisplayItem(first, foregroundDrawingType),
+        TestDisplayItem(second, backgroundDrawingType),
+        TestDisplayItem(second, foregroundDrawingType),
+        TestDisplayItem(unaffected, backgroundDrawingType),
+        TestDisplayItem(unaffected, foregroundDrawingType));
+
+    first.setDisplayItemsUncached();
+    drawRect(context, second, backgroundDrawingType, FloatRect(100, 100, 50, 200));
+    drawRect(context, second, foregroundDrawingType, FloatRect(100, 100, 50, 200));
+    drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 100, 100));
+    drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 100, 100));
+    drawRect(context, unaffected, backgroundDrawingType, FloatRect(300, 300, 10, 10));
+    drawRect(context, unaffected, foregroundDrawingType, FloatRect(300, 300, 10, 10));
+
+    EXPECT_EQ(4, numCachedNewItems());
+#if DCHECK_IS_ON()
+    EXPECT_EQ(4, numSequentialMatches()); // second, unaffected
+    EXPECT_EQ(0, numOutOfOrderMatches());
+    EXPECT_EQ(2, numIndexedItems());
+#endif
+
+    getPaintController().commitNewDisplayItems();
+
+    EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 6,
+        TestDisplayItem(second, backgroundDrawingType),
+        TestDisplayItem(second, foregroundDrawingType),
+        TestDisplayItem(first, backgroundDrawingType),
+        TestDisplayItem(first, foregroundDrawingType),
+        TestDisplayItem(unaffected, backgroundDrawingType),
+        TestDisplayItem(unaffected, foregroundDrawingType));
 }
 
 TEST_F(PaintControllerTest, UpdateNewItemInMiddle)
@@ -179,6 +265,14 @@
     drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 100, 100));
     drawRect(context, third, backgroundDrawingType, FloatRect(125, 100, 200, 50));
     drawRect(context, second, backgroundDrawingType, FloatRect(100, 100, 50, 200));
+
+    EXPECT_EQ(2, numCachedNewItems());
+#if DCHECK_IS_ON()
+    EXPECT_EQ(2, numSequentialMatches()); // first, second
+    EXPECT_EQ(0, numOutOfOrderMatches());
+    EXPECT_EQ(0, numIndexedItems());
+#endif
+
     getPaintController().commitNewDisplayItems();
 
     EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 3,
@@ -217,6 +311,14 @@
     drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 100, 100));
     drawRect(context, second, foregroundDrawingType, FloatRect(100, 100, 50, 200));
     drawRect(context, third, foregroundDrawingType, FloatRect(300, 100, 50, 50));
+
+    EXPECT_EQ(4, numCachedNewItems());
+#if DCHECK_IS_ON()
+    EXPECT_EQ(4, numSequentialMatches());
+    EXPECT_EQ(0, numOutOfOrderMatches());
+    EXPECT_EQ(2, numIndexedItems());
+#endif
+
     getPaintController().commitNewDisplayItems();
 
     EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 6,
@@ -248,6 +350,7 @@
     drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 150, 150));
     drawRect(context, second, backgroundDrawingType, FloatRect(200, 200, 50, 50));
     drawRect(context, second, foregroundDrawingType, FloatRect(200, 200, 50, 50));
+    EXPECT_EQ(0, numCachedNewItems());
     getPaintController().commitNewDisplayItems();
 
     EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 4,
@@ -259,6 +362,14 @@
     first.setDisplayItemsUncached();
     drawRect(context, second, backgroundDrawingType, FloatRect(200, 200, 50, 50));
     drawRect(context, second, foregroundDrawingType, FloatRect(200, 200, 50, 50));
+
+    EXPECT_EQ(2, numCachedNewItems());
+#if DCHECK_IS_ON()
+    EXPECT_EQ(2, numSequentialMatches());
+    EXPECT_EQ(0, numOutOfOrderMatches());
+    EXPECT_EQ(2, numIndexedItems());
+#endif
+
     getPaintController().commitNewDisplayItems();
 
     EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 2,
@@ -286,6 +397,7 @@
     drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 150, 150));
     drawRect(context, second, backgroundDrawingType, FloatRect(200, 200, 50, 50));
     drawRect(context, second, foregroundDrawingType, FloatRect(200, 200, 50, 50));
+    EXPECT_EQ(0, numCachedNewItems());
     getPaintController().commitNewDisplayItems();
 
     EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 4,
@@ -298,6 +410,7 @@
     second.setDisplayItemsUncached();
     drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 150, 150));
     drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 150, 150));
+    EXPECT_EQ(0, numCachedNewItems());
     getPaintController().commitNewDisplayItems();
 
     EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 2,
@@ -327,6 +440,14 @@
     first.setDisplayItemsUncached();
     drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 150, 150));
     drawRect(context, second, backgroundDrawingType, FloatRect(100, 100, 150, 150));
+
+    EXPECT_EQ(1, numCachedNewItems());
+#if DCHECK_IS_ON()
+    EXPECT_EQ(1, numSequentialMatches());
+    EXPECT_EQ(0, numOutOfOrderMatches());
+    EXPECT_EQ(1, numIndexedItems());
+#endif
+
     getPaintController().commitNewDisplayItems();
 
     EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 2,
@@ -483,9 +604,12 @@
     EXPECT_TRUE(SubsequenceRecorder::useCachedSubsequenceIfPossible(context, container2));
     EXPECT_TRUE(SubsequenceRecorder::useCachedSubsequenceIfPossible(context, container1));
 
-    EXPECT_DISPLAY_LIST(getPaintController().newDisplayItemList(), 2,
-        TestDisplayItem(container2, DisplayItem::CachedSubsequence),
-        TestDisplayItem(container1, DisplayItem::CachedSubsequence));
+    EXPECT_EQ(12, numCachedNewItems());
+#if DCHECK_IS_ON()
+    EXPECT_EQ(1, numSequentialMatches());
+    EXPECT_EQ(1, numOutOfOrderMatches());
+    EXPECT_EQ(5, numIndexedItems());
+#endif
 
     getPaintController().commitNewDisplayItems();
 
@@ -602,14 +726,13 @@
         EXPECT_TRUE(SubsequenceRecorder::useCachedSubsequenceIfPossible(context, content1));
         drawRect(context, container1, foregroundDrawingType, FloatRect(100, 100, 100, 100));
     }
-    EXPECT_DISPLAY_LIST(getPaintController().newDisplayItemList(), 7,
-        TestDisplayItem(content2, DisplayItem::Subsequence),
-        TestDisplayItem(content2, foregroundDrawingType),
-        TestDisplayItem(content2, DisplayItem::EndSubsequence),
-        TestDisplayItem(container1, DisplayItem::Subsequence),
-        TestDisplayItem(content1, DisplayItem::CachedSubsequence),
-        TestDisplayItem(container1, foregroundDrawingType),
-        TestDisplayItem(container1, DisplayItem::EndSubsequence));
+
+    EXPECT_EQ(4, numCachedNewItems());
+#if DCHECK_IS_ON()
+    EXPECT_EQ(1, numSequentialMatches());
+    EXPECT_EQ(0, numOutOfOrderMatches());
+    EXPECT_EQ(2, numIndexedItems());
+#endif
 
     getPaintController().commitNewDisplayItems();
 
@@ -667,10 +790,12 @@
     drawRect(context, content, foregroundDrawingType, rect2);
     getPaintController().endSkippingCache();
 
-    EXPECT_DISPLAY_LIST(getPaintController().newDisplayItemList(), 3,
-        TestDisplayItem(multicol, DisplayItem::drawingTypeToCachedDrawingType(backgroundDrawingType)),
-        TestDisplayItem(content, foregroundDrawingType),
-        TestDisplayItem(content, foregroundDrawingType));
+    EXPECT_EQ(1, numCachedNewItems());
+#if DCHECK_IS_ON()
+    EXPECT_EQ(1, numSequentialMatches());
+    EXPECT_EQ(0, numOutOfOrderMatches());
+    EXPECT_EQ(0, numIndexedItems());
+#endif
 
     getPaintController().commitNewDisplayItems();
 
diff --git a/third_party/WebKit/Source/platform/graphics/paint/README.md b/third_party/WebKit/Source/platform/graphics/paint/README.md
index 618a5fc9..009a752 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/README.md
+++ b/third_party/WebKit/Source/platform/graphics/paint/README.md
@@ -134,10 +134,6 @@
 
 ### Standalone display items
 
-#### [CachedDisplayItem](CachedDisplayItem.h)
-
-See [Display item caching](../../../core/paint/README.md#paint-result-caching).
-
 #### [DrawingDisplayItem](DrawingDisplayItem.h)
 
 Holds an `SkPicture` which contains the Skia commands required to draw some atom
@@ -164,14 +160,17 @@
 a `PaintController`.
 
 `PaintController` is responsible for producing the paint artifact. It contains
-the *current* paint artifact, which is always complete (i.e. it has no
-`CachedDisplayItem` objects), and *new* display items and paint chunks, which
+the *current* paint artifact, and *new* display items and paint chunks, which
 are added as content is painted.
 
+Painters should call `PaintController::useCachedDrawingIfPossible()` or
+`PaintController::useCachedSubsequenceIfPossible()` and if the function returns
+`true`, existing display items that are still valid in the *current* paint artifact
+will be reused and the painter should skip real painting of the drawing or subsequence.
+
 When the new display items have been populated, clients call
-`commitNewDisplayItems`, which merges the previous artifact with the new data,
-producing a new paint artifact, where `CachedDisplayItem` objects have been
-replaced with the cached content from the previous artifact.
+`commitNewDisplayItems`, which replaces the previous artifact with the new data,
+producing a new paint artifact.
 
 At this point, the paint artifact is ready to be drawn or composited.
 
@@ -193,11 +192,12 @@
 A display item is treated as validly cached in a paint controller if its cache
 generation matches the paint controller's cache generation.
 
-`kInvalidCacheGeneration` is a special cache generation value which matches no
-other cache generations. When a `DisplayItemClient` is invalidated, we set its
-cache generation to `kInvalidCacheGeneration`. When a `PaintController` is
-cleared (e.g. when the corresponding `GraphicsLayer` is fully invalidated), we
-also set its cache generation to `kInvalidCacheGeneration`.
+A cache generation value smaller than `kFirstValidGeneration` matches no
+other cache generations thus is always treated as invalid. When a
+`DisplayItemClient` is invalidated, we set its cache generation to one of
+`PaintInvalidationReason` values which are smaller than `kFirstValidGeneration`.
+When a `PaintController` is cleared (e.g. when the corresponding `GraphicsLayer`
+is fully invalidated), we also invalidate its cache generation.
 
 For now we use a uint32_t variable to store cache generation. Assuming there is
 an animation in 60fps needing main-thread repaint, the cache generation will
diff --git a/third_party/WebKit/Source/platform/graphics/paint/SubsequenceRecorder.cpp b/third_party/WebKit/Source/platform/graphics/paint/SubsequenceRecorder.cpp
index 19648b8e..861529e 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/SubsequenceRecorder.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/SubsequenceRecorder.cpp
@@ -6,36 +6,11 @@
 
 #include "platform/RuntimeEnabledFeatures.h"
 #include "platform/graphics/GraphicsContext.h"
-#include "platform/graphics/paint/CachedDisplayItem.h"
 #include "platform/graphics/paint/PaintController.h"
 #include "platform/graphics/paint/SubsequenceDisplayItem.h"
 
 namespace blink {
 
-bool SubsequenceRecorder::useCachedSubsequenceIfPossible(GraphicsContext& context, const DisplayItemClient& client)
-{
-    if (context.getPaintController().displayItemConstructionIsDisabled() || context.getPaintController().subsequenceCachingIsDisabled())
-        return false;
-
-    if (!context.getPaintController().clientCacheIsValid(client))
-        return false;
-
-    // TODO(pdr): Implement subsequence caching for spv2 (crbug.com/596983).
-    if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
-        return false;
-
-    context.getPaintController().createAndAppend<CachedDisplayItem>(client, DisplayItem::CachedSubsequence);
-
-#if ENABLE(ASSERT)
-    // When under-invalidation checking is enabled, we output CachedSubsequence display item
-    // followed by forced painting of the subsequence.
-    if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled())
-        return false;
-#endif
-
-    return true;
-}
-
 SubsequenceRecorder::SubsequenceRecorder(GraphicsContext& context, const DisplayItemClient& client)
     : m_paintController(context.getPaintController())
     , m_client(client)
diff --git a/third_party/WebKit/Source/platform/graphics/paint/SubsequenceRecorder.h b/third_party/WebKit/Source/platform/graphics/paint/SubsequenceRecorder.h
index 8840ce45..3d2bbbea 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/SubsequenceRecorder.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/SubsequenceRecorder.h
@@ -5,7 +5,9 @@
 #ifndef SubsequenceRecorder_h
 #define SubsequenceRecorder_h
 
+#include "platform/graphics/GraphicsContext.h"
 #include "platform/graphics/paint/DisplayItem.h"
+#include "platform/graphics/paint/PaintController.h"
 #include "wtf/Allocator.h"
 #include "wtf/Noncopyable.h"
 
@@ -26,7 +28,10 @@
     DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
     WTF_MAKE_NONCOPYABLE(SubsequenceRecorder);
 public:
-    static bool useCachedSubsequenceIfPossible(GraphicsContext&, const DisplayItemClient&);
+    static bool useCachedSubsequenceIfPossible(GraphicsContext& context, const DisplayItemClient& client)
+    {
+        return context.getPaintController().useCachedSubsequenceIfPossible(client);
+    }
 
     SubsequenceRecorder(GraphicsContext&, const DisplayItemClient&);
     ~SubsequenceRecorder();
diff --git a/third_party/WebKit/Source/platform/image-decoders/ImageDecoderTestHelpers.cpp b/third_party/WebKit/Source/platform/image-decoders/ImageDecoderTestHelpers.cpp
index 6e11a895..af147d1 100644
--- a/third_party/WebKit/Source/platform/image-decoders/ImageDecoderTestHelpers.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/ImageDecoderTestHelpers.cpp
@@ -10,6 +10,7 @@
 #include "platform/testing/UnitTestHelpers.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "wtf/StringHasher.h"
+#include "wtf/text/StringBuilder.h"
 #include <memory>
 
 namespace blink {
@@ -23,13 +24,13 @@
 
 PassRefPtr<SharedBuffer> readFile(const char* dir, const char* fileName)
 {
-    String filePath = testing::blinkRootDir();
-    filePath.append("/");
+    StringBuilder filePath;
+    filePath.append(testing::blinkRootDir());
+    filePath.append('/');
     filePath.append(dir);
-    filePath.append("/");
+    filePath.append('/');
     filePath.append(fileName);
-
-    return testing::readFromFile(filePath);
+    return testing::readFromFile(filePath.toString());
 }
 
 unsigned hashBitmap(const SkBitmap& bitmap)
diff --git a/third_party/WebKit/Source/platform/inspector_protocol/ErrorSupport.cpp b/third_party/WebKit/Source/platform/inspector_protocol/ErrorSupport.cpp
index 4f58a39..0ad89ade 100644
--- a/third_party/WebKit/Source/platform/inspector_protocol/ErrorSupport.cpp
+++ b/third_party/WebKit/Source/platform/inspector_protocol/ErrorSupport.cpp
@@ -42,7 +42,7 @@
     String16Builder builder;
     for (size_t i = 0; i < m_path.size(); ++i) {
         if (i)
-            builder.append(".");
+            builder.append('.');
         builder.append(m_path[i]);
     }
     builder.append(": ");
diff --git a/third_party/WebKit/Source/platform/network/ResourceRequest.cpp b/third_party/WebKit/Source/platform/network/ResourceRequest.cpp
index c05ad618..99b0af3 100644
--- a/third_party/WebKit/Source/platform/network/ResourceRequest.cpp
+++ b/third_party/WebKit/Source/platform/network/ResourceRequest.cpp
@@ -40,6 +40,21 @@
 
 double ResourceRequest::s_defaultTimeoutInterval = INT_MAX;
 
+ResourceRequest::ResourceRequest()
+{
+    initialize(KURL());
+}
+
+ResourceRequest::ResourceRequest(const String& urlString)
+{
+    initialize(KURL(ParsedURLString, urlString));
+}
+
+ResourceRequest::ResourceRequest(const KURL& url)
+{
+    initialize(url);
+}
+
 ResourceRequest::ResourceRequest(CrossThreadResourceRequestData* data)
     : ResourceRequest()
 {
@@ -80,6 +95,10 @@
     m_redirectStatus = data->m_redirectStatus;
 }
 
+ResourceRequest::ResourceRequest(const ResourceRequest&) = default;
+
+ResourceRequest& ResourceRequest::operator=(const ResourceRequest&) = default;
+
 std::unique_ptr<CrossThreadResourceRequestData> ResourceRequest::copyData() const
 {
     std::unique_ptr<CrossThreadResourceRequestData> data = wrapUnique(new CrossThreadResourceRequestData());
diff --git a/third_party/WebKit/Source/platform/network/ResourceRequest.h b/third_party/WebKit/Source/platform/network/ResourceRequest.h
index ffcac5b..568a000 100644
--- a/third_party/WebKit/Source/platform/network/ResourceRequest.h
+++ b/third_party/WebKit/Source/platform/network/ResourceRequest.h
@@ -73,22 +73,12 @@
         virtual ~ExtraData() { }
     };
 
-    ResourceRequest()
-    {
-        initialize(KURL());
-    }
-
-    ResourceRequest(const String& urlString)
-    {
-        initialize(KURL(ParsedURLString, urlString));
-    }
-
-    ResourceRequest(const KURL& url)
-    {
-        initialize(url);
-    }
-
+    ResourceRequest();
+    ResourceRequest(const String& urlString);
+    ResourceRequest(const KURL&);
     explicit ResourceRequest(CrossThreadResourceRequestData*);
+    ResourceRequest(const ResourceRequest&);
+    ResourceRequest& operator=(const ResourceRequest&);
 
     // Gets a copy of the data suitable for passing to another thread.
     std::unique_ptr<CrossThreadResourceRequestData> copyData() const;
diff --git a/third_party/WebKit/Source/platform/network/ResourceResponse.cpp b/third_party/WebKit/Source/platform/network/ResourceResponse.cpp
index d1a85c9..f29d13ea 100644
--- a/third_party/WebKit/Source/platform/network/ResourceResponse.cpp
+++ b/third_party/WebKit/Source/platform/network/ResourceResponse.cpp
@@ -33,6 +33,20 @@
 
 namespace blink {
 
+namespace {
+
+Vector<ResourceResponse::SignedCertificateTimestamp> isolatedCopy(const Vector<ResourceResponse::SignedCertificateTimestamp>& src)
+{
+    Vector<ResourceResponse::SignedCertificateTimestamp> result;
+    result.reserveCapacity(src.size());
+    for (const auto& timestamp : src) {
+        result.append(timestamp.isolatedCopy());
+    }
+    return result;
+}
+
+} // namespace
+
 ResourceResponse::SignedCertificateTimestamp::SignedCertificateTimestamp(
     const blink::WebURLResponse::SignedCertificateTimestamp& sct)
     : m_status(sct.status)
@@ -46,6 +60,19 @@
 {
 }
 
+ResourceResponse::SignedCertificateTimestamp ResourceResponse::SignedCertificateTimestamp::isolatedCopy() const
+{
+    return SignedCertificateTimestamp(
+        m_status.isolatedCopy(),
+        m_origin.isolatedCopy(),
+        m_logDescription.isolatedCopy(),
+        m_logId.isolatedCopy(),
+        m_timestamp,
+        m_hashAlgorithm.isolatedCopy(),
+        m_signatureAlgorithm.isolatedCopy(),
+        m_signatureData.isolatedCopy());
+}
+
 ResourceResponse::ResourceResponse()
     : m_expectedContentLength(0)
     , m_httpStatusCode(0)
@@ -164,6 +191,9 @@
     // whatever values may be present in the opaque m_extraData structure.
 }
 
+ResourceResponse::ResourceResponse(const ResourceResponse&) = default;
+ResourceResponse& ResourceResponse::operator=(const ResourceResponse&) = default;
+
 std::unique_ptr<CrossThreadResourceResponseData> ResourceResponse::copyData() const
 {
     std::unique_ptr<CrossThreadResourceResponseData> data = wrapUnique(new CrossThreadResourceResponseData);
@@ -189,7 +219,7 @@
     data->m_securityDetails.numUnknownSCTs = m_securityDetails.numUnknownSCTs;
     data->m_securityDetails.numInvalidSCTs = m_securityDetails.numInvalidSCTs;
     data->m_securityDetails.numValidSCTs = m_securityDetails.numValidSCTs;
-    data->m_securityDetails.sctList = m_securityDetails.sctList;
+    data->m_securityDetails.sctList = isolatedCopy(m_securityDetails.sctList);
     data->m_httpVersion = m_httpVersion;
     data->m_appCacheID = m_appCacheID;
     data->m_appCacheManifestURL = m_appCacheManifestURL.copy();
diff --git a/third_party/WebKit/Source/platform/network/ResourceResponse.h b/third_party/WebKit/Source/platform/network/ResourceResponse.h
index a87900a..68b63877 100644
--- a/third_party/WebKit/Source/platform/network/ResourceResponse.h
+++ b/third_party/WebKit/Source/platform/network/ResourceResponse.h
@@ -61,7 +61,7 @@
         SecurityStyleAuthenticated
     };
 
-    class SignedCertificateTimestamp {
+    class PLATFORM_EXPORT SignedCertificateTimestamp final {
     public:
         SignedCertificateTimestamp(
             String status,
@@ -84,6 +84,8 @@
         }
         explicit SignedCertificateTimestamp(
             const struct blink::WebURLResponse::SignedCertificateTimestamp&);
+        SignedCertificateTimestamp isolatedCopy() const;
+
         String m_status;
         String m_origin;
         String m_logDescription;
@@ -131,6 +133,8 @@
 
     ResourceResponse();
     ResourceResponse(const KURL&, const AtomicString& mimeType, long long expectedLength, const AtomicString& textEncodingName, const String& filename);
+    ResourceResponse(const ResourceResponse&);
+    ResourceResponse& operator=(const ResourceResponse&);
 
     bool isNull() const { return m_isNull; }
     bool isHTTP() const;
diff --git a/third_party/WebKit/Source/platform/network/ResourceResponseTest.cpp b/third_party/WebKit/Source/platform/network/ResourceResponseTest.cpp
new file mode 100644
index 0000000..1a20323
--- /dev/null
+++ b/third_party/WebKit/Source/platform/network/ResourceResponseTest.cpp
@@ -0,0 +1,42 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/network/ResourceResponse.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+
+TEST(ResourceResponseTest, SignedCertificateTimestampIsolatedCopy)
+{
+    ResourceResponse::SignedCertificateTimestamp src(
+        "status",
+        "origin",
+        "logDescription",
+        "logId",
+        7,
+        "hashAlgorithm",
+        "signatureAlgorithm",
+        "signatureData");
+
+    ResourceResponse::SignedCertificateTimestamp dest = src.isolatedCopy();
+
+    EXPECT_EQ(src.m_status, dest.m_status);
+    EXPECT_NE(src.m_status.impl(), dest.m_status.impl());
+    EXPECT_EQ(src.m_origin, dest.m_origin);
+    EXPECT_NE(src.m_origin.impl(), dest.m_origin.impl());
+    EXPECT_EQ(src.m_logDescription, dest.m_logDescription);
+    EXPECT_NE(src.m_logDescription.impl(), dest.m_logDescription.impl());
+    EXPECT_EQ(src.m_logId, dest.m_logId);
+    EXPECT_NE(src.m_logId.impl(), dest.m_logId.impl());
+    EXPECT_EQ(src.m_timestamp, dest.m_timestamp);
+    EXPECT_EQ(src.m_hashAlgorithm, dest.m_hashAlgorithm);
+    EXPECT_NE(src.m_hashAlgorithm.impl(), dest.m_hashAlgorithm.impl());
+    EXPECT_EQ(src.m_signatureAlgorithm, dest.m_signatureAlgorithm);
+    EXPECT_NE(src.m_signatureAlgorithm.impl(), dest.m_signatureAlgorithm.impl());
+    EXPECT_EQ(src.m_signatureData, dest.m_signatureData);
+    EXPECT_NE(src.m_signatureData.impl(), dest.m_signatureData.impl());
+}
+
+} // namespace blink
diff --git a/third_party/WebKit/Source/platform/testing/weburl_loader_mock.cc b/third_party/WebKit/Source/platform/testing/weburl_loader_mock.cc
index 3984742..45affb8 100644
--- a/third_party/WebKit/Source/platform/testing/weburl_loader_mock.cc
+++ b/third_party/WebKit/Source/platform/testing/weburl_loader_mock.cc
@@ -67,7 +67,6 @@
       ParsedURLString, redirectResponse.httpHeaderField("Location"));
 
   WebURLRequest newRequest;
-  newRequest.initialize();
   newRequest.setURL(redirectURL);
   newRequest.setFirstPartyForCookies(redirectURL);
   newRequest.setDownloadToFile(request.downloadToFile());
diff --git a/third_party/WebKit/Source/platform/text/DateTimeFormatTest.cpp b/third_party/WebKit/Source/platform/text/DateTimeFormatTest.cpp
index cacbd786..53729df 100644
--- a/third_party/WebKit/Source/platform/text/DateTimeFormatTest.cpp
+++ b/third_party/WebKit/Source/platform/text/DateTimeFormatTest.cpp
@@ -147,10 +147,10 @@
             builder.append("Tokens(");
             for (unsigned index = 0; index < m_tokens.size(); ++index) {
                 if (index)
-                    builder.append(",");
+                    builder.append(',');
                 builder.append(m_tokens[index].toString());
             }
-            builder.append(")");
+            builder.append(')');
             return builder.toString();
         }
 
diff --git a/third_party/WebKit/Source/platform/v8_inspector/InjectedScript.cpp b/third_party/WebKit/Source/platform/v8_inspector/InjectedScript.cpp
index 6594dbe..f42cdb6a 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/InjectedScript.cpp
+++ b/third_party/WebKit/Source/platform/v8_inspector/InjectedScript.cpp
@@ -51,7 +51,6 @@
 
 using blink::protocol::Array;
 using blink::protocol::Debugger::CallFrame;
-using blink::protocol::Debugger::FunctionDetails;
 using blink::protocol::Runtime::PropertyDescriptor;
 using blink::protocol::Runtime::InternalPropertyDescriptor;
 using blink::protocol::Runtime::RemoteObject;
diff --git a/third_party/WebKit/Source/platform/v8_inspector/InjectedScriptSource.js b/third_party/WebKit/Source/platform/v8_inspector/InjectedScriptSource.js
index a310ea8..d2b3b27 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/InjectedScriptSource.js
+++ b/third_party/WebKit/Source/platform/v8_inspector/InjectedScriptSource.js
@@ -199,6 +199,20 @@
     __proto__: null
 }
 
+/**
+ * @type {!Map<string, string>}
+ * @const
+ */
+InjectedScript.closureTypes = new Map([
+    ["local", "Local"],
+    ["closure", "Closure"],
+    ["catch", "Catch"],
+    ["block", "Block"],
+    ["script", "Script"],
+    ["with", "With Block"],
+    ["global", "Global"]
+]);
+
 InjectedScript.prototype = {
     /**
      * @param {*} object
@@ -324,10 +338,20 @@
      */
     getProperties: function(object, objectGroupName, ownProperties, accessorPropertiesOnly, generatePreview)
     {
+        var subtype = this._subtype(object);
+        if (subtype === "internal#scope") {
+            // Internally, scope contains object with scope variables and additional information like type,
+            // we use additional information for preview and would like to report variables as scope
+            // properties.
+            object = object.object;
+        }
+
         var descriptors = [];
         var iter = this._propertyDescriptors(object, ownProperties, accessorPropertiesOnly, undefined);
         // Go over properties, wrap object values.
         for (var descriptor of iter) {
+            if (subtype === "internal#scopeList" && descriptor.name === "length")
+                continue;
             if ("get" in descriptor)
                 descriptor.get = this._wrapObject(descriptor.get, objectGroupName);
             if ("set" in descriptor)
@@ -627,6 +651,12 @@
             return this._describeIncludingPrimitives(obj.value);
         }
 
+        if (subtype === "internal#scopeList")
+            return "Scopes[" + obj.length + "]";
+
+        if (subtype === "internal#scope")
+            return (InjectedScript.closureTypes.get(obj.type) || "Unknown") + (obj.name ? " (" + obj.name + ")" : "");
+
         return className;
     },
 
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleAgentImpl.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleAgentImpl.cpp
index 55eff2c4..cce207b 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleAgentImpl.cpp
+++ b/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleAgentImpl.cpp
@@ -35,7 +35,6 @@
     m_enabled = true;
     m_session->debugger()->enableStackCapturingIfNeeded();
     reportAllMessages();
-    m_session->client()->consoleEnabled();
 }
 
 void V8ConsoleAgentImpl::disable(ErrorString* errorString)
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.cpp
index d59b983a..ef1426ca 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.cpp
+++ b/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.cpp
@@ -30,6 +30,7 @@
     case SecurityMessageSource: return protocol::Console::ConsoleMessage::SourceEnum::Security;
     case OtherMessageSource: return protocol::Console::ConsoleMessage::SourceEnum::Other;
     case DeprecationMessageSource: return protocol::Console::ConsoleMessage::SourceEnum::Deprecation;
+    case WorkerMessageSource: return protocol::Console::ConsoleMessage::SourceEnum::Worker;
     }
     return protocol::Console::ConsoleMessage::SourceEnum::Other;
 }
@@ -199,28 +200,15 @@
 
 } // namespace
 
-V8ConsoleMessage::V8ConsoleMessage(
-    double timestamp,
-    MessageSource source,
-    MessageLevel level,
-    const String16& message,
-    const String16& url,
-    unsigned lineNumber,
-    unsigned columnNumber,
-    std::unique_ptr<V8StackTrace> stackTrace,
-    int scriptId,
-    const String16& requestIdentifier)
-    : m_origin(V8MessageOrigin::kConsole)
+V8ConsoleMessage::V8ConsoleMessage(V8MessageOrigin origin, double timestamp, MessageSource source, MessageLevel level, const String16& message)
+    : m_origin(origin)
     , m_timestamp(timestamp)
     , m_source(source)
     , m_level(level)
     , m_message(message)
-    , m_url(url)
-    , m_lineNumber(lineNumber)
-    , m_columnNumber(columnNumber)
-    , m_stackTrace(std::move(stackTrace))
-    , m_scriptId(scriptId)
-    , m_requestIdentifier(requestIdentifier)
+    , m_lineNumber(0)
+    , m_columnNumber(0)
+    , m_scriptId(0)
     , m_contextId(0)
     , m_type(LogMessageType)
     , m_exceptionId(0)
@@ -232,6 +220,15 @@
 {
 }
 
+void V8ConsoleMessage::setLocation(const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace> stackTrace, int scriptId)
+{
+    m_url = url;
+    m_lineNumber = lineNumber;
+    m_columnNumber = columnNumber;
+    m_stackTrace = std::move(stackTrace);
+    m_scriptId = scriptId;
+}
+
 void V8ConsoleMessage::reportToFrontend(protocol::Console::Frontend* frontend, V8InspectorSessionImpl* session, bool generatePreview) const
 {
     DCHECK_EQ(V8MessageOrigin::kConsole, m_origin);
@@ -257,6 +254,8 @@
         result->setParameters(std::move(args));
     if (m_stackTrace)
         result->setStack(m_stackTrace->buildInspectorObject());
+    if (m_source == WorkerMessageSource && !m_workerId.isEmpty())
+        result->setWorkerId(m_workerId);
     frontend->messageAdded(std::move(result));
 }
 
@@ -376,7 +375,8 @@
             actualMessage = V8ValueStringBuilder::toString(messageArguments.at(0)->Get(context->isolate()), context->isolate());
     }
 
-    std::unique_ptr<V8ConsoleMessage> message = wrapUnique(new V8ConsoleMessage(timestamp, ConsoleAPIMessageSource, level, actualMessage, url, lineNumber, columnNumber, std::move(stackTrace), 0 /* scriptId */, String16() /* requestIdentifier */));
+    std::unique_ptr<V8ConsoleMessage> message = wrapUnique(new V8ConsoleMessage(V8MessageOrigin::kConsole, timestamp, ConsoleAPIMessageSource, level, actualMessage));
+    message->setLocation(url, lineNumber, columnNumber, std::move(stackTrace), 0);
     message->m_type = type;
     if (messageArguments.size()) {
         message->m_contextId = context->contextId();
@@ -390,9 +390,9 @@
 // static
 std::unique_ptr<V8ConsoleMessage> V8ConsoleMessage::createForException(double timestamp, const String16& messageText, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace> stackTrace, int scriptId, v8::Isolate* isolate, int contextId, v8::Local<v8::Value> exception, unsigned exceptionId)
 {
-    std::unique_ptr<V8ConsoleMessage> message = wrapUnique(new V8ConsoleMessage(timestamp, JSMessageSource, ErrorMessageLevel, messageText, url, lineNumber, columnNumber, std::move(stackTrace), scriptId, String16() /* requestIdentifier */));
+    std::unique_ptr<V8ConsoleMessage> message = wrapUnique(new V8ConsoleMessage(V8MessageOrigin::kException, timestamp, JSMessageSource, ErrorMessageLevel, messageText));
+    message->setLocation(url, lineNumber, columnNumber, std::move(stackTrace), scriptId);
     message->m_exceptionId = exceptionId;
-    message->m_origin = V8MessageOrigin::kException;
     if (contextId && !exception.IsEmpty()) {
         message->m_contextId = contextId;
         message->m_arguments.push_back(wrapUnique(new v8::Global<v8::Value>(isolate, exception)));
@@ -403,12 +403,21 @@
 // static
 std::unique_ptr<V8ConsoleMessage> V8ConsoleMessage::createForRevokedException(double timestamp, const String16& messageText, unsigned revokedExceptionId)
 {
-    std::unique_ptr<V8ConsoleMessage> message = wrapUnique(new V8ConsoleMessage(timestamp, JSMessageSource, ErrorMessageLevel, messageText, String16(), 0, 0, nullptr, 0, String16()));
-    message->m_origin = V8MessageOrigin::kRevokedException;
+    std::unique_ptr<V8ConsoleMessage> message = wrapUnique(new V8ConsoleMessage(V8MessageOrigin::kRevokedException, timestamp, JSMessageSource, ErrorMessageLevel, messageText));
     message->m_revokedExceptionId = revokedExceptionId;
     return message;
 }
 
+// static
+std::unique_ptr<V8ConsoleMessage> V8ConsoleMessage::createExternal(double timestamp, MessageSource source, MessageLevel level, const String16& messageText, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace> stackTrace, int scriptId, const String16& requestIdentifier, const String16& workerId)
+{
+    std::unique_ptr<V8ConsoleMessage> message = wrapUnique(new V8ConsoleMessage(V8MessageOrigin::kConsole, timestamp, source, level, messageText));
+    message->setLocation(url, lineNumber, columnNumber, std::move(stackTrace), scriptId);
+    message->m_requestIdentifier = requestIdentifier;
+    message->m_workerId = workerId;
+    return message;
+}
+
 void V8ConsoleMessage::contextDestroyed(int contextId)
 {
     if (contextId != m_contextId)
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.h b/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.h
index 9cdf132..d68d2a1 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.h
+++ b/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.h
@@ -25,17 +25,6 @@
 
 class V8ConsoleMessage {
 public:
-    V8ConsoleMessage(
-        double timestamp,
-        MessageSource,
-        MessageLevel,
-        const String16& message,
-        const String16& url,
-        unsigned lineNumber,
-        unsigned columnNumber,
-        std::unique_ptr<V8StackTrace>,
-        int scriptId,
-        const String16& requestIdentifier);
     ~V8ConsoleMessage();
 
     static std::unique_ptr<V8ConsoleMessage> createForConsoleAPI(
@@ -65,6 +54,19 @@
         const String16& message,
         unsigned revokedExceptionId);
 
+    static std::unique_ptr<V8ConsoleMessage> createExternal(
+        double timestamp,
+        MessageSource,
+        MessageLevel,
+        const String16& message,
+        const String16& url,
+        unsigned lineNumber,
+        unsigned columnNumber,
+        std::unique_ptr<V8StackTrace>,
+        int scriptId,
+        const String16& requestIdentifier,
+        const String16& workerId);
+
     V8MessageOrigin origin() const;
     void reportToFrontend(protocol::Console::Frontend*, V8InspectorSessionImpl*, bool generatePreview) const;
     void reportToFrontend(protocol::Runtime::Frontend*, V8InspectorSessionImpl*, bool generatePreview) const;
@@ -73,9 +75,12 @@
     void contextDestroyed(int contextId);
 
 private:
+    V8ConsoleMessage(V8MessageOrigin, double timestamp, MessageSource, MessageLevel, const String16& message);
+
     using Arguments = std::vector<std::unique_ptr<v8::Global<v8::Value>>>;
     std::unique_ptr<protocol::Array<protocol::Runtime::RemoteObject>> wrapArguments(V8InspectorSessionImpl*, bool generatePreview) const;
     std::unique_ptr<protocol::Runtime::RemoteObject> wrapException(V8InspectorSessionImpl*, bool generatePreview) const;
+    void setLocation(const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace>, int scriptId);
 
     V8MessageOrigin m_origin;
     double m_timestamp;
@@ -88,6 +93,7 @@
     std::unique_ptr<V8StackTrace> m_stackTrace;
     int m_scriptId;
     String16 m_requestIdentifier;
+    String16 m_workerId;
     int m_contextId;
     MessageType m_type;
     unsigned m_exceptionId;
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp
index 1bc5962..6432807 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp
+++ b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp
@@ -28,7 +28,6 @@
 using blink::protocol::Debugger::BreakpointId;
 using blink::protocol::Debugger::CallFrame;
 using blink::protocol::Runtime::ExceptionDetails;
-using blink::protocol::Debugger::FunctionDetails;
 using blink::protocol::Runtime::ScriptId;
 using blink::protocol::Runtime::StackTrace;
 using blink::protocol::Runtime::RemoteObject;
@@ -595,43 +594,6 @@
     *scriptSource = toProtocolString(it->second->source(m_isolate));
 }
 
-void V8DebuggerAgentImpl::getFunctionDetails(ErrorString* errorString, const String16& functionId, std::unique_ptr<FunctionDetails>* details)
-{
-    if (!checkEnabled(errorString))
-        return;
-    InjectedScript::ObjectScope scope(errorString, m_debugger, m_session->contextGroupId(), functionId);
-    if (!scope.initialize())
-        return;
-    if (!scope.object()->IsFunction()) {
-        *errorString = "Value with given id is not a function";
-        return;
-    }
-    v8::Local<v8::Function> function = scope.object().As<v8::Function>();
-
-    v8::Local<v8::Value> scopesValue;
-    v8::Local<v8::Array> scopes;
-    if (m_debugger->functionScopes(function).ToLocal(&scopesValue) && scopesValue->IsArray()) {
-        scopes = scopesValue.As<v8::Array>();
-        if (!scope.injectedScript()->wrapPropertyInArray(errorString, scopes, toV8StringInternalized(m_isolate, "object"), scope.objectGroupName()))
-            return;
-    }
-
-    std::unique_ptr<FunctionDetails> functionDetails = FunctionDetails::create()
-        .setLocation(buildProtocolLocation(String16::number(function->ScriptId()), function->GetScriptLineNumber(), function->GetScriptColumnNumber()))
-        .setFunctionName(toProtocolStringWithTypeCheck(function->GetDebugName()))
-        .setIsGenerator(function->IsGeneratorFunction()).build();
-
-    if (!scopes.IsEmpty()) {
-        protocol::ErrorSupport errorSupport;
-        std::unique_ptr<protocol::Array<protocol::Debugger::Scope>> scopeChain = protocol::Array<protocol::Debugger::Scope>::parse(toProtocolValue(scope.context(), scopes).get(), &errorSupport);
-        if (hasInternalError(errorString, errorSupport.hasErrors()))
-            return;
-        functionDetails->setScopeChain(std::move(scopeChain));
-    }
-
-    *details = std::move(functionDetails);
-}
-
 void V8DebuggerAgentImpl::schedulePauseOnNextStatement(const String16& breakReason, std::unique_ptr<protocol::DictionaryValue> data)
 {
     if (!enabled() || m_scheduledDebuggerStep == StepInto || m_javaScriptPauseScheduled || debugger().isPaused() || !debugger().breakpointsActivated())
@@ -842,10 +804,13 @@
     }
 
     String16Builder patternBuilder;
-    patternBuilder.append("(");
-    for (size_t i = 0; i < patterns->length() - 1; ++i)
-        patternBuilder.append(patterns->get(i) + "|");
-    patternBuilder.append(patterns->get(patterns->length() - 1) + ")");
+    patternBuilder.append('(');
+    for (size_t i = 0; i < patterns->length() - 1; ++i) {
+        patternBuilder.append(patterns->get(i));
+        patternBuilder.append("|");
+    }
+    patternBuilder.append(patterns->get(patterns->length() - 1));
+    patternBuilder.append(')');
     String16 pattern = patternBuilder.toString();
     if (!setBlackboxPattern(errorString, pattern))
         return;
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.h b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.h
index fdae2de..f1960cc 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.h
+++ b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.h
@@ -92,9 +92,6 @@
         std::unique_ptr<protocol::Array<protocol::Debugger::CallFrame>>* newCallFrames,
         Maybe<protocol::Runtime::StackTrace>* asyncStackTrace) override;
     void getScriptSource(ErrorString*, const String16& scriptId, String16* scriptSource) override;
-    void getFunctionDetails(ErrorString*,
-        const String16& functionId,
-        std::unique_ptr<protocol::Debugger::FunctionDetails>*) override;
     void pause(ErrorString*) override;
     void resume(ErrorString*) override;
     void stepOver(ErrorString*) override;
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.cpp
index a0b0639..157f6bf 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.cpp
+++ b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.cpp
@@ -41,6 +41,7 @@
 #include "platform/v8_inspector/V8DebuggerAgentImpl.h"
 #include "platform/v8_inspector/V8InjectedScriptHost.h"
 #include "platform/v8_inspector/V8InspectorSessionImpl.h"
+#include "platform/v8_inspector/V8InternalValueType.h"
 #include "platform/v8_inspector/V8RuntimeAgentImpl.h"
 #include "platform/v8_inspector/V8StackTraceImpl.h"
 #include "platform/v8_inspector/V8StringUtil.h"
@@ -651,7 +652,18 @@
         return v8::Local<v8::Value>::New(m_isolate, v8::Undefined(m_isolate));
     }
     v8::Local<v8::Value> argv[] = { function };
-    return callDebuggerMethod("getFunctionScopes", 1, argv);
+    v8::Local<v8::Value> scopesValue;
+    if (!callDebuggerMethod("getFunctionScopes", 1, argv).ToLocal(&scopesValue) || !scopesValue->IsArray())
+        return v8::MaybeLocal<v8::Value>();
+    v8::Local<v8::Array> scopes = scopesValue.As<v8::Array>();
+    v8::Local<v8::Context> context = m_debuggerContext.Get(m_isolate);
+    if (!markAsInternal(context, scopes, V8InternalValueType::kScopeList))
+        return v8::MaybeLocal<v8::Value>();
+    if (!markArrayEntriesAsInternal(context, scopes, V8InternalValueType::kScope))
+        return v8::MaybeLocal<v8::Value>();
+    if (!scopes->SetPrototype(context, v8::Null(m_isolate)).FromMaybe(false))
+        return v8::Undefined(m_isolate);
+    return scopes;
 }
 
 v8::MaybeLocal<v8::Array> V8DebuggerImpl::internalProperties(v8::Local<v8::Context> context, v8::Local<v8::Value> value)
@@ -659,6 +671,18 @@
     v8::Local<v8::Array> properties;
     if (!v8::Debug::GetInternalProperties(m_isolate, value).ToLocal(&properties))
         return v8::MaybeLocal<v8::Array>();
+    if (value->IsFunction()) {
+        v8::Local<v8::Function> function = value.As<v8::Function>();
+        v8::Local<v8::Value> location = functionLocation(context, function);
+        if (location->IsObject()) {
+            properties->Set(properties->Length(), v8InternalizedString("[[FunctionLocation]]"));
+            properties->Set(properties->Length(), location);
+        }
+        if (function->IsGeneratorFunction()) {
+            properties->Set(properties->Length(), v8InternalizedString("[[IsGenerator]]"));
+            properties->Set(properties->Length(), v8::True(m_isolate));
+        }
+    }
     if (!enabled())
         return properties;
     if (value->IsMap() || value->IsWeakMap() || value->IsSet() || value->IsWeakSet() || value->IsSetIterator() || value->IsMapIterator()) {
@@ -675,6 +699,15 @@
             properties->Set(properties->Length(), location);
         }
     }
+    if (value->IsFunction()) {
+        v8::Local<v8::Function> function = value.As<v8::Function>();
+        v8::Local<v8::Value> boundFunction = function->GetBoundFunction();
+        v8::Local<v8::Value> scopes;
+        if (boundFunction->IsUndefined() && functionScopes(function).ToLocal(&scopes)) {
+            properties->Set(properties->Length(), v8InternalizedString("[[Scopes]]"));
+            properties->Set(properties->Length(), scopes);
+        }
+    }
     return properties;
 }
 
@@ -689,13 +722,8 @@
     if (!entriesValue->IsArray())
         return v8::Undefined(m_isolate);
     v8::Local<v8::Array> entries = entriesValue.As<v8::Array>();
-    for (size_t i = 0; i < entries->Length(); ++i) {
-        v8::Local<v8::Value> entry;
-        if (!entries->Get(context, i).ToLocal(&entry) || !entry->IsObject())
-            continue;
-        if (!entry.As<v8::Object>()->SetPrivate(context, V8InjectedScriptHost::internalEntryPrivate(m_isolate), v8::True(m_isolate)).FromMaybe(false))
-            continue;
-    }
+    if (!markArrayEntriesAsInternal(context, entries, V8InternalValueType::kEntry))
+        return v8::Undefined(m_isolate);
     if (!entries->SetPrototype(context, v8::Null(m_isolate)).FromMaybe(false))
         return v8::Undefined(m_isolate);
     return entries;
@@ -712,7 +740,28 @@
     if (!location->IsObject())
         return v8::Null(m_isolate);
     v8::Local<v8::Context> context = m_debuggerContext.Get(m_isolate);
-    if (!location.As<v8::Object>()->SetPrivate(context, V8InjectedScriptHost::internalLocationPrivate(m_isolate), v8::True(m_isolate)).FromMaybe(false))
+    if (!markAsInternal(context, v8::Local<v8::Object>::Cast(location), V8InternalValueType::kLocation))
+        return v8::Null(m_isolate);
+    return location;
+}
+
+v8::Local<v8::Value> V8DebuggerImpl::functionLocation(v8::Local<v8::Context> context, v8::Local<v8::Function> function)
+{
+    int scriptId = function->ScriptId();
+    if (scriptId == v8::UnboundScript::kNoScriptId)
+        return v8::Null(m_isolate);
+    int lineNumber = function->GetScriptLineNumber();
+    int columnNumber = function->GetScriptColumnNumber();
+    if (lineNumber == v8::Function::kLineOffsetNotFound || columnNumber == v8::Function::kLineOffsetNotFound)
+        return v8::Null(m_isolate);
+    v8::Local<v8::Object> location = v8::Object::New(m_isolate);
+    if (!location->Set(context, v8InternalizedString("scriptId"), toV8String(m_isolate, String16::number(scriptId))).FromMaybe(false))
+        return v8::Null(m_isolate);
+    if (!location->Set(context, v8InternalizedString("lineNumber"), v8::Integer::New(m_isolate, lineNumber)).FromMaybe(false))
+        return v8::Null(m_isolate);
+    if (!location->Set(context, v8InternalizedString("columnNumber"), v8::Integer::New(m_isolate, columnNumber)).FromMaybe(false))
+        return v8::Null(m_isolate);
+    if (!markAsInternal(context, location, V8InternalValueType::kLocation))
         return v8::Null(m_isolate);
     return location;
 }
@@ -1007,11 +1056,11 @@
     m_isolate->GetCpuProfiler()->SetIdle(false);
 }
 
-bool V8DebuggerImpl::addConsoleMessage(int contextGroupId, MessageSource source, MessageLevel level, const String16& message, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace> stackTrace, int scriptId, const String16& requestIdentifier)
+bool V8DebuggerImpl::addConsoleMessage(int contextGroupId, MessageSource source, MessageLevel level, const String16& message, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace> stackTrace, int scriptId, const String16& requestIdentifier, const String16& workerId)
 {
     if (m_muteConsoleCount)
         return false;
-    ensureConsoleMessageStorage(contextGroupId)->addMessage(wrapUnique(new V8ConsoleMessage(m_client->currentTimeMS(), source, level, message, url, lineNumber, columnNumber, std::move(stackTrace), scriptId, requestIdentifier)));
+    ensureConsoleMessageStorage(contextGroupId)->addMessage(V8ConsoleMessage::createExternal(m_client->currentTimeMS(), source, level, message, url, lineNumber, columnNumber, std::move(stackTrace), scriptId, requestIdentifier, workerId));
     return true;
 }
 
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.h b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.h
index a4596af..9435684 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.h
+++ b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.h
@@ -129,7 +129,7 @@
     void didExecuteScript(v8::Local<v8::Context>) override;
     void idleStarted() override;
     void idleFinished() override;
-    bool addConsoleMessage(int contextGroupId, MessageSource, MessageLevel, const String16& message, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace>, int scriptId, const String16& requestIdentifier) override;
+    bool addConsoleMessage(int contextGroupId, MessageSource, MessageLevel, const String16& message, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace>, int scriptId, const String16& requestIdentifier, const String16& workerId) override;
     void logToConsole(v8::Local<v8::Context>, const String16& message, v8::Local<v8::Value> arg1, v8::Local<v8::Value> arg2) override;
     void exceptionThrown(int contextGroupId, const String16& errorMessage, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace>, int scriptId) override;
     unsigned promiseRejected(v8::Local<v8::Context>, const String16& errorMessage, v8::Local<v8::Value> exception, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace>, int scriptId) override;
@@ -177,6 +177,7 @@
 
     v8::Local<v8::Value> collectionEntries(v8::Local<v8::Context>, v8::Local<v8::Object>);
     v8::Local<v8::Value> generatorObjectLocation(v8::Local<v8::Object>);
+    v8::Local<v8::Value> functionLocation(v8::Local<v8::Context>, v8::Local<v8::Function>);
 
     v8::Isolate* m_isolate;
     V8DebuggerClient* m_client;
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.cpp
index 1ef3bbba..d4083f60 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.cpp
+++ b/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.cpp
@@ -8,6 +8,7 @@
 #include "platform/v8_inspector/InjectedScriptNative.h"
 #include "platform/v8_inspector/V8Compat.h"
 #include "platform/v8_inspector/V8DebuggerImpl.h"
+#include "platform/v8_inspector/V8InternalValueType.h"
 #include "platform/v8_inspector/V8StringUtil.h"
 #include "platform/v8_inspector/public/V8DebuggerClient.h"
 
@@ -54,16 +55,6 @@
     return injectedScriptHost;
 }
 
-v8::Local<v8::Private> V8InjectedScriptHost::internalEntryPrivate(v8::Isolate* isolate)
-{
-    return v8::Private::ForApi(isolate, toV8StringInternalized(isolate, "V8InjectedScriptHost#internalEntry"));
-}
-
-v8::Local<v8::Private> V8InjectedScriptHost::internalLocationPrivate(v8::Isolate* isolate)
-{
-    return v8::Private::ForApi(isolate, toV8StringInternalized(isolate, "V8InjectedScriptHost#internalLocation"));
-}
-
 void V8InjectedScriptHost::internalConstructorNameCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
     if (info.Length() < 1 || !info[0]->IsObject())
@@ -100,6 +91,13 @@
 
     v8::Isolate* isolate = info.GetIsolate();
     v8::Local<v8::Value> value = info[0];
+    if (value->IsObject()) {
+        v8::Local<v8::Value> internalType = v8InternalValueTypeFrom(isolate->GetCurrentContext(), v8::Local<v8::Object>::Cast(value));
+        if (internalType->IsString()) {
+            info.GetReturnValue().Set(internalType);
+            return;
+        }
+    }
     if (value->IsArray() || value->IsTypedArray() || value->IsArgumentsObject()) {
         info.GetReturnValue().Set(toV8StringInternalized(isolate, "array"));
         return;
@@ -136,17 +134,6 @@
         info.GetReturnValue().Set(toV8StringInternalized(isolate, "proxy"));
         return;
     }
-    if (value->IsObject()) {
-        v8::Local<v8::Object> obj = value.As<v8::Object>();
-        if (obj->HasPrivate(isolate->GetCurrentContext(), internalEntryPrivate(isolate)).FromMaybe(false)) {
-            info.GetReturnValue().Set(toV8StringInternalized(isolate, "internal#entry"));
-            return;
-        }
-        if (obj->HasPrivate(isolate->GetCurrentContext(), internalLocationPrivate(isolate)).FromMaybe(false)) {
-            info.GetReturnValue().Set(toV8StringInternalized(isolate, "internal#location"));
-            return;
-        }
-    }
     String16 subtype = unwrapDebugger(info)->client()->valueSubtype(value);
     if (!subtype.isEmpty()) {
         info.GetReturnValue().Set(toV8String(isolate, subtype));
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.h b/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.h
index 9a25824..bf49fa71 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.h
+++ b/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.h
@@ -21,10 +21,6 @@
     // We expect that debugger outlives any JS context and thus V8InjectedScriptHost (owned by JS)
     // is destroyed before debugger.
     static v8::Local<v8::Object> create(v8::Local<v8::Context>, V8DebuggerImpl*);
-
-    static v8::Local<v8::Private> internalEntryPrivate(v8::Isolate*);
-    static v8::Local<v8::Private> internalLocationPrivate(v8::Isolate*);
-
 private:
     static void internalConstructorNameCallback(const v8::FunctionCallbackInfo<v8::Value>&);
     static void formatAccessorsAsProperties(const v8::FunctionCallbackInfo<v8::Value>&);
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8InternalValueType.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8InternalValueType.cpp
new file mode 100644
index 0000000..fcb56e3
--- /dev/null
+++ b/third_party/WebKit/Source/platform/v8_inspector/V8InternalValueType.cpp
@@ -0,0 +1,71 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/v8_inspector/V8InternalValueType.h"
+
+#include "platform/v8_inspector/V8StringUtil.h"
+
+namespace blink {
+
+namespace {
+
+v8::Local<v8::Private> internalSubtypePrivate(v8::Isolate* isolate)
+{
+    return v8::Private::ForApi(isolate, toV8StringInternalized(isolate, "V8InternalType#internalSubtype"));
+}
+
+v8::Local<v8::String> subtypeForInternalType(v8::Isolate* isolate, V8InternalValueType type)
+{
+    switch (type) {
+    case V8InternalValueType::kEntry:
+        return toV8StringInternalized(isolate, "internal#entry");
+    case V8InternalValueType::kLocation:
+        return toV8StringInternalized(isolate, "internal#location");
+    case V8InternalValueType::kScope:
+        return toV8StringInternalized(isolate, "internal#scope");
+    case V8InternalValueType::kScopeList:
+        return toV8StringInternalized(isolate, "internal#scopeList");
+    }
+    NOTREACHED();
+    return v8::Local<v8::String>();
+}
+
+} // namespace
+
+bool markAsInternal(v8::Local<v8::Context> context, v8::Local<v8::Object> object, V8InternalValueType type)
+{
+    v8::Isolate* isolate = context->GetIsolate();
+    v8::Local<v8::Private> privateValue = internalSubtypePrivate(isolate);
+    v8::Local<v8::String> subtype = subtypeForInternalType(isolate, type);
+    return object->SetPrivate(context, privateValue, subtype).FromMaybe(false);
+}
+
+bool markArrayEntriesAsInternal(v8::Local<v8::Context> context, v8::Local<v8::Array> array, V8InternalValueType type)
+{
+    v8::Isolate* isolate = context->GetIsolate();
+    v8::Local<v8::Private> privateValue = internalSubtypePrivate(isolate);
+    v8::Local<v8::String> subtype = subtypeForInternalType(isolate, type);
+    for (size_t i = 0; i < array->Length(); ++i) {
+        v8::Local<v8::Value> entry;
+        if (!array->Get(context, i).ToLocal(&entry) || !entry->IsObject())
+            return false;
+        if (!entry.As<v8::Object>()->SetPrivate(context, privateValue, subtype).FromMaybe(false))
+            return false;
+    }
+    return true;
+}
+
+v8::Local<v8::Value> v8InternalValueTypeFrom(v8::Local<v8::Context> context, v8::Local<v8::Object> object)
+{
+    v8::Isolate* isolate = context->GetIsolate();
+    v8::Local<v8::Private> privateValue = internalSubtypePrivate(isolate);
+    if (!object->HasPrivate(context, privateValue).FromMaybe(false))
+        return v8::Null(isolate);
+    v8::Local<v8::Value> subtypeValue;
+    if (!object->GetPrivate(context, privateValue).ToLocal(&subtypeValue) || !subtypeValue->IsString())
+        return v8::Null(isolate);
+    return subtypeValue;
+}
+
+} // namespace blink
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8InternalValueType.h b/third_party/WebKit/Source/platform/v8_inspector/V8InternalValueType.h
new file mode 100644
index 0000000..4bb7172
--- /dev/null
+++ b/third_party/WebKit/Source/platform/v8_inspector/V8InternalValueType.h
@@ -0,0 +1,21 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8InternalValueType_h
+#define V8InternalValueType_h
+
+#include <v8.h>
+
+namespace blink {
+
+enum class V8InternalValueType { kEntry, kLocation, kScope, kScopeList };
+
+bool markAsInternal(v8::Local<v8::Context>, v8::Local<v8::Object>, V8InternalValueType);
+bool markArrayEntriesAsInternal(v8::Local<v8::Context>, v8::Local<v8::Array>, V8InternalValueType);
+v8::Local<v8::Value> v8InternalValueTypeFrom(v8::Local<v8::Context>, v8::Local<v8::Object>);
+
+
+} // namespace blink
+
+#endif // V8InternalValueType_h
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8StackTraceImpl.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8StackTraceImpl.cpp
index 5c79b57..e7fb57a 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/V8StackTraceImpl.cpp
+++ b/third_party/WebKit/Source/platform/v8_inspector/V8StackTraceImpl.cpp
@@ -72,6 +72,8 @@
     , m_lineNumber(lineNumber)
     , m_columnNumber(column)
 {
+    DCHECK(m_lineNumber != v8::Message::kNoLineNumberInfo);
+    DCHECK(m_columnNumber != v8::Message::kNoColumnInfo);
 }
 
 V8StackTraceImpl::Frame::~Frame()
@@ -86,8 +88,8 @@
         .setFunctionName(m_functionName)
         .setScriptId(m_scriptId)
         .setUrl(m_scriptName)
-        .setLineNumber(m_lineNumber)
-        .setColumnNumber(m_columnNumber)
+        .setLineNumber(m_lineNumber - 1)
+        .setColumnNumber(m_columnNumber - 1)
         .build();
 }
 
diff --git a/third_party/WebKit/Source/platform/v8_inspector/js_protocol.json b/third_party/WebKit/Source/platform/v8_inspector/js_protocol.json
index 1a630c2..b01d7a4c 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/js_protocol.json
+++ b/third_party/WebKit/Source/platform/v8_inspector/js_protocol.json
@@ -152,8 +152,8 @@
                     { "name": "functionName", "type": "string", "description": "JavaScript function name." },
                     { "name": "scriptId", "$ref": "ScriptId", "description": "JavaScript script id." },
                     { "name": "url", "type": "string", "description": "JavaScript script name or url." },
-                    { "name": "lineNumber", "type": "integer", "description": "JavaScript script line number." },
-                    { "name": "columnNumber", "type": "integer", "description": "JavaScript script column number." }
+                    { "name": "lineNumber", "type": "integer", "description": "JavaScript script line number (0-based)." },
+                    { "name": "columnNumber", "type": "integer", "description": "JavaScript script column number (0-based)." }
                 ]
             },
             {
@@ -376,18 +376,6 @@
                 "description": "Location in the source code."
             },
             {
-                "id": "FunctionDetails",
-                "hidden": true,
-                "type": "object",
-                "properties": [
-                    { "name": "location", "$ref": "Location", "optional": true, "description": "Location of the function, none for native functions." },
-                    { "name": "functionName", "type": "string", "description": "Name of the function." },
-                    { "name": "isGenerator", "type": "boolean", "description": "Whether this is a generator function." },
-                    { "name": "scopeChain", "type": "array", "optional": true, "items": { "$ref": "Scope" }, "description": "Scope chain for this closure." }
-                ],
-                "description": "Information about the function."
-            },
-            {
                 "id": "CallFrame",
                 "type": "object",
                 "properties": [
@@ -579,17 +567,6 @@
                 "description": "Returns source for the script with given id."
             },
             {
-                "name": "getFunctionDetails",
-                "hidden": true,
-                "parameters": [
-                    { "name": "functionId", "$ref": "Runtime.RemoteObjectId", "description": "Id of the function to get details for." }
-                ],
-                "returns": [
-                    { "name": "details", "$ref": "FunctionDetails", "description": "Information about the function." }
-                ],
-                "description": "Returns detailed information on given function."
-            },
-            {
                 "name": "setPauseOnExceptions",
                 "parameters": [
                     { "name": "state", "type": "string", "enum": ["none", "uncaught", "all"], "description": "Pause on exceptions mode." }
@@ -741,7 +718,7 @@
                 "type": "object",
                 "description": "Console message.",
                 "properties": [
-                    { "name": "source", "type": "string", "enum": ["xml", "javascript", "network", "console-api", "storage", "appcache", "rendering", "security", "other", "deprecation"], "description": "Message source." },
+                    { "name": "source", "type": "string", "enum": ["xml", "javascript", "network", "console-api", "storage", "appcache", "rendering", "security", "other", "deprecation", "worker"], "description": "Message source." },
                     { "name": "level", "type": "string", "enum": ["log", "warning", "error", "debug", "info"], "description": "Message severity." },
                     { "name": "text", "type": "string", "description": "Message text." },
                     { "name": "type", "type": "string", "optional": true, "enum": ["log", "dir", "dirxml", "table", "trace", "clear", "startGroup", "startGroupCollapsed", "endGroup", "assert", "profile", "profileEnd"], "description": "Console message type." },
@@ -754,7 +731,8 @@
                     { "name": "stack", "$ref": "Runtime.StackTrace", "optional": true, "description": "JavaScript stack trace for assertions and error messages." },
                     { "name": "networkRequestId", "type": "string", "optional": true, "description": "Identifier of the network request associated with this message." },
                     { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp, when this message was fired.", "hidden": true },
-                    { "name": "executionContextId", "$ref": "Runtime.ExecutionContextId", "optional": true, "description": "Identifier of the context where this message was created", "hidden": true }
+                    { "name": "executionContextId", "$ref": "Runtime.ExecutionContextId", "optional": true, "description": "Identifier of the context where this message was created", "hidden": true },
+                    { "name": "workerId", "type": "string", "optional": true, "description": "Identifier of the worker this message came from.", "hidden": true }
                 ]
             }
         ],
diff --git a/third_party/WebKit/Source/platform/v8_inspector/public/V8ConsoleTypes.h b/third_party/WebKit/Source/platform/v8_inspector/public/V8ConsoleTypes.h
index 75f26fe2..544da40 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/public/V8ConsoleTypes.h
+++ b/third_party/WebKit/Source/platform/v8_inspector/public/V8ConsoleTypes.h
@@ -18,6 +18,7 @@
     SecurityMessageSource,
     OtherMessageSource,
     DeprecationMessageSource,
+    WorkerMessageSource
 };
 
 enum MessageLevel {
diff --git a/third_party/WebKit/Source/platform/v8_inspector/public/V8Debugger.h b/third_party/WebKit/Source/platform/v8_inspector/public/V8Debugger.h
index c0ebce29..e6cb6f8 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/public/V8Debugger.h
+++ b/third_party/WebKit/Source/platform/v8_inspector/public/V8Debugger.h
@@ -39,8 +39,8 @@
     virtual void didExecuteScript(v8::Local<v8::Context>) = 0;
     virtual void idleStarted() = 0;
     virtual void idleFinished() = 0;
-    // TODO(dgozman): remove requestIdentifier.
-    virtual bool addConsoleMessage(int contextGroupId, MessageSource, MessageLevel, const String16& message, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace>, int scriptId, const String16& requestIdentifier) = 0;
+    // TODO(dgozman): remove requestIdentifier and workerId.
+    virtual bool addConsoleMessage(int contextGroupId, MessageSource, MessageLevel, const String16& message, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace>, int scriptId, const String16& requestIdentifier, const String16& workerId) = 0;
     // TODO(dgozman): can we remove this method?
     virtual void logToConsole(v8::Local<v8::Context>, const String16& message, v8::Local<v8::Value> arg1, v8::Local<v8::Value> arg2) = 0;
     // TODO(dgozman): can we pass exception object?
diff --git a/third_party/WebKit/Source/platform/v8_inspector/public/V8InspectorSessionClient.h b/third_party/WebKit/Source/platform/v8_inspector/public/V8InspectorSessionClient.h
index fb52973..1378b110e 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/public/V8InspectorSessionClient.h
+++ b/third_party/WebKit/Source/platform/v8_inspector/public/V8InspectorSessionClient.h
@@ -22,7 +22,6 @@
     virtual bool canExecuteScripts() = 0;
     virtual void profilingStarted() = 0;
     virtual void profilingStopped() = 0;
-    virtual void consoleEnabled() = 0;
     virtual void consoleCleared() = 0;
 };
 
diff --git a/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.cpp b/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.cpp
index be4f185c..e99659a 100644
--- a/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.cpp
+++ b/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.cpp
@@ -65,50 +65,40 @@
 
 static URLSchemesSet& mixedContentRestrictingSchemes()
 {
-    DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesSet, mixedContentRestrictingSchemes, ());
-
-    if (mixedContentRestrictingSchemes.isEmpty())
-        mixedContentRestrictingSchemes.add("https");
-
+    DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesSet, mixedContentRestrictingSchemes, ({
+        "https",
+    }));
     return mixedContentRestrictingSchemes;
 }
 
 static URLSchemesSet& secureSchemes()
 {
-    DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesSet, secureSchemes, ());
-
-    if (secureSchemes.isEmpty()) {
-        secureSchemes.add("https");
-        secureSchemes.add("about");
-        secureSchemes.add("data");
-        secureSchemes.add("wss");
-    }
-
+    DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesSet, secureSchemes, ({
+        "https",
+        "about",
+        "data",
+        "wss",
+    }));
     return secureSchemes;
 }
 
 static URLSchemesSet& schemesWithUniqueOrigins()
 {
-    DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesSet, schemesWithUniqueOrigins, ());
-
-    if (schemesWithUniqueOrigins.isEmpty()) {
-        schemesWithUniqueOrigins.add("about");
-        schemesWithUniqueOrigins.add("javascript");
+    DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesSet, schemesWithUniqueOrigins, ({
+        "about",
+        "javascript",
         // This is a willful violation of HTML5.
         // See https://bugs.webkit.org/show_bug.cgi?id=11885
-        schemesWithUniqueOrigins.add("data");
-    }
-
+        "data",
+    }));
     return schemesWithUniqueOrigins;
 }
 
 static URLSchemesSet& emptyDocumentSchemes()
 {
-    DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesSet, emptyDocumentSchemes, ());
-
-    if (emptyDocumentSchemes.isEmpty())
-        emptyDocumentSchemes.add("about");
-
+    DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesSet, emptyDocumentSchemes, ({
+        "about",
+    }));
     return emptyDocumentSchemes;
 }
 
diff --git a/third_party/WebKit/Source/platform/weborigin/SecurityOrigin.cpp b/third_party/WebKit/Source/platform/weborigin/SecurityOrigin.cpp
index 4560bab..e2ad63b 100644
--- a/third_party/WebKit/Source/platform/weborigin/SecurityOrigin.cpp
+++ b/third_party/WebKit/Source/platform/weborigin/SecurityOrigin.cpp
@@ -505,7 +505,7 @@
     builder.append("://");
     if (includeSuborigin && hasSuborigin()) {
         builder.append(m_suborigin.name());
-        builder.append("_");
+        builder.append('_');
     }
     builder.append(m_host);
 
diff --git a/third_party/WebKit/Source/web/AssociatedURLLoaderTest.cpp b/third_party/WebKit/Source/web/AssociatedURLLoaderTest.cpp
index f1a6a401..1fdf3d3 100644
--- a/third_party/WebKit/Source/web/AssociatedURLLoaderTest.cpp
+++ b/third_party/WebKit/Source/web/AssociatedURLLoaderTest.cpp
@@ -184,7 +184,6 @@
     void CheckMethodFails(const char* unsafeMethod)
     {
         WebURLRequest request;
-        request.initialize();
         request.setURL(toKURL("http://www.test.com/success.html"));
         request.setHTTPMethod(WebString::fromUTF8(unsafeMethod));
         WebURLLoaderOptions options;
@@ -200,7 +199,6 @@
     void CheckHeaderFails(const char* headerField, const char* headerValue)
     {
         WebURLRequest request;
-        request.initialize();
         request.setURL(toKURL("http://www.test.com/success.html"));
         if (equalIgnoringCase(WebString::fromUTF8(headerField), "referer"))
             request.setHTTPReferrer(WebString::fromUTF8(headerValue), WebReferrerPolicyDefault);
@@ -235,7 +233,6 @@
 
         KURL url = toKURL(id);
         WebURLRequest request;
-        request.initialize();
         request.setURL(url);
 
         WebString headerNameString(WebString::fromUTF8(headerName));
@@ -288,7 +285,6 @@
 {
     KURL url = toKURL("http://www.test.com/SameOriginSuccess.html");
     WebURLRequest request;
-    request.initialize();
     request.setURL(url);
 
     m_expectedResponse = WebURLResponse();
@@ -311,7 +307,6 @@
     // This is cross-origin since the frame was loaded from www.test.com.
     KURL url = toKURL("http://www.other.com/SameOriginRestriction.html");
     WebURLRequest request;
-    request.initialize();
     request.setURL(url);
     CheckFails(request);
 }
@@ -322,7 +317,6 @@
     // This is cross-origin since the frame was loaded from www.test.com.
     KURL url = toKURL("http://www.other.com/CrossOriginSuccess");
     WebURLRequest request;
-    request.initialize();
     request.setURL(url);
     // No-CORS requests (CrossOriginRequestPolicyAllow) aren't allowed for the
     // default context. So we set the context as Script here.
@@ -350,7 +344,6 @@
     // This is cross-origin since the frame was loaded from www.test.com.
     KURL url = toKURL("http://www.other.com/CrossOriginWithAccessControlSuccess.html");
     WebURLRequest request;
-    request.initialize();
     request.setURL(url);
 
     m_expectedResponse = WebURLResponse();
@@ -376,7 +369,6 @@
     // This is cross-origin since the frame was loaded from www.test.com.
     KURL url = toKURL("http://www.other.com/CrossOriginWithAccessControlFailure.html");
     WebURLRequest request;
-    request.initialize();
     request.setURL(url);
 
     m_expectedResponse = WebURLResponse();
@@ -408,7 +400,6 @@
     // This is cross-origin since the frame was loaded from www.test.com.
     KURL url = toKURL("http://www.other.com/CrossOriginWithAccessControlFailure.html");
     WebURLRequest request;
-    request.initialize();
     request.setURL(url);
 
     m_expectedResponse = WebURLResponse();
@@ -439,7 +430,6 @@
     KURL redirectURL = toKURL(redirect);
 
     WebURLRequest request;
-    request.initialize();
     request.setURL(url);
 
     m_expectedRedirectResponse = WebURLResponse();
@@ -449,7 +439,6 @@
     Platform::current()->getURLLoaderMockFactory()->registerURL(url, m_expectedRedirectResponse, m_frameFilePath);
 
     m_expectedNewRequest = WebURLRequest();
-    m_expectedNewRequest.initialize();
     m_expectedNewRequest.setURL(redirectURL);
 
     m_expectedResponse = WebURLResponse();
@@ -475,7 +464,6 @@
     KURL redirectURL = toKURL(redirect);
 
     WebURLRequest request;
-    request.initialize();
     request.setURL(url);
 
     m_expectedRedirectResponse = WebURLResponse();
@@ -485,7 +473,6 @@
     Platform::current()->getURLLoaderMockFactory()->registerURL(url, m_expectedRedirectResponse, m_frameFilePath);
 
     m_expectedNewRequest = WebURLRequest();
-    m_expectedNewRequest.initialize();
     m_expectedNewRequest.setURL(redirectURL);
 
     m_expectedResponse = WebURLResponse();
@@ -512,7 +499,6 @@
     KURL redirectURL = toKURL(redirect);
 
     WebURLRequest request;
-    request.initialize();
     request.setURL(url);
 
     m_expectedRedirectResponse = WebURLResponse();
@@ -522,7 +508,6 @@
     Platform::current()->getURLLoaderMockFactory()->registerURL(url, m_expectedRedirectResponse, m_frameFilePath);
 
     m_expectedNewRequest = WebURLRequest();
-    m_expectedNewRequest.initialize();
     m_expectedNewRequest.setURL(redirectURL);
 
     m_expectedResponse = WebURLResponse();
@@ -552,7 +537,6 @@
     KURL redirectURL = toKURL(redirect);
 
     WebURLRequest request;
-    request.initialize();
     request.setURL(url);
     // Add a CORS simple header.
     request.setHTTPHeaderField("accept", "application/json");
@@ -566,7 +550,6 @@
     Platform::current()->getURLLoaderMockFactory()->registerURL(url, m_expectedRedirectResponse, m_frameFilePath);
 
     m_expectedNewRequest = WebURLRequest();
-    m_expectedNewRequest.initialize();
     m_expectedNewRequest.setURL(redirectURL);
     m_expectedNewRequest.setHTTPHeaderField("accept", "application/json");
 
@@ -678,7 +661,6 @@
 TEST_F(AssociatedURLLoaderTest, CrossOriginHeaderAllowResponseHeaders)
 {
     WebURLRequest request;
-    request.initialize();
     KURL url = toKURL("http://www.other.com/CrossOriginHeaderAllowResponseHeaders.html");
     request.setURL(url);
 
diff --git a/third_party/WebKit/Source/web/ExternalPopupMenu.cpp b/third_party/WebKit/Source/web/ExternalPopupMenu.cpp
index 59c77900..c92afdc 100644
--- a/third_party/WebKit/Source/web/ExternalPopupMenu.cpp
+++ b/third_party/WebKit/Source/web/ExternalPopupMenu.cpp
@@ -213,7 +213,7 @@
         ownerElement->valueChanged(static_cast<unsigned>(-1));
     } else {
         for (size_t i = 0; i < indices.size(); ++i)
-            ownerElement->listBoxSelectItem(toPopupMenuItemIndex(indices[i], *ownerElement), (i > 0), false, (i == indices.size() - 1));
+            ownerElement->listBoxSelectItem(toPopupMenuItemIndex(indices[i], *ownerElement), (i > 0), (i == indices.size() - 1));
     }
 
     m_webExternalPopupMenu = 0;
diff --git a/third_party/WebKit/Source/web/FullscreenController.cpp b/third_party/WebKit/Source/web/FullscreenController.cpp
index 39914a7..6e14369 100644
--- a/third_party/WebKit/Source/web/FullscreenController.cpp
+++ b/third_party/WebKit/Source/web/FullscreenController.cpp
@@ -60,7 +60,7 @@
 {
 }
 
-void FullscreenController::didEnterFullScreen()
+void FullscreenController::didEnterFullscreen()
 {
     if (!m_provisionalFullScreenElement)
         return;
@@ -81,7 +81,7 @@
         m_haveEnteredFullscreen = true;
     }
 
-    Fullscreen::from(document).didEnterFullScreenForElement(element);
+    Fullscreen::from(document).didEnterFullscreenForElement(element);
     DCHECK_EQ(Fullscreen::currentFullScreenElementFrom(document), element);
 
     if (isHTMLVideoElement(element)) {
@@ -91,7 +91,7 @@
     }
 }
 
-void FullscreenController::didExitFullScreen()
+void FullscreenController::didExitFullscreen()
 {
     if (!m_fullScreenFrame)
         return;
@@ -120,7 +120,7 @@
                     m_webViewImpl->setVisualViewportOffset(m_exitFullscreenVisualViewportOffset);
                 }
 
-                fullscreen->didExitFullScreenForElement();
+                fullscreen->didExitFullscreen();
             }
         }
     }
@@ -140,11 +140,11 @@
     // We are already in fullscreen mode.
     if (m_fullScreenFrame) {
         m_provisionalFullScreenElement = element;
-        didEnterFullScreen();
+        didEnterFullscreen();
         return;
     }
 
-    // We need to store these values here rather than didEnterFullScreen since
+    // We need to store these values here rather than didEnterFullscreen since
     // by the time the latter is called, a Resize has already occured, clamping
     // the scroll offset.
     if (!m_haveEnteredFullscreen) {
@@ -216,4 +216,3 @@
 }
 
 } // namespace blink
-
diff --git a/third_party/WebKit/Source/web/FullscreenController.h b/third_party/WebKit/Source/web/FullscreenController.h
index 039535c..a4e1ffd 100644
--- a/third_party/WebKit/Source/web/FullscreenController.h
+++ b/third_party/WebKit/Source/web/FullscreenController.h
@@ -46,8 +46,8 @@
 public:
     static FullscreenController* create(WebViewImpl*);
 
-    void didEnterFullScreen();
-    void didExitFullScreen();
+    void didEnterFullscreen();
+    void didExitFullscreen();
 
     void enterFullScreenForElement(Element*);
     void exitFullScreenForElement(Element*);
diff --git a/third_party/WebKit/Source/web/PageOverlay.h b/third_party/WebKit/Source/web/PageOverlay.h
index 2f39d28..09a6c3a 100644
--- a/third_party/WebKit/Source/web/PageOverlay.h
+++ b/third_party/WebKit/Source/web/PageOverlay.h
@@ -39,14 +39,9 @@
 namespace blink {
 
 class GraphicsContext;
-class WebPageOverlay;
 class WebViewImpl;
 
 // Manages a layer that is overlaid on a WebView's content.
-// Clients can paint by implementing WebPageOverlay.
-//
-// With Slimming Paint, internal clients can extract a GraphicsContext to add
-// to the PaintController owned by the GraphicsLayer
 class WEB_EXPORT PageOverlay : public GraphicsLayerClient, public DisplayItemClient {
 public:
     class Delegate : public GarbageCollectedFinalized<Delegate> {
diff --git a/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeProxy.h b/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeProxy.h
index 6d3b95b..60750e1 100644
--- a/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeProxy.h
+++ b/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeProxy.h
@@ -87,7 +87,6 @@
     void reportException(const String& errorMessage, std::unique_ptr<SourceLocation>) override;
     void reportConsoleMessage(ConsoleMessage*) override;
     void postMessageToPageInspector(const String&) override;
-    void postWorkerConsoleAgentEnabled() override { }
     void didEvaluateWorkerScript(bool success) override;
     void didInitializeWorkerContext() override;
     void workerGlobalScopeStarted(WorkerGlobalScope*) override;
diff --git a/third_party/WebKit/Source/web/WebDataSourceImpl.cpp b/third_party/WebKit/Source/web/WebDataSourceImpl.cpp
index 6a086e9a..4f97c50 100644
--- a/third_party/WebKit/Source/web/WebDataSourceImpl.cpp
+++ b/third_party/WebKit/Source/web/WebDataSourceImpl.cpp
@@ -47,13 +47,11 @@
 
 const WebURLRequest& WebDataSourceImpl::originalRequest() const
 {
-    m_originalRequestWrapper.bind(DocumentLoader::originalRequest());
     return m_originalRequestWrapper;
 }
 
 const WebURLRequest& WebDataSourceImpl::request() const
 {
-    m_requestWrapper.bind(DocumentLoader::request());
     return m_requestWrapper;
 }
 
@@ -134,6 +132,8 @@
 
 WebDataSourceImpl::WebDataSourceImpl(LocalFrame* frame, const ResourceRequest& request, const SubstituteData& data)
     : DocumentLoader(frame, request, data)
+    , m_originalRequestWrapper(DocumentLoader::originalRequest())
+    , m_requestWrapper(DocumentLoader::request())
     , m_responseWrapper(DocumentLoader::response())
 {
 }
diff --git a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
index c126931..2195baa 100644
--- a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
+++ b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
@@ -228,14 +228,14 @@
     m_ignoreInputEvents = newValue;
 }
 
-void WebFrameWidgetImpl::didEnterFullScreen()
+void WebFrameWidgetImpl::didEnterFullscreen()
 {
-    view()->didEnterFullScreen();
+    view()->didEnterFullscreen();
 }
 
-void WebFrameWidgetImpl::didExitFullScreen()
+void WebFrameWidgetImpl::didExitFullscreen()
 {
-    view()->didExitFullScreen();
+    view()->didExitFullscreen();
 }
 
 void WebFrameWidgetImpl::beginFrame(double lastFrameTimeMonotonic)
diff --git a/third_party/WebKit/Source/web/WebFrameWidgetImpl.h b/third_party/WebKit/Source/web/WebFrameWidgetImpl.h
index e06018a..b6ebe6a9 100644
--- a/third_party/WebKit/Source/web/WebFrameWidgetImpl.h
+++ b/third_party/WebKit/Source/web/WebFrameWidgetImpl.h
@@ -74,8 +74,8 @@
     WebSize size() override;
     void resize(const WebSize&) override;
     void resizeVisualViewport(const WebSize&) override;
-    void didEnterFullScreen() override;
-    void didExitFullScreen() override;
+    void didEnterFullscreen() override;
+    void didExitFullscreen() override;
     void beginFrame(double lastFrameTimeMonotonic) override;
     void updateAllLifecyclePhases() override;
     void paint(WebCanvas*, const WebRect&) override;
diff --git a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
index a4a1f40..a889e406 100644
--- a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
+++ b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
@@ -995,6 +995,11 @@
     Element* editable = frame()->selection().rootEditableElementOrDocumentElement();
     if (!editable)
         return false;
+
+    // TODO(dglazkov): The use of updateStyleAndLayoutIgnorePendingStylesheets needs to be audited.
+    // see http://crbug.com/590369 for more details.
+    editable->document().updateStyleAndLayoutIgnorePendingStylesheets();
+
     const EphemeralRange range = PlainTextRange(location, location + length).createRange(*editable);
     if (range.isNull())
         return false;
diff --git a/third_party/WebKit/Source/web/WebRange.cpp b/third_party/WebKit/Source/web/WebRange.cpp
index 261bbe9..49cd2fa9 100644
--- a/third_party/WebKit/Source/web/WebRange.cpp
+++ b/third_party/WebKit/Source/web/WebRange.cpp
@@ -79,6 +79,11 @@
     LocalFrame* webFrame = toWebLocalFrameImpl(frame)->frame();
     Element* selectionRoot = webFrame->selection().rootEditableElement();
     ContainerNode* scope = selectionRoot ? selectionRoot : webFrame->document()->documentElement();
+
+    // TODO(dglazkov): The use of updateStyleAndLayoutIgnorePendingStylesheets needs to be audited.
+    // see http://crbug.com/590369 for more details.
+    scope->document().updateStyleAndLayoutIgnorePendingStylesheets();
+
     return createRange(PlainTextRange(start, start + length).createRange(*scope));
 }
 
diff --git a/third_party/WebKit/Source/web/WebRemoteFrameImpl.cpp b/third_party/WebKit/Source/web/WebRemoteFrameImpl.cpp
index 17e6630a5..ef3f0a4 100644
--- a/third_party/WebKit/Source/web/WebRemoteFrameImpl.cpp
+++ b/third_party/WebKit/Source/web/WebRemoteFrameImpl.cpp
@@ -524,7 +524,7 @@
     return owner->layoutObject()->style()->pointerEvents() == PE_NONE;
 }
 
-void WebRemoteFrameImpl::willEnterFullScreen()
+void WebRemoteFrameImpl::willEnterFullscreen()
 {
     // This should only ever be called when the FrameOwner is local.
     HTMLFrameOwnerElement* ownerElement = toHTMLFrameOwnerElement(frame()->owner());
diff --git a/third_party/WebKit/Source/web/WebRemoteFrameImpl.h b/third_party/WebKit/Source/web/WebRemoteFrameImpl.h
index 82cde800..6bb8a28 100644
--- a/third_party/WebKit/Source/web/WebRemoteFrameImpl.h
+++ b/third_party/WebKit/Source/web/WebRemoteFrameImpl.h
@@ -129,7 +129,7 @@
 
     bool isIgnoredForHitTest() const override;
 
-    void willEnterFullScreen() override;
+    void willEnterFullscreen() override;
 
     DECLARE_TRACE();
 
diff --git a/third_party/WebKit/Source/web/WebSharedWorkerImpl.h b/third_party/WebKit/Source/web/WebSharedWorkerImpl.h
index 3c675336..f0d5a88 100644
--- a/third_party/WebKit/Source/web/WebSharedWorkerImpl.h
+++ b/third_party/WebKit/Source/web/WebSharedWorkerImpl.h
@@ -78,7 +78,6 @@
     void reportException(const WTF::String&, std::unique_ptr<SourceLocation>) override;
     void reportConsoleMessage(ConsoleMessage*) override;
     void postMessageToPageInspector(const WTF::String&) override;
-    void postWorkerConsoleAgentEnabled() override { }
     void didEvaluateWorkerScript(bool success) override { }
     void workerGlobalScopeStarted(WorkerGlobalScope*) override;
     void workerGlobalScopeClosed() override;
diff --git a/third_party/WebKit/Source/web/WebViewFrameWidget.cpp b/third_party/WebKit/Source/web/WebViewFrameWidget.cpp
index 8f59183..0b95d8a 100644
--- a/third_party/WebKit/Source/web/WebViewFrameWidget.cpp
+++ b/third_party/WebKit/Source/web/WebViewFrameWidget.cpp
@@ -53,14 +53,14 @@
     return m_webView->resizeVisualViewport(size);
 }
 
-void WebViewFrameWidget::didEnterFullScreen()
+void WebViewFrameWidget::didEnterFullscreen()
 {
-    return m_webView->didEnterFullScreen();
+    return m_webView->didEnterFullscreen();
 }
 
-void WebViewFrameWidget::didExitFullScreen()
+void WebViewFrameWidget::didExitFullscreen()
 {
-    return m_webView->didExitFullScreen();
+    return m_webView->didExitFullscreen();
 }
 
 void WebViewFrameWidget::beginFrame(double lastFrameTimeMonotonic)
diff --git a/third_party/WebKit/Source/web/WebViewFrameWidget.h b/third_party/WebKit/Source/web/WebViewFrameWidget.h
index 9f8f6aa7..8f39239 100644
--- a/third_party/WebKit/Source/web/WebViewFrameWidget.h
+++ b/third_party/WebKit/Source/web/WebViewFrameWidget.h
@@ -42,8 +42,8 @@
     WebSize size() override;
     void resize(const WebSize&) override;
     void resizeVisualViewport(const WebSize&) override;
-    void didEnterFullScreen() override;
-    void didExitFullScreen() override;
+    void didEnterFullscreen() override;
+    void didExitFullscreen() override;
     void beginFrame(double lastFrameTimeMonotonic) override;
     void updateAllLifecyclePhases() override;
     void paint(WebCanvas*, const WebRect& viewPort) override;
diff --git a/third_party/WebKit/Source/web/WebViewImpl.cpp b/third_party/WebKit/Source/web/WebViewImpl.cpp
index 1e2ee8b..992feed 100644
--- a/third_party/WebKit/Source/web/WebViewImpl.cpp
+++ b/third_party/WebKit/Source/web/WebViewImpl.cpp
@@ -88,6 +88,7 @@
 #include "core/page/PointerLockController.h"
 #include "core/page/ScopedPageLoadDeferrer.h"
 #include "core/page/TouchDisambiguation.h"
+#include "core/page/scrolling/RootScrollerController.h"
 #include "core/paint/PaintLayer.h"
 #include "core/timing/DOMWindowPerformance.h"
 #include "core/timing/Performance.h"
@@ -1952,14 +1953,14 @@
         newSize, topControls().height(), topControls().shrinkViewport());
 }
 
-void WebViewImpl::didEnterFullScreen()
+void WebViewImpl::didEnterFullscreen()
 {
-    m_fullscreenController->didEnterFullScreen();
+    m_fullscreenController->didEnterFullscreen();
 }
 
-void WebViewImpl::didExitFullScreen()
+void WebViewImpl::didExitFullscreen()
 {
-    m_fullscreenController->didExitFullScreen();
+    m_fullscreenController->didExitFullscreen();
 }
 
 void WebViewImpl::didUpdateFullScreenSize()
@@ -4192,31 +4193,31 @@
 void WebViewImpl::registerViewportLayersWithCompositor()
 {
     DCHECK(m_layerTreeView);
-    DCHECK(!page()->deprecatedLocalMainFrame()->contentLayoutItem().isNull());
+    DCHECK(page()->deprecatedLocalMainFrame());
 
-    PaintLayerCompositor* compositor =
-        page()->deprecatedLocalMainFrame()->contentLayoutItem().compositor();
+    Document* document = page()->deprecatedLocalMainFrame()->document();
 
-    DCHECK(compositor);
+    DCHECK(document);
 
     // Get the outer viewport scroll layer.
-    WebLayer* scrollLayer =
-        compositor->scrollLayer()
-            ? compositor->scrollLayer()->platformLayer()
-            : nullptr;
+    GraphicsLayer* layoutViewportScrollLayer =
+        document->rootScrollerController()->rootScrollerLayer();
+    WebLayer* layoutViewportWebLayer = layoutViewportScrollLayer
+        ? layoutViewportScrollLayer->platformLayer()
+        : nullptr;
 
     VisualViewport& visualViewport = page()->frameHost().visualViewport();
 
     // TODO(bokan): This was moved here from when registerViewportLayers was a
     // part of VisualViewport and maybe doesn't belong here. See comment inside
     // the mehtod.
-    visualViewport.setScrollLayerOnScrollbars(scrollLayer);
+    visualViewport.setScrollLayerOnScrollbars(layoutViewportWebLayer);
 
     m_layerTreeView->registerViewportLayers(
         visualViewport.overscrollElasticityLayer()->platformLayer(),
         visualViewport.pageScaleLayer()->platformLayer(),
         visualViewport.scrollLayer()->platformLayer(),
-        scrollLayer);
+        layoutViewportWebLayer);
 }
 
 void WebViewImpl::setRootGraphicsLayer(GraphicsLayer* layer)
diff --git a/third_party/WebKit/Source/web/WebViewImpl.h b/third_party/WebKit/Source/web/WebViewImpl.h
index 75da1eb..24a70c7 100644
--- a/third_party/WebKit/Source/web/WebViewImpl.h
+++ b/third_party/WebKit/Source/web/WebViewImpl.h
@@ -108,8 +108,8 @@
     WebSize size() override;
     void resize(const WebSize&) override;
     void resizeVisualViewport(const WebSize&) override;
-    void didEnterFullScreen() override;
-    void didExitFullScreen() override;
+    void didEnterFullscreen() override;
+    void didExitFullscreen() override;
 
     void beginFrame(double lastFrameTimeMonotonic) override;
 
diff --git a/third_party/WebKit/Source/web/tests/FrameSerializerTest.cpp b/third_party/WebKit/Source/web/tests/FrameSerializerTest.cpp
index 5ad77bd..763c01b 100644
--- a/third_party/WebKit/Source/web/tests/FrameSerializerTest.cpp
+++ b/third_party/WebKit/Source/web/tests/FrameSerializerTest.cpp
@@ -183,7 +183,7 @@
 
         StringBuilder uriBuilder;
         uriBuilder.append(m_rewriteFolder);
-        uriBuilder.append("/");
+        uriBuilder.append('/');
         uriBuilder.append(m_rewriteURLs.get(completeURL));
         rewrittenLink = uriBuilder.toString();
         return true;
diff --git a/third_party/WebKit/Source/web/tests/FrameTestHelpers.cpp b/third_party/WebKit/Source/web/tests/FrameTestHelpers.cpp
index 46cde927..2fd3ccc 100644
--- a/third_party/WebKit/Source/web/tests/FrameTestHelpers.cpp
+++ b/third_party/WebKit/Source/web/tests/FrameTestHelpers.cpp
@@ -113,7 +113,7 @@
     static int uniqueNameCounter = 0;
     StringBuilder uniqueName;
     uniqueName.append(name);
-    uniqueName.append(" ");
+    uniqueName.append(' ');
     uniqueName.appendNumber(uniqueNameCounter++);
     return uniqueName.toString();
 }
@@ -123,7 +123,6 @@
 void loadFrame(WebFrame* frame, const std::string& url)
 {
     WebURLRequest urlRequest;
-    urlRequest.initialize();
     urlRequest.setURL(URLTestHelpers::toKURL(url));
     urlRequest.setRequestorOrigin(WebSecurityOrigin::createUnique());
     frame->loadRequest(urlRequest);
diff --git a/third_party/WebKit/Source/web/tests/RootScrollerTest.cpp b/third_party/WebKit/Source/web/tests/RootScrollerTest.cpp
index 2f48e5c..ae6cd44 100644
--- a/third_party/WebKit/Source/web/tests/RootScrollerTest.cpp
+++ b/third_party/WebKit/Source/web/tests/RootScrollerTest.cpp
@@ -7,6 +7,7 @@
 #include "core/frame/TopControls.h"
 #include "core/html/HTMLFrameOwnerElement.h"
 #include "core/page/Page.h"
+#include "core/page/scrolling/RootScrollerController.h"
 #include "platform/testing/URLTestHelpers.h"
 #include "platform/testing/UnitTestHelpers.h"
 #include "public/platform/Platform.h"
@@ -155,6 +156,11 @@
         return frameHost().topControls();
     }
 
+    Element* effectiveRootScroller(Document* doc) const
+    {
+        return doc->rootScrollerController()->effectiveRootScroller();
+    }
+
 protected:
     std::string m_baseURL;
     RootScrollerTestWebViewClient m_client;
@@ -172,7 +178,7 @@
     ASSERT_EQ(nullptr, mainFrame()->document()->rootScroller());
 
     Element* htmlElement = mainFrame()->document()->documentElement();
-    EXPECT_EQ(htmlElement, mainFrame()->document()->effectiveRootScroller());
+    EXPECT_EQ(htmlElement, effectiveRootScroller(mainFrame()->document()));
 }
 
 // Tests that setting an element as the root scroller causes it to control url
@@ -294,13 +300,13 @@
     mainFrame()->document()->setRootScroller(container, exceptionState);
 
     ASSERT_EQ(container, mainFrame()->document()->rootScroller());
-    ASSERT_EQ(container, mainFrame()->document()->effectiveRootScroller());
+    ASSERT_EQ(container, effectiveRootScroller(mainFrame()->document()));
 
     mainFrame()->document()->body()->removeChild(container);
     mainFrameView()->updateAllLifecyclePhases();
 
     ASSERT_EQ(container, mainFrame()->document()->rootScroller());
-    ASSERT_NE(container, mainFrame()->document()->effectiveRootScroller());
+    ASSERT_NE(container, effectiveRootScroller(mainFrame()->document()));
 }
 
 // Tests that setting an element that isn't a valid scroller as the root
@@ -317,7 +323,7 @@
         mainFrame()->document()->setRootScroller(element, exceptionState);
         mainFrameView()->updateAllLifecyclePhases();
         ASSERT_EQ(element, mainFrame()->document()->rootScroller());
-        ASSERT_NE(element, mainFrame()->document()->effectiveRootScroller());
+        ASSERT_NE(element, effectiveRootScroller(mainFrame()->document()));
     }
 
     {
@@ -327,7 +333,7 @@
         mainFrame()->document()->setRootScroller(element, exceptionState);
         mainFrameView()->updateAllLifecyclePhases();
         ASSERT_EQ(element, mainFrame()->document()->rootScroller());
-        ASSERT_NE(element, mainFrame()->document()->effectiveRootScroller());
+        ASSERT_NE(element, effectiveRootScroller(mainFrame()->document()));
     }
 }
 
@@ -342,14 +348,14 @@
     TrackExceptionState exceptionState;
 
     ASSERT_EQ(nullptr, mainFrame()->document()->rootScroller());
-    ASSERT_EQ(htmlElement, mainFrame()->document()->effectiveRootScroller());
+    ASSERT_EQ(htmlElement, effectiveRootScroller(mainFrame()->document()));
 
     {
         mainFrame()->document()->setRootScroller(container, exceptionState);
         mainFrameView()->updateAllLifecyclePhases();
 
         ASSERT_EQ(container, mainFrame()->document()->rootScroller());
-        ASSERT_EQ(container, mainFrame()->document()->effectiveRootScroller());
+        ASSERT_EQ(container, effectiveRootScroller(mainFrame()->document()));
 
         executeScript(
             "document.querySelector('#container').style.display = 'inline'");
@@ -357,7 +363,7 @@
 
         ASSERT_EQ(container, mainFrame()->document()->rootScroller());
         ASSERT_EQ(htmlElement,
-            mainFrame()->document()->effectiveRootScroller());
+            effectiveRootScroller(mainFrame()->document()));
     }
 
     executeScript(
@@ -365,14 +371,14 @@
     mainFrame()->document()->setRootScroller(nullptr, exceptionState);
     mainFrameView()->updateAllLifecyclePhases();
     ASSERT_EQ(nullptr, mainFrame()->document()->rootScroller());
-    ASSERT_EQ(htmlElement, mainFrame()->document()->effectiveRootScroller());
+    ASSERT_EQ(htmlElement, effectiveRootScroller(mainFrame()->document()));
 
     {
         mainFrame()->document()->setRootScroller(container, exceptionState);
         mainFrameView()->updateAllLifecyclePhases();
 
         ASSERT_EQ(container, mainFrame()->document()->rootScroller());
-        ASSERT_EQ(container, mainFrame()->document()->effectiveRootScroller());
+        ASSERT_EQ(container, effectiveRootScroller(mainFrame()->document()));
 
         executeScript(
             "document.querySelector('#container').style.width = '98%'");
@@ -380,7 +386,7 @@
 
         ASSERT_EQ(container, mainFrame()->document()->rootScroller());
         ASSERT_EQ(htmlElement,
-            mainFrame()->document()->effectiveRootScroller());
+            effectiveRootScroller(mainFrame()->document()));
     }
 }
 
@@ -407,7 +413,7 @@
 
         ASSERT_EQ(innerContainer, mainFrame()->document()->rootScroller());
         ASSERT_EQ(innerContainer,
-            mainFrame()->document()->effectiveRootScroller());
+            effectiveRootScroller(mainFrame()->document()));
     }
 
     {
@@ -420,7 +426,7 @@
         mainFrameView()->updateAllLifecyclePhases();
 
         ASSERT_EQ(iframe, mainFrame()->document()->rootScroller());
-        ASSERT_EQ(iframe, mainFrame()->document()->effectiveRootScroller());
+        ASSERT_EQ(iframe, effectiveRootScroller(mainFrame()->document()));
     }
 }
 
@@ -437,7 +443,7 @@
             mainFrame()->document()->getElementById("iframe"));
 
         ASSERT_EQ(iframe->contentDocument()->documentElement(),
-            iframe->contentDocument()->effectiveRootScroller());
+            effectiveRootScroller(iframe->contentDocument()));
 
         Element* innerContainer =
             iframe->contentDocument()->getElementById("container");
@@ -449,7 +455,7 @@
 
         ASSERT_EQ(innerContainer, iframe->contentDocument()->rootScroller());
         ASSERT_EQ(innerContainer,
-            iframe->contentDocument()->effectiveRootScroller());
+            effectiveRootScroller(iframe->contentDocument()));
     }
 }
 
diff --git a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
index 12fa421..6cf1755 100644
--- a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
@@ -3320,7 +3320,6 @@
     FrameTestHelpers::WebViewHelper webViewHelper(this);
     webViewHelper.initialize();
     WebURLRequest request;
-    request.initialize();
     request.setURL(toKURL(m_baseURL + "fixed_layout.html"));
     request.setRequestorOrigin(WebSecurityOrigin::createUnique());
     webViewHelper.webView()->mainFrame()->loadRequest(request);
@@ -6288,7 +6287,6 @@
     WebFrame* frame = webViewHelper.webView()->mainFrame();
     const FrameLoader& mainFrameLoader = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->loader();
     WebURLRequest request;
-    request.initialize();
     request.setURL(toKURL(url));
     request.setRequestorOrigin(WebSecurityOrigin::createUnique());
     frame->loadRequest(request);
@@ -6470,7 +6468,7 @@
     UserGestureIndicator gesture(DefinitelyProcessingUserGesture);
     Element* divFullscreen = document->getElementById("div1");
     Fullscreen::from(*document).requestFullscreen(*divFullscreen, Fullscreen::PrefixedRequest);
-    webViewImpl->didEnterFullScreen();
+    webViewImpl->didEnterFullscreen();
     webViewImpl->updateAllLifecyclePhases();
     ASSERT_TRUE(Fullscreen::isFullScreen(*document));
 
@@ -6503,7 +6501,7 @@
     UserGestureIndicator gesture(DefinitelyProcessingUserGesture);
     Element* divFullscreen = document->getElementById("div1");
     Fullscreen::from(*document).requestFullscreen(*divFullscreen, Fullscreen::PrefixedRequest);
-    webViewImpl->didEnterFullScreen();
+    webViewImpl->didEnterFullscreen();
     webViewImpl->updateAllLifecyclePhases();
 
     // Verify that the viewports are nonscrollable.
@@ -6517,7 +6515,7 @@
     ASSERT_FALSE(visualViewportScrollLayer->userScrollableVertical());
 
     // Verify that the viewports are scrollable upon exiting fullscreen.
-    webViewImpl->didExitFullScreen();
+    webViewImpl->didExitFullscreen();
     webViewImpl->updateAllLifecyclePhases();
     ASSERT_FALSE(Fullscreen::isFullScreen(*document));
     ASSERT_TRUE(layoutViewportScrollLayer->userScrollableHorizontal());
@@ -6540,7 +6538,7 @@
     Document* document = toWebLocalFrameImpl(webViewImpl->mainFrame())->frame()->document();
     UserGestureIndicator gesture(DefinitelyProcessingUserGesture);
     Fullscreen::from(*document).requestFullscreen(*document->documentElement(), Fullscreen::PrefixedRequest);
-    webViewImpl->didEnterFullScreen();
+    webViewImpl->didEnterFullscreen();
     webViewImpl->updateAllLifecyclePhases();
 
     // Verify that the main frame is still scrollable.
@@ -6575,7 +6573,7 @@
     UserGestureIndicator gesture(DefinitelyProcessingUserGesture);
     Element* divFullscreen = document->getElementById("div1");
     Fullscreen::from(*document).requestFullscreen(*divFullscreen, Fullscreen::PrefixedRequest);
-    webViewImpl->didEnterFullScreen();
+    webViewImpl->didEnterFullscreen();
     webViewImpl->updateAllLifecyclePhases();
 
     // Verify that the element is sized to the viewport.
@@ -6615,7 +6613,7 @@
     Document* document = toWebLocalFrameImpl(webViewImpl->mainFrame())->frame()->document();
     UserGestureIndicator gesture(DefinitelyProcessingUserGesture);
     Fullscreen::from(*document).requestFullscreen(*document->documentElement(), Fullscreen::PrefixedRequest);
-    webViewImpl->didEnterFullScreen();
+    webViewImpl->didEnterFullscreen();
     webViewImpl->updateAllLifecyclePhases();
     EXPECT_EQ(384, layoutViewItem.logicalWidth().floor());
     EXPECT_EQ(640, layoutViewItem.logicalHeight().floor());
@@ -6623,7 +6621,7 @@
     EXPECT_FLOAT_EQ(1.0, webViewImpl->minimumPageScaleFactor());
     EXPECT_FLOAT_EQ(1.0, webViewImpl->maximumPageScaleFactor());
 
-    webViewImpl->didExitFullScreen();
+    webViewImpl->didExitFullscreen();
     webViewImpl->updateAllLifecyclePhases();
     EXPECT_EQ(320, layoutViewItem.logicalWidth().floor());
     EXPECT_EQ(533, layoutViewItem.logicalHeight().floor());
@@ -6649,7 +6647,7 @@
     Document* document = toWebLocalFrameImpl(webViewImpl->mainFrame())->frame()->document();
     UserGestureIndicator gesture(DefinitelyProcessingUserGesture);
     Fullscreen::from(*document).requestFullscreen(*document->documentElement(), Fullscreen::PrefixedRequest);
-    webViewImpl->didEnterFullScreen();
+    webViewImpl->didEnterFullscreen();
     webViewImpl->updateAllLifecyclePhases();
     EXPECT_EQ(384, layoutViewItem.logicalWidth().floor());
     EXPECT_EQ(640, layoutViewItem.logicalHeight().floor());
@@ -6669,7 +6667,7 @@
     EXPECT_FLOAT_EQ(1.0, webViewImpl->minimumPageScaleFactor());
     EXPECT_FLOAT_EQ(1.0, webViewImpl->maximumPageScaleFactor());
 
-    webViewImpl->didExitFullScreen();
+    webViewImpl->didExitFullscreen();
     webViewImpl->updateAllLifecyclePhases();
     EXPECT_EQ(320, layoutViewItem.logicalWidth().floor());
     EXPECT_EQ(192, layoutViewItem.logicalHeight().floor());
@@ -6708,7 +6706,7 @@
         Fullscreen::from(*document).requestFullscreen(*document->body(), Fullscreen::PrefixedRequest);
     }
 
-    webViewImpl->didEnterFullScreen();
+    webViewImpl->didEnterFullscreen();
     webViewImpl->updateAllLifecyclePhases();
     client.m_screenInfo.rect.width = screenSizeMinusStatusBars.width;
     client.m_screenInfo.rect.height = screenSizeMinusStatusBars.height;
@@ -6722,7 +6720,7 @@
     EXPECT_FLOAT_EQ(1.0, webViewImpl->minimumPageScaleFactor());
     EXPECT_FLOAT_EQ(1.0, webViewImpl->maximumPageScaleFactor());
 
-    webViewImpl->didExitFullScreen();
+    webViewImpl->didExitFullscreen();
     webViewImpl->updateAllLifecyclePhases();
     client.m_screenInfo.rect.width = screenSizeMinusStatusBars.width;
     client.m_screenInfo.rect.height = screenSizeMinusStatusBars.height;
@@ -6772,7 +6770,7 @@
     UserGestureIndicator gesture(DefinitelyProcessingUserGesture);
     Fullscreen::from(*document).requestFullscreen(
         *document->documentElement(), Fullscreen::PrefixedRequest);
-    webViewImpl->didEnterFullScreen();
+    webViewImpl->didEnterFullscreen();
     webViewImpl->updateAllLifecyclePhases();
 
     // Entering fullscreen causes layout size and page scale limits to be
@@ -6789,7 +6787,7 @@
     KURL testURL = toKURL("about:blank");
     WebFrame* frame = webViewHelper.webView()->mainFrame();
     FrameTestHelpers::loadHTMLString(frame, source, testURL);
-    webViewImpl->didExitFullScreen();
+    webViewImpl->didExitFullscreen();
     webViewImpl->updateAllLifecyclePhases();
 
     // Make sure the new page's layout size and scale factor limits aren't
@@ -8808,7 +8806,6 @@
     WebURLRequest request;
     std::string redirectURL = m_baseURL + "foo.html";
     URLTestHelpers::registerMockedURLLoad(toKURL(redirectURL), "foo.html");
-    request.initialize();
     request.setURL(toKURL("javascript:location='" + redirectURL + "'"));
     request.setRequestorOrigin(WebSecurityOrigin::createUnique());
     helper.webViewImpl()->mainFrame()->toWebLocalFrame()->loadRequest(request);
diff --git a/third_party/WebKit/Source/web/tests/WebURLRequestTest.cpp b/third_party/WebKit/Source/web/tests/WebURLRequestTest.cpp
index 8e4ab33..fac8a317 100644
--- a/third_party/WebKit/Source/web/tests/WebURLRequestTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebURLRequestTest.cpp
@@ -60,7 +60,6 @@
         TestExtraData* extraData = new TestExtraData(&alive);
         EXPECT_TRUE(alive);
 
-        urlRequest.initialize();
         urlRequest.setExtraData(extraData);
         EXPECT_EQ(extraData, urlRequest.getExtraData());
         {
diff --git a/third_party/WebKit/Source/web/tests/WebViewTest.cpp b/third_party/WebKit/Source/web/tests/WebViewTest.cpp
index fdd36128..3d5dab5 100644
--- a/third_party/WebKit/Source/web/tests/WebViewTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebViewTest.cpp
@@ -1186,7 +1186,7 @@
 
     Element* element = static_cast<Element*>(webViewImpl->mainFrame()->document().body());
     webViewImpl->enterFullScreenForElement(element);
-    webViewImpl->didEnterFullScreen();
+    webViewImpl->didEnterFullscreen();
 
     // Page scale factor must be 1.0 during fullscreen for elements to be sized
     // properly.
@@ -1197,7 +1197,7 @@
     webViewImpl->enterFullScreenForElement(otherElement);
 
     // Confirm that exiting fullscreen restores the parameters.
-    webViewImpl->didExitFullScreen();
+    webViewImpl->didExitFullscreen();
     EXPECT_EQ(2.0f, webViewImpl->pageScaleFactor());
     EXPECT_EQ(94, webViewImpl->mainFrame()->scrollOffset().width);
     EXPECT_EQ(111, webViewImpl->mainFrame()->scrollOffset().height);
@@ -2057,7 +2057,6 @@
 
     // Make a request from a local frame.
     WebURLRequest webURLRequestWithTargetStart;
-    webURLRequestWithTargetStart.initialize();
     LocalFrame* localFrame = toWebLocalFrameImpl(webViewImpl->mainFrame()->firstChild())->frame();
     FrameLoadRequest requestWithTargetStart(localFrame->document(), webURLRequestWithTargetStart.toResourceRequest(), "_top");
     localFrame->loader().load(requestWithTargetStart);
@@ -2077,7 +2076,6 @@
 
     // Make a request that will open a new window
     WebURLRequest webURLRequest;
-    webURLRequest.initialize();
     FrameLoadRequest request(0, webURLRequest.toResourceRequest(), "_blank");
     toLocalFrame(webViewImpl->page()->mainFrame())->loader().load(request);
     ASSERT_TRUE(client.createdWebView());
@@ -2085,7 +2083,6 @@
 
     // Make a request from the new window that will navigate the original window. The original window should be focused.
     WebURLRequest webURLRequestWithTargetStart;
-    webURLRequestWithTargetStart.initialize();
     FrameLoadRequest requestWithTargetStart(0, webURLRequestWithTargetStart.toResourceRequest(), "_start");
     toLocalFrame(toWebViewImpl(client.createdWebView())->page()->mainFrame())->loader().load(requestWithTargetStart);
     EXPECT_TRUE(client.didFocusCalled());
diff --git a/third_party/WebKit/Source/web/tests/sim/SimTest.cpp b/third_party/WebKit/Source/web/tests/sim/SimTest.cpp
index 984f7a1..e583b2d 100644
--- a/third_party/WebKit/Source/web/tests/sim/SimTest.cpp
+++ b/third_party/WebKit/Source/web/tests/sim/SimTest.cpp
@@ -41,7 +41,6 @@
 void SimTest::loadURL(const String& url)
 {
     WebURLRequest request;
-    request.initialize();
     request.setURL(KURL(ParsedURLString, url));
     request.setRequestorOrigin(WebSecurityOrigin::createUnique());
     webView().mainFrameImpl()->loadRequest(request);
diff --git a/third_party/WebKit/Source/wtf/RetainPtr.h b/third_party/WebKit/Source/wtf/RetainPtr.h
index 56c155a..4528231 100644
--- a/third_party/WebKit/Source/wtf/RetainPtr.h
+++ b/third_party/WebKit/Source/wtf/RetainPtr.h
@@ -106,11 +106,7 @@
     PtrType operator->() const { return m_ptr; }
 
     bool operator!() const { return !m_ptr; }
-
-    // This conversion operator allows implicit conversion to bool but not to
-    // other integer types.
-    typedef PtrType RetainPtr::*UnspecifiedBoolType;
-    operator UnspecifiedBoolType() const { return m_ptr ? &RetainPtr::m_ptr : 0; }
+    explicit operator bool() const { return m_ptr; }
 
     RetainPtr& operator=(const RetainPtr&);
     template <typename U> RetainPtr& operator=(const RetainPtr<U>&);
diff --git a/third_party/WebKit/Source/wtf/WeakPtr.h b/third_party/WebKit/Source/wtf/WeakPtr.h
index c377957..8bec53f 100644
--- a/third_party/WebKit/Source/wtf/WeakPtr.h
+++ b/third_party/WebKit/Source/wtf/WeakPtr.h
@@ -107,8 +107,7 @@
         return get();
     }
 
-    typedef RefPtr<WeakReference<T>> (WeakPtr::*UnspecifiedBoolType);
-    operator UnspecifiedBoolType() const { return get() ? &WeakPtr::m_ref : 0; }
+    explicit operator bool() const { return get(); }
 
 private:
     RefPtr<WeakReference<T>> m_ref;
diff --git a/third_party/WebKit/Source/wtf/text/AtomicString.h b/third_party/WebKit/Source/wtf/text/AtomicString.h
index 7345d82..b2a8e54b 100644
--- a/third_party/WebKit/Source/wtf/text/AtomicString.h
+++ b/third_party/WebKit/Source/wtf/text/AtomicString.h
@@ -25,6 +25,7 @@
 #include "wtf/HashTableDeletedValueType.h"
 #include "wtf/WTFExport.h"
 #include "wtf/text/CString.h"
+#include "wtf/text/StringView.h"
 #include "wtf/text/WTFString.h"
 #include <cstring>
 #include <iosfwd>
@@ -206,6 +207,13 @@
 // double-quotes, and escapes chracters other than ASCII printables.
 WTF_EXPORT std::ostream& operator<<(std::ostream&, const AtomicString&);
 
+inline StringView::StringView(const AtomicString& string, unsigned offset, unsigned length)
+    : StringView(string.impl(), offset, length) {}
+inline StringView::StringView(const AtomicString& string, unsigned offset)
+    : StringView(string.impl(), offset) {}
+inline StringView::StringView(const AtomicString& string)
+    : StringView(string.impl()) {}
+
 } // namespace WTF
 
 WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(AtomicString);
diff --git a/third_party/WebKit/Source/wtf/text/StringImpl.cpp b/third_party/WebKit/Source/wtf/text/StringImpl.cpp
index e7004b92..2b7ceb2 100644
--- a/third_party/WebKit/Source/wtf/text/StringImpl.cpp
+++ b/third_party/WebKit/Source/wtf/text/StringImpl.cpp
@@ -1431,26 +1431,6 @@
     return findIgnoringASCIICaseInner(searchStart, matchString->characters16(), index, searchLength, matchLength);
 }
 
-size_t StringImpl::findNextLineStart(unsigned index)
-{
-    if (is8Bit())
-        return WTF::findNextLineStart(characters8(), m_length, index);
-    return WTF::findNextLineStart(characters16(), m_length, index);
-}
-
-size_t StringImpl::count(LChar c) const
-{
-    int count = 0;
-    if (is8Bit()) {
-        for (size_t i = 0; i < m_length; ++i)
-            count += characters8()[i] == c;
-    } else {
-        for (size_t i = 0; i < m_length; ++i)
-            count += characters16()[i] == c;
-    }
-    return count;
-}
-
 size_t StringImpl::reverseFind(UChar c, unsigned index)
 {
     if (is8Bit())
diff --git a/third_party/WebKit/Source/wtf/text/StringImpl.h b/third_party/WebKit/Source/wtf/text/StringImpl.h
index 22897f1..c1cb3ee 100644
--- a/third_party/WebKit/Source/wtf/text/StringImpl.h
+++ b/third_party/WebKit/Source/wtf/text/StringImpl.h
@@ -379,13 +379,9 @@
     size_t findIgnoringCase(StringImpl*, unsigned index = 0);
     size_t findIgnoringASCIICase(StringImpl*, unsigned index = 0);
 
-    size_t findNextLineStart(unsigned index = UINT_MAX);
-
     size_t reverseFind(UChar, unsigned index = UINT_MAX);
     size_t reverseFind(StringImpl*, unsigned index = UINT_MAX);
 
-    size_t count(LChar) const;
-
     bool startsWith(UChar) const;
     bool startsWith(const char*, unsigned prefixLength) const;
     bool startsWith(const StringImpl*) const;
@@ -586,53 +582,6 @@
 }
 
 template<typename CharacterType>
-inline size_t findNextLineStart(const CharacterType* characters, unsigned length, unsigned index = 0)
-{
-    while (index < length) {
-        CharacterType c = characters[index++];
-        if ((c != '\n') && (c != '\r'))
-            continue;
-
-        // There can only be a start of a new line if there are more characters
-        // beyond the current character.
-        if (index < length) {
-            // The 3 common types of line terminators are 1. \r\n (Windows),
-            // 2. \r (old MacOS) and 3. \n (Unix'es).
-
-            if (c == '\n')
-                return index; // Case 3: just \n.
-
-            CharacterType c2 = characters[index];
-            if (c2 != '\n')
-                return index; // Case 2: just \r.
-
-            // Case 1: \r\n.
-            // But, there's only a start of a new line if there are more
-            // characters beyond the \r\n.
-            if (++index < length)
-                return index;
-        }
-    }
-    return kNotFound;
-}
-
-template<typename CharacterType>
-inline size_t reverseFindLineTerminator(const CharacterType* characters, unsigned length, unsigned index = UINT_MAX)
-{
-    if (!length)
-        return kNotFound;
-    if (index >= length)
-        index = length - 1;
-    CharacterType c = characters[index];
-    while ((c != '\n') && (c != '\r')) {
-        if (!index--)
-            return kNotFound;
-        c = characters[index];
-    }
-    return index;
-}
-
-template<typename CharacterType>
 inline size_t reverseFind(const CharacterType* characters, unsigned length, CharacterType matchCharacter, unsigned index = UINT_MAX)
 {
     if (!length)
diff --git a/third_party/WebKit/Source/wtf/text/StringView.cpp b/third_party/WebKit/Source/wtf/text/StringView.cpp
index e88703b..115ac206 100644
--- a/third_party/WebKit/Source/wtf/text/StringView.cpp
+++ b/third_party/WebKit/Source/wtf/text/StringView.cpp
@@ -4,6 +4,9 @@
 
 #include "wtf/text/StringView.h"
 
+#include "wtf/text/AtomicString.h"
+#include "wtf/text/WTFString.h"
+
 namespace WTF {
 
 StringView::StringView(const UChar* chars)
diff --git a/third_party/WebKit/Source/wtf/text/StringView.h b/third_party/WebKit/Source/wtf/text/StringView.h
index 7b47931..6433c38 100644
--- a/third_party/WebKit/Source/wtf/text/StringView.h
+++ b/third_party/WebKit/Source/wtf/text/StringView.h
@@ -10,14 +10,15 @@
 #if DCHECK_IS_ON()
 #include "wtf/RefPtr.h"
 #endif
-#include "wtf/text/AtomicString.h"
 #include "wtf/text/StringImpl.h"
 #include "wtf/text/Unicode.h"
-#include "wtf/text/WTFString.h"
 #include <cstring>
 
 namespace WTF {
 
+class AtomicString;
+class String;
+
 // A string like object that wraps either an 8bit or 16bit byte sequence
 // and keeps track of the length and the type, it does NOT own the bytes.
 //
@@ -42,25 +43,21 @@
     StringView(StringImpl*, unsigned offset);
     StringView(StringImpl*, unsigned offset, unsigned length);
 
-    // From a String:
-    StringView(const String& string, unsigned offset, unsigned length)
-        : StringView(string.impl(), offset, length) {}
-    StringView(const String& string, unsigned offset)
-        : StringView(string.impl(), offset) {}
-    StringView(const String& string)
-        : StringView(string.impl()) {}
+    // From an String, implemented in String.h
+    inline StringView(const String&, unsigned offset, unsigned length);
+    inline StringView(const String&, unsigned offset);
+    inline StringView(const String&);
 
-    // From an AtomicString:
-    StringView(const AtomicString& string, unsigned offset, unsigned length)
-        : StringView(string.impl(), offset, length) {}
-    StringView(const AtomicString& string, unsigned offset)
-        : StringView(string.impl(), offset) {}
-    StringView(const AtomicString& string)
-        : StringView(string.impl()) {}
+    // From an AtomicString, implemented in AtomicString.h
+    inline StringView(const AtomicString&, unsigned offset, unsigned length);
+    inline StringView(const AtomicString&, unsigned offset);
+    inline StringView(const AtomicString&);
 
     // From a literal string or LChar buffer:
     StringView(const LChar* chars, unsigned length)
-        : StringView(reinterpret_cast<const void*>(chars), length, true) {}
+        : m_impl(StringImpl::empty())
+        , m_characters8(chars)
+        , m_length(length) {}
     StringView(const char* chars, unsigned length)
         : StringView(reinterpret_cast<const LChar*>(chars), length) {}
     StringView(const LChar* chars)
@@ -70,14 +67,10 @@
 
     // From a wide literal string or UChar buffer.
     StringView(const UChar* chars, unsigned length)
-        : StringView(reinterpret_cast<const void*>(chars), length, false) {}
-    StringView(const UChar* chars);
-
-    // From a byte pointer.
-    StringView(const void* bytes, unsigned length, bool is8Bit)
-        : m_impl(is8Bit ? StringImpl::empty() : StringImpl::empty16Bit())
-        , m_bytes(bytes)
+        : m_impl(StringImpl::empty16Bit())
+        , m_characters16(chars)
         , m_length(length) {}
+    StringView(const UChar* chars);
 
 #if DCHECK_IS_ON()
     ~StringView();
diff --git a/third_party/WebKit/Source/wtf/text/StringViewTest.cpp b/third_party/WebKit/Source/wtf/text/StringViewTest.cpp
index 1b0b72e7..6c8c620 100644
--- a/third_party/WebKit/Source/wtf/text/StringViewTest.cpp
+++ b/third_party/WebKit/Source/wtf/text/StringViewTest.cpp
@@ -289,20 +289,6 @@
     EXPECT_EQ(String("12"), StringView(kChars16, 2).toString());
 }
 
-TEST(StringViewTest, ConstructionRawBytes)
-{
-    // StringView(const void* bytes, unsigned length, bool is8Bit);
-    StringView view8(reinterpret_cast<const void*>(kChars), 2, true);
-    ASSERT_TRUE(view8.is8Bit());
-    EXPECT_EQ(2u, view8.length());
-    EXPECT_EQ("12", view8);
-
-    StringView view16(reinterpret_cast<const void*>(kChars16), 3, false);
-    ASSERT_FALSE(view16.is8Bit());
-    EXPECT_EQ(3u, view16.length());
-    EXPECT_EQ("123", view16);
-}
-
 TEST(StringViewTest, IsEmpty)
 {
     EXPECT_FALSE(StringView(kChars).isEmpty());
diff --git a/third_party/WebKit/Source/wtf/text/WTFString.h b/third_party/WebKit/Source/wtf/text/WTFString.h
index 839454d9..4950c1d 100644
--- a/third_party/WebKit/Source/wtf/text/WTFString.h
+++ b/third_party/WebKit/Source/wtf/text/WTFString.h
@@ -30,6 +30,7 @@
 #include "wtf/WTFExport.h"
 #include "wtf/text/ASCIIFastPath.h"
 #include "wtf/text/StringImpl.h"
+#include "wtf/text/StringView.h"
 #include <algorithm>
 #include <iosfwd>
 
@@ -191,9 +192,6 @@
     size_t find(const LChar* str, unsigned start = 0) const
         { return m_impl ? m_impl->find(str, start) : kNotFound; }
 
-    size_t findNextLineStart(unsigned start = 0) const
-        { return m_impl ? m_impl->findNextLineStart(start) : kNotFound; }
-
     // Find the last instance of a single character or string.
     size_t reverseFind(UChar c, unsigned start = UINT_MAX) const
         { return m_impl ? m_impl->reverseFind(c, start) : kNotFound; }
@@ -639,6 +637,13 @@
 // double-quotes, and escapes chracters other than ASCII printables.
 WTF_EXPORT std::ostream& operator<<(std::ostream&, const String&);
 
+inline StringView::StringView(const String& string, unsigned offset, unsigned length)
+    : StringView(string.impl(), offset, length) {}
+inline StringView::StringView(const String& string, unsigned offset)
+    : StringView(string.impl(), offset) {}
+inline StringView::StringView(const String& string)
+    : StringView(string.impl()) {}
+
 } // namespace WTF
 
 WTF_ALLOW_MOVE_AND_INIT_WITH_MEM_FUNCTIONS(String);
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs.py
index bd8cdf11..d8617bb 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs.py
@@ -11,6 +11,7 @@
 import logging
 import optparse
 
+from webkitpy.common.checkout.scm.git import Git
 from webkitpy.common.net.rietveld import latest_try_jobs
 from webkitpy.common.net.web import Web
 from webkitpy.layout_tests.models.test_expectations import BASELINE_SUFFIX_LIST
@@ -29,7 +30,7 @@
         super(RebaselineFromTryJobs, self).__init__(options=[
             optparse.make_option(
                 '--issue', type='int', default=None,
-                help='Rietveld issue number.'),
+                help='Rietveld issue number; if none given, this will be obtained via `git cl issue`.'),
             optparse.make_option(
                 '--dry-run', action='store_true', default=False,
                 help='Dry run mode; list actions that would be performed but do not do anything.'),
@@ -39,25 +40,40 @@
         self.web = Web()
 
     def execute(self, options, args, tool):
-        if not options.issue:
-            # TODO(qyearsley): If no issue number is given, get the one for the current branch.
-            _log.info('No issue number provided.')
+        issue_number = self._get_issue_number(options)
+        if not issue_number:
             return
-
         if args:
             test_prefix_list = {}
-            try_jobs = latest_try_jobs(options.issue, self._try_bots(), self.web)
+            try_jobs = latest_try_jobs(issue_number, self._try_bots(), self.web)
             builders = [j.builder_name for j in try_jobs]
             for t in args:
                 test_prefix_list[t] = {b: BASELINE_SUFFIX_LIST for b in builders}
         else:
-            test_prefix_list = self._test_prefix_list(options.issue)
+            test_prefix_list = self._test_prefix_list(issue_number)
         self._log_test_prefix_list(test_prefix_list)
 
         if options.dry_run:
             return
         self._rebaseline(options, test_prefix_list, skip_checking_actual_results=True)
 
+    def _get_issue_number(self, options):
+        """Gets the Rietveld CL number from either |options| or from the current local branch."""
+        if options.issue:
+            return options.issue
+        issue_number = self._git().get_issue_number()
+        _log.debug('Issue number for current branch: %s' % issue_number)
+        if not issue_number.isdigit():
+            _log.error('No issue number given and no issue for current branch.')
+            return None
+        return int(issue_number)
+
+    def _git(self):
+        """Returns a Git instance; can be overridden for tests."""
+        # Pass in a current working directory inside of the repo so
+        # that this command can be called from outside of the repo.
+        return Git(cwd=self._tool.filesystem.dirname(self._tool.path()))
+
     def _test_prefix_list(self, issue_number):
         """Returns a collection of test, builder and file extensions to get new baselines for."""
         builders_to_tests = self._builders_to_tests(issue_number)
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs_unittest.py
index 30820fca..b8650b68 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs_unittest.py
@@ -11,6 +11,7 @@
 from webkitpy.tool.commands.rebaseline_unittest import BaseTestCase
 from webkitpy.tool.mock_tool import MockOptions
 from webkitpy.layout_tests.builder_list import BuilderList
+from webkitpy.common.checkout.scm.scm_mock import MockSCM
 
 
 class RebaselineFromTryJobsTest(BaseTestCase):
@@ -47,16 +48,29 @@
                 "is_try_builder": True,
             },
         })
+        self.git = MockSCM()
+        self.git.get_issue_number = lambda: 'None'
+        self.command._git = lambda: self.git
+
+    @staticmethod
+    def command_options(**kwargs):
+        options = {
+            'issue': None,
+            'dry_run': False,
+            'optimize': True,
+            'verbose': False,
+        }
+        options.update(kwargs)
+        return MockOptions(**options)
 
     def test_execute_with_issue_number_given(self):
         oc = OutputCapture()
         try:
             oc.capture_output()
-            options = MockOptions(issue=11112222, dry_run=False, optimize=True, verbose=False)
-            self.command.execute(options, [], self.tool)
+            self.command.execute(self.command_options(issue=11112222), [], self.tool)
         finally:
             _, _, logs = oc.restore_output()
-        self.assertEqual(
+        self.assertMultiLineEqual(
             logs,
             ('Tests to rebaseline:\n'
              '  svg/dynamic-updates/SVGFEDropShadowElement-dom-stdDeviation-attr.html: MOCK Try Win\n'
@@ -70,7 +84,25 @@
         oc = OutputCapture()
         try:
             oc.capture_output()
-            self.command.execute(MockOptions(issue=None), [], self.tool)
+            self.command.execute(self.command_options(), [], self.tool)
         finally:
             _, _, logs = oc.restore_output()
-        self.assertEqual(logs, 'No issue number provided.\n')
+        self.assertEqual(logs, 'No issue number given and no issue for current branch.\n')
+
+    def test_execute_with_issue_number_from_branch(self):
+        self.git.get_issue_number = lambda: '11112222'
+        oc = OutputCapture()
+        try:
+            oc.capture_output()
+            self.command.execute(self.command_options(), [], self.tool)
+        finally:
+            _, _, logs = oc.restore_output()
+        self.assertMultiLineEqual(
+            logs,
+            ('Tests to rebaseline:\n'
+             '  svg/dynamic-updates/SVGFEDropShadowElement-dom-stdDeviation-attr.html: MOCK Try Win\n'
+             '  fast/dom/prototype-inheritance.html: MOCK Try Win\n'
+             '  fast/dom/prototype-taco.html: MOCK Try Win\n'
+             'Rebaselining fast/dom/prototype-inheritance.html\n'
+             'Rebaselining fast/dom/prototype-taco.html\n'
+             'Rebaselining svg/dynamic-updates/SVGFEDropShadowElement-dom-stdDeviation-attr.html\n'))
diff --git a/third_party/WebKit/public/platform/WebCrypto.h b/third_party/WebKit/public/platform/WebCrypto.h
index d327197..cfd49c5 100644
--- a/third_party/WebKit/public/platform/WebCrypto.h
+++ b/third_party/WebKit/public/platform/WebCrypto.h
@@ -38,6 +38,8 @@
 #include "WebString.h"
 #include "WebVector.h"
 
+#include <memory>
+
 #if INSIDE_BLINK
 #include "platform/heap/Handle.h"
 #endif
@@ -214,11 +216,8 @@
     // This is the exception to the "Completing the request" guarantees
     // outlined above. This is useful for Blink internal crypto and is not part
     // of the WebCrypto standard. createDigestor must provide the result via
-    // the WebCryptoDigestor object synchronously. createDigestor may return 0
-    // if it fails to create a WebCryptoDigestor. If it succeeds, the
-    // WebCryptoDigestor returned by createDigestor must be freed by the
-    // caller.
-    virtual WebCryptoDigestor* createDigestor(WebCryptoAlgorithmId algorithmId) { return nullptr; }
+    // the WebCryptoDigestor object synchronously. This will never return null.
+    virtual std::unique_ptr<WebCryptoDigestor> createDigestor(WebCryptoAlgorithmId algorithmId) { return nullptr; }
 
     // -----------------------
     // Structured clone
diff --git a/third_party/WebKit/public/platform/WebURLRequest.h b/third_party/WebKit/public/platform/WebURLRequest.h
index 3563123..283c90c6 100644
--- a/third_party/WebKit/public/platform/WebURLRequest.h
+++ b/third_party/WebKit/public/platform/WebURLRequest.h
@@ -35,6 +35,7 @@
 #include "WebCommon.h"
 #include "WebHTTPBody.h"
 #include "WebReferrerPolicy.h"
+#include <memory>
 
 namespace blink {
 
@@ -44,7 +45,6 @@
 class WebSecurityOrigin;
 class WebString;
 class WebURL;
-class WebURLRequestPrivate;
 enum class WebCachePolicy;
 
 class WebURLRequest {
@@ -158,25 +158,11 @@
         virtual ~ExtraData() { }
     };
 
-    ~WebURLRequest() { reset(); }
-
-    WebURLRequest() : m_private(0) { }
-    WebURLRequest(const WebURLRequest& r) : m_private(0) { assign(r); }
-    WebURLRequest& operator=(const WebURLRequest& r)
-    {
-        assign(r);
-        return *this;
-    }
-
-    explicit WebURLRequest(const WebURL& url) : m_private(0)
-    {
-        initialize();
-        setURL(url);
-    }
-
-    BLINK_PLATFORM_EXPORT void initialize();
-    BLINK_PLATFORM_EXPORT void reset();
-    BLINK_PLATFORM_EXPORT void assign(const WebURLRequest&);
+    BLINK_PLATFORM_EXPORT ~WebURLRequest();
+    BLINK_PLATFORM_EXPORT WebURLRequest();
+    BLINK_PLATFORM_EXPORT WebURLRequest(const WebURLRequest&);
+    BLINK_PLATFORM_EXPORT explicit WebURLRequest(const WebURL&);
+    BLINK_PLATFORM_EXPORT WebURLRequest& operator=(const WebURLRequest&);
 
     BLINK_PLATFORM_EXPORT bool isNull() const;
 
@@ -323,13 +309,23 @@
 #if INSIDE_BLINK
     BLINK_PLATFORM_EXPORT ResourceRequest& toMutableResourceRequest();
     BLINK_PLATFORM_EXPORT const ResourceRequest& toResourceRequest() const;
-#endif
 
 protected:
-    BLINK_PLATFORM_EXPORT void assign(WebURLRequestPrivate*);
+    // Permit subclasses to set arbitrary ResourceRequest pointer as
+    // |m_resourceRequest|. |m_ownedResourceRequest| is not set in this case.
+    BLINK_PLATFORM_EXPORT explicit WebURLRequest(ResourceRequest&);
+#endif
 
 private:
-    WebURLRequestPrivate* m_private;
+    struct ResourceRequestContainer;
+
+    // If this instance owns a ResourceRequest then |m_ownedResourceRequest|
+    // is non-null and |m_resourceRequest| points to the ResourceRequest
+    // instance it contains.
+    std::unique_ptr<ResourceRequestContainer> m_ownedResourceRequest;
+
+    // Should never be null.
+    ResourceRequest* m_resourceRequest;
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/public/platform/WebURLResponse.h b/third_party/WebKit/public/platform/WebURLResponse.h
index 5fbe8b3e..bbcfe3a 100644
--- a/third_party/WebKit/public/platform/WebURLResponse.h
+++ b/third_party/WebKit/public/platform/WebURLResponse.h
@@ -294,9 +294,8 @@
 #if INSIDE_BLINK
 protected:
     // Permit subclasses to set arbitrary ResourceResponse pointer as
-    // |m_resourceResponse|. Parameter must be non-null.
-    // |m_ownedResourceResponse| is not set in this case.
-    BLINK_PLATFORM_EXPORT explicit WebURLResponse(ResourceResponse*);
+    // |m_resourceResponse|. |m_ownedResourceResponse| is not set in this case.
+    BLINK_PLATFORM_EXPORT explicit WebURLResponse(ResourceResponse&);
 #endif
 
 private:
diff --git a/third_party/WebKit/public/platform/modules/websockets/WebSocketHandle.h b/third_party/WebKit/public/platform/modules/websockets/WebSocketHandle.h
index df17eba..189a9bf 100644
--- a/third_party/WebKit/public/platform/modules/websockets/WebSocketHandle.h
+++ b/third_party/WebKit/public/platform/modules/websockets/WebSocketHandle.h
@@ -57,7 +57,7 @@
 
     virtual ~WebSocketHandle() { }
 
-    virtual void connect(const WebURL&, const WebVector<WebString>& protocols, const WebSecurityOrigin&, const WebString& user_agent_override, WebSocketHandleClient*) = 0;
+    virtual void connect(const WebURL&, const WebVector<WebString>& protocols, const WebSecurityOrigin&, const WebURL& first_party_for_cookies, const WebString& user_agent_override, WebSocketHandleClient*) = 0;
     virtual void send(bool fin, MessageType, const char* data, size_t /* size */) = 0;
     virtual void flowControl(int64_t quota) = 0;
     virtual void close(unsigned short code, const WebString& reason) = 0;
diff --git a/third_party/WebKit/public/web/WebFrameClient.h b/third_party/WebKit/public/web/WebFrameClient.h
index 3c34e68ed..2aef5e036 100644
--- a/third_party/WebKit/public/web/WebFrameClient.h
+++ b/third_party/WebKit/public/web/WebFrameClient.h
@@ -654,14 +654,11 @@
     // Fullscreen ----------------------------------------------------------
 
     // Called to enter/exit fullscreen mode.
-    // After calling enterFullscreen, WebWidget::{will,Did}EnterFullScreen
-    // should bound resizing the WebWidget into fullscreen mode.
-    // Similarly, when exitFullScreen is called,
-    // WebWidget::{will,Did}ExitFullScreen should bound resizing the WebWidget
-    // out of fullscreen mode.
-    // Note: the return value is ignored.
-    virtual bool enterFullscreen() { return false; }
-    virtual bool exitFullscreen() { return false; }
+    // After calling enterFullscreen or exitFullscreen,
+    // WebWidget::didEnterFullscreen or WebWidget::didExitFullscreen
+    // respectively will be called once the fullscreen mode has changed.
+    virtual void enterFullscreen() { }
+    virtual void exitFullscreen() { }
 
 
     // Sudden termination --------------------------------------------------
diff --git a/third_party/WebKit/public/web/WebRemoteFrame.h b/third_party/WebKit/public/web/WebRemoteFrame.h
index 37ca0a3..804d33d 100644
--- a/third_party/WebKit/public/web/WebRemoteFrame.h
+++ b/third_party/WebKit/public/web/WebRemoteFrame.h
@@ -68,7 +68,7 @@
     // corresponds to the HTMLFrameOwnerElement to be fullscreened. Calling
     // this prepares FullscreenController to enter fullscreen for that frame
     // owner.
-    virtual void willEnterFullScreen() = 0;
+    virtual void willEnterFullscreen() = 0;
 
     // Temporary method to allow embedders to get the script context of a
     // remote frame. This should only be used by legacy code that has not yet
diff --git a/third_party/WebKit/public/web/WebView.h b/third_party/WebKit/public/web/WebView.h
index f7748f4..4f81bb6 100644
--- a/third_party/WebKit/public/web/WebView.h
+++ b/third_party/WebKit/public/web/WebView.h
@@ -53,7 +53,6 @@
 class WebHitTestResult;
 class WebLocalFrame;
 class WebPageImportanceSignals;
-class WebPageOverlay;
 class WebPrerendererClient;
 class WebRemoteFrame;
 class WebSettings;
@@ -85,8 +84,8 @@
     using WebWidget::size;
     using WebWidget::resize;
     using WebWidget::resizeVisualViewport;
-    using WebWidget::didEnterFullScreen;
-    using WebWidget::didExitFullScreen;
+    using WebWidget::didEnterFullscreen;
+    using WebWidget::didExitFullscreen;
     using WebWidget::beginFrame;
     using WebWidget::updateAllLifecyclePhases;
     using WebWidget::paint;
diff --git a/third_party/WebKit/public/web/WebWidget.h b/third_party/WebKit/public/web/WebWidget.h
index bfaa2ee..5f959da 100644
--- a/third_party/WebKit/public/web/WebWidget.h
+++ b/third_party/WebKit/public/web/WebWidget.h
@@ -72,8 +72,8 @@
     virtual void resizeVisualViewport(const WebSize&) { }
 
     // Called to notify the WebWidget of entering/exiting fullscreen mode.
-    virtual void didEnterFullScreen() { }
-    virtual void didExitFullScreen() { }
+    virtual void didEnterFullscreen() { }
+    virtual void didExitFullscreen() { }
 
     // Called to update imperative animation state. This should be called before
     // paint, although the client can rate-limit these calls.
diff --git a/third_party/boringssl/BUILD.generated.gni b/third_party/boringssl/BUILD.generated.gni
index 5d1aa79..d1ac9be 100644
--- a/third_party/boringssl/BUILD.generated.gni
+++ b/third_party/boringssl/BUILD.generated.gni
@@ -282,16 +282,15 @@
   "src/ssl/custom_extensions.c",
   "src/ssl/d1_both.c",
   "src/ssl/d1_lib.c",
-  "src/ssl/d1_meth.c",
   "src/ssl/d1_pkt.c",
   "src/ssl/d1_srtp.c",
+  "src/ssl/dtls_method.c",
   "src/ssl/dtls_record.c",
   "src/ssl/handshake_client.c",
   "src/ssl/handshake_server.c",
   "src/ssl/s3_both.c",
   "src/ssl/s3_enc.c",
   "src/ssl/s3_lib.c",
-  "src/ssl/s3_meth.c",
   "src/ssl/s3_pkt.c",
   "src/ssl/ssl_aead_ctx.c",
   "src/ssl/ssl_asn1.c",
@@ -306,6 +305,7 @@
   "src/ssl/ssl_stat.c",
   "src/ssl/t1_enc.c",
   "src/ssl/t1_lib.c",
+  "src/ssl/tls_method.c",
   "src/ssl/tls_record.c",
 ]
 
diff --git a/third_party/boringssl/boringssl.gypi b/third_party/boringssl/boringssl.gypi
index 399fb58..2c7e7c7 100644
--- a/third_party/boringssl/boringssl.gypi
+++ b/third_party/boringssl/boringssl.gypi
@@ -10,16 +10,15 @@
       'src/ssl/custom_extensions.c',
       'src/ssl/d1_both.c',
       'src/ssl/d1_lib.c',
-      'src/ssl/d1_meth.c',
       'src/ssl/d1_pkt.c',
       'src/ssl/d1_srtp.c',
+      'src/ssl/dtls_method.c',
       'src/ssl/dtls_record.c',
       'src/ssl/handshake_client.c',
       'src/ssl/handshake_server.c',
       'src/ssl/s3_both.c',
       'src/ssl/s3_enc.c',
       'src/ssl/s3_lib.c',
-      'src/ssl/s3_meth.c',
       'src/ssl/s3_pkt.c',
       'src/ssl/ssl_aead_ctx.c',
       'src/ssl/ssl_asn1.c',
@@ -34,6 +33,7 @@
       'src/ssl/ssl_stat.c',
       'src/ssl/t1_enc.c',
       'src/ssl/t1_lib.c',
+      'src/ssl/tls_method.c',
       'src/ssl/tls_record.c',
     ],
     'boringssl_crypto_sources': [
diff --git a/tools/android/loading/sandwich_prefetch.py b/tools/android/loading/sandwich_prefetch.py
index 22c9b00..0f53263 100644
--- a/tools/android/loading/sandwich_prefetch.py
+++ b/tools/android/loading/sandwich_prefetch.py
@@ -651,7 +651,7 @@
       runner = self._common_builder.CreateSandwichRunner()
       for transformer in transformer_list:
         transformer(runner)
-      runner.wpr_archive_path = self._wpr_archive_path
+      runner.wpr_archive_path = self._common_builder.original_wpr_task.path
       runner.wpr_out_log_path = os.path.join(
           RunBenchmark.path, sandwich_runner.WPR_LOG_FILENAME)
       runner.cache_archive_path = BuildBenchmarkCacheArchive.path
diff --git a/tools/gn/docs/cookbook.md b/tools/gn/docs/cookbook.md
index 942b572..a11bc13 100644
--- a/tools/gn/docs/cookbook.md
+++ b/tools/gn/docs/cookbook.md
@@ -261,7 +261,6 @@
 | `enable_service_discovery` (0/1)        | `enable_service_discovery` (true/false)        | `//build/config/features.gni` |
 | `enable_spellcheck` (0/1)               | `enable_spellcheck` (true/false)               | `//build/config/features.gni` |
 | `enable_session_service` (0/1)          | `enable_session_service` (true/false)          | `//build/config/features.gni` |
-| `enable_settings_app` (0/1)             | `enable_settings_app` (true/false)             | `//build/config/features.gni` |
 | `enable_task_manager` (0/1)             | `enable_task_manager` (true/false)             | `//build/config/features.gni` |
 | `enable_themes` (0/1)                   | `enable_themes` (true/false)                   | `//build/config/features.gni` |
 | `enable_webrtc` (0/1)                   | `enable_webrtc` (true/false)                   | `//build/config/features.gni` |
diff --git a/tools/grit/grit_rule.gni b/tools/grit/grit_rule.gni
index 107a4bc..b77a24d 100644
--- a/tools/grit/grit_rule.gni
+++ b/tools/grit/grit_rule.gni
@@ -263,12 +263,6 @@
     "enable_app_list",
   ]
 }
-if (enable_settings_app) {
-  grit_defines += [
-    "-D",
-    "enable_settings_app",
-  ]
-}
 if (enable_webrtc) {
   grit_defines += [
     "-D",
diff --git a/tools/ipc_fuzzer/fuzzer/fuzzer.cc b/tools/ipc_fuzzer/fuzzer/fuzzer.cc
index cba3809..5a7db7f5 100644
--- a/tools/ipc_fuzzer/fuzzer/fuzzer.cc
+++ b/tools/ipc_fuzzer/fuzzer/fuzzer.cc
@@ -705,14 +705,7 @@
 template <>
 struct FuzzTraits<cc::CompositorFrameAck> {
   static bool Fuzz(cc::CompositorFrameAck* p, Fuzzer* fuzzer) {
-    if (!FuzzParam(&p->resources, fuzzer))
-      return false;
-
-    if (!p->gl_frame_data)
-      p->gl_frame_data.reset(new cc::GLFrameData);
-    if (!FuzzParam(p->gl_frame_data.get(), fuzzer))
-      return false;
-    return true;
+    return FuzzParam(&p->resources, fuzzer);
   }
 };
 
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index c14d60a..89300f41 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -13304,6 +13304,13 @@
   </description>
 </action>
 
+<action name="Signin_Impression_FromAutofillDropdown">
+  <owner>mathp@chromium.org</owner>
+  <description>
+    Recorded when showing sign in entry in the Autofill dropdown.
+  </description>
+</action>
+
 <action name="Signin_Impression_FromAvatarBubbleSignin">
   <owner>gogerald@chromium.org</owner>
   <description>
@@ -13358,6 +13365,13 @@
   </description>
 </action>
 
+<action name="Signin_Impression_FromPasswordBubble">
+  <owner>gogerald@chromium.org</owner>
+  <description>
+    Recorded when showing sign in entry in the saving password bubble.
+  </description>
+</action>
+
 <action name="Signin_Impression_FromRecentTabs">
   <owner>gogerald@chromium.org</owner>
   <description>
@@ -13810,6 +13824,59 @@
   </description>
 </action>
 
+<action name="StatusArea_Display_Default_Selected">
+  <owner>bruthig@chromium.org</owner>
+  <owner>tbuckley@chromium.org</owner>
+  <description>
+    Counts the number of times the user selects the display row in the system
+    menu. This action does not always open the display settings, e.g. if the row
+    is slected from the lock screen. Use the
+    StatusArea_Display_Default_ShowSettings metric to see how often the settings
+    are actually launched.
+  </description>
+</action>
+
+<action name="StatusArea_Display_Default_ShowSettings">
+  <owner>bruthig@chromium.org</owner>
+  <owner>tbuckley@chromium.org</owner>
+  <description>
+    Counts the number of times the display settings are opened as a result of
+    the user selecting the display row in the system menu.
+  </description>
+</action>
+
+<action name="StatusArea_Display_Notification_Created">
+  <owner>bruthig@chromium.org</owner>
+  <owner>tbuckley@chromium.org</owner>
+  <description>
+    Counts the number of times a new display notification is added to the
+    notification center.
+  </description>
+</action>
+
+<action name="StatusArea_Display_Notification_Selected">
+  <owner>bruthig@chromium.org</owner>
+  <owner>tbuckley@chromium.org</owner>
+  <description>
+    Counts the number of times the user selects the display notification. This
+    action does not always open the display settings, e.g. if the notification
+    is selected from the lock screen. Use the
+    StatusArea_Display_Notification_Show_Settings metric to see how often the
+    settings are actually launched. Note these notifications are managed by the
+    notification center.
+  </description>
+</action>
+
+<action name="StatusArea_Display_Notification_Show_Settings">
+  <owner>bruthig@chromium.org</owner>
+  <owner>tbuckley@chromium.org</owner>
+  <description>
+    Counts the number of times the display settings are opened as a result of
+    the user selecting the display notification. Note these notifications are
+    managed by the notification center.
+  </description>
+</action>
+
 <action name="StatusArea_Drive_CancelOperation">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <description>Please enter the description of this user action.</description>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 78e185b6..fb3ba7f 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -3074,6 +3074,14 @@
   </summary>
 </histogram>
 
+<histogram name="Autofill.QueriedCreditCardFormIsSecure" enum="BooleanSecure">
+  <owner>mathp@chromium.org</owner>
+  <summary>
+    For credit card forms that are queried for Autofill, a ratio of how many are
+    within secure contexts (which includes mixed passive content).
+  </summary>
+</histogram>
+
 <histogram name="Autofill.SaveCreditCardPrompt"
     enum="AutofillSaveCreditCardPrompt">
   <owner>jdonnelly@chromium.org</owner>
@@ -21231,6 +21239,15 @@
   </summary>
 </histogram>
 
+<histogram name="Media.Audio.OutputDeviceAuthorizationTime" units="ms">
+  <owner>olka@chromium.org</owner>
+  <summary>
+    Time delta between the moment output device authorization request is
+    received by the browser and the moment its processessing is finished (and
+    reply is to be sent back to the renderer if IPC is not closed yet).
+  </summary>
+</histogram>
+
 <histogram name="Media.Audio.PhysicalProcessorsMac">
   <owner>henrika@chromium.org</owner>
   <summary>
@@ -21348,6 +21365,35 @@
   </summary>
 </histogram>
 
+<histogram
+    name="Media.Audio.Render.SinkCache.GetOutputDeviceInfoCacheUtilization"
+    enum="GetOutputDeviceInfoCacheHit">
+  <owner>olka@chromium.org</owner>
+  <summary>
+    Whether a cached sink was used to get audio output device information, or a
+    new sink was created for that.
+  </summary>
+</histogram>
+
+<histogram name="Media.Audio.Render.SinkCache.InfoSinkReusedForOutput"
+    enum="BooleanReused">
+  <owner>olka@chromium.org</owner>
+  <summary>
+    When a new sink is created to get output device information, it is cached.
+    This metric shows if such a sink is later reused for audio output (can
+    happen no more than once) or deleted unused after timeout expires. Logged
+    when one of the abovementioned events takes place.
+  </summary>
+</histogram>
+
+<histogram name="Media.Audio.Render.SinkCache.UsedForSinkCreation"
+    enum="BooleanUsage">
+  <owner>olka@chromium.org</owner>
+  <summary>
+    Whether a sink was created through the sink cache or directly.
+  </summary>
+</histogram>
+
 <histogram name="Media.Audio.RenderFailsWhenBufferSizeChangesMac"
     enum="BooleanChanged">
   <owner>henrika@chromium.org</owner>
@@ -59958,6 +60004,15 @@
   </summary>
 </histogram>
 
+<histogram name="UMA.PersistentHistograms.InitResult"
+    enum="PersistentHistogramsInitResult">
+  <owner>bcwhite@chromium.org</owner>
+  <summary>
+    A count of successes and various failure modes related to collecting and
+    processing performance data obtained through &quot;perf&quot; on Chrome OS.
+  </summary>
+</histogram>
+
 <histogram name="UMA.ProfilesCount.AfterErase">
   <obsolete>
     Deprecated as of Jun 2016. The histogram was added for debugging purpose and
@@ -63169,6 +63224,18 @@
   </summary>
 </histogram>
 
+<histogram name="WebFont.InterventionResult.MissedCache"
+    enum="WebFontInterventionResult">
+  <owner>toyoshim@chromium.org</owner>
+  <owner>kenjibaheux@chromium.org</owner>
+  <summary>
+    Like InterventionResult, this records whether User Agent Intervention was
+    triggered, and whether the request (would have) timed out or not. But this
+    version records only when data actually comes from network, not from disk or
+    memory cache, and is not provided in a data URL format.
+  </summary>
+</histogram>
+
 <histogram name="WebFont.LayoutLatency" units="ms">
   <obsolete>
     Renamed to WebFont.StyleRecalcToDownloadLatency for clarity.
@@ -70573,6 +70640,7 @@
   <int value="2" label="Ignore">
     The user did not interact with the info bar.
   </int>
+  <int value="3" label="Dismiss">The user explicitly closed the infobar.</int>
 </enum>
 
 <enum name="DefaultBrowserState" type="int">
@@ -78351,6 +78419,21 @@
   <int value="2" label="Gesture predicted but didn't occur"/>
 </enum>
 
+<enum name="GetOutputDeviceInfoCacheHit" type="int">
+  <int value="0" label="Miss: no cached sink found">
+    Output parmeters for a device are requested, and there is no corresponding
+    sink cached; new sink is created and cached.
+  </int>
+  <int value="1" label="Miss: cannot lookup by session id">
+    If session id is used to specify a device, we always have to create and
+    cache a new sink.
+  </int>
+  <int value="2" label="Hit">
+    Output parmeters for a device are requested, and there is a corresponding
+    sink cached.
+  </int>
+</enum>
+
 <enum name="GetPerfDataOutcome" type="int">
   <int value="0" label="Success.">
     Perf data was collected, parsed and attached to the UMA protobuf
@@ -86128,6 +86211,13 @@
   <int value="10" label="PERMISSION_BACKGROUND_SYNC"/>
 </enum>
 
+<enum name="PersistentHistogramsInitResult" type="int">
+  <int value="0" label="Local-Memory Success"/>
+  <int value="1" label="Local-Memory Failure"/>
+  <int value="2" label="Mapped-File Success"/>
+  <int value="3" label="Mapped-File Failure"/>
+</enum>
+
 <enum name="PhotoEditorFileType" type="int">
   <int value="0" label="jpg"/>
   <int value="1" label="png"/>
@@ -98464,7 +98554,8 @@
              data reduction proxy."/>
   <suffix name="Clients.DataReductionProxy.LoFiOn"
       label="PageLoadMetrics that are a result of a navigation through the
-             data reduction proxy with LoFi requested."/>
+             data reduction proxy with session in LoFi enabled or control
+             field trial, and when the connection was slow."/>
   <suffix name="Clients.DocWrite.Evaluator"
       label="PageLoadMetrics from a page that could have been evaluated by
              the DocumentWriteEvaluator"/>
diff --git a/tools/perf/page_sets/data/dual_browser_story.json b/tools/perf/page_sets/data/dual_browser_story.json
index 208221a..b9c8ffa 100644
--- a/tools/perf/page_sets/data/dual_browser_story.json
+++ b/tools/perf/page_sets/data/dual_browser_story.json
@@ -1,30 +1,34 @@
 {
-    "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating.",
     "archives": {
-        "dual_browser_story_001.wpr": [
-            "http_en_m_wikipedia_org_wiki_Science",
-            "google_weather_94110",
-            "google_1600_amphitheatre_pkwy_mountain_view_ca",
-            "google_population_of_california",
-            "google_cat_pictures",
-            "google_tip_on_100_bill",
-            "http_www_amazon_com_gp_aw_s_k_nexus",
-            "http_search_yahoo_com_search__ylt_p_google",
-            "http_yandex_ru_touchsearch_text_science",
-            "google_sfo_jfk_flights",
-            "https_mobile_twitter_com_justinbieber_skip_interstitial_true",
-            "google_tom_hanks",
-            "http_m_taobao_com_channel_act_mobile_20131111_women_html",
-            "http_www_baidu_com_s_word_google",
-            "https_www_google_ca_hl_en_q_science",
-            "google_movies_94110",
-            "google_goog",
-            "google_science",
-            "https_m_facebook_com_rihanna",
-            "http_m_youtube_com_results_q_science"
-        ],
         "dual_browser_story_000.wpr": [
             "https_www_google_com_hl_en_q_science"
+        ],
+        "dual_browser_story_001.wpr": [
+            "http_m_taobao_com_channel_act_mobile_20131111_women_html",
+            "https_www_google_ca_hl_en_q_science"
+        ],
+        "dual_browser_story_002.wpr": [
+            "http_www_amazon_com_gp_aw_s_k_nexus",
+            "http_m_youtube_com_results_q_science",
+            "google_weather_94110",
+            "google_tom_hanks",
+            "http_search_yahoo_com_search__ylt_p_google",
+            "google_sfo_jfk_flights",
+            "google_goog",
+            "https_mobile_twitter_com_justinbieber_skip_interstitial_true",
+            "http_m_intl_taobao_com_group_purchase_html",
+            "https_www_google_co_uk_hl_en_q_science",
+            "google_population_of_california",
+            "https_m_facebook_com_rihanna",
+            "http_yandex_ru_touchsearch_text_science",
+            "google_cat_pictures",
+            "google_movies_94110",
+            "google_science",
+            "http_en_m_wikipedia_org_wiki_Science",
+            "google_1600_amphitheatre_pkwy_mountain_view_ca",
+            "google_tip_on_100_bill",
+            "http_www_baidu_com_s_word_google"
         ]
-    }
-}
+    },
+    "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating."
+}
\ No newline at end of file
diff --git a/tools/perf/page_sets/data/dual_browser_story_002.wpr.sha1 b/tools/perf/page_sets/data/dual_browser_story_002.wpr.sha1
new file mode 100644
index 0000000..bdd814b
--- /dev/null
+++ b/tools/perf/page_sets/data/dual_browser_story_002.wpr.sha1
@@ -0,0 +1 @@
+c444ca554bd48238dd6a07d1f7773a68f7edc90d
\ No newline at end of file
diff --git a/tools/perf/page_sets/data/memory_top_10_mobile.json b/tools/perf/page_sets/data/memory_top_10_mobile.json
index c300ea3..4ef26a5 100644
--- a/tools/perf/page_sets/data/memory_top_10_mobile.json
+++ b/tools/perf/page_sets/data/memory_top_10_mobile.json
@@ -1,27 +1,33 @@
 {
-    "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating.", 
     "archives": {
         "memory_top_10_mobile_000.wpr": [
-            "after_http_en_m_wikipedia_org_wiki_Science", 
-            "after_https_mobile_twitter_com_justinbieber_skip_interstitial_true", 
-            "after_http_yandex_ru_touchsearch_text_science", 
-            "https_www_google_com_hl_en_q_science", 
-            "http_search_yahoo_com_search__ylt_p_google", 
-            "after_http_m_youtube_com_results_q_science", 
-            "https_mobile_twitter_com_justinbieber_skip_interstitial_true", 
-            "https_m_facebook_com_rihanna", 
-            "after_http_www_amazon_com_gp_aw_s_k_nexus", 
-            "after_http_search_yahoo_com_search__ylt_p_google", 
-            "after_https_www_google_com_hl_en_q_science", 
-            "http_en_m_wikipedia_org_wiki_Science", 
-            "http_www_baidu_com_s_word_google", 
-            "after_http_www_baidu_com_s_word_google", 
-            "after_https_m_facebook_com_rihanna", 
-            "http_www_amazon_com_gp_aw_s_k_nexus", 
-            "after_http_m_taobao_com_channel_act_mobile_20131111_women_html", 
-            "http_yandex_ru_touchsearch_text_science", 
-            "http_m_youtube_com_results_q_science", 
+            "https_www_google_com_hl_en_q_science",
+            "after_https_www_google_com_hl_en_q_science",
+            "after_http_m_taobao_com_channel_act_mobile_20131111_women_html",
             "http_m_taobao_com_channel_act_mobile_20131111_women_html"
+        ],
+        "memory_top_10_mobile_001.wpr": [
+            "after_http_m_intl_taobao_com_group_purchase_html",
+            "http_m_youtube_com_results_q_science",
+            "https_m_facebook_com_rihanna",
+            "http_m_intl_taobao_com_group_purchase_html",
+            "after_http_en_m_wikipedia_org_wiki_Science",
+            "after_http_m_youtube_com_results_q_science",
+            "http_search_yahoo_com_search__ylt_p_google",
+            "after_http_www_baidu_com_s_word_google",
+            "after_http_www_amazon_com_gp_aw_s_k_nexus",
+            "after_https_www_google_co_uk_hl_en_q_science",
+            "after_http_yandex_ru_touchsearch_text_science",
+            "http_en_m_wikipedia_org_wiki_Science",
+            "http_www_baidu_com_s_word_google",
+            "http_www_amazon_com_gp_aw_s_k_nexus",
+            "after_http_search_yahoo_com_search__ylt_p_google",
+            "http_yandex_ru_touchsearch_text_science",
+            "after_https_m_facebook_com_rihanna",
+            "https_www_google_co_uk_hl_en_q_science",
+            "after_https_mobile_twitter_com_justinbieber_skip_interstitial_true",
+            "https_mobile_twitter_com_justinbieber_skip_interstitial_true"
         ]
-    }
+    },
+    "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating."
 }
\ No newline at end of file
diff --git a/tools/perf/page_sets/data/memory_top_10_mobile_001.wpr.sha1 b/tools/perf/page_sets/data/memory_top_10_mobile_001.wpr.sha1
new file mode 100644
index 0000000..1c878f0
--- /dev/null
+++ b/tools/perf/page_sets/data/memory_top_10_mobile_001.wpr.sha1
@@ -0,0 +1 @@
+8578c7ef3560fab0ad205affec3bf917ab1c9d13
\ No newline at end of file
diff --git a/tools/perf/page_sets/data/top_10_mobile.json b/tools/perf/page_sets/data/top_10_mobile.json
index fa98bb4..a1af9a4 100644
--- a/tools/perf/page_sets/data/top_10_mobile.json
+++ b/tools/perf/page_sets/data/top_10_mobile.json
@@ -1,20 +1,24 @@
 {
-    "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating.", 
     "archives": {
         "top_10_mobile_000.wpr": [
             "https://mobile.twitter.com/justinbieber&"
-        ], 
+        ],
         "top_10_mobile_003.wpr": [
-            "http://m.youtube.com/results?q=science", 
-            "http://yandex.ru/touchsearch?text=science", 
-            "http://m.taobao.com/channel/act/mobile/20131111-women.html", 
-            "http://search.yahoo.com/search;_ylt=?p=google", 
-            "http://www.baidu.com/s?word=google", 
-            "http://www.amazon.com/gp/aw/s/?k=nexus", 
-            "http://en.m.wikipedia.org/wiki/Science", 
-            "https://mobile.twitter.com/justinbieber?skip_interstitial=true", 
-            "https://www.google.com/#hl=en&q=science", 
-            "https://m.facebook.com/rihanna"
+            "http://m.taobao.com/channel/act/mobile/20131111-women.html",
+            "https://www.google.com/#hl=en&q=science"
+        ],
+        "top_10_mobile_004.wpr": [
+            "https://m.facebook.com/rihanna",
+            "http://www.baidu.com/s?word=google",
+            "https://mobile.twitter.com/justinbieber?skip_interstitial=true",
+            "http://m.youtube.com/results?q=science",
+            "http://en.m.wikipedia.org/wiki/Science",
+            "http://m.intl.taobao.com/group-purchase.html",
+            "http://www.amazon.com/gp/aw/s/?k=nexus",
+            "https://www.google.co.uk/#hl=en&q=science",
+            "http://search.yahoo.com/search;_ylt=?p=google",
+            "http://yandex.ru/touchsearch?text=science"
         ]
-    }
+    },
+    "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating."
 }
\ No newline at end of file
diff --git a/tools/perf/page_sets/data/top_10_mobile_004.wpr.sha1 b/tools/perf/page_sets/data/top_10_mobile_004.wpr.sha1
new file mode 100644
index 0000000..64eb84c6f
--- /dev/null
+++ b/tools/perf/page_sets/data/top_10_mobile_004.wpr.sha1
@@ -0,0 +1 @@
+e4d9749fe4f1073674003142ff4ae77d95548296
\ No newline at end of file
diff --git a/tools/perf/page_sets/dual_browser_story.py b/tools/perf/page_sets/dual_browser_story.py
index cb0826c..debaf60 100644
--- a/tools/perf/page_sets/dual_browser_story.py
+++ b/tools/perf/page_sets/dual_browser_story.py
@@ -19,7 +19,7 @@
 from page_sets.top_10_mobile import URL_LIST
 
 
-GOOGLE_SEARCH = 'https://www.google.com/search?'
+GOOGLE_SEARCH = 'https://www.google.co.uk/search?'
 
 SEARCH_QUERIES = [
   'science',
diff --git a/tools/perf/page_sets/mac_gpu_sites.py b/tools/perf/page_sets/mac_gpu_sites.py
index f95e0994..f5e26c9 100644
--- a/tools/perf/page_sets/mac_gpu_sites.py
+++ b/tools/perf/page_sets/mac_gpu_sites.py
@@ -42,6 +42,16 @@
         shared_page_state_class=shared_page_state_class)
 
 
+class TrivialCanvasPage(page_module.Page):
+
+  def __init__(self, page_set, shared_page_state_class):
+    super(TrivialCanvasPage, self).__init__(
+        url='file://trivial_sites/trivial_canvas.html',
+        page_set=page_set,
+        name=self.__class__.__name__ + shared_page_state_class.__name__,
+        shared_page_state_class=shared_page_state_class)
+
+
 class MacGpuTrivialPagesStorySet(story.StorySet):
 
   def __init__(self):
@@ -49,10 +59,13 @@
     self.AddStory(TrivialScrollingPage(self, shared_page_state.SharedPageState))
     self.AddStory(TrivialBlinkingCursorPage(
         self, shared_page_state.SharedPageState))
+    self.AddStory(TrivialCanvasPage(self, shared_page_state.SharedPageState))
     self.AddStory(TrivialScrollingPage(self, _NoOverlaysSharedPageState))
     self.AddStory(TrivialBlinkingCursorPage(self, _NoOverlaysSharedPageState))
+    self.AddStory(TrivialCanvasPage(self, _NoOverlaysSharedPageState))
     self.AddStory(TrivialScrollingPage(self, _NoGpuSharedPageState))
     self.AddStory(TrivialBlinkingCursorPage(self, _NoGpuSharedPageState))
+    self.AddStory(TrivialCanvasPage(self, _NoGpuSharedPageState))
 
   @property
   def allow_mixed_story_states(self):
diff --git a/tools/perf/page_sets/text_selection_sites.py b/tools/perf/page_sets/text_selection_sites.py
index 90885d57..435379c 100644
--- a/tools/perf/page_sets/text_selection_sites.py
+++ b/tools/perf/page_sets/text_selection_sites.py
@@ -151,7 +151,7 @@
 
     # A subset of top_10_mobile page set
     page_urls = [
-        'https://www.google.com/#hl=en&q=science',
+        'https://www.google.co.uk/#hl=en&q=science',
         'https://m.facebook.com/rihanna',
         'http://search.yahoo.com/search;_ylt=?p=google',
         'http://www.baidu.com/s?word=google',
diff --git a/tools/perf/page_sets/top_10_mobile.py b/tools/perf/page_sets/top_10_mobile.py
index 485cac9..099b8ff 100644
--- a/tools/perf/page_sets/top_10_mobile.py
+++ b/tools/perf/page_sets/top_10_mobile.py
@@ -9,7 +9,7 @@
 URL_LIST = [
     # Why: #1 (Alexa) most visited page worldwide, picked a reasonable
     # search term
-    'https://www.google.com/#hl=en&q=science',
+    'https://www.google.co.uk/#hl=en&q=science',
     # Why: #2 (Alexa) most visited page worldwide, picked the most liked
     # page
     'https://m.facebook.com/rihanna',
@@ -32,7 +32,7 @@
     'http://www.amazon.com/gp/aw/s/?k=nexus',
     # Why: #13 (Alexa) most visited page worldwide, picked the first real
     # page
-    'http://m.taobao.com/channel/act/mobile/20131111-women.html',
+    'http://m.intl.taobao.com/group-purchase.html',
     # Why: #18 (Alexa) most visited page worldwide, picked a reasonable
     # search term
     'http://yandex.ru/touchsearch?text=science',
diff --git a/tools/perf/page_sets/trivial_sites/trivial_canvas.html b/tools/perf/page_sets/trivial_sites/trivial_canvas.html
new file mode 100644
index 0000000..56719379
--- /dev/null
+++ b/tools/perf/page_sets/trivial_sites/trivial_canvas.html
@@ -0,0 +1,37 @@
+<!doctype html>
+<!--
+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.
+-->
+<html style="height:100%">
+<head>
+  <style>
+    html, body {
+      margin: 0;
+      padding: 0;
+    }
+  </style>
+</head>
+<body style="height:100%">
+  <canvas id="canvas" width="200" height="100"></canvas>
+</body>
+<script>
+  var canvas = document.querySelector('canvas');
+  canvas.style.width ='100%';
+  canvas.style.height='100%';
+  canvas.width  = canvas.offsetWidth;
+  canvas.height = canvas.offsetHeight;
+  var ctx = canvas.getContext("2d");
+  var rColor = 0;
+
+  function animate() {
+    rColor += 1;
+    rColor %= 255;
+    ctx.fillStyle = 'rgb(' + rColor + ',0,0)';
+    ctx.fillRect(0, 0, canvas.width, canvas.height);
+    window.requestAnimationFrame(animate);
+  }
+  window.onload = animate;
+</script>
+</html>
diff --git a/tools/valgrind/drmemory/suppressions_full.txt b/tools/valgrind/drmemory/suppressions_full.txt
index 32c46d9..bd01cffd 100644
--- a/tools/valgrind/drmemory/suppressions_full.txt
+++ b/tools/valgrind/drmemory/suppressions_full.txt
@@ -1660,12 +1660,6 @@
 *!SpellcheckLanguage::SpellCheckWord
 *!SpellCheck::SpellCheckWord
 
-UNINITIALIZED READ
-name=bug_387373
-*!blink::WebEmbeddedWorkerImpl::startWorkerContext
-*!content::EmbeddedWorkerDispatcher::OnStartWorker
-*!EmbeddedWorkerMsg_StartWorker::Dispatch<>
-
 UNADDRESSABLE ACCESS
 name=bug_389132
 content.dll!crypto_kernel_do_load_cipher_type
diff --git a/ui/app_list/app_list_menu.cc b/ui/app_list/app_list_menu.cc
index 4f71d21a..8a1a069 100644
--- a/ui/app_list/app_list_menu.cc
+++ b/ui/app_list/app_list_menu.cc
@@ -50,9 +50,6 @@
     menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
   }
 
-  menu_model_.AddItem(SHOW_SETTINGS, l10n_util::GetStringUTF16(
-      IDS_APP_LIST_OPEN_SETTINGS));
-
   menu_model_.AddItem(SHOW_HELP, l10n_util::GetStringUTF16(
       IDS_APP_LIST_HELP));
 
@@ -73,8 +70,9 @@
   return true;
 }
 
-bool AppListMenu::GetAcceleratorForCommandId(int command_id,
-                                             ui::Accelerator* accelerator) {
+bool AppListMenu::GetAcceleratorForCommandId(
+    int command_id,
+    ui::Accelerator* accelerator) const {
   return false;
 }
 
@@ -85,9 +83,6 @@
     return;
   }
   switch (command_id) {
-    case SHOW_SETTINGS:
-      delegate_->OpenSettings();
-      break;
     case SHOW_HELP:
       delegate_->OpenHelp();
       break;
diff --git a/ui/app_list/app_list_menu.h b/ui/app_list/app_list_menu.h
index 232f82d..92b11b2 100644
--- a/ui/app_list/app_list_menu.h
+++ b/ui/app_list/app_list_menu.h
@@ -13,7 +13,7 @@
 
 // Menu for the app list. This is shown in the top right hand corner of the
 // app list.
-// TODO(benwells): We should consider moving this into Chrome.
+// TODO(benwells): We should delete this. http://crbug.com/600915.
 class AppListMenu : public ui::SimpleMenuModel::Delegate {
  public:
   enum AppListMenuCommands {
@@ -36,7 +36,7 @@
   bool IsCommandIdChecked(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
 
   ui::SimpleMenuModel menu_model_;
diff --git a/ui/app_list/app_list_switches.cc b/ui/app_list/app_list_switches.cc
index 0c47326..531ebc6 100644
--- a/ui/app_list/app_list_switches.cc
+++ b/ui/app_list/app_list_switches.cc
@@ -40,11 +40,6 @@
 const char kDisableDriveSearchInChromeLauncher[] =
     "disable-drive-search-in-app-launcher";
 
-// Enable/disable the new "blended" algorithm in app_list::Mixer. This is just
-// forcing the AppListMixer/Blended field trial.
-const char kEnableNewAppListMixer[] = "enable-new-app-list-mixer";
-const char kDisableNewAppListMixer[] = "disable-new-app-list-mixer";
-
 // If set, the app list will forget it has been installed on startup. Note this
 // doesn't prevent the app list from running, it just makes Chrome think the app
 // list hasn't been enabled (as in kEnableAppList) yet.
diff --git a/ui/app_list/app_list_switches.h b/ui/app_list/app_list_switches.h
index 21955d5..05c6f0b 100644
--- a/ui/app_list/app_list_switches.h
+++ b/ui/app_list/app_list_switches.h
@@ -18,8 +18,6 @@
 APP_LIST_EXPORT extern const char kEnableCenteredAppList[];
 APP_LIST_EXPORT extern const char kEnableExperimentalAppList[];
 APP_LIST_EXPORT extern const char kDisableExperimentalAppList[];
-APP_LIST_EXPORT extern const char kEnableNewAppListMixer[];
-APP_LIST_EXPORT extern const char kDisableNewAppListMixer[];
 APP_LIST_EXPORT extern const char kEnableSyncAppList[];
 APP_LIST_EXPORT extern const char kDisableSyncAppList[];
 APP_LIST_EXPORT extern const char kEnableDriveSearchInChromeLauncher[];
diff --git a/ui/app_list/app_list_view_delegate.h b/ui/app_list/app_list_view_delegate.h
index b3c4c2c..51f9033 100644
--- a/ui/app_list/app_list_view_delegate.h
+++ b/ui/app_list/app_list_view_delegate.h
@@ -117,9 +117,6 @@
   // Invoked when the app list is closing.
   virtual void ViewClosing() = 0;
 
-  // Open the settings UI.
-  virtual void OpenSettings() = 0;
-
   // Open the help UI.
   virtual void OpenHelp() = 0;
 
diff --git a/ui/app_list/search/mixer.cc b/ui/app_list/search/mixer.cc
index e49f3ba4..f5b7e998 100644
--- a/ui/app_list/search/mixer.cc
+++ b/ui/app_list/search/mixer.cc
@@ -10,10 +10,7 @@
 #include <string>
 #include <vector>
 
-#include "base/command_line.h"
 #include "base/macros.h"
-#include "base/metrics/field_trial.h"
-#include "ui/app_list/app_list_switches.h"
 #include "ui/app_list/search_provider.h"
 #include "ui/app_list/search_result.h"
 
@@ -21,19 +18,8 @@
 
 namespace {
 
-// Maximum number of results to show. Ignored if the AppListMixer field trial is
-// "Blended".
-const size_t kMaxResults = 6;
-
-// The minimum number of results to show, if the AppListMixer field trial is
-// "Blended". If this quota is not reached, the per-group limitations are
-// removed and we try again. (We may still not reach the minumum, but at least
-// we tried.) Ignored if the field trial is off.
-const size_t kMinBlendedResults = 6;
-
-const char kAppListMixerFieldTrialName[] = "AppListMixer";
-const char kAppListMixerFieldTrialEnabled[] = "Blended";
-const char kAppListMixerFieldTrialDisabled[] = "Control";
+// Maximum number of results to show.
+const size_t kMinResults = 6;
 
 void UpdateResult(const SearchResult& source, SearchResult* target) {
   target->set_display_type(source.display_type());
@@ -43,37 +29,6 @@
   target->set_details_tags(source.details_tags());
 }
 
-// Returns true if the "AppListMixer" trial is set to "Blended". This is an
-// experiment on the new Mixer logic that allows results from different groups
-// to be blended together, rather than stratified.
-bool IsBlendedMixerTrialEnabled() {
-  // Note: It's important to query the field trial state first, to ensure that
-  // UMA reports the correct group.
-  const std::string group_name =
-      base::FieldTrialList::FindFullName(kAppListMixerFieldTrialName);
-
-  // Respect command-line flags first.
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kDisableNewAppListMixer)) {
-    return false;
-  }
-
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableNewAppListMixer)) {
-    return true;
-  }
-
-  // Next, respect field-trial groups.
-  if (group_name == kAppListMixerFieldTrialEnabled)
-    return true;
-
-  if (group_name == kAppListMixerFieldTrialDisabled)
-    return false;
-
-  // By default, enable the new logic if the experimental app list is enabled.
-  return app_list::switches::IsExperimentalAppListEnabled();
-}
-
 }  // namespace
 
 Mixer::SortData::SortData() : result(NULL), score(0.0) {
@@ -91,8 +46,8 @@
 // Used to group relevant providers together for mixing their results.
 class Mixer::Group {
  public:
-  Group(size_t max_results, double boost, double multiplier)
-      : max_results_(max_results), boost_(boost), multiplier_(multiplier) {}
+  Group(size_t max_results, double multiplier)
+      : max_results_(max_results), multiplier_(multiplier) {}
   ~Group() {}
 
   void AddProvider(SearchProvider* provider) { providers_.push_back(provider); }
@@ -110,7 +65,7 @@
         double relevance = std::min(std::max(result->relevance(), 0.0), 1.0);
 
         double multiplier = multiplier_;
-        double boost = boost_;
+        double boost = 0.0;
 
         // Recommendations should not be affected by query-to-launch correlation
         // from KnownResults as it causes recommendations to become dominated by
@@ -159,7 +114,6 @@
  private:
   typedef std::vector<SearchProvider*> Providers;
   const size_t max_results_;
-  const double boost_;
   const double multiplier_;
 
   Providers providers_;  // Not owned.
@@ -174,28 +128,11 @@
 Mixer::~Mixer() {
 }
 
-size_t Mixer::AddGroup(size_t max_results, double boost, double multiplier) {
-  // Only consider |boost| if the AppListMixer field trial is default.
-  // Only consider |multiplier| if the AppListMixer field trial is "Blended".
-  if (IsBlendedMixerTrialEnabled())
-    boost = 0.0;
-  else
-    multiplier = 1.0;
-  groups_.push_back(new Group(max_results, boost, multiplier));
+size_t Mixer::AddGroup(size_t max_results, double multiplier) {
+  groups_.push_back(new Group(max_results, multiplier));
   return groups_.size() - 1;
 }
 
-size_t Mixer::AddOmniboxGroup(size_t max_results,
-                              double boost,
-                              double multiplier) {
-  // There should not already be an omnibox group.
-  DCHECK(!has_omnibox_group_);
-  size_t id = AddGroup(max_results, boost, multiplier);
-  omnibox_group_ = id;
-  has_omnibox_group_ = true;
-  return id;
-}
-
 void Mixer::AddProviderToGroup(size_t group_id, SearchProvider* provider) {
   groups_[group_id]->AddProvider(provider);
 }
@@ -205,78 +142,39 @@
   FetchResults(is_voice_query, known_results);
 
   SortedResults results;
+  results.reserve(kMinResults);
 
-  if (IsBlendedMixerTrialEnabled()) {
-    results.reserve(kMinBlendedResults);
+  // Add results from each group. Limit to the maximum number of results in each
+  // group.
+  for (const Group* group : groups_) {
+    size_t num_results =
+        std::min(group->results().size(), group->max_results());
+    results.insert(results.end(), group->results().begin(),
+                   group->results().begin() + num_results);
+  }
+  // Remove results with duplicate IDs before sorting. If two providers give a
+  // result with the same ID, the result from the provider with the *lower group
+  // number* will be kept (e.g., an app result takes priority over a web store
+  // result with the same ID).
+  RemoveDuplicates(&results);
+  std::sort(results.begin(), results.end());
 
-    // Add results from each group. Limit to the maximum number of results in
-    // each group.
+  if (results.size() < kMinResults) {
+    size_t original_size = results.size();
+    // We didn't get enough results. Insert all the results again, and this
+    // time, do not limit the maximum number of results from each group. (This
+    // will result in duplicates, which will be removed by RemoveDuplicates.)
     for (const Group* group : groups_) {
-      size_t num_results =
-          std::min(group->results().size(), group->max_results());
       results.insert(results.end(), group->results().begin(),
-                     group->results().begin() + num_results);
+                     group->results().end());
     }
-    // Remove results with duplicate IDs before sorting. If two providers give a
-    // result with the same ID, the result from the provider with the *lower
-    // group number* will be kept (e.g., an app result takes priority over a web
-    // store result with the same ID).
     RemoveDuplicates(&results);
-    std::sort(results.begin(), results.end());
-
-    if (results.size() < kMinBlendedResults) {
-      size_t original_size = results.size();
-      // We didn't get enough results. Insert all the results again, and this
-      // time, do not limit the maximum number of results from each group. (This
-      // will result in duplicates, which will be removed by RemoveDuplicates.)
-      for (const Group* group : groups_) {
-        results.insert(results.end(), group->results().begin(),
-                       group->results().end());
-      }
-      RemoveDuplicates(&results);
-      // Sort just the newly added results. This ensures that, for example, if
-      // there are 6 Omnibox results (score = 0.8) and 1 People result (score =
-      // 0.4) that the People result will be 5th, not 7th, because the Omnibox
-      // group has a soft maximum of 4 results. (Otherwise, the People result
-      // would not be seen at all once the result list is truncated.)
-      std::sort(results.begin() + original_size, results.end());
-    }
-  } else {
-    results.reserve(kMaxResults);
-
-    // Add results from non-omnibox groups first. Limit to the maximum number of
-    // results in each group.
-    for (size_t i = 0; i < groups_.size(); ++i) {
-      if (!has_omnibox_group_ || i != omnibox_group_) {
-        const Group& group = *groups_[i];
-        size_t num_results =
-            std::min(group.results().size(), group.max_results());
-        results.insert(results.end(), group.results().begin(),
-                       group.results().begin() + num_results);
-      }
-    }
-
-    // Collapse duplicate apps from local and web store.
-    RemoveDuplicates(&results);
-
-    // Fill the remaining slots with omnibox results. Always add at least one
-    // omnibox result (even if there are no more slots; if we over-fill the
-    // vector, the web store and people results will be removed in a later
-    // step). Note: max_results() is ignored for the omnibox group.
-    if (has_omnibox_group_) {
-      CHECK_LT(omnibox_group_, groups_.size());
-      const Group& omnibox_group = *groups_[omnibox_group_];
-      const size_t omnibox_results = std::min(
-          omnibox_group.results().size(),
-          results.size() < kMaxResults ? kMaxResults - results.size() : 1);
-      results.insert(results.end(), omnibox_group.results().begin(),
-                     omnibox_group.results().begin() + omnibox_results);
-    }
-
-    std::sort(results.begin(), results.end());
-    RemoveDuplicates(&results);
-    if (results.size() > kMaxResults)
-      results.resize(kMaxResults);
+    // Sort just the newly added results. This ensures that, for example, if
+    // there are 6 Omnibox results (score = 0.8) and 1 People result (score =
+    // 0.4) that the People result will be 5th, not 7th, because the Omnibox
+    // group has a soft maximum of 4 results. (Otherwise, the People result
+    // would not be seen at all once the result list is truncated.)
+    std::sort(results.begin() + original_size, results.end());
   }
 
   Publish(results, ui_results_);
diff --git a/ui/app_list/search/mixer.h b/ui/app_list/search/mixer.h
index b7898d7..e0aa3bd 100644
--- a/ui/app_list/search/mixer.h
+++ b/ui/app_list/search/mixer.h
@@ -28,30 +28,18 @@
 // Mixer collects results from providers, sorts them and publishes them to the
 // SearchResults UI model. The targeted results have 6 slots to hold the
 // result. The search controller can specify any number of groups, each with a
-// different number of results and priority boost. The "omnibox" group is
-// expected to contain omnibox results, and will be treated specially.
+// different number of results and priority boost.
 class APP_LIST_EXPORT Mixer {
  public:
   explicit Mixer(AppListModel::SearchResults* ui_results);
   ~Mixer();
 
-  // Adds a new mixer group. A maximum of |max_results| results will be
-  // displayed from this group (if 0, will allow unlimited results from this
-  // group). Behaviour depends on the AppListMixer field trial:
-  // - If default: Each result in the group will have its score boosted by
-  //   |boost|. |multiplier| is ignored.
-  // - If "Blended": |max_results| is a "soft" maximum; if there aren't enough
-  //   results from all groups, more than |max_results| may be chosen from this
-  //   group. Each result in the group will have its score multiplied by
-  //   |multiplier|. |boost| is ignored.
-  // Returns the group's group_id.
-  size_t AddGroup(size_t max_results, double boost, double multiplier);
-
-  // Adds a new mixer group for the special "omnibox" group. This group will be
-  // treated specially by the Mixer (it will be truncated such that it fills the
-  // remaining slots without overflowing, but with at least one result). A
-  // maximum of one group should be added using this method.
-  size_t AddOmniboxGroup(size_t max_results, double boost, double multiplier);
+  // Adds a new mixer group. A "soft" maximum of |max_results| results will be
+  // chosen from this group (if 0, will allow unlimited results from this
+  // group). If there aren't enough results from all groups, more than
+  // |max_results| may be chosen from this group. Each result in the group will
+  // have its score multiplied by |multiplier|. Returns the group's group_id.
+  size_t AddGroup(size_t max_results, double multiplier);
 
   // Associates a provider with a mixer group.
   void AddProviderToGroup(size_t group_id, SearchProvider* provider);
@@ -94,14 +82,6 @@
   AppListModel::SearchResults* ui_results_;  // Not owned.
   Groups groups_;
 
-  // The ID of the omnibox group. The group with this ID will be treated
-  // specially by the Mixer. Ignored if the AppListMixer field trial is
-  // "Blended".
-  // TODO(mgiuca): Remove this after the field trial is complete.
-  size_t omnibox_group_ = 0;
-  // Whether |omnibox_group_| has been set.
-  bool has_omnibox_group_ = false;
-
   DISALLOW_COPY_AND_ASSIGN(Mixer);
 };
 
diff --git a/ui/app_list/search/mixer_unittest.cc b/ui/app_list/search/mixer_unittest.cc
index 92e06298..6e1809c 100644
--- a/ui/app_list/search/mixer_unittest.cc
+++ b/ui/app_list/search/mixer_unittest.cc
@@ -12,11 +12,9 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/scoped_vector.h"
-#include "base/metrics/field_trial.h"
 #include "base/strings/string16.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/test/mock_entropy_provider.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/app_list/app_list_model.h"
 #include "ui/app_list/search/history_types.h"
@@ -28,7 +26,6 @@
 
 // Maximum number of results to show in each mixer group.
 const size_t kMaxAppsGroupResults = 4;
-// Ignored unless AppListMixer field trial is "Blended".
 const size_t kMaxOmniboxResults = 4;
 const size_t kMaxWebstoreResults = 2;
 
@@ -115,21 +112,13 @@
   DISALLOW_COPY_AND_ASSIGN(TestSearchProvider);
 };
 
-// Test is parameterized with bool. True enables the "Blended" field trial.
-class MixerTest : public testing::Test,
-                  public testing::WithParamInterface<bool> {
+class MixerTest : public testing::Test {
  public:
-  MixerTest()
-      : is_voice_query_(false),
-        field_trial_list_(new base::MockEntropyProvider()) {}
+  MixerTest() : is_voice_query_(false) {}
   ~MixerTest() override {}
 
   // testing::Test overrides:
   void SetUp() override {
-    // If the parameter is true, enable the field trial.
-    const char* field_trial_name = GetParam() ? "Blended" : "Control";
-    base::FieldTrialList::CreateFieldTrial("AppListMixer", field_trial_name);
-
     results_.reset(new AppListModel::SearchResults);
 
     providers_.push_back(new TestSearchProvider("app"));
@@ -140,10 +129,9 @@
 
     mixer_.reset(new Mixer(results_.get()));
 
-    size_t apps_group_id = mixer_->AddGroup(kMaxAppsGroupResults, 3.0, 1.0);
-    size_t omnibox_group_id =
-        mixer_->AddOmniboxGroup(kMaxOmniboxResults, 2.0, 1.0);
-    size_t webstore_group_id = mixer_->AddGroup(kMaxWebstoreResults, 1.0, 0.5);
+    size_t apps_group_id = mixer_->AddGroup(kMaxAppsGroupResults, 1.0);
+    size_t omnibox_group_id = mixer_->AddGroup(kMaxOmniboxResults, 1.0);
+    size_t webstore_group_id = mixer_->AddGroup(kMaxWebstoreResults, 0.5);
 
     mixer_->AddProviderToGroup(apps_group_id, providers_[0]);
     mixer_->AddProviderToGroup(omnibox_group_id, providers_[1]);
@@ -196,57 +184,48 @@
 
   ScopedVector<TestSearchProvider> providers_;
 
-  base::FieldTrialList field_trial_list_;
-
   DISALLOW_COPY_AND_ASSIGN(MixerTest);
 };
 
-TEST_P(MixerTest, Basic) {
-  // Note: Some cases in |expected_blended| have vastly more results than
-  // others, due to the "at least 6" mechanism. If it gets at least 6 results
-  // from all providers, it stops at 6. If not, it fetches potentially many more
-  // results from all providers. Not ideal, but currently by design.
+TEST_F(MixerTest, Basic) {
+  // Note: Some cases in |expected| have vastly more results than others, due to
+  // the "at least 6" mechanism. If it gets at least 6 results from all
+  // providers, it stops at 6. If not, it fetches potentially many more results
+  // from all providers. Not ideal, but currently by design.
   struct TestCase {
     const size_t app_results;
     const size_t omnibox_results;
     const size_t webstore_results;
-    const char* expected_default;  // Expected results with trial off.
-    const char* expected_blended;  // Expected results with trial on.
+    const char* expected;
   } kTestCases[] = {
-      {0, 0, 0, "", ""},
-      {10, 0, 0, "app0,app1,app2,app3",
-       "app0,app1,app2,app3,app4,app5,app6,app7,app8,app9"},
-      {0, 0, 10, "webstore0,webstore1",
+      {0, 0, 0, ""},
+      {10, 0, 0, "app0,app1,app2,app3,app4,app5,app6,app7,app8,app9"},
+      {0, 0, 10,
        "webstore0,webstore1,webstore2,webstore3,webstore4,webstore5,webstore6,"
        "webstore7,webstore8,webstore9"},
-      {4, 6, 0, "app0,app1,app2,app3,omnibox0,omnibox1",
-       "app0,omnibox0,app1,omnibox1,app2,omnibox2,app3,omnibox3"},
-      {4, 6, 2, "app0,app1,app2,app3,omnibox0,webstore0",
+      {4, 6, 0, "app0,omnibox0,app1,omnibox1,app2,omnibox2,app3,omnibox3"},
+      {4, 6, 2,
        "app0,omnibox0,app1,omnibox1,app2,omnibox2,app3,omnibox3,webstore0,"
        "webstore1"},
-      {10, 10, 10, "app0,app1,app2,app3,omnibox0,webstore0",
+      {10, 10, 10,
        "app0,omnibox0,app1,omnibox1,app2,omnibox2,app3,omnibox3,webstore0,"
        "webstore1"},
-      {0, 10, 0, "omnibox0,omnibox1,omnibox2,omnibox3,omnibox4,omnibox5",
+      {0, 10, 0,
        "omnibox0,omnibox1,omnibox2,omnibox3,omnibox4,omnibox5,omnibox6,"
        "omnibox7,omnibox8,omnibox9"},
-      {0, 10, 1, "omnibox0,omnibox1,omnibox2,omnibox3,omnibox4,webstore0",
+      {0, 10, 1,
        "omnibox0,omnibox1,omnibox2,omnibox3,webstore0,omnibox4,omnibox5,"
        "omnibox6,omnibox7,omnibox8,omnibox9"},
-      {0, 10, 2, "omnibox0,omnibox1,omnibox2,omnibox3,webstore0,webstore1",
-       "omnibox0,omnibox1,omnibox2,omnibox3,webstore0,webstore1"},
-      {1, 10, 0, "app0,omnibox0,omnibox1,omnibox2,omnibox3,omnibox4",
+      {0, 10, 2, "omnibox0,omnibox1,omnibox2,omnibox3,webstore0,webstore1"},
+      {1, 10, 0,
        "app0,omnibox0,omnibox1,omnibox2,omnibox3,omnibox4,omnibox5,omnibox6,"
        "omnibox7,omnibox8,omnibox9"},
-      {2, 10, 0, "app0,app1,omnibox0,omnibox1,omnibox2,omnibox3",
-       "app0,omnibox0,app1,omnibox1,omnibox2,omnibox3"},
-      {2, 10, 1, "app0,app1,omnibox0,omnibox1,omnibox2,webstore0",
-       "app0,omnibox0,app1,omnibox1,omnibox2,omnibox3,webstore0"},
-      {2, 10, 2, "app0,app1,omnibox0,omnibox1,webstore0,webstore1",
+      {2, 10, 0, "app0,omnibox0,app1,omnibox1,omnibox2,omnibox3"},
+      {2, 10, 1, "app0,omnibox0,app1,omnibox1,omnibox2,omnibox3,webstore0"},
+      {2, 10, 2,
        "app0,omnibox0,app1,omnibox1,omnibox2,omnibox3,webstore0,webstore1"},
-      {2, 0, 2, "app0,app1,webstore0,webstore1",
-       "app0,app1,webstore0,webstore1"},
-      {0, 0, 0, "", ""},
+      {2, 0, 2, "app0,app1,webstore0,webstore1"},
+      {0, 0, 0, ""},
   };
 
   for (size_t i = 0; i < arraysize(kTestCases); ++i) {
@@ -255,13 +234,11 @@
     webstore_provider()->set_count(kTestCases[i].webstore_results);
     RunQuery();
 
-    const char* expected = GetParam() ? kTestCases[i].expected_blended
-                                      : kTestCases[i].expected_default;
-    EXPECT_EQ(expected, GetResults()) << "Case " << i;
+    EXPECT_EQ(kTestCases[i].expected, GetResults()) << "Case " << i;
   }
 }
 
-TEST_P(MixerTest, RemoveDuplicates) {
+TEST_F(MixerTest, RemoveDuplicates) {
   const std::string dup = "dup";
 
   // This gives "dup0,dup1,dup2".
@@ -283,7 +260,7 @@
 }
 
 // Tests that "known results" have priority over others.
-TEST_P(MixerTest, KnownResultsPriority) {
+TEST_F(MixerTest, KnownResultsPriority) {
   // This gives omnibox 0 -- 5.
   omnibox_provider()->set_count(6);
 
@@ -302,7 +279,7 @@
 }
 
 // Tests that "known results" are not considered for recommendation results.
-TEST_P(MixerTest, KnownResultsIgnoredForRecommendations) {
+TEST_F(MixerTest, KnownResultsIgnoredForRecommendations) {
   // This gives omnibox 0 -- 5.
   omnibox_provider()->set_count(6);
   omnibox_provider()->set_display_type(SearchResult::DISPLAY_RECOMMENDATION);
@@ -320,7 +297,7 @@
             GetResults());
 }
 
-TEST_P(MixerTest, VoiceQuery) {
+TEST_F(MixerTest, VoiceQuery) {
   omnibox_provider()->set_count(3);
   RunQuery();
   EXPECT_EQ("omnibox0,omnibox1,omnibox2", GetResults());
@@ -342,7 +319,7 @@
   EXPECT_EQ("omnibox1,omnibox2,omnibox0", GetResults());
 }
 
-TEST_P(MixerTest, Publish) {
+TEST_F(MixerTest, Publish) {
   std::unique_ptr<SearchResult> result1(new TestSearchResult("app1", 0));
   std::unique_ptr<SearchResult> result2(new TestSearchResult("app2", 0));
   std::unique_ptr<SearchResult> result3(new TestSearchResult("app3", 0));
@@ -430,7 +407,5 @@
             TestSearchResult::GetInstanceId(ui_results.GetItemAt(2)));
 }
 
-INSTANTIATE_TEST_CASE_P(MixerTestInstance, MixerTest, testing::Bool());
-
 }  // namespace test
 }  // namespace app_list
diff --git a/ui/app_list/search_controller.cc b/ui/app_list/search_controller.cc
index c72080e..589134154 100644
--- a/ui/app_list/search_controller.cc
+++ b/ui/app_list/search_controller.cc
@@ -112,16 +112,8 @@
   result->InvokeAction(action_index, event_flags);
 }
 
-size_t SearchController::AddGroup(size_t max_results,
-                                  double boost,
-                                  double multiplier) {
-  return mixer_->AddGroup(max_results, boost, multiplier);
-}
-
-size_t SearchController::AddOmniboxGroup(size_t max_results,
-                                         double boost,
-                                         double multiplier) {
-  return mixer_->AddOmniboxGroup(max_results, boost, multiplier);
+size_t SearchController::AddGroup(size_t max_results, double multiplier) {
+  return mixer_->AddGroup(max_results, multiplier);
 }
 
 void SearchController::AddProvider(size_t group_id,
diff --git a/ui/app_list/search_controller.h b/ui/app_list/search_controller.h
index 8ba61d2..8df0d61 100644
--- a/ui/app_list/search_controller.h
+++ b/ui/app_list/search_controller.h
@@ -43,10 +43,7 @@
                           int event_flags);
 
   // Adds a new mixer group. See Mixer::AddGroup.
-  size_t AddGroup(size_t max_results, double boost, double multiplier);
-
-  // Adds a new mixer group. See Mixer::AddOmniboxGroup.
-  size_t AddOmniboxGroup(size_t max_results, double boost, double multiplier);
+  size_t AddGroup(size_t max_results, double multiplier);
 
   // Takes ownership of |provider| and associates it with given mixer group.
   void AddProvider(size_t group_id, std::unique_ptr<SearchProvider> provider);
diff --git a/ui/app_list/test/app_list_test_view_delegate.h b/ui/app_list/test/app_list_test_view_delegate.h
index bc370e0..d6a9e87 100644
--- a/ui/app_list/test/app_list_test_view_delegate.h
+++ b/ui/app_list/test/app_list_test_view_delegate.h
@@ -72,7 +72,6 @@
   void ViewInitialized() override {}
   void Dismiss() override;
   void ViewClosing() override {}
-  void OpenSettings() override {}
   void OpenHelp() override {}
   void OpenFeedback() override {}
   void StartSpeechRecognition() override {}
diff --git a/ui/arc/BUILD.gn b/ui/arc/BUILD.gn
index f73d031b..f36d77f 100644
--- a/ui/arc/BUILD.gn
+++ b/ui/arc/BUILD.gn
@@ -48,6 +48,7 @@
     ":arc",
     "//base",
     "//base/test:test_support",
+    "//components/arc:arc_base",
     "//components/arc:arc_test_support",
     "//mojo/edk/system",
     "//testing/gtest",
diff --git a/ui/arc/notification/arc_notification_manager.cc b/ui/arc/notification/arc_notification_manager.cc
index a6e3fa5..0c226ce8 100644
--- a/ui/arc/notification/arc_notification_manager.cc
+++ b/ui/arc/notification/arc_notification_manager.cc
@@ -27,17 +27,18 @@
       main_profile_id_(main_profile_id),
       message_center_(message_center),
       binding_(this) {
-  arc_bridge_service()->AddObserver(this);
+  arc_bridge_service()->notifications()->AddObserver(this);
 }
 
 ArcNotificationManager::~ArcNotificationManager() {
-  arc_bridge_service()->RemoveObserver(this);
+  arc_bridge_service()->notifications()->RemoveObserver(this);
 }
 
-void ArcNotificationManager::OnNotificationsInstanceReady() {
+void ArcNotificationManager::OnInstanceReady() {
   DCHECK(!ready_);
 
-  auto notifications_instance = arc_bridge_service()->notifications_instance();
+  auto notifications_instance =
+      arc_bridge_service()->notifications()->instance();
   if (!notifications_instance) {
     VLOG(2) << "Request to refresh app list when bridge service is not ready.";
     return;
@@ -47,7 +48,7 @@
   ready_ = true;
 }
 
-void ArcNotificationManager::OnNotificationsInstanceClosed() {
+void ArcNotificationManager::OnInstanceClosed() {
   DCHECK(ready_);
   while (!items_.empty()) {
     auto it = items_.begin();
@@ -109,7 +110,8 @@
   std::unique_ptr<ArcNotificationItem> item = std::move(it->second);
   items_.erase(it);
 
-  auto notifications_instance = arc_bridge_service()->notifications_instance();
+  auto notifications_instance =
+      arc_bridge_service()->notifications()->instance();
 
   // On shutdown, the ARC channel may quit earlier then notifications.
   if (!notifications_instance) {
@@ -130,7 +132,8 @@
     return;
   }
 
-  auto notifications_instance = arc_bridge_service()->notifications_instance();
+  auto notifications_instance =
+      arc_bridge_service()->notifications()->instance();
 
   // On shutdown, the ARC channel may quit earlier then notifications.
   if (!notifications_instance) {
@@ -144,14 +147,16 @@
 }
 
 void ArcNotificationManager::SendNotificationButtonClickedOnChrome(
-    const std::string& key, int button_index) {
+    const std::string& key,
+    int button_index) {
   if (items_.find(key) == items_.end()) {
     VLOG(3) << "Chrome requests to fire a click event on notification (key: "
             << key << "), but it is gone.";
     return;
   }
 
-  auto notifications_instance = arc_bridge_service()->notifications_instance();
+  auto notifications_instance =
+      arc_bridge_service()->notifications()->instance();
 
   // On shutdown, the ARC channel may quit earlier then notifications.
   if (!notifications_instance) {
@@ -178,8 +183,8 @@
       command = mojom::ArcNotificationEvent::BUTTON_5_CLICKED;
       break;
     default:
-      VLOG(3) << "Invalid button index (key: " << key << ", index: " <<
-          button_index << ").";
+      VLOG(3) << "Invalid button index (key: " << key
+              << ", index: " << button_index << ").";
       return;
   }
 
diff --git a/ui/arc/notification/arc_notification_manager.h b/ui/arc/notification/arc_notification_manager.h
index f75b828..26fe969 100644
--- a/ui/arc/notification/arc_notification_manager.h
+++ b/ui/arc/notification/arc_notification_manager.h
@@ -11,6 +11,7 @@
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_service.h"
 #include "components/arc/common/notifications.mojom.h"
+#include "components/arc/instance_holder.h"
 #include "components/signin/core/account_id/account_id.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "ui/message_center/message_center.h"
@@ -19,9 +20,10 @@
 
 class ArcNotificationItem;
 
-class ArcNotificationManager : public ArcService,
-                               public ArcBridgeService::Observer,
-                               public mojom::NotificationsHost {
+class ArcNotificationManager
+    : public ArcService,
+      public InstanceHolder<mojom::NotificationsInstance>::Observer,
+      public mojom::NotificationsHost {
  public:
   ArcNotificationManager(ArcBridgeService* bridge_service,
                          const AccountId& main_profile_id);
@@ -32,9 +34,9 @@
 
   ~ArcNotificationManager() override;
 
-  // ArcBridgeService::Observer implementation:
-  void OnNotificationsInstanceReady() override;
-  void OnNotificationsInstanceClosed() override;
+  // InstanceHolder<mojom::NotificationsInstance>::Observer implementation:
+  void OnInstanceReady() override;
+  void OnInstanceClosed() override;
 
   // mojom::NotificationsHost implementation:
   void OnNotificationPosted(mojom::ArcNotificationDataPtr data) override;
@@ -45,8 +47,8 @@
   // Methods called from ArcNotificationItem:
   void SendNotificationRemovedFromChrome(const std::string& key);
   void SendNotificationClickedOnChrome(const std::string& key);
-  void SendNotificationButtonClickedOnChrome(
-      const std::string& key, int button_index);
+  void SendNotificationButtonClickedOnChrome(const std::string& key,
+                                             int button_index);
 
  private:
   const AccountId main_profile_id_;
diff --git a/ui/arc/notification/arc_notification_manager_unittest.cc b/ui/arc/notification/arc_notification_manager_unittest.cc
index eadbb84..f7298c7a 100644
--- a/ui/arc/notification/arc_notification_manager_unittest.cc
+++ b/ui/arc/notification/arc_notification_manager_unittest.cc
@@ -2,8 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <memory>
+#include <string>
+#include <vector>
+
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "components/arc/instance_holder.h"
 #include "components/arc/test/fake_arc_bridge_instance.h"
 #include "components/arc/test/fake_arc_bridge_service.h"
 #include "components/arc/test/fake_notifications_instance.h"
@@ -52,17 +57,18 @@
   DISALLOW_COPY_AND_ASSIGN(MockMessageCenter);
 };
 
-class ArcBridgeServiceObserver : public ArcBridgeService::Observer {
+class NotificationsObserver
+    : public InstanceHolder<mojom::NotificationsInstance>::Observer {
  public:
-  ArcBridgeServiceObserver() = default;
-  void OnNotificationsInstanceReady() override { ready_ = true; }
+  NotificationsObserver() = default;
+  void OnInstanceReady() override { ready_ = true; }
 
   bool IsReady() { return ready_; }
 
  private:
   bool ready_ = false;
 
-  DISALLOW_COPY_AND_ASSIGN(ArcBridgeServiceObserver);
+  DISALLOW_COPY_AND_ASSIGN(NotificationsObserver);
 };
 
 }  // anonymous namespace
@@ -117,15 +123,15 @@
     arc_notification_manager_.reset(new ArcNotificationManager(
         service(), EmptyAccountId(), message_center_.get()));
 
-    ArcBridgeServiceObserver observer;
-    service_->AddObserver(&observer);
+    NotificationsObserver observer;
+    service_->notifications()->AddObserver(&observer);
     service_->OnNotificationsInstanceReady(
         std::move(arc_notifications_instance));
 
     while (!observer.IsReady())
       loop_.RunUntilIdle();
 
-    service_->RemoveObserver(&observer);
+    service_->notifications()->RemoveObserver(&observer);
   }
 
   void TearDown() override {
@@ -177,7 +183,7 @@
   CreateNotificationWithKey("notification3");
   EXPECT_EQ(3u, message_center()->GetVisibleNotifications().size());
 
-  arc_notification_manager()->OnNotificationsInstanceClosed();
+  arc_notification_manager()->OnInstanceClosed();
 
   EXPECT_EQ(0u, message_center()->GetVisibleNotifications().size());
 }
diff --git a/ui/base/accelerators/accelerator.h b/ui/base/accelerators/accelerator.h
index e3f079c..e1a140f 100644
--- a/ui/base/accelerators/accelerator.h
+++ b/ui/base/accelerators/accelerator.h
@@ -118,8 +118,9 @@
  public:
   // Gets the accelerator for the specified command id. Returns true if the
   // command id has a valid accelerator, false otherwise.
-  virtual bool GetAcceleratorForCommandId(int command_id,
-                                          ui::Accelerator* accelerator) = 0;
+  virtual bool GetAcceleratorForCommandId(
+      int command_id,
+      ui::Accelerator* accelerator) const = 0;
 
  protected:
   virtual ~AcceleratorProvider() {}
diff --git a/ui/base/cocoa/menu_controller_unittest.mm b/ui/base/cocoa/menu_controller_unittest.mm
index 1b56248..138c112 100644
--- a/ui/base/cocoa/menu_controller_unittest.mm
+++ b/ui/base/cocoa/menu_controller_unittest.mm
@@ -46,7 +46,7 @@
     return true;
   }
   bool GetAcceleratorForCommandId(int command_id,
-                                  Accelerator* accelerator) override {
+                                  Accelerator* accelerator) const override {
     return false;
   }
   void ExecuteCommand(int command_id, int event_flags) override {
diff --git a/ui/base/models/button_menu_item_model.h b/ui/base/models/button_menu_item_model.h
index 9c78b598..efe3f8f 100644
--- a/ui/base/models/button_menu_item_model.h
+++ b/ui/base/models/button_menu_item_model.h
@@ -39,8 +39,9 @@
 
     // Gets the accelerator for the specified command id. Returns true if the
     // command id has a valid accelerator, false otherwise.
-    virtual bool GetAcceleratorForCommandId(int command_id,
-                                            ui::Accelerator* accelerator) = 0;
+    virtual bool GetAcceleratorForCommandId(
+        int command_id,
+        ui::Accelerator* accelerator) const = 0;
 
    protected:
     virtual ~Delegate() {}
diff --git a/ui/base/models/simple_menu_model.cc b/ui/base/models/simple_menu_model.cc
index b466051..09b08d2 100644
--- a/ui/base/models/simple_menu_model.cc
+++ b/ui/base/models/simple_menu_model.cc
@@ -256,8 +256,8 @@
   MenuItemsChanged();
 }
 
-int SimpleMenuModel::GetIndexOfCommandId(int command_id) {
-  for (ItemVector::iterator i = items_.begin(); i != items_.end(); ++i) {
+int SimpleMenuModel::GetIndexOfCommandId(int command_id) const {
+  for (ItemVector::const_iterator i = items_.begin(); i != items_.end(); ++i) {
     if (i->command_id == command_id)
       return static_cast<int>(std::distance(items_.begin(), i));
   }
diff --git a/ui/base/models/simple_menu_model.h b/ui/base/models/simple_menu_model.h
index 639830d1..c86f958 100644
--- a/ui/base/models/simple_menu_model.h
+++ b/ui/base/models/simple_menu_model.h
@@ -39,7 +39,7 @@
     // command id has a valid accelerator, false otherwise.
     virtual bool GetAcceleratorForCommandId(
         int command_id,
-        ui::Accelerator* accelerator) = 0;
+        ui::Accelerator* accelerator) const = 0;
 
     // Some command ids have labels, sublabels, minor text and icons that change
     // over time.
@@ -134,7 +134,7 @@
 
   // Returns the index of the item that has the given |command_id|. Returns
   // -1 if not found.
-  int GetIndexOfCommandId(int command_id);
+  int GetIndexOfCommandId(int command_id) const;
 
   // Overridden from MenuModel:
   bool HasIcons() const override;
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc
index cbd42b6..b217cdd 100644
--- a/ui/compositor/compositor.cc
+++ b/ui/compositor/compositor.cc
@@ -211,7 +211,7 @@
   host_->animation_host()->AddAnimationTimeline(animation_timeline_.get());
 
   host_->SetRootLayer(root_web_layer_);
-  host_->set_surface_id_namespace(surface_id_allocator_->id_namespace());
+  host_->set_surface_client_id(surface_id_allocator_->client_id());
   host_->SetVisible(true);
 }
 
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc
index d845d68..ac8ea89 100644
--- a/ui/compositor/layer.cc
+++ b/ui/compositor/layer.cc
@@ -590,7 +590,7 @@
 }
 
 void Layer::SetShowSurface(
-    cc::SurfaceId surface_id,
+    const cc::SurfaceId& surface_id,
     const cc::SurfaceLayer::SatisfyCallback& satisfy_callback,
     const cc::SurfaceLayer::RequireCallback& require_callback,
     gfx::Size surface_size,
@@ -673,6 +673,11 @@
 
   damaged_region_.Union(invalid_rect);
   ScheduleDraw();
+
+  if (layer_mask_) {
+    layer_mask_->damaged_region_.Union(invalid_rect);
+    layer_mask_->ScheduleDraw();
+  }
   return true;
 }
 
@@ -690,6 +695,8 @@
 
   for (cc::Region::Iterator iter(damaged_region_); iter.has_rect(); iter.next())
     cc_layer_->SetNeedsDisplayRect(iter.rect());
+  if (layer_mask_)
+    layer_mask_->SendDamagedRects();
 
   if (content_layer_)
     paint_region_.Union(damaged_region_);
diff --git a/ui/compositor/layer.h b/ui/compositor/layer.h
index f5d4526..8167fa7 100644
--- a/ui/compositor/layer.h
+++ b/ui/compositor/layer.h
@@ -297,7 +297,7 @@
   void SetTextureScale(float x_scale, float y_scale);
 
   // Begins showing content from a surface with a particular id.
-  void SetShowSurface(cc::SurfaceId surface_id,
+  void SetShowSurface(const cc::SurfaceId& surface_id,
                       const cc::SurfaceLayer::SatisfyCallback& satisfy_callback,
                       const cc::SurfaceLayer::RequireCallback& require_callback,
                       gfx::Size surface_size,
diff --git a/ui/compositor/layer_unittest.cc b/ui/compositor/layer_unittest.cc
index 6aeaec31..0e65b71 100644
--- a/ui/compositor/layer_unittest.cc
+++ b/ui/compositor/layer_unittest.cc
@@ -633,6 +633,28 @@
   EXPECT_FALSE(d3.painted());
 }
 
+// Tests that scheduling paint on a layer with a mask updates the mask.
+TEST_F(LayerWithRealCompositorTest, SchedulePaintUpdatesMask) {
+  std::unique_ptr<Layer> layer(
+      CreateColorLayer(SK_ColorRED, gfx::Rect(20, 20, 400, 400)));
+  std::unique_ptr<Layer> mask_layer(CreateLayer(ui::LAYER_TEXTURED));
+  mask_layer->SetBounds(gfx::Rect(layer->GetTargetBounds().size()));
+  layer->SetMaskLayer(mask_layer.get());
+
+  GetCompositor()->SetRootLayer(layer.get());
+  WaitForDraw();
+
+  DrawTreeLayerDelegate d1(layer->bounds());
+  layer->set_delegate(&d1);
+  DrawTreeLayerDelegate d2(mask_layer->bounds());
+  mask_layer->set_delegate(&d2);
+
+  layer->SchedulePaint(gfx::Rect(5, 5, 5, 5));
+  WaitForDraw();
+  EXPECT_TRUE(d1.painted());
+  EXPECT_TRUE(d2.painted());
+}
+
 // Tests no-texture Layers.
 // Create this hierarchy:
 // L1 - red
diff --git a/ui/compositor/test/in_process_context_factory.cc b/ui/compositor/test/in_process_context_factory.cc
index f923cd3..03cfca7 100644
--- a/ui/compositor/test/in_process_context_factory.cc
+++ b/ui/compositor/test/in_process_context_factory.cc
@@ -103,7 +103,7 @@
 InProcessContextFactory::InProcessContextFactory(
     bool context_factory_for_test,
     cc::SurfaceManager* surface_manager)
-    : next_surface_id_namespace_(1u),
+    : next_surface_client_id_(1u),
       use_test_surface_(true),
       context_factory_for_test_(context_factory_for_test),
       surface_manager_(surface_manager) {
@@ -179,7 +179,7 @@
     per_compositor_data_[compositor.get()] = base::MakeUnique<cc::Display>(
         surface_manager_, GetSharedBitmapManager(), GetGpuMemoryBufferManager(),
         compositor->GetRendererSettings(),
-        compositor->surface_id_allocator()->id_namespace(),
+        compositor->surface_id_allocator()->client_id(),
         std::move(begin_frame_source), std::move(display_output_surface),
         std::move(scheduler), base::MakeUnique<cc::TextureMailboxDeleter>(
                                   compositor->task_runner().get()));
@@ -252,9 +252,9 @@
 std::unique_ptr<cc::SurfaceIdAllocator>
 InProcessContextFactory::CreateSurfaceIdAllocator() {
   std::unique_ptr<cc::SurfaceIdAllocator> allocator(
-      new cc::SurfaceIdAllocator(next_surface_id_namespace_++));
+      new cc::SurfaceIdAllocator(next_surface_client_id_++));
   if (surface_manager_)
-    allocator->RegisterSurfaceIdNamespace(surface_manager_);
+    allocator->RegisterSurfaceClientId(surface_manager_);
   return allocator;
 }
 
diff --git a/ui/compositor/test/in_process_context_factory.h b/ui/compositor/test/in_process_context_factory.h
index 1e2321c..e84cd285 100644
--- a/ui/compositor/test/in_process_context_factory.h
+++ b/ui/compositor/test/in_process_context_factory.h
@@ -79,7 +79,7 @@
   cc::TestGpuMemoryBufferManager gpu_memory_buffer_manager_;
   cc::TestImageFactory image_factory_;
   cc::TestTaskGraphRunner task_graph_runner_;
-  uint32_t next_surface_id_namespace_;
+  uint32_t next_surface_client_id_;
   bool use_test_surface_;
   bool context_factory_for_test_;
   cc::SurfaceManager* surface_manager_;
diff --git a/ui/events/keycodes/keyboard_code_conversion_xkb.cc b/ui/events/keycodes/keyboard_code_conversion_xkb.cc
index f6bd7df..e164054 100644
--- a/ui/events/keycodes/keyboard_code_conversion_xkb.cc
+++ b/ui/events/keycodes/keyboard_code_conversion_xkb.cc
@@ -238,7 +238,7 @@
     case XKB_KEY_XF86AudioRaiseVolume:
       return DomKey::AUDIO_VOLUME_UP;
     case XKB_KEY_XF86AudioPlay:
-      return DomKey::MEDIA_PLAY;
+      return DomKey::MEDIA_PLAY_PAUSE;
     case XKB_KEY_XF86AudioStop:
       return DomKey::MEDIA_STOP;
     case XKB_KEY_XF86AudioPrev:
diff --git a/ui/file_manager/audio_player/js/compiled_resources.gyp b/ui/file_manager/audio_player/js/compiled_resources.gyp
index 98f6fa3..0099655 100644
--- a/ui/file_manager/audio_player/js/compiled_resources.gyp
+++ b/ui/file_manager/audio_player/js/compiled_resources.gyp
@@ -12,8 +12,6 @@
           '../../../webui/resources/js/cr/event_target.js',
           '../../../webui/resources/js/cr/ui.js',
           '../../../webui/resources/js/cr/ui/array_data_model.js',
-          # Referenced in common/js/util.js.
-          '../../../webui/resources/js/cr/ui/dialogs.js',
           '../../../webui/resources/js/load_time_data.js',
           '../../../webui/resources/js/promise_resolver.js',
           '../../../webui/resources/js/util.js',
diff --git a/ui/file_manager/file_manager/background/js/compiled_resources.gyp b/ui/file_manager/file_manager/background/js/compiled_resources.gyp
index 8232bc9..60de7c33 100644
--- a/ui/file_manager/file_manager/background/js/compiled_resources.gyp
+++ b/ui/file_manager/file_manager/background/js/compiled_resources.gyp
@@ -15,7 +15,6 @@
           '../../../../webui/resources/js/util.js',
           '../../../../webui/resources/js/cr/event_target.js',
           '../../../../webui/resources/js/cr/ui/array_data_model.js',
-          '../../../../webui/resources/js/cr/ui/dialogs.js',
           '../../common/js/lru_cache.js',
           '../../../image_loader/image_loader_client.js',
           '../../common/js/error_util.js',
diff --git a/ui/file_manager/file_manager/common/js/util.js b/ui/file_manager/file_manager/common/js/util.js
index 7f60f6d3d..1f0a9de1 100644
--- a/ui/file_manager/file_manager/common/js/util.js
+++ b/ui/file_manager/file_manager/common/js/util.js
@@ -885,45 +885,6 @@
 };
 
 /**
- * Sets up and shows the alert to inform a user the task is opened in the
- * desktop of the running profile.
- *
- * TODO(hirono): Move the function from the util namespace.
- * @param {cr.ui.dialogs.AlertDialog} alertDialog Alert dialog to be shown.
- * @param {Array<Entry>} entries List of opened entries.
- */
-util.showOpenInOtherDesktopAlert = function(alertDialog, entries) {
-  if (!entries.length)
-    return;
-  chrome.fileManagerPrivate.getProfiles(
-      function(profiles, currentId, displayedId) {
-        // Find strings.
-        var displayName;
-        for (var i = 0; i < profiles.length; i++) {
-          if (profiles[i].profileId === currentId) {
-            displayName = profiles[i].displayName;
-            break;
-          }
-        }
-        if (!displayName) {
-          console.warn('Display name is not found.');
-          return;
-        }
-
-        var title = entries.length > 1 ?
-            entries[0].name + '\u2026' /* ellipsis */ : entries[0].name;
-        var message = strf(entries.length > 1 ?
-                           'OPEN_IN_OTHER_DESKTOP_MESSAGE_PLURAL' :
-                           'OPEN_IN_OTHER_DESKTOP_MESSAGE',
-                           displayName,
-                           currentId);
-
-        // Show the dialog.
-        alertDialog.showWithTitle(title, message, null, null, null);
-      }.bind(this));
-};
-
-/**
  * Runs chrome.test.sendMessage in test environment. Does nothing if running
  * in production environment.
  *
diff --git a/ui/file_manager/file_manager/foreground/css/common.css b/ui/file_manager/file_manager/foreground/css/common.css
index 07b43bb2..ff6d1ee 100644
--- a/ui/file_manager/file_manager/foreground/css/common.css
+++ b/ui/file_manager/file_manager/foreground/css/common.css
@@ -138,7 +138,7 @@
   -webkit-margin-end: 0;
   -webkit-margin-start: 5px;
   font-weight: 500;
-  height: 32px;
+  min-height: 32px;
   min-width: 70px;
   padding: auto;
 }
diff --git a/ui/file_manager/file_manager/foreground/js/file_tasks.js b/ui/file_manager/file_manager/foreground/js/file_tasks.js
index 89f5402..64381415 100644
--- a/ui/file_manager/file_manager/foreground/js/file_tasks.js
+++ b/ui/file_manager/file_manager/foreground/js/file_tasks.js
@@ -496,10 +496,8 @@
         break;
       case 'message_sent':
         util.isTeleported(window).then(function(teleported) {
-          if (teleported) {
-            util.showOpenInOtherDesktopAlert(
-                this.ui_.alertDialog, this.entries_);
-          }
+          if (teleported)
+            this.ui_.showOpenInOtherDesktopAlert(this.entries_);
         }.bind(this));
         callback(true, this.entries_);
         break;
@@ -546,10 +544,8 @@
             if (result !== 'message_sent')
               return;
             util.isTeleported(window).then(function(teleported) {
-              if (teleported) {
-                util.showOpenInOtherDesktopAlert(
-                    this.ui_.alertDialog, this.entries_);
-              }
+              if (teleported)
+                this.ui_.showOpenInOtherDesktopAlert(this.entries_);
             }.bind(this));
       }.bind(this));
     }
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js b/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js
index 9d50915..a6e91eed 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js
@@ -550,3 +550,40 @@
   customSplitter.decorate(splitterElement);
   splitterElement.resizeNextElement = !!opt_resizeNextElement;
 };
+
+/**
+ * Sets up and shows the alert to inform a user the task is opened in the
+ * desktop of the running profile.
+ *
+ * @param {Array<Entry>} entries List of opened entries.
+ */
+FileManagerUI.prototype.showOpenInOtherDesktopAlert = function(entries) {
+  if (!entries.length)
+    return;
+  chrome.fileManagerPrivate.getProfiles(
+    function(profiles, currentId, displayedId) {
+      // Find strings.
+      var displayName;
+      for (var i = 0; i < profiles.length; i++) {
+        if (profiles[i].profileId === currentId) {
+          displayName = profiles[i].displayName;
+          break;
+        }
+      }
+      if (!displayName) {
+        console.warn('Display name is not found.');
+        return;
+      }
+
+      var title = entries.length > 1 ?
+          entries[0].name + '\u2026' /* ellipsis */ : entries[0].name;
+      var message = strf(entries.length > 1 ?
+                         'OPEN_IN_OTHER_DESKTOP_MESSAGE_PLURAL' :
+                         'OPEN_IN_OTHER_DESKTOP_MESSAGE',
+                         displayName,
+                         currentId);
+
+      // Show the dialog.
+      this.alertDialog.showWithTitle(title, message, null, null, null);
+    }.bind(this));
+};
diff --git a/ui/file_manager/gallery/js/compiled_resources.gyp b/ui/file_manager/gallery/js/compiled_resources.gyp
index 4038e15..0c168d46 100644
--- a/ui/file_manager/gallery/js/compiled_resources.gyp
+++ b/ui/file_manager/gallery/js/compiled_resources.gyp
@@ -12,7 +12,6 @@
           '../../../webui/resources/js/cr/event_target.js',
           '../../../webui/resources/js/cr/ui.js',
           '../../../webui/resources/js/cr/ui/array_data_model.js',
-          '../../../webui/resources/js/cr/ui/dialogs.js',
           '../../../webui/resources/js/load_time_data.js',
           '../../../webui/resources/js/promise_resolver.js',
           '../../../webui/resources/js/util.js',
diff --git a/ui/file_manager/video_player/js/compiled_resources.gyp b/ui/file_manager/video_player/js/compiled_resources.gyp
index 749d44b1..a5377d2c 100644
--- a/ui/file_manager/video_player/js/compiled_resources.gyp
+++ b/ui/file_manager/video_player/js/compiled_resources.gyp
@@ -12,8 +12,6 @@
           '../../../webui/resources/js/cr/event_target.js',
           '../../../webui/resources/js/cr/ui.js',
           '../../../webui/resources/js/cr/ui/array_data_model.js',
-          # Referenced in common/js/util.js.
-          '../../../webui/resources/js/cr/ui/dialogs.js',
           '../../../webui/resources/js/promise_resolver.js',
           '../../../webui/resources/js/load_time_data.js',
           '../../../webui/resources/js/util.js',
diff --git a/ui/message_center/message_center_tray.cc b/ui/message_center/message_center_tray.cc
index ffafe5d..246054e 100644
--- a/ui/message_center/message_center_tray.cc
+++ b/ui/message_center/message_center_tray.cc
@@ -41,7 +41,7 @@
   bool IsCommandIdChecked(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
 
  private:
@@ -83,7 +83,7 @@
 
 bool NotificationMenuModel::GetAcceleratorForCommandId(
     int command_id,
-    ui::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) const {
   return false;
 }
 
diff --git a/ui/message_center/views/desktop_popup_alignment_delegate.cc b/ui/message_center/views/desktop_popup_alignment_delegate.cc
index 27a2aed7..a6c0e53 100644
--- a/ui/message_center/views/desktop_popup_alignment_delegate.cc
+++ b/ui/message_center/views/desktop_popup_alignment_delegate.cc
@@ -14,7 +14,7 @@
 
 DesktopPopupAlignmentDelegate::DesktopPopupAlignmentDelegate()
     : alignment_(POPUP_ALIGNMENT_BOTTOM | POPUP_ALIGNMENT_RIGHT),
-      display_id_(display::Display::kInvalidDisplayID),
+      primary_display_id_(display::Display::kInvalidDisplayID),
       screen_(NULL) {}
 
 DesktopPopupAlignmentDelegate::~DesktopPopupAlignmentDelegate() {
@@ -29,7 +29,7 @@
   screen_ = screen;
   screen_->AddObserver(this);
   display::Display display = screen_->GetPrimaryDisplay();
-  display_id_ = display.id();
+  primary_display_id_ = display.id();
   RecomputeAlignment(display);
 }
 
@@ -89,19 +89,40 @@
   // Do nothing, which will use the default container.
 }
 
+// Anytime the display configuration changes, we need to recompute the alignment
+// on the primary display. But, we get different events on different platforms.
+// On Windows, for example, when switching from a laptop display to an external
+// monitor, we get a OnDisplayMetricsChanged() event. On Linux, we get a
+// OnDisplayRemoved() and a OnDisplayAdded() instead. In order to account for
+// these slightly different abstractions, we update on every event.
+void DesktopPopupAlignmentDelegate::UpdatePrimaryDisplay() {
+  display::Display primary_display = screen_->GetPrimaryDisplay();
+  if (primary_display.id() != primary_display_id_) {
+    primary_display_id_ = primary_display.id();
+    RecomputeAlignment(primary_display);
+    DoUpdateIfPossible();
+  }
+}
+
 void DesktopPopupAlignmentDelegate::OnDisplayAdded(
-    const display::Display& new_display) {}
+    const display::Display& added_display) {
+  // The added display could be the new primary display.
+  UpdatePrimaryDisplay();
+}
 
 void DesktopPopupAlignmentDelegate::OnDisplayRemoved(
-    const display::Display& old_display) {}
+    const display::Display& removed_display) {
+  // The removed display may have been the primary display.
+  UpdatePrimaryDisplay();
+}
 
 void DesktopPopupAlignmentDelegate::OnDisplayMetricsChanged(
     const display::Display& display,
     uint32_t metrics) {
-  if (display.id() == display_id_) {
-    RecomputeAlignment(display);
-    DoUpdateIfPossible();
-  }
+  // Set to kInvalidDisplayID so the alignment is updated regardless of whether
+  // the primary display actually changed.
+  primary_display_id_ = display::Display::kInvalidDisplayID;
+  UpdatePrimaryDisplay();
 }
 
 }  // namespace message_center
diff --git a/ui/message_center/views/desktop_popup_alignment_delegate.h b/ui/message_center/views/desktop_popup_alignment_delegate.h
index aa919db..00807dc5 100644
--- a/ui/message_center/views/desktop_popup_alignment_delegate.h
+++ b/ui/message_center/views/desktop_popup_alignment_delegate.h
@@ -52,6 +52,8 @@
     POPUP_ALIGNMENT_RIGHT = 1 << 3,
   };
 
+  void UpdatePrimaryDisplay();
+
   // Overridden from display::DisplayObserver:
   void OnDisplayAdded(const display::Display& new_display) override;
   void OnDisplayRemoved(const display::Display& old_display) override;
@@ -59,7 +61,7 @@
                                uint32_t metrics) override;
 
   int32_t alignment_;
-  int64_t display_id_;
+  int64_t primary_display_id_;
   display::Screen* screen_;
   gfx::Rect work_area_;
 
diff --git a/ui/message_center/views/notifier_settings_view.cc b/ui/message_center/views/notifier_settings_view.cc
index 2d6e15d..2f5afe2 100644
--- a/ui/message_center/views/notifier_settings_view.cc
+++ b/ui/message_center/views/notifier_settings_view.cc
@@ -218,7 +218,7 @@
   bool IsCommandIdChecked(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
 
  private:
@@ -257,7 +257,7 @@
 
 bool NotifierGroupMenuModel::GetAcceleratorForCommandId(
     int command_id,
-    ui::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) const {
   return false;
 }
 
diff --git a/ui/strings/ui_strings.grd b/ui/strings/ui_strings.grd
index 83cb365..c4587b3 100644
--- a/ui/strings/ui_strings.grd
+++ b/ui/strings/ui_strings.grd
@@ -591,15 +591,15 @@
         <message name="IDS_MESSAGE_CENTER_NOTIFIER_HATS_NAME" desc="The name of hats notifier that is a system component">
           Hats
         </message>
+        <message name="IDS_MESSAGE_CENTER_NOTIFIER_QUICK_UNLOCK_FEATURE_NAME" desc="The name of quick unlock feature notifier that is a system component">
+          Quick Unlock Feature
+        </message>
       </if>
 
       <!-- App list -->
       <message name="IDS_APP_LIST_HELP" desc="The menu entry to show the app list help UI.">
         Help
       </message>
-      <message name="IDS_APP_LIST_OPEN_SETTINGS" desc="The menu entry to show the settings UI.">
-        Settings
-      </message>
       <message name="IDS_APP_LIST_OPEN_FEEDBACK" desc="The menu entry to show the feedback UI.">
         Send feedback
       </message>
diff --git a/ui/views/controls/button/label_button.cc b/ui/views/controls/button/label_button.cc
index 0618cca6..53b9247 100644
--- a/ui/views/controls/button/label_button.cc
+++ b/ui/views/controls/button/label_button.cc
@@ -541,6 +541,7 @@
 void LabelButton::ChildPreferredSizeChanged(View* child) {
   ResetCachedPreferredSize();
   PreferredSizeChanged();
+  Layout();
 }
 
 ui::NativeTheme::Part LabelButton::GetThemePart() const {
diff --git a/ui/views/controls/button/label_button_unittest.cc b/ui/views/controls/button/label_button_unittest.cc
index 5c94c30..702ed68 100644
--- a/ui/views/controls/button/label_button_unittest.cc
+++ b/ui/views/controls/button/label_button_unittest.cc
@@ -311,16 +311,29 @@
   const base::string16 text(ASCIIToUTF16("abc"));
   const base::string16 longer_text(ASCIIToUTF16("abcdefghijklm"));
   button_->SetText(text);
-
+  button_->SizeToPreferredSize();
+  gfx::Rect bounds(button_->bounds());
   const int original_width = button_->GetPreferredSize().width();
+  EXPECT_EQ(original_width, bounds.width());
 
-  // The button size increases when the text size is increased.
+  // Reserve more space in the button.
+  bounds.set_width(bounds.width() * 10);
+  button_->SetBoundsRect(bounds);
+
+  // Label view in the button is sized to short text.
+  const int original_label_width = button_->label()->bounds().width();
+
+  // The button preferred size and the label size increase when the text size
+  // is increased.
   button_->SetText(longer_text);
-  EXPECT_GT(button_->GetPreferredSize().width(), original_width);
+  EXPECT_GT(button_->label()->bounds().width(), original_label_width * 2);
+  EXPECT_GT(button_->GetPreferredSize().width(), original_width * 2);
 
-  // The button returns to its original size when the original text is restored.
+  // The button and the label view return to its original size when the original
+  // text is restored.
   button_->SetMinSize(gfx::Size());
   button_->SetText(text);
+  EXPECT_EQ(original_label_width, button_->label()->bounds().width());
   EXPECT_EQ(original_width, button_->GetPreferredSize().width());
 }
 
diff --git a/ui/views/controls/menu/menu_runner_cocoa_unittest.mm b/ui/views/controls/menu/menu_runner_cocoa_unittest.mm
index 09449d2..b9a6656 100644
--- a/ui/views/controls/menu/menu_runner_cocoa_unittest.mm
+++ b/ui/views/controls/menu/menu_runner_cocoa_unittest.mm
@@ -35,8 +35,9 @@
       return command_id == model_->checked_command_;
     }
     bool IsCommandIdEnabled(int command_id) const override { return true; }
-    bool GetAcceleratorForCommandId(int command_id,
-                                    ui::Accelerator* accelerator) override {
+    bool GetAcceleratorForCommandId(
+        int command_id,
+        ui::Accelerator* accelerator) const override {
       return false;
     }
     void ExecuteCommand(int command_id, int event_flags) override {}
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc
index fa1025e..381fef4 100644
--- a/ui/views/controls/textfield/textfield.cc
+++ b/ui/views/controls/textfield/textfield.cc
@@ -1179,7 +1179,7 @@
 }
 
 bool Textfield::GetAcceleratorForCommandId(int command_id,
-                                           ui::Accelerator* accelerator) {
+                                           ui::Accelerator* accelerator) const {
   switch (command_id) {
     case IDS_APP_UNDO:
       *accelerator = ui::Accelerator(ui::VKEY_Z, ui::EF_CONTROL_DOWN);
diff --git a/ui/views/controls/textfield/textfield.h b/ui/views/controls/textfield/textfield.h
index ac1f0cf..54391a38 100644
--- a/ui/views/controls/textfield/textfield.h
+++ b/ui/views/controls/textfield/textfield.h
@@ -272,7 +272,7 @@
   bool IsCommandIdChecked(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
 
   // ui::TextInputClient overrides:
diff --git a/ui/views/examples/menu_example.cc b/ui/views/examples/menu_example.cc
index 378c90a..8f86c61 100644
--- a/ui/views/examples/menu_example.cc
+++ b/ui/views/examples/menu_example.cc
@@ -32,7 +32,7 @@
   bool IsCommandIdChecked(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
 
  private:
@@ -121,7 +121,7 @@
 
 bool ExampleMenuModel::GetAcceleratorForCommandId(
     int command_id,
-    ui::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) const {
   // We don't use this in the example.
   return false;
 }
diff --git a/ui/views/examples/tree_view_example.cc b/ui/views/examples/tree_view_example.cc
index 68f99e2..35a812c 100644
--- a/ui/views/examples/tree_view_example.cc
+++ b/ui/views/examples/tree_view_example.cc
@@ -155,7 +155,7 @@
 
 bool TreeViewExample::GetAcceleratorForCommandId(
     int command_id,
-    ui::Accelerator* accelerator) {
+    ui::Accelerator* accelerator) const {
   return false;
 }
 
diff --git a/ui/views/examples/tree_view_example.h b/ui/views/examples/tree_view_example.h
index fb0ccf93..bbdc02f0 100644
--- a/ui/views/examples/tree_view_example.h
+++ b/ui/views/examples/tree_view_example.h
@@ -64,7 +64,7 @@
   bool IsCommandIdChecked(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+                                  ui::Accelerator* accelerator) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
 
   // The tree view to be tested.
diff --git a/ui/views/touchui/touch_selection_controller_impl_unittest.cc b/ui/views/touchui/touch_selection_controller_impl_unittest.cc
index b1a5e36..68cb780 100644
--- a/ui/views/touchui/touch_selection_controller_impl_unittest.cc
+++ b/ui/views/touchui/touch_selection_controller_impl_unittest.cc
@@ -688,7 +688,7 @@
     return false;
   }
   bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override {
+                                  ui::Accelerator* accelerator) const override {
     NOTREACHED();
     return false;
   }
diff --git a/ui/webui/resources/cr_elements/cr_shared_menu/compiled_resources2.gyp b/ui/webui/resources/cr_elements/cr_shared_menu/compiled_resources2.gyp
index 1ff8af3..745731b 100644
--- a/ui/webui/resources/cr_elements/cr_shared_menu/compiled_resources2.gyp
+++ b/ui/webui/resources/cr_elements/cr_shared_menu/compiled_resources2.gyp
@@ -9,8 +9,7 @@
         '../../js/compiled_resources2.gyp:assert',
         '../../js/compiled_resources2.gyp:cr',
         '../../js/compiled_resources2.gyp:util',
-        '../../js/cr/ui/compiled_resources2.gyp:position_util',
-        '<(EXTERNS_GYP):web_animations',
+        '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/compiled_resources2.gyp:iron-a11y-keys-behavior-extracted',
       ],
 
       'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
diff --git a/ui/webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.html b/ui/webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.html
index e140f73f..6522f729 100644
--- a/ui/webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.html
+++ b/ui/webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.html
@@ -1,26 +1,33 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/html/cr.html">
-<link rel="import" href="chrome://resources/html/cr/ui/position_util.html">
 <link rel="import" href="chrome://resources/html/util.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/web-animations.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-dropdown/iron-dropdown.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/fade-in-animation.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/fade-out-animation.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/shadow.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-listbox/paper-listbox.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-menu-button/paper-menu-button-animations.html">
 
 <dom-module id="cr-shared-menu">
   <template>
     <style>
-      :host {
+      #menu {
         @apply(--shadow-elevation-2dp);
-        display: none;
+        background-color: white;
         overflow: hidden;
-        position: absolute;
+        padding: 8px 0;
+        position: relative;
       }
-
     </style>
-    <paper-listbox id="menu">
-      <content></content>
-    </paper-listbox>
+    <iron-dropdown id="dropdown" allow-outside-scroll restore-focus-on-close
+        vertical-align="auto" horizontal-align="right" opened="{{menuOpen}}"
+        open-animation-config="[[openAnimationConfig]]"
+        close-animation-config="[[closeAnimationConfig]]">
+      <div id="menu" class="dropdown-content" role="menu">
+        <content></content>
+      </div>
+    </iron-dropdown>
   </template>
   <script src="cr_shared_menu.js"></script>
 </dom-module>
diff --git a/ui/webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.js b/ui/webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.js
index ab746bd..e08fd0d 100644
--- a/ui/webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.js
+++ b/ui/webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.js
@@ -4,14 +4,16 @@
 
 /** Same as paper-menu-button's custom easing cubic-bezier param. */
 var SLIDE_CUBIC_BEZIER = 'cubic-bezier(0.3, 0.95, 0.5, 1)';
-var FADE_CUBIC_BEZIER = 'cubic-bezier(0.4, 0, 0.2, 1)';
 
 Polymer({
   is: 'cr-shared-menu',
 
+  behaviors: [Polymer.IronA11yKeysBehavior],
+
   properties: {
     menuOpen: {
       type: Boolean,
+      observer: 'menuOpenChanged_',
       value: false,
     },
 
@@ -24,48 +26,112 @@
       type: Object,
       value: null,
     },
+
+    /** @override */
+    keyEventTarget: {
+      type: Object,
+      value: function() {
+        return this.$.menu;
+      }
+    },
+
+    openAnimationConfig: {
+      type: Object,
+      value: function() {
+        return [{
+          name: 'fade-in-animation',
+          timing: {
+            delay: 50,
+            duration: 200
+          }
+        }, {
+          name: 'paper-menu-grow-width-animation',
+          timing: {
+            delay: 50,
+            duration: 150,
+            easing: SLIDE_CUBIC_BEZIER
+          }
+        }, {
+          name: 'paper-menu-grow-height-animation',
+          timing: {
+            delay: 100,
+            duration: 275,
+            easing: SLIDE_CUBIC_BEZIER
+          }
+        }];
+      }
+    },
+
+    closeAnimationConfig: {
+      type: Object,
+      value: function() {
+        return [{
+          name: 'fade-out-animation',
+          timing: {
+            duration: 150
+          }
+        }, {
+          name: 'paper-menu-shrink-width-animation',
+          timing: {
+            delay: 100,
+            duration: 50,
+            easing: SLIDE_CUBIC_BEZIER
+          }
+        }, {
+          name: 'paper-menu-shrink-height-animation',
+          timing: {
+            delay: 200,
+            easing: 'ease-in'
+          }
+        }];
+      }
+    }
+  },
+
+  keyBindings: {
+    'tab': 'onTabPressed_',
   },
 
   /**
-   * Current animation being played, or null if there is none.
-   * @type {?Animation}
-   * @private
-   */
-  animation_: null,
-
-  /**
    * The last anchor that was used to open a menu. It's necessary for toggling.
-   * @type {?Element}
+   * @private {?Element}
    */
   lastAnchor_: null,
 
   /**
-   * Adds listeners to the window in order to dismiss the menu on resize and
-   * when escape is pressed.
+   * The first focusable child in the menu's light DOM.
+   * @private {?Element}
    */
+  firstFocus_: null,
+
+  /**
+   * The last focusable child in the menu's light DOM.
+   * @private {?Element}
+   */
+  lastFocus_: null,
+
+  /** @override */
   attached: function() {
     window.addEventListener('resize', this.closeMenu.bind(this));
-    window.addEventListener('keydown', function(e) {
-      // Escape button on keyboard
-      if (e.keyCode == 27)
-        this.closeMenu();
-    }.bind(this));
+
+    var focusableChildren = Polymer.dom(this).querySelectorAll(
+        '[tabindex],button');
+    if (focusableChildren.length > 0) {
+      this.$.dropdown.focusTarget = focusableChildren[0];
+      this.firstFocus_ = focusableChildren[0];
+      this.lastFocus_ = focusableChildren[focusableChildren.length - 1];
+    }
   },
 
   /** Closes the menu. */
   closeMenu: function() {
-    if (!this.menuOpen)
-      return;
-    // If there is a open menu animation going, cancel it and start closing.
-    this.cancelAnimation_();
+    if (this.root.activeElement == null) {
+      // Something else has taken focus away from the menu. Do not attempt to
+      // restore focus to the button which opened the menu.
+      this.$.dropdown.restoreFocusOnClose = false;
+    }
     this.menuOpen = false;
-    this.itemData = null;
-    this.animation_ = this.animateClose_();
-    this.animation_.addEventListener('finish', function() {
-      this.style.display = 'none';
-      // Reset the animation for the next time the menu opens.
-      this.cancelAnimation_();
-    }.bind(this));
+    this.$.dropdown.restoreFocusOnClose = true;
   },
 
   /**
@@ -74,30 +140,12 @@
    * @param {!Object} itemData The contextual item's data.
    */
   openMenu: function(anchor, itemData) {
-    this.menuOpen = true;
-    this.style.display = 'block';
     this.itemData = itemData;
     this.lastAnchor_ = anchor;
 
     // Move the menu to the anchor.
-    var anchorRect = anchor.getBoundingClientRect();
-    var parentRect = this.offsetParent.getBoundingClientRect();
-
-    var left = (isRTL() ? anchorRect.left : anchorRect.right) - parentRect.left;
-    var top = anchorRect.top - parentRect.top;
-
-    cr.ui.positionPopupAtPoint(left, top, this, cr.ui.AnchorType.BEFORE);
-
-    // Handle the bottom of the screen.
-    if (this.getBoundingClientRect().top != anchorRect.top) {
-      var bottom = anchorRect.bottom - parentRect.top;
-      cr.ui.positionPopupAtPoint(left, bottom, this, cr.ui.AnchorType.BEFORE);
-    }
-
-    this.$.menu.focus();
-
-    this.cancelAnimation_();
-    this.animation_ = this.animateOpen_();
+    this.$.dropdown.positionTarget = anchor;
+    this.menuOpen = true;
   },
 
   /**
@@ -106,128 +154,44 @@
    * @param {!Object} itemData The contextual item's data.
    */
   toggleMenu: function(anchor, itemData) {
-    // If there is an animation going (e.g. user clicks too fast), cancel it and
-    // start the new action.
-    this.cancelAnimation_();
     if (anchor == this.lastAnchor_ && this.menuOpen)
       this.closeMenu();
     else
       this.openMenu(anchor, itemData);
   },
 
-  /** @private */
-  cancelAnimation_: function() {
-    if (this.animation_) {
-      this.animation_.cancel();
-      this.animation_ = null;
-    }
-  },
-
   /**
-   * @param {!Array<!KeyframeEffect>} effects
-   * @return {!Animation}
+   * Trap focus inside the menu. As a very basic heuristic, will wrap focus from
+   * the first element with a nonzero tabindex to the last such element.
+   * TODO(tsergeant): Use iron-focus-wrap-behavior once it is available
+   * (https://github.com/PolymerElements/iron-overlay-behavior/issues/179).
+   * @param {CustomEvent} e
    */
-  playEffects: function(effects) {
-    /** @type {function(new:Object, !Array<!KeyframeEffect>)} */
-    window.GroupEffect;
+  onTabPressed_: function(e) {
+    if (!this.firstFocus_ || !this.lastFocus_)
+      return;
 
-    /** @type {{play: function(Object): !Animation}} */
-    document.timeline;
+    var toFocus;
+    var keyEvent = e.detail.keyboardEvent;
+    if (keyEvent.shiftKey && keyEvent.target == this.firstFocus_)
+      toFocus = this.lastFocus_;
+    else if (keyEvent.target == this.lastFocus_)
+      toFocus = this.firstFocus_;
 
-    return document.timeline.play(new window.GroupEffect(effects));
+    if (!toFocus)
+      return;
+
+    e.preventDefault();
+    toFocus.focus();
   },
 
   /**
-   * Slide-in animation when opening the menu. The animation configuration is
-   * the same as paper-menu-button except for a shorter delay time.
+   * Ensure the menu is reset properly when it is closed by the dropdown (eg,
+   * clicking outside).
    * @private
-   * @return {!Animation}
    */
-  animateOpen_: function() {
-    var rect = this.getBoundingClientRect();
-    var height = rect.height;
-    var width = rect.width;
-
-    var fadeIn = new KeyframeEffect(/** @type {Animatable} */(this), [{
-      'opacity': '0'
-    }, {
-      'opacity': '1'
-    }], /** @type {!KeyframeEffectOptions} */({
-      delay: 50,
-      duration: 200,
-      easing: FADE_CUBIC_BEZIER,
-      fill: 'both'
-    }));
-
-    var growHeight = new KeyframeEffect(/** @type {Animatable} */(this), [{
-      height: (height / 2) + 'px'
-    }, {
-      height: height + 'px'
-    }], /** @type {!KeyframeEffectOptions} */({
-      delay: 50,
-      duration: 275,
-      easing: SLIDE_CUBIC_BEZIER,
-      fill: 'both'
-    }));
-
-    var growWidth = new KeyframeEffect(/** @type {Animatable} */(this), [{
-      width: (width / 2) + 'px'
-    }, {
-      width: width + 'px'
-    }], /** @type {!KeyframeEffectOptions} */({
-      delay: 50,
-      duration: 150,
-      easing: SLIDE_CUBIC_BEZIER,
-      fill: 'both'
-    }));
-
-    return this.playEffects([fadeIn, growHeight, growWidth]);
-  },
-
-  /**
-   * Slide-out animation when closing the menu. The animation configuration is
-   * the same as paper-menu-button.
-   * @private
-   * @return {!Animation}
-   */
-  animateClose_: function() {
-    var rect = this.getBoundingClientRect();
-    var height = rect.height;
-    var width = rect.width;
-
-    var fadeOut = new KeyframeEffect(/** @type {Animatable} */(this), [{
-      'opacity': '1'
-    }, {
-      'opacity': '0'
-    }], /** @type {!KeyframeEffectOptions} */({
-      duration: 150,
-      easing: FADE_CUBIC_BEZIER,
-      fill: 'both'
-    }));
-
-    var shrinkHeight = new KeyframeEffect(/** @type {Animatable} */(this), [{
-      height: height + 'px',
-      transform: 'translateY(0)'
-    }, {
-      height: height / 2 + 'px',
-      transform: 'translateY(-20px)'
-    }], /** @type {!KeyframeEffectOptions} */({
-      duration: 200,
-      easing: 'ease-in',
-      fill: 'both'
-    }));
-
-    var shrinkWidth = new KeyframeEffect(/** @type {Animatable} */(this), [{
-      width: width + 'px'
-    }, {
-      width: width - (width / 20) + 'px'
-    }], /** @type {!KeyframeEffectOptions} */({
-      delay: 100,
-      duration: 50,
-      easing: SLIDE_CUBIC_BEZIER,
-      fill: 'both'
-    }));
-
-    return this.playEffects([fadeOut, shrinkHeight, shrinkWidth]);
+  menuOpenChanged_: function() {
+    if (!this.menuOpen)
+      this.itemData = null;
   },
 });
diff --git a/ui/webui/resources/images/eol.svg b/ui/webui/resources/images/eol.svg
index 00743f8..14d9498 100644
--- a/ui/webui/resources/images/eol.svg
+++ b/ui/webui/resources/images/eol.svg
@@ -1 +1,7 @@
-<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><title>EOL_setting_100</title><path d="M3.97 2.13h-.025l.01.01.016-.01zM1.668 4.41v.024c.004-.005.007-.01.012-.014l-.013-.01zm14.16-2.54C14.19.7 12.192 0 10.026 0 7.863 0 5.865.698 4.23 1.87c-.006.005 4.594 4.624 4.594 4.624l1.204-1.505 4.986 6.234h-1.462l4.567 4.57c1.183-1.65 1.88-3.65 1.88-5.817 0-2.166-.697-4.165-1.87-5.8-.637-.89-1.415-1.668-2.304-2.306zm2.045 14.194v-.027c-.004.005-.008.01-.01.015l.01.012zm.248 2.02l-1.036-1.057-4.563-4.565-4.713-4.696-4.835-4.838-1.047-1.046-.79-.792L0 2.224 1.925 4.15C.753 5.812.055 7.81.055 9.977s.698 4.166 1.87 5.8c.638.89 1.416 1.67 2.305 2.307 1.634 1.173 3.632 1.87 5.798 1.87 2.165 0 4.163-.697 5.798-1.87L17.768 20l1.134-1.135-.782-.78zm-5.705-3H7.488v-3.86H5.042L6.8 9.027l5.615 5.724v.335z" fill="#DB4437" fill-rule="evenodd"/></svg>
+<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <g id="Notification-Icon" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="Artboard-4-Copy-3" fill="#DB4437">
+            <path d="M4.57403661,2.91638517 L4.55031697,2.91638517 L4.56057411,2.92664728 C4.56506161,2.92344037 4.56954911,2.91959208 4.57403661,2.91638517 Z M2.50042738,4.96765297 L2.50042738,4.99074272 C2.50363274,4.98625305 2.50683809,4.98240475 2.51068452,4.97791508 L2.50042738,4.96765297 Z M17.0847995,15.4572626 L17.0847995,15.4335314 C17.0815941,15.4380211 17.0777477,15.4425108 17.0745423,15.4470005 L17.0847995,15.4572626 Z M17.3075718,17.2753239 L16.3754541,16.3241544 L12.2687513,12.2154616 L8.02614146,7.98939582 L3.67454947,3.63505366 L2.73281573,2.69350494 L2.02058551,1.98092958 L1,3.00200966 L2.73281573,4.73502373 C1.67761237,6.23072647 1.05000356,8.02980288 1.05000356,9.97960405 C1.05000356,11.9294052 1.67761237,13.7284816 2.73281573,15.2004532 C3.30657454,16.0008979 4.0066244,16.701287 4.80668139,17.2753239 C6.27794002,18.3310386 8.07614502,18.9589516 10.0250018,18.9589516 C11.9738585,18.9589516 13.7720635,18.3310386 15.2433222,17.2753239 L16.9908825,19 L18.0114681,17.9789199 L17.3075718,17.2753239 Z M15.2433222,2.68362766 C13.7720635,1.62855433 11.9738585,1 10.0250018,1 C8.07614502,1 6.27794002,1.62855433 4.80668139,2.68362766 C4.80155282,2.68747595 8.94159128,6.84491384 8.94159128,6.84491384 L10.0250018,5.0300293 L15.0415647,11 L13.1963815,11 L17.3069307,15.2143071 C18.3723912,13.7288665 19,11.9291487 19,9.9793475 C19,8.03018771 18.3723912,6.23046992 17.3171878,4.75849831 C16.743429,3.95805362 16.0433792,3.25766451 15.2433222,2.68362766 Z M12,15 L7.012146,15 L7.01214607,11.0111083 L4.5,11 L6.7267679,9.12400051 L12,14.6000004 L12,15 Z" id="Combined-Shape"></path>
+        </g>
+    </g>
+</svg>