diff --git a/AUTHORS b/AUTHORS
index 4100e723..75487640 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -392,6 +392,7 @@
 Kirk Shoop <kirk.shoop@microsoft.com>
 Kihwang Kim <pwangkk@gmail.com>
 Klemen Forstnerič <klemen.forstneric@gmail.com>
+Konrad Dzwinel <kdzwinel@gmail.com>
 Krishna Chaitanya <krish.botta@samsung.com>
 Kristof Kosztyo <kkosztyo.u-szeged@partner.samsung.com>
 Krzysztof Czech <k.czech@samsung.com>
diff --git a/DEPS b/DEPS
index 434a7de..f9407b0 100644
--- a/DEPS
+++ b/DEPS
@@ -40,11 +40,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'bbab477b49e2aed0f257206ce457814c953d574b',
+  'skia_revision': 'b399e38518c7c28e94579ce382e64fdf0697a7e9',
   # 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': '35e713ce9a5629d09b38019e0e5725bf43d018dd',
+  'v8_revision': '642e2c8722ff4d846c295047dc0f6a58ceea7e35',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -64,7 +64,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '6814f49aa83916aea14bea2a1e78dac455436713',
+  'pdfium_revision': '8df02348924f66e14131aa378abc6c6ea7a352b6',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
@@ -96,7 +96,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '19565fdb148afc5fc752516f395f715f5d27c1f1',
+  'catapult_revision': 'e6e0862c81652393de2dd878322e8c0c1e43d428',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -201,7 +201,7 @@
     Var('chromium_git') + '/webm/libvpx.git' + '@' +  'd7f1d60c51b47f6d22be919362caad09469a058b',
 
   'src/third_party/ffmpeg':
-    Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '26be2ced90769f25f83b9a613fe3b3e47c1ce4c6',
+    Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + 'f309edd7828e3ea500c2891187d15926690ddd27',
 
   'src/third_party/usrsctp/usrsctplib':
     Var('chromium_git') + '/external/github.com/sctplab/usrsctp' + '@' + '7f9228152ab3d70e6848cc9c67389a0d4218740e',
diff --git a/android_webview/java/src/org/chromium/android_webview/AwAutofillClient.java b/android_webview/java/src/org/chromium/android_webview/AwAutofillClient.java
index 65781e4..7bf412e 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwAutofillClient.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwAutofillClient.java
@@ -4,6 +4,7 @@
 
 package org.chromium.android_webview;
 
+import android.graphics.Color;
 import android.view.View;
 import android.view.ViewGroup;
 
@@ -64,7 +65,8 @@
                     public void deleteSuggestion(int listIndex) { }
                 });
         }
-        mAutofillPopup.filterAndShow(suggestions, isRtl);
+        mAutofillPopup.filterAndShow(suggestions, isRtl, Color.TRANSPARENT /* backgroundColor */,
+                Color.TRANSPARENT /* dividerColor */, 0 /* dropdownItemHeight */);
     }
 
     @CalledByNative
@@ -89,8 +91,9 @@
     @CalledByNative
     private static void addToAutofillSuggestionArray(AutofillSuggestion[] array, int index,
             String name, String label, int uniqueId) {
-        array[index] =
-                new AutofillSuggestion(name, label, DropdownItem.NO_ICON, uniqueId, false, false);
+        array[index] = new AutofillSuggestion(name, label, DropdownItem.NO_ICON,
+                false /* isIconAtLeft */, uniqueId, false /* isDeletable */,
+                false /* isMultilineLabel */, false /* isBoldLabel */);
     }
 
     private native void nativeDismissed(long nativeAwAutofillClient);
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java
index 71f6033..508cc11 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContents.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -633,6 +633,22 @@
         @Override
         public void onScrollUpdateGestureConsumed() {
             mScrollAccessibilityHelper.postViewScrolledAccessibilityEventCallback();
+            mZoomControls.invokeZoomPicker();
+        }
+
+        @Override
+        public void onScrollStarted(int scrollOffsetY, int scrollExtentY) {
+            mZoomControls.invokeZoomPicker();
+        }
+
+        @Override
+        public void onScaleLimitsChanged(float minPageScaleFactor, float maxPageScaleFactor) {
+            mZoomControls.invokeZoomPicker();
+        }
+
+        @Override
+        public void onScrollOffsetOrExtentChanged(int scrollOffsetY, int scrollExtentY) {
+            mZoomControls.updateZoomControls();
         }
     }
 
@@ -793,14 +809,12 @@
             Context context, ViewAndroidDelegate viewDelegate,
             InternalAccessDelegate internalDispatcher, WebContents webContents,
             GestureStateListener gestureStateListener, ContentViewClient contentViewClient,
-            ContentViewCore.ZoomControlsDelegate zoomControlsDelegate,
             WindowAndroid windowAndroid) {
         contentViewCore.initialize(viewDelegate, internalDispatcher, webContents, windowAndroid);
         contentViewCore.setActionModeCallback(
                 new AwActionModeCallback(this, contentViewCore.getActionModeCallbackHelper()));
         contentViewCore.addGestureStateListener(gestureStateListener);
         contentViewCore.setContentViewClient(contentViewClient);
-        contentViewCore.setZoomControlsDelegate(zoomControlsDelegate);
     }
 
     boolean isFullScreen() {
@@ -1040,7 +1054,7 @@
                 mContentViewCore.getRenderCoordinates());
         initializeContentViewCore(mContentViewCore, mContext, mViewAndroidDelegate,
                 mInternalAccessAdapter, webContents, new AwGestureStateListener(),
-                mContentViewClient, mZoomControls, mWindowAndroid.getWindowAndroid());
+                mContentViewClient, mWindowAndroid.getWindowAndroid());
         nativeSetJavaPeers(mNativeAwContents, this, mWebContentsDelegate, mContentsClientBridge,
                 mIoThreadClient, mInterceptNavigationDelegate);
         mWebContents = mContentViewCore.getWebContents();
@@ -2170,7 +2184,7 @@
      */
     public void invokeZoomPicker() {
         if (TRACE) Log.i(TAG, "%s invokeZoomPicker", this);
-        if (!isDestroyed(WARN)) mContentViewCore.invokeZoomPicker();
+        if (!isDestroyed(WARN)) mZoomControls.invokeZoomPicker();
     }
 
     /**
@@ -3162,6 +3176,7 @@
             }
 
             mScrollAccessibilityHelper.removePostedCallbacks();
+            mZoomControls.dismissZoomPicker();
         }
 
         @Override
diff --git a/android_webview/java/src/org/chromium/android_webview/AwZoomControls.java b/android_webview/java/src/org/chromium/android_webview/AwZoomControls.java
index 1df85a9..3b938fe1 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwZoomControls.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwZoomControls.java
@@ -11,9 +11,7 @@
 import android.widget.FrameLayout;
 import android.widget.ZoomButtonsController;
 
-import org.chromium.content.browser.ContentViewCore.ZoomControlsDelegate;
-
-class AwZoomControls implements ZoomControlsDelegate {
+class AwZoomControls {
 
     private AwContents mAwContents;
     // It is advised to use getZoomController() where possible.
@@ -23,7 +21,6 @@
         mAwContents = awContents;
     }
 
-    @Override
     public void invokeZoomPicker() {
         ZoomButtonsController zoomController = getZoomController();
         if (zoomController != null) {
@@ -31,7 +28,6 @@
         }
     }
 
-    @Override
     public void dismissZoomPicker() {
         ZoomButtonsController zoomController = getZoomController();
         if (zoomController != null) {
@@ -39,7 +35,6 @@
         }
     }
 
-    @Override
     public void updateZoomControls() {
         ZoomButtonsController zoomController = getZoomController();
         if (zoomController == null) {
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/PlatformMediaCodecTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/PlatformMediaCodecTest.java
index e5a0567..42942e8 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/PlatformMediaCodecTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/PlatformMediaCodecTest.java
@@ -4,7 +4,9 @@
 
 package org.chromium.android_webview.test;
 
-import org.chromium.base.test.util.DisabledTest;
+import android.test.suitebuilder.annotation.MediumTest;
+
+import org.chromium.base.test.util.Feature;
 import org.chromium.content.browser.ContentViewCore;
 import org.chromium.content.browser.test.util.DOMUtils;
 import org.chromium.content_public.browser.WebContents;
@@ -28,11 +30,8 @@
         enableJavaScriptOnUiThread(mTestContainerView.getAwContents());
     }
 
-    /*
     @MediumTest
     @Feature({"AndroidWebView"})
-    */
-    @DisabledTest(message = "crbug.com/620890")
     public void testCanPlayPlatformMediaCodecs() throws Throwable {
         loadUrlSync(mTestContainerView.getAwContents(), mContentsClient.getOnPageFinishedHelper(),
                 "file:///android_asset/platform-media-codec-test.html");
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index daf50c66..4605647 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -119,6 +119,8 @@
     "common/login_status.h",
     "common/material_design/material_design_controller.cc",
     "common/material_design/material_design_controller.h",
+    "common/media_controller.cc",
+    "common/media_controller.h",
     "common/metrics/gesture_action_type.h",
     "common/metrics/pointer_metrics_recorder.cc",
     "common/metrics/pointer_metrics_recorder.h",
@@ -228,7 +230,6 @@
     "common/system/chromeos/ime_menu/ime_menu_tray.h",
     "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",
diff --git a/ash/common/accelerators/accelerator_controller.cc b/ash/common/accelerators/accelerator_controller.cc
index d3993c2..db032bb3 100644
--- a/ash/common/accelerators/accelerator_controller.cc
+++ b/ash/common/accelerators/accelerator_controller.cc
@@ -13,7 +13,7 @@
 #include "ash/common/accessibility_types.h"
 #include "ash/common/focus_cycler.h"
 #include "ash/common/ime_control_delegate.h"
-#include "ash/common/media_delegate.h"
+#include "ash/common/media_controller.h"
 #include "ash/common/multi_profile_uma.h"
 #include "ash/common/new_window_controller.h"
 #include "ash/common/session/session_state_delegate.h"
@@ -133,15 +133,15 @@
 }
 
 void HandleMediaNextTrack() {
-  WmShell::Get()->media_delegate()->HandleMediaNextTrack();
+  WmShell::Get()->media_controller()->HandleMediaNextTrack();
 }
 
 void HandleMediaPlayPause() {
-  WmShell::Get()->media_delegate()->HandleMediaPlayPause();
+  WmShell::Get()->media_controller()->HandleMediaPlayPause();
 }
 
 void HandleMediaPrevTrack() {
-  WmShell::Get()->media_delegate()->HandleMediaPrevTrack();
+  WmShell::Get()->media_controller()->HandleMediaPrevTrack();
 }
 
 bool CanHandleNewIncognitoWindow() {
diff --git a/ash/common/accelerators/accelerator_table.cc b/ash/common/accelerators/accelerator_table.cc
index 4181c1dc..00a1a32e 100644
--- a/ash/common/accelerators/accelerator_table.cc
+++ b/ash/common/accelerators/accelerator_table.cc
@@ -341,6 +341,7 @@
     DISABLE_CAPS_LOCK,
     KEYBOARD_BRIGHTNESS_DOWN,
     KEYBOARD_BRIGHTNESS_UP,
+    SHOW_IME_MENU_BUBBLE,
     TOGGLE_CAPS_LOCK,
     TOGGLE_HIGH_CONTRAST,
     TOGGLE_SPOKEN_FEEDBACK,
diff --git a/ash/common/media_controller.cc b/ash/common/media_controller.cc
new file mode 100644
index 0000000..7a72fe4
--- /dev/null
+++ b/ash/common/media_controller.cc
@@ -0,0 +1,55 @@
+// 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 "ash/common/media_controller.h"
+
+namespace ash {
+
+MediaController::MediaController() {}
+
+MediaController::~MediaController() {}
+
+void MediaController::BindRequest(mojom::MediaControllerRequest request) {
+  bindings_.AddBinding(this, std::move(request));
+}
+
+void MediaController::AddObserver(MediaCaptureObserver* observer) {
+  observers_.AddObserver(observer);
+}
+
+void MediaController::RemoveObserver(MediaCaptureObserver* observer) {
+  observers_.RemoveObserver(observer);
+}
+
+void MediaController::HandleMediaNextTrack() {
+  if (client_)
+    client_->HandleMediaNextTrack();
+}
+
+void MediaController::HandleMediaPlayPause() {
+  if (client_)
+    client_->HandleMediaPlayPause();
+}
+
+void MediaController::HandleMediaPrevTrack() {
+  if (client_)
+    client_->HandleMediaPrevTrack();
+}
+
+void MediaController::RequestCaptureState() {
+  if (client_)
+    client_->RequestCaptureState();
+}
+
+void MediaController::SetClient(mojom::MediaClientAssociatedPtrInfo client) {
+  client_.Bind(std::move(client));
+}
+
+void MediaController::NotifyCaptureState(
+    const std::vector<mojom::MediaCaptureState>& capture_states) {
+  for (auto& observer : observers_)
+    observer.OnMediaCaptureChanged(capture_states);
+}
+
+}  // namespace ash
diff --git a/ash/common/media_controller.h b/ash/common/media_controller.h
new file mode 100644
index 0000000..22165915
--- /dev/null
+++ b/ash/common/media_controller.h
@@ -0,0 +1,65 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_COMMON_MEDIA_CONTROLLER_H_
+#define ASH_COMMON_MEDIA_CONTROLLER_H_
+
+#include "ash/public/interfaces/media.mojom.h"
+#include "base/macros.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+
+namespace ash {
+
+// Forwards notifications from the MediaController to observers.
+class MediaCaptureObserver {
+ public:
+  // Called when media capture state has changed.
+  virtual void OnMediaCaptureChanged(
+      const std::vector<mojom::MediaCaptureState>& capture_states) = 0;
+
+ protected:
+  virtual ~MediaCaptureObserver() {}
+};
+
+// Provides the MediaController interface to the outside world. This lets a
+// consumer of ash provide a MediaClient, which we will dispatch to if one has
+// been provided to us.
+class MediaController : public mojom::MediaController,
+                        public mojom::MediaClient {
+ public:
+  MediaController();
+  ~MediaController() override;
+
+  void BindRequest(mojom::MediaControllerRequest request);
+
+  void AddObserver(MediaCaptureObserver* observer);
+  void RemoveObserver(MediaCaptureObserver* observer);
+
+  // mojom::MediaClient:
+  void HandleMediaNextTrack() override;
+  void HandleMediaPlayPause() override;
+  void HandleMediaPrevTrack() override;
+  void RequestCaptureState() override;
+
+ private:
+  friend class MultiProfileMediaTrayItemTest;
+
+  // mojom::MediaController:
+  void SetClient(mojom::MediaClientAssociatedPtrInfo client) override;
+  void NotifyCaptureState(
+      const std::vector<mojom::MediaCaptureState>& capture_states) override;
+
+  mojo::BindingSet<mojom::MediaController> bindings_;
+
+  mojom::MediaClientAssociatedPtr client_;
+
+  base::ObserverList<MediaCaptureObserver> observers_;
+
+  DISALLOW_COPY_AND_ASSIGN(MediaController);
+};
+
+}  // namespace ash
+
+#endif  // ASH_COMMON_MEDIA_CONTROLLER_H_
diff --git a/ash/common/media_delegate.h b/ash/common/media_delegate.h
deleted file mode 100644
index 018add7..0000000
--- a/ash/common/media_delegate.h
+++ /dev/null
@@ -1,40 +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.
-
-#ifndef ASH_COMMON_MEDIA_DELEGATE_H_
-#define ASH_COMMON_MEDIA_DELEGATE_H_
-
-#include "ash/public/cpp/session_types.h"
-
-namespace ash {
-
-enum MediaCaptureState {
-  MEDIA_CAPTURE_NONE = 0,
-  MEDIA_CAPTURE_AUDIO = 1 << 0,
-  MEDIA_CAPTURE_VIDEO = 1 << 1,
-  MEDIA_CAPTURE_AUDIO_VIDEO = MEDIA_CAPTURE_AUDIO | MEDIA_CAPTURE_VIDEO,
-};
-
-// A delegate class to control media playback.
-class MediaDelegate {
- public:
-  virtual ~MediaDelegate() {}
-
-  // Handles the Next Track Media shortcut key.
-  virtual void HandleMediaNextTrack() = 0;
-
-  // Handles the Play/Pause Toggle Media shortcut key.
-  virtual void HandleMediaPlayPause() = 0;
-
-  // Handles the Previous Track Media shortcut key.
-  virtual void HandleMediaPrevTrack() = 0;
-
-  // Returns the current media recording state of web contents that belongs to
-  // the the user @ |index|. See session_types.h for a description of UserIndex.
-  virtual MediaCaptureState GetMediaCaptureState(UserIndex index) = 0;
-};
-
-}  // namespace ash
-
-#endif  // ASH_COMMON_MEDIA_DELEGATE_H_
diff --git a/ash/common/mojo_interface_factory.cc b/ash/common/mojo_interface_factory.cc
index 3cdd6f1..038a2dc 100644
--- a/ash/common/mojo_interface_factory.cc
+++ b/ash/common/mojo_interface_factory.cc
@@ -8,9 +8,11 @@
 
 #include "ash/common/accelerators/accelerator_controller.h"
 #include "ash/common/cast_config_controller.h"
+#include "ash/common/media_controller.h"
 #include "ash/common/new_window_controller.h"
 #include "ash/common/session/session_controller.h"
 #include "ash/common/shelf/shelf_controller.h"
+#include "ash/common/shell_delegate.h"
 #include "ash/common/shutdown_controller.h"
 #include "ash/common/system/locale/locale_notification_controller.h"
 #include "ash/common/system/tray/system_tray_controller.h"
@@ -19,6 +21,7 @@
 #include "ash/common/wm_shell.h"
 #include "base/bind.h"
 #include "services/service_manager/public/cpp/interface_registry.h"
+#include "ui/app_list/presenter/app_list.h"
 
 #if defined(OS_CHROMEOS)
 #include "ash/common/system/chromeos/network/vpn_list.h"
@@ -33,6 +36,10 @@
   WmShell::Get()->accelerator_controller()->BindRequest(std::move(request));
 }
 
+void BindAppListRequestOnMainThread(app_list::mojom::AppListRequest request) {
+  WmShell::Get()->app_list()->BindRequest(std::move(request));
+}
+
 void BindCastConfigOnMainThread(mojom::CastConfigRequest request) {
   WmShell::Get()->cast_config()->BindRequest(std::move(request));
 }
@@ -43,6 +50,11 @@
       std::move(request));
 }
 
+void BindMediaControllerRequestOnMainThread(
+    mojom::MediaControllerRequest request) {
+  WmShell::Get()->media_controller()->BindRequest(std::move(request));
+}
+
 void BindNewWindowControllerRequestOnMainThread(
     mojom::NewWindowControllerRequest request) {
   WmShell::Get()->new_window_controller()->BindRequest(std::move(request));
@@ -91,11 +103,15 @@
   registry->AddInterface(
       base::Bind(&BindAcceleratorControllerRequestOnMainThread),
       main_thread_task_runner);
+  registry->AddInterface(base::Bind(&BindAppListRequestOnMainThread),
+                         main_thread_task_runner);
   registry->AddInterface(base::Bind(&BindCastConfigOnMainThread),
                          main_thread_task_runner);
   registry->AddInterface(
       base::Bind(&BindLocaleNotificationControllerOnMainThread),
       main_thread_task_runner);
+  registry->AddInterface(base::Bind(&BindMediaControllerRequestOnMainThread),
+                         main_thread_task_runner);
   registry->AddInterface(
       base::Bind(&BindNewWindowControllerRequestOnMainThread),
       main_thread_task_runner);
diff --git a/ash/common/shell_delegate.h b/ash/common/shell_delegate.h
index d95f49ac..c007086 100644
--- a/ash/common/shell_delegate.h
+++ b/ash/common/shell_delegate.h
@@ -38,7 +38,6 @@
 
 class AccessibilityDelegate;
 class GPUSupport;
-class MediaDelegate;
 class PaletteDelegate;
 class SessionStateDelegate;
 class ShelfDelegate;
@@ -113,9 +112,6 @@
   // Creates a accessibility delegate. Shell takes ownership of the delegate.
   virtual AccessibilityDelegate* CreateAccessibilityDelegate() = 0;
 
-  // Creates a media delegate. Shell takes ownership of the delegate.
-  virtual MediaDelegate* CreateMediaDelegate() = 0;
-
   virtual std::unique_ptr<PaletteDelegate> CreatePaletteDelegate() = 0;
 
   // Creates a menu model for the |wm_shelf| and optional shelf |item|.
diff --git a/ash/common/system/chromeos/media_security/media_capture_observer.h b/ash/common/system/chromeos/media_security/media_capture_observer.h
deleted file mode 100644
index 6aa1eac..0000000
--- a/ash/common/system/chromeos/media_security/media_capture_observer.h
+++ /dev/null
@@ -1,21 +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 ASH_COMMON_SYSTEM_CHROMEOS_MEDIA_SECURITY_MEDIA_CAPTURE_OBSERVER_H_
-#define ASH_COMMON_SYSTEM_CHROMEOS_MEDIA_SECURITY_MEDIA_CAPTURE_OBSERVER_H_
-
-namespace ash {
-
-class MediaCaptureObserver {
- public:
-  // Called when media capture state has changed.
-  virtual void OnMediaCaptureChanged() = 0;
-
- protected:
-  virtual ~MediaCaptureObserver() {}
-};
-
-}  // namespace ash
-
-#endif  // ASH_COMMON_SYSTEM_CHROMEOS_MEDIA_SECURITY_MEDIA_CAPTURE_OBSERVER_H_
diff --git a/ash/common/system/chromeos/media_security/multi_profile_media_tray_item.cc b/ash/common/system/chromeos/media_security/multi_profile_media_tray_item.cc
index eea69c65..9c0bdf6d 100644
--- a/ash/common/system/chromeos/media_security/multi_profile_media_tray_item.cc
+++ b/ash/common/system/chromeos/media_security/multi_profile_media_tray_item.cc
@@ -5,9 +5,8 @@
 #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"
+#include "ash/common/media_controller.h"
 #include "ash/common/session/session_state_delegate.h"
-#include "ash/common/system/chromeos/media_security/media_capture_observer.h"
 #include "ash/common/system/tray/system_tray_notifier.h"
 #include "ash/common/system/tray/tray_constants.h"
 #include "ash/common/system/tray/tray_item_view.h"
@@ -32,24 +31,25 @@
         UseMd()
             ? gfx::CreateVectorIcon(kSystemTrayRecordingIcon, kTrayIconColor)
             : *bundle.GetImageSkiaNamed(IDR_AURA_UBER_TRAY_RECORDING));
-    OnMediaCaptureChanged();
-    WmShell::Get()->system_tray_notifier()->AddMediaCaptureObserver(this);
+    WmShell::Get()->media_controller()->AddObserver(this);
+    SetVisible(false);
+    WmShell::Get()->media_controller()->RequestCaptureState();
     set_id(VIEW_ID_MEDIA_TRAY_VIEW);
   }
 
   ~MultiProfileMediaTrayView() override {
-    WmShell::Get()->system_tray_notifier()->RemoveMediaCaptureObserver(this);
+    WmShell::Get()->media_controller()->RemoveObserver(this);
   }
 
   // MediaCaptureObserver:
-  void OnMediaCaptureChanged() override {
-    MediaDelegate* media_delegate = WmShell::Get()->media_delegate();
+  void OnMediaCaptureChanged(
+      const std::vector<mojom::MediaCaptureState>& capture_states) override {
     SessionStateDelegate* session_state_delegate =
         WmShell::Get()->GetSessionStateDelegate();
     // The user at 0 is the current desktop user.
     for (UserIndex index = 1;
          index < session_state_delegate->NumberOfLoggedInUsers(); ++index) {
-      if (media_delegate->GetMediaCaptureState(index) != MEDIA_CAPTURE_NONE) {
+      if (capture_states[index] != mojom::MediaCaptureState::NONE) {
         SetVisible(true);
         return;
       }
diff --git a/ash/common/system/chromeos/media_security/multi_profile_media_tray_item_unittest.cc b/ash/common/system/chromeos/media_security/multi_profile_media_tray_item_unittest.cc
index 16a4a4de..d09cd84 100644
--- a/ash/common/system/chromeos/media_security/multi_profile_media_tray_item_unittest.cc
+++ b/ash/common/system/chromeos/media_security/multi_profile_media_tray_item_unittest.cc
@@ -5,11 +5,14 @@
 #include "ash/common/system/chromeos/media_security/multi_profile_media_tray_item.h"
 
 #include "ash/common/ash_view_ids.h"
+#include "ash/common/media_controller.h"
 #include "ash/common/system/status_area_widget.h"
 #include "ash/common/system/tray/system_tray.h"
 #include "ash/common/system/tray/system_tray_bubble.h"
 #include "ash/common/system/tray/tray_item_view.h"
 #include "ash/common/test/test_session_state_delegate.h"
+#include "ash/common/wm_shell.h"
+#include "ash/public/interfaces/media.mojom.h"
 #include "ash/test/ash_test_base.h"
 #include "ash/test/ash_test_helper.h"
 #include "ash/test/status_area_widget_test_helper.h"
@@ -18,12 +21,28 @@
 
 namespace ash {
 
-using MultiProfileMediaTrayItemTest = test::AshTestBase;
+class MultiProfileMediaTrayItemTest : public test::AshTestBase {
+ public:
+  MultiProfileMediaTrayItemTest() {}
+  ~MultiProfileMediaTrayItemTest() override {}
 
+  void SetMediaCaptureState(mojom::MediaCaptureState state) {
+    // Create the fake update.
+    test::TestSessionStateDelegate* session_state_delegate =
+        test::AshTestHelper::GetTestSessionStateDelegate();
+    std::vector<mojom::MediaCaptureState> v;
+    for (int i = 0; i < session_state_delegate->NumberOfLoggedInUsers(); ++i)
+      v.push_back(state);
+    WmShell::Get()->media_controller()->NotifyCaptureState(v);
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MultiProfileMediaTrayItemTest);
+};
+
+// ash_unittests. still failing.
 TEST_F(MultiProfileMediaTrayItemTest, NotifyMediaCaptureChange) {
   TrayItemView::DisableAnimationsForTest();
-  test::TestShellDelegate* shell_delegate =
-      ash_test_helper()->test_shell_delegate();
   test::TestSessionStateDelegate* session_state_delegate =
       test::AshTestHelper::GetTestSessionStateDelegate();
   session_state_delegate->set_logged_in_users(2);
@@ -39,18 +58,19 @@
   views::View* tray_view =
       widget->GetRootView()->GetViewByID(VIEW_ID_MEDIA_TRAY_VIEW);
 
+  SetMediaCaptureState(mojom::MediaCaptureState::NONE);
   EXPECT_FALSE(tray_view->visible());
   EXPECT_FALSE(in_user_view->visible());
 
-  shell_delegate->SetMediaCaptureState(MEDIA_CAPTURE_AUDIO);
+  SetMediaCaptureState(mojom::MediaCaptureState::AUDIO);
   EXPECT_TRUE(tray_view->visible());
   EXPECT_TRUE(in_user_view->visible());
 
-  shell_delegate->SetMediaCaptureState(MEDIA_CAPTURE_AUDIO_VIDEO);
+  SetMediaCaptureState(mojom::MediaCaptureState::AUDIO_VIDEO);
   EXPECT_TRUE(tray_view->visible());
   EXPECT_TRUE(in_user_view->visible());
 
-  shell_delegate->SetMediaCaptureState(MEDIA_CAPTURE_NONE);
+  SetMediaCaptureState(mojom::MediaCaptureState::NONE);
   EXPECT_FALSE(tray_view->visible());
   EXPECT_FALSE(in_user_view->visible());
 }
diff --git a/ash/common/system/tray/system_tray_notifier.cc b/ash/common/system/tray/system_tray_notifier.cc
index e530b8c..665beda 100644
--- a/ash/common/system/tray/system_tray_notifier.cc
+++ b/ash/common/system/tray/system_tray_notifier.cc
@@ -13,7 +13,6 @@
 #if defined(OS_CHROMEOS)
 #include "ash/common/system/chromeos/bluetooth/bluetooth_observer.h"
 #include "ash/common/system/chromeos/enterprise/enterprise_domain_observer.h"
-#include "ash/common/system/chromeos/media_security/media_capture_observer.h"
 #include "ash/common/system/chromeos/network/network_observer.h"
 #include "ash/common/system/chromeos/network/network_portal_detector_observer.h"
 #include "ash/common/system/chromeos/screen_security/screen_capture_observer.h"
@@ -197,21 +196,6 @@
     observer.OnLogoutDialogDurationChanged(duration);
 }
 
-void SystemTrayNotifier::AddMediaCaptureObserver(
-    MediaCaptureObserver* observer) {
-  media_capture_observers_.AddObserver(observer);
-}
-
-void SystemTrayNotifier::RemoveMediaCaptureObserver(
-    MediaCaptureObserver* observer) {
-  media_capture_observers_.RemoveObserver(observer);
-}
-
-void SystemTrayNotifier::NotifyMediaCaptureChanged() {
-  for (auto& observer : media_capture_observers_)
-    observer.OnMediaCaptureChanged();
-}
-
 void SystemTrayNotifier::AddNetworkObserver(NetworkObserver* observer) {
   network_observers_.AddObserver(observer);
 }
diff --git a/ash/common/system/tray/system_tray_notifier.h b/ash/common/system/tray/system_tray_notifier.h
index 7b1ccb6..26e72d5 100644
--- a/ash/common/system/tray/system_tray_notifier.h
+++ b/ash/common/system/tray/system_tray_notifier.h
@@ -31,7 +31,6 @@
 class EnterpriseDomainObserver;
 class LastWindowClosedObserver;
 class LogoutButtonObserver;
-class MediaCaptureObserver;
 class NetworkObserver;
 class NetworkPortalDetectorObserver;
 class ScreenCaptureObserver;
@@ -101,11 +100,6 @@
   void NotifyShowLoginButtonChanged(bool show_login_button);
   void NotifyLogoutDialogDurationChanged(base::TimeDelta duration);
 
-  // Media capture.
-  void AddMediaCaptureObserver(MediaCaptureObserver* observer);
-  void RemoveMediaCaptureObserver(MediaCaptureObserver* observer);
-  void NotifyMediaCaptureChanged();
-
   // Network.
   void AddNetworkObserver(NetworkObserver* observer);
   void RemoveNetworkObserver(NetworkObserver* observer);
@@ -161,7 +155,6 @@
   base::ObserverList<EnterpriseDomainObserver> enterprise_domain_observers_;
   base::ObserverList<LastWindowClosedObserver> last_window_closed_observers_;
   base::ObserverList<LogoutButtonObserver> logout_button_observers_;
-  base::ObserverList<MediaCaptureObserver> media_capture_observers_;
   base::ObserverList<NetworkObserver> network_observers_;
   base::ObserverList<NetworkPortalDetectorObserver>
       network_portal_detector_observers_;
diff --git a/ash/common/system/user/user_card_view.cc b/ash/common/system/user/user_card_view.cc
index 157d07e..83ca4e39 100644
--- a/ash/common/system/user/user_card_view.cc
+++ b/ash/common/system/user/user_card_view.cc
@@ -7,12 +7,13 @@
 #include <algorithm>
 #include <vector>
 
+#include "ash/common/ash_view_ids.h"
 #include "ash/common/login_status.h"
 #include "ash/common/material_design/material_design_controller.h"
+#include "ash/common/media_controller.h"
 #include "ash/common/session/session_state_delegate.h"
 #include "ash/common/system/tray/system_tray_controller.h"
 #include "ash/common/system/tray/system_tray_delegate.h"
-#include "ash/common/system/tray/system_tray_notifier.h"
 #include "ash/common/system/tray/tray_constants.h"
 #include "ash/common/system/tray/tray_popup_item_style.h"
 #include "ash/common/system/tray/tray_utils.h"
@@ -48,11 +49,6 @@
 #include "ui/views/layout/box_layout.h"
 #include "ui/views/layout/fill_layout.h"
 
-#if defined(OS_CHROMEOS)
-#include "ash/common/ash_view_ids.h"
-#include "ash/common/media_delegate.h"
-#endif
-
 namespace ash {
 namespace tray {
 
@@ -93,7 +89,6 @@
   return image_view;
 }
 
-#if defined(OS_CHROMEOS)
 class MediaIndicator : public views::View, public MediaCaptureObserver {
  public:
   explicit MediaIndicator(UserIndex index)
@@ -108,31 +103,37 @@
     label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
     label_->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
         ui::ResourceBundle::SmallFont));
-    OnMediaCaptureChanged();
-    WmShell::Get()->system_tray_notifier()->AddMediaCaptureObserver(this);
+    WmShell::Get()->media_controller()->AddObserver(this);
+    SetVisible(false);
+    WmShell::Get()->media_controller()->RequestCaptureState();
     set_id(VIEW_ID_USER_VIEW_MEDIA_INDICATOR);
   }
 
   ~MediaIndicator() override {
-    WmShell::Get()->system_tray_notifier()->RemoveMediaCaptureObserver(this);
+    WmShell::Get()->media_controller()->RemoveObserver(this);
   }
 
   // MediaCaptureObserver:
-  void OnMediaCaptureChanged() override {
-    MediaCaptureState state =
-        WmShell::Get()->media_delegate()->GetMediaCaptureState(index_);
+  void OnMediaCaptureChanged(
+      const std::vector<mojom::MediaCaptureState>& capture_states) override {
+    if (static_cast<size_t>(index_) >= capture_states.size()) {
+      NOTREACHED();
+      return;
+    }
+
+    mojom::MediaCaptureState state = capture_states[index_];
     int res_id = 0;
     switch (state) {
-      case MEDIA_CAPTURE_AUDIO_VIDEO:
+      case mojom::MediaCaptureState::AUDIO_VIDEO:
         res_id = IDS_ASH_STATUS_TRAY_MEDIA_RECORDING_AUDIO_VIDEO;
         break;
-      case MEDIA_CAPTURE_AUDIO:
+      case mojom::MediaCaptureState::AUDIO:
         res_id = IDS_ASH_STATUS_TRAY_MEDIA_RECORDING_AUDIO;
         break;
-      case MEDIA_CAPTURE_VIDEO:
+      case mojom::MediaCaptureState::VIDEO:
         res_id = IDS_ASH_STATUS_TRAY_MEDIA_RECORDING_VIDEO;
         break;
-      case MEDIA_CAPTURE_NONE:
+      case mojom::MediaCaptureState::NONE:
         break;
     }
     SetMessage(res_id ? l10n_util::GetStringUTF16(res_id) : base::string16());
@@ -152,7 +153,6 @@
 
   DISALLOW_COPY_AND_ASSIGN(MediaIndicator);
 };
-#endif
 
 // The user details shown in public account mode. This is essentially a label
 // but with custom painting code as the text is styled with multiple colors and
@@ -389,9 +389,7 @@
           views::CreateEmptyBorder(0, kMenuExtraMarginFromLeftEdge, 0, 0));
     }
 
-#if defined(OS_CHROMEOS)
-    WmShell::Get()->system_tray_notifier()->AddMediaCaptureObserver(this);
-#endif
+    WmShell::Get()->media_controller()->AddObserver(this);
   }
 
   if (login_status == LoginStatus::PUBLIC)
@@ -403,10 +401,8 @@
 }
 
 UserCardView::~UserCardView() {
-#if defined(OS_CHROMEOS)
   if (UseMd())
-    WmShell::Get()->system_tray_notifier()->RemoveMediaCaptureObserver(this);
-#endif
+    WmShell::Get()->media_controller()->RemoveObserver(this);
 }
 
 void UserCardView::PaintChildren(const ui::PaintContext& context) {
@@ -426,25 +422,24 @@
   node_data->SetName(base::JoinString(labels, base::ASCIIToUTF16(" ")));
 }
 
-void UserCardView::OnMediaCaptureChanged() {
-#if defined(OS_CHROMEOS)
+void UserCardView::OnMediaCaptureChanged(
+    const std::vector<mojom::MediaCaptureState>& capture_states) {
   if (is_active_user())
     return;
 
-  MediaCaptureState state =
-      WmShell::Get()->media_delegate()->GetMediaCaptureState(user_index_);
+  mojom::MediaCaptureState state = capture_states[user_index_];
   int res_id = 0;
   switch (state) {
-    case MEDIA_CAPTURE_AUDIO_VIDEO:
+    case mojom::MediaCaptureState::AUDIO_VIDEO:
       res_id = IDS_ASH_STATUS_TRAY_MEDIA_RECORDING_AUDIO_VIDEO;
       break;
-    case MEDIA_CAPTURE_AUDIO:
+    case mojom::MediaCaptureState::AUDIO:
       res_id = IDS_ASH_STATUS_TRAY_MEDIA_RECORDING_AUDIO;
       break;
-    case MEDIA_CAPTURE_VIDEO:
+    case mojom::MediaCaptureState::VIDEO:
       res_id = IDS_ASH_STATUS_TRAY_MEDIA_RECORDING_VIDEO;
       break;
-    case MEDIA_CAPTURE_NONE:
+    case mojom::MediaCaptureState::NONE:
       break;
   }
   if (res_id)
@@ -453,7 +448,6 @@
   media_capture_icon_->SetVisible(!!res_id);
   user_name_->SetVisible(!res_id);
   Layout();
-#endif
 }
 
 void UserCardView::AddPublicModeUserContent(int max_width) {
@@ -520,7 +514,6 @@
     if (user_name)
       AddChildView(user_name);
     if (user_email) {
-#if defined(OS_CHROMEOS)
       // Only non active user can have a media indicator.
       MediaIndicator* media_indicator = new MediaIndicator(user_index_);
       views::View* email_indicator_view = new views::View;
@@ -535,9 +528,6 @@
       details->AddChildView(email_indicator_view);
       details->AddChildView(media_indicator->GetMessageView());
       AddChildView(details);
-#else
-      AddChildView(user_email);
-#endif
     }
   }
 }
@@ -609,12 +599,11 @@
         gfx::Insets(0, (media_capture_width -
                         media_capture_icon_->GetPreferredSize().width()) /
                            2)));
-#if defined(OS_CHROMEOS)
+
     media_capture_icon_->set_id(VIEW_ID_USER_VIEW_MEDIA_INDICATOR);
-#endif
     AddChildView(media_capture_icon_);
 
-    OnMediaCaptureChanged();
+    WmShell::Get()->media_controller()->RequestCaptureState();
   }
 }
 
diff --git a/ash/common/system/user/user_card_view.h b/ash/common/system/user/user_card_view.h
index e9d849f20..b64553f2 100644
--- a/ash/common/system/user/user_card_view.h
+++ b/ash/common/system/user/user_card_view.h
@@ -5,7 +5,7 @@
 #ifndef ASH_COMMON_SYSTEM_USER_USER_CARD_VIEW_H_
 #define ASH_COMMON_SYSTEM_USER_USER_CARD_VIEW_H_
 
-#include "ash/common/system/chromeos/media_security/media_capture_observer.h"
+#include "ash/common/media_controller.h"
 #include "base/macros.h"
 #include "ui/views/view.h"
 
@@ -34,7 +34,8 @@
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
 
   // MediaCaptureObserver:
-  void OnMediaCaptureChanged() override;
+  void OnMediaCaptureChanged(
+      const std::vector<mojom::MediaCaptureState>& capture_states) override;
 
  private:
   // Creates the content for the public mode.
diff --git a/ash/common/wm_shell.cc b/ash/common/wm_shell.cc
index 2190f74..7f4f683 100644
--- a/ash/common/wm_shell.cc
+++ b/ash/common/wm_shell.cc
@@ -14,6 +14,7 @@
 #include "ash/common/devtools/ash_devtools_dom_agent.h"
 #include "ash/common/focus_cycler.h"
 #include "ash/common/keyboard/keyboard_ui.h"
+#include "ash/common/media_controller.h"
 #include "ash/common/new_window_controller.h"
 #include "ash/common/palette_delegate.h"
 #include "ash/common/session/session_controller.h"
@@ -47,6 +48,7 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "ui/app_list/presenter/app_list.h"
 #include "ui/app_list/presenter/app_list_presenter.h"
 #include "ui/display/display.h"
 #include "ui/views/focus/focus_manager_factory.h"
@@ -79,7 +81,6 @@
   // Some delegates access WmShell during their construction. Create them here
   // instead of the WmShell constructor.
   accessibility_delegate_.reset(delegate_->CreateAccessibilityDelegate());
-  media_delegate_.reset(delegate_->CreateMediaDelegate());
   palette_delegate_ = delegate_->CreatePaletteDelegate();
   toast_manager_.reset(new ToastManager);
 
@@ -249,11 +250,13 @@
 
 WmShell::WmShell(std::unique_ptr<ShellDelegate> shell_delegate)
     : delegate_(std::move(shell_delegate)),
+      app_list_(base::MakeUnique<app_list::AppList>()),
       cast_config_(base::MakeUnique<CastConfigController>()),
       focus_cycler_(base::MakeUnique<FocusCycler>()),
       immersive_context_(base::MakeUnique<ImmersiveContextAsh>()),
       locale_notification_controller_(
           base::MakeUnique<LocaleNotificationController>()),
+      media_controller_(base::MakeUnique<MediaController>()),
       new_window_controller_(base::MakeUnique<NewWindowController>()),
       session_controller_(base::MakeUnique<SessionController>()),
       shelf_controller_(base::MakeUnique<ShelfController>()),
diff --git a/ash/common/wm_shell.h b/ash/common/wm_shell.h
index 9eff74d..e0267f04 100644
--- a/ash/common/wm_shell.h
+++ b/ash/common/wm_shell.h
@@ -11,7 +11,6 @@
 #include <vector>
 
 #include "ash/ash_export.h"
-#include "ash/common/media_delegate.h"
 #include "ash/common/metrics/gesture_action_type.h"
 #include "ash/common/metrics/user_metrics_action.h"
 #include "ash/common/wm/lock_state_observer.h"
@@ -21,6 +20,10 @@
 #include "ui/compositor/layer_type.h"
 #include "ui/wm/public/window_types.h"
 
+namespace app_list {
+class AppList;
+}
+
 namespace base {
 class SequencedWorkerPool;
 }
@@ -53,6 +56,7 @@
 class KeyboardUI;
 class LocaleNotificationController;
 class MaximizeModeController;
+class MediaController;
 class MruWindowTracker;
 class NewWindowController;
 class PaletteDelegate;
@@ -117,6 +121,8 @@
     return accessibility_delegate_.get();
   }
 
+  app_list::AppList* app_list() { return app_list_.get(); }
+
   BrightnessControlDelegate* brightness_control_delegate() {
     return brightness_control_delegate_.get();
   }
@@ -141,7 +147,7 @@
 
   MruWindowTracker* mru_window_tracker() { return mru_window_tracker_.get(); }
 
-  MediaDelegate* media_delegate() { return media_delegate_.get(); }
+  MediaController* media_controller() { return media_controller_.get(); }
 
   NewWindowController* new_window_controller() {
     return new_window_controller_.get();
@@ -481,6 +487,7 @@
 
   std::unique_ptr<AcceleratorController> accelerator_controller_;
   std::unique_ptr<AccessibilityDelegate> accessibility_delegate_;
+  std::unique_ptr<app_list::AppList> app_list_;
   std::unique_ptr<BrightnessControlDelegate> brightness_control_delegate_;
   std::unique_ptr<CastConfigController> cast_config_;
   std::unique_ptr<FocusCycler> focus_cycler_;
@@ -490,7 +497,7 @@
   std::unique_ptr<KeyboardUI> keyboard_ui_;
   std::unique_ptr<LocaleNotificationController> locale_notification_controller_;
   std::unique_ptr<MaximizeModeController> maximize_mode_controller_;
-  std::unique_ptr<MediaDelegate> media_delegate_;
+  std::unique_ptr<MediaController> media_controller_;
   std::unique_ptr<MruWindowTracker> mru_window_tracker_;
   std::unique_ptr<NewWindowController> new_window_controller_;
   std::unique_ptr<PaletteDelegate> palette_delegate_;
diff --git a/ash/mus/app_list_presenter_mus.cc b/ash/mus/app_list_presenter_mus.cc
index 9bb13fbf9..86d2cac 100644
--- a/ash/mus/app_list_presenter_mus.cc
+++ b/ash/mus/app_list_presenter_mus.cc
@@ -4,37 +4,34 @@
 
 #include "ash/mus/app_list_presenter_mus.h"
 
-#include "content/public/common/service_names.mojom.h"
-#include "services/service_manager/public/cpp/connector.h"
+#include "ash/common/wm_shell.h"
+#include "ui/app_list/presenter/app_list.h"
 
 namespace ash {
 
-namespace {
-
-bool HasConnection(app_list::mojom::AppListPresenterPtr* interface_ptr) {
-  return interface_ptr->is_bound() && !interface_ptr->encountered_error();
-}
-
-}  // namespace
-
-AppListPresenterMus::AppListPresenterMus(service_manager::Connector* connector)
-    : connector_(connector) {}
+AppListPresenterMus::AppListPresenterMus() {}
 
 AppListPresenterMus::~AppListPresenterMus() {}
 
 void AppListPresenterMus::Show(int64_t display_id) {
-  ConnectIfNeeded();
-  presenter_->Show(display_id);
+  app_list::mojom::AppListPresenter* app_list_presenter =
+      WmShell::Get()->app_list()->GetAppListPresenter();
+  if (app_list_presenter)
+    app_list_presenter->Show(display_id);
 }
 
 void AppListPresenterMus::Dismiss() {
-  ConnectIfNeeded();
-  presenter_->Dismiss();
+  app_list::mojom::AppListPresenter* app_list_presenter =
+      WmShell::Get()->app_list()->GetAppListPresenter();
+  if (app_list_presenter)
+    app_list_presenter->Dismiss();
 }
 
 void AppListPresenterMus::ToggleAppList(int64_t display_id) {
-  ConnectIfNeeded();
-  presenter_->ToggleAppList(display_id);
+  app_list::mojom::AppListPresenter* app_list_presenter =
+      WmShell::Get()->app_list()->GetAppListPresenter();
+  if (app_list_presenter)
+    app_list_presenter->ToggleAppList(display_id);
 }
 
 bool AppListPresenterMus::IsVisible() const {
@@ -49,13 +46,4 @@
   return false;
 }
 
-void AppListPresenterMus::ConnectIfNeeded() {
-  if (!connector_ || HasConnection(&presenter_))
-    return;
-  connector_->ConnectToInterface(content::mojom::kBrowserServiceName,
-                                 &presenter_);
-  CHECK(HasConnection(&presenter_))
-      << "Could not connect to app_list::mojom::AppListPresenter.";
-}
-
 }  // namespace ash
diff --git a/ash/mus/app_list_presenter_mus.h b/ash/mus/app_list_presenter_mus.h
index 2ed64ee8..5127557 100644
--- a/ash/mus/app_list_presenter_mus.h
+++ b/ash/mus/app_list_presenter_mus.h
@@ -7,19 +7,14 @@
 
 #include "base/macros.h"
 #include "ui/app_list/presenter/app_list_presenter.h"
-#include "ui/app_list/presenter/app_list_presenter.mojom.h"
-
-namespace service_manager {
-class Connector;
-}
 
 namespace ash {
 
 // Mus+ash implementation of the AppListPresenter interface for mash, which
-// talks to the app list service in chrome.
+// talks to the app list presenter service in chrome.
 class AppListPresenterMus : public app_list::AppListPresenter {
  public:
-  explicit AppListPresenterMus(service_manager::Connector* connector);
+  AppListPresenterMus();
   ~AppListPresenterMus() override;
 
   // app_list::AppListPresenter:
@@ -30,13 +25,6 @@
   bool GetTargetVisibility() const override;
 
  private:
-  // Connect to the app list service in chrome if the connection hasn't
-  // been established or has an error.
-  void ConnectIfNeeded();
-
-  service_manager::Connector* connector_;
-  app_list::mojom::AppListPresenterPtr presenter_;
-
   DISALLOW_COPY_AND_ASSIGN(AppListPresenterMus);
 };
 
diff --git a/ash/mus/manifest.json b/ash/mus/manifest.json
index 9b25900e..12fb98a 100644
--- a/ash/mus/manifest.json
+++ b/ash/mus/manifest.json
@@ -7,9 +7,11 @@
         // Modifications here should correspond with changes to
         // chrome_content_browser_manifest_overlay.json.
         "ash": [
+          "app_list::mojom::AppList",
           "ash::mojom::AcceleratorController",
           "ash::mojom::CastConfig",
           "ash::mojom::LocaleNotificationController",
+          "ash::mojom::MediaController",
           "ash::mojom::NewWindowController",
           "ash::mojom::SessionController",
           "ash::mojom::ShelfController",
diff --git a/ash/mus/shell_delegate_mus.cc b/ash/mus/shell_delegate_mus.cc
index 054100e..37ec044 100644
--- a/ash/mus/shell_delegate_mus.cc
+++ b/ash/mus/shell_delegate_mus.cc
@@ -7,7 +7,6 @@
 #include <utility>
 
 #include "ash/common/gpu_support_stub.h"
-#include "ash/common/media_delegate.h"
 #include "ash/common/palette_delegate.h"
 #include "ash/common/session/session_state_delegate.h"
 #include "ash/common/wm_shell.h"
@@ -19,7 +18,6 @@
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
 #include "components/user_manager/user_info_impl.h"
-#include "ui/app_list/presenter/app_list_presenter.h"
 #include "ui/gfx/image/image.h"
 
 #if defined(OS_CHROMEOS)
@@ -89,28 +87,10 @@
   DISALLOW_COPY_AND_ASSIGN(SessionStateDelegateStub);
 };
 
-class MediaDelegateStub : public MediaDelegate {
- public:
-  MediaDelegateStub() {}
-  ~MediaDelegateStub() override {}
-
-  // MediaDelegate:
-  void HandleMediaNextTrack() override { NOTIMPLEMENTED(); }
-  void HandleMediaPlayPause() override { NOTIMPLEMENTED(); }
-  void HandleMediaPrevTrack() override { NOTIMPLEMENTED(); }
-  MediaCaptureState GetMediaCaptureState(UserIndex index) override {
-    NOTIMPLEMENTED();
-    return MEDIA_CAPTURE_NONE;
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MediaDelegateStub);
-};
-
 }  // namespace
 
 ShellDelegateMus::ShellDelegateMus(service_manager::Connector* connector)
-    : connector_(connector), app_list_presenter_(connector) {
+    : connector_(connector) {
   // |connector_| may be null in tests.
 }
 
@@ -198,12 +178,6 @@
   return new AccessibilityDelegateMus(connector_);
 }
 
-MediaDelegate* ShellDelegateMus::CreateMediaDelegate() {
-  // TODO: http://crbug.com/647409.
-  NOTIMPLEMENTED() << " Using a stub MediaDelegate implementation";
-  return new MediaDelegateStub;
-}
-
 std::unique_ptr<PaletteDelegate> ShellDelegateMus::CreatePaletteDelegate() {
   // TODO: http://crbug.com/647417.
   NOTIMPLEMENTED();
diff --git a/ash/mus/shell_delegate_mus.h b/ash/mus/shell_delegate_mus.h
index 81e6701..a876c8ba 100644
--- a/ash/mus/shell_delegate_mus.h
+++ b/ash/mus/shell_delegate_mus.h
@@ -40,7 +40,6 @@
   std::unique_ptr<WallpaperDelegate> CreateWallpaperDelegate() override;
   SessionStateDelegate* CreateSessionStateDelegate() override;
   AccessibilityDelegate* CreateAccessibilityDelegate() override;
-  MediaDelegate* CreateMediaDelegate() override;
   std::unique_ptr<PaletteDelegate> CreatePaletteDelegate() override;
   ui::MenuModel* CreateContextMenu(WmShelf* wm_shelf,
                                    const ShelfItem* item) override;
diff --git a/ash/public/interfaces/BUILD.gn b/ash/public/interfaces/BUILD.gn
index b581aa3..edc79f7b 100644
--- a/ash/public/interfaces/BUILD.gn
+++ b/ash/public/interfaces/BUILD.gn
@@ -10,6 +10,7 @@
     "ash_window_type.mojom",
     "cast_config.mojom",
     "locale.mojom",
+    "media.mojom",
     "new_window.mojom",
     "session_controller.mojom",
     "shelf.mojom",
diff --git a/ash/public/interfaces/media.mojom b/ash/public/interfaces/media.mojom
new file mode 100644
index 0000000..bf56de4
--- /dev/null
+++ b/ash/public/interfaces/media.mojom
@@ -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.
+
+module ash.mojom;
+
+// Describes whether media is currently being captured.
+enum MediaCaptureState {
+  NONE = 0,
+  AUDIO = 1,
+  VIDEO = 2,
+  AUDIO_VIDEO = 3
+};
+
+// Allows clients (e.g. Chrome browser) to interface with the ash media
+// indicators.
+interface MediaController {
+  // Sets the client interface.
+  SetClient(associated MediaClient client);
+
+  // Called when the media capture state changes on the client, or in response
+  // to a RequestCaptureState() request. Returns an array of MediaCaptureState
+  // by index of the shell content. (These indexes are unstable, but are
+  // unlikely to change in practice, see comments in chrome's MediaClient::
+  // RequestCaptureState()).
+  NotifyCaptureState(array<MediaCaptureState> state);
+};
+
+// This delegate allows the UI code in ash to forward UI commands.
+interface MediaClient {
+  // Handles the Next Track Media shortcut key.
+  HandleMediaNextTrack();
+
+  // Handles the Play/Pause Toggle Media shortcut key.
+  HandleMediaPlayPause();
+
+  // Handles the Previous Track Media shortcut key.
+  HandleMediaPrevTrack();
+
+  // Requests that the client resends the NotifyMediaCaptureChanged() message.
+  RequestCaptureState();
+};
diff --git a/ash/resources/BUILD.gn b/ash/resources/BUILD.gn
index 1454da5..57aeab68 100644
--- a/ash/resources/BUILD.gn
+++ b/ash/resources/BUILD.gn
@@ -6,6 +6,7 @@
 import("//tools/grit/repack.gni")
 import("//ui/base/ui_features.gni")
 
+assert(is_chromeos)
 assert(enable_hidpi)
 
 grit("resources") {
@@ -27,7 +28,10 @@
 
     sources = [
       "$root_gen_dir/ash/resources/ash_resources_${percent}_percent.pak",
+      "$root_gen_dir/ui/app_list/resources/app_list_resources_${percent}_percent.pak",
+      "$root_gen_dir/ui/chromeos/resources/ui_chromeos_resources_${percent}_percent.pak",
       "$root_gen_dir/ui/resources/ui_resources_${percent}_percent.pak",
+      "$root_gen_dir/ui/views/resources/views_resources_${percent}_percent.pak",
     ]
 
     if (percent == "100") {
@@ -40,34 +44,20 @@
 
     deps = [
       "//ash/resources",
+      "//ui/app_list/resources",
+      "//ui/chromeos/resources",
       "//ui/resources",
+      "//ui/views/resources",
     ]
 
     if (defined(invoker.deps)) {
       deps += invoker.deps
     }
 
-    if (toolkit_views) {
-      deps += [
-        "//ui/app_list/resources",
-        "//ui/views/resources",
-      ]
-      sources += [
-        "$root_gen_dir/ui/app_list/resources/app_list_resources_${percent}_percent.pak",
-        "$root_gen_dir/ui/views/resources/views_resources_${percent}_percent.pak",
-      ]
-
-      if (percent == "100") {
-        # TODO(msw): This seems bad, but follows repack_ui_test_pak's example.
-        deps += [ "//third_party/WebKit/public:resources_grit" ]
-        sources +=
-            [ "$root_gen_dir/blink/public/resources/blink_resources.pak" ]
-      }
-    }
-
-    if (is_chromeos) {
-      sources += [ "$root_gen_dir/ui/chromeos/resources/ui_chromeos_resources_${percent}_percent.pak" ]
-      deps += [ "//ui/chromeos/resources" ]
+    if (percent == "100") {
+      # TODO(msw): This seems bad, but follows repack_ui_test_pak's example.
+      deps += [ "//third_party/WebKit/public:resources_grit" ]
+      sources += [ "$root_gen_dir/blink/public/resources/blink_resources.pak" ]
     }
   }
 }
diff --git a/ash/shell/shell_delegate_impl.cc b/ash/shell/shell_delegate_impl.cc
index b9c7c01..5670f7d4 100644
--- a/ash/shell/shell_delegate_impl.cc
+++ b/ash/shell/shell_delegate_impl.cc
@@ -8,7 +8,6 @@
 #include "ash/common/accessibility_delegate.h"
 #include "ash/common/default_accessibility_delegate.h"
 #include "ash/common/gpu_support_stub.h"
-#include "ash/common/media_delegate.h"
 #include "ash/common/palette_delegate.h"
 #include "ash/common/session/session_state_delegate.h"
 #include "ash/common/system/tray/default_system_tray_delegate.h"
@@ -36,23 +35,6 @@
 namespace shell {
 namespace {
 
-class MediaDelegateImpl : public MediaDelegate {
- public:
-  MediaDelegateImpl() {}
-  ~MediaDelegateImpl() override {}
-
-  // MediaDelegate:
-  void HandleMediaNextTrack() override {}
-  void HandleMediaPlayPause() override {}
-  void HandleMediaPrevTrack() override {}
-  MediaCaptureState GetMediaCaptureState(UserIndex index) override {
-    return MEDIA_CAPTURE_VIDEO;
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MediaDelegateImpl);
-};
-
 class PaletteDelegateImpl : public PaletteDelegate {
  public:
   PaletteDelegateImpl() {}
@@ -239,10 +221,6 @@
   return new DefaultAccessibilityDelegate;
 }
 
-MediaDelegate* ShellDelegateImpl::CreateMediaDelegate() {
-  return new MediaDelegateImpl;
-}
-
 std::unique_ptr<PaletteDelegate> ShellDelegateImpl::CreatePaletteDelegate() {
   return base::MakeUnique<PaletteDelegateImpl>();
 }
diff --git a/ash/shell/shell_delegate_impl.h b/ash/shell/shell_delegate_impl.h
index 590da66..7d8ae41 100644
--- a/ash/shell/shell_delegate_impl.h
+++ b/ash/shell/shell_delegate_impl.h
@@ -46,7 +46,6 @@
   std::unique_ptr<WallpaperDelegate> CreateWallpaperDelegate() override;
   SessionStateDelegate* CreateSessionStateDelegate() override;
   AccessibilityDelegate* CreateAccessibilityDelegate() override;
-  MediaDelegate* CreateMediaDelegate() override;
   std::unique_ptr<PaletteDelegate> CreatePaletteDelegate() override;
   ui::MenuModel* CreateContextMenu(WmShelf* wm_shelf,
                                    const ShelfItem* item) override;
diff --git a/ash/test/test_shell_delegate.cc b/ash/test/test_shell_delegate.cc
index d91c644..3402d6a 100644
--- a/ash/test/test_shell_delegate.cc
+++ b/ash/test/test_shell_delegate.cc
@@ -10,7 +10,6 @@
 #include "ash/app_list/app_list_presenter_delegate_factory.h"
 #include "ash/common/default_accessibility_delegate.h"
 #include "ash/common/gpu_support_stub.h"
-#include "ash/common/media_delegate.h"
 #include "ash/common/palette_delegate.h"
 #include "ash/common/session/session_state_delegate.h"
 #include "ash/common/test/test_session_state_delegate.h"
@@ -38,27 +37,6 @@
 namespace test {
 namespace {
 
-class MediaDelegateImpl : public MediaDelegate {
- public:
-  MediaDelegateImpl() : state_(MEDIA_CAPTURE_NONE) {}
-  ~MediaDelegateImpl() override {}
-
-  void set_media_capture_state(MediaCaptureState state) { state_ = state; }
-
- private:
-  // MediaDelegate:
-  void HandleMediaNextTrack() override {}
-  void HandleMediaPlayPause() override {}
-  void HandleMediaPrevTrack() override {}
-  MediaCaptureState GetMediaCaptureState(UserIndex index) override {
-    return state_;
-  }
-
-  MediaCaptureState state_;
-
-  DISALLOW_COPY_AND_ASSIGN(MediaDelegateImpl);
-};
-
 class AppListViewDelegateFactoryImpl
     : public app_list::AppListViewDelegateFactory {
  public:
@@ -159,10 +137,6 @@
   return new DefaultAccessibilityDelegate();
 }
 
-MediaDelegate* TestShellDelegate::CreateMediaDelegate() {
-  return new MediaDelegateImpl;
-}
-
 std::unique_ptr<PaletteDelegate> TestShellDelegate::CreatePaletteDelegate() {
   return nullptr;
 }
@@ -198,13 +172,5 @@
 
 void TestShellDelegate::UpdateTouchscreenStatusFromPrefs() {}
 
-void TestShellDelegate::SetMediaCaptureState(MediaCaptureState state) {
-#if defined(OS_CHROMEOS)
-  static_cast<MediaDelegateImpl*>(WmShell::Get()->media_delegate())
-      ->set_media_capture_state(state);
-  WmShell::Get()->system_tray_notifier()->NotifyMediaCaptureChanged();
-#endif
-}
-
 }  // namespace test
 }  // namespace ash
diff --git a/ash/test/test_shell_delegate.h b/ash/test/test_shell_delegate.h
index b3aee0c5..a2722be 100644
--- a/ash/test/test_shell_delegate.h
+++ b/ash/test/test_shell_delegate.h
@@ -8,7 +8,6 @@
 #include <memory>
 #include <string>
 
-#include "ash/common/media_delegate.h"
 #include "ash/common/shell_delegate.h"
 #include "ash/common/test/test_session_state_delegate.h"
 #include "base/macros.h"
@@ -52,7 +51,6 @@
   std::unique_ptr<WallpaperDelegate> CreateWallpaperDelegate() override;
   TestSessionStateDelegate* CreateSessionStateDelegate() override;
   AccessibilityDelegate* CreateAccessibilityDelegate() override;
-  MediaDelegate* CreateMediaDelegate() override;
   std::unique_ptr<PaletteDelegate> CreatePaletteDelegate() override;
   ui::MenuModel* CreateContextMenu(WmShelf* wm_shelf,
                                    const ShelfItem* item) override;
@@ -71,7 +69,6 @@
     return app_list_presenter_.get();
   }
 
-  void SetMediaCaptureState(MediaCaptureState state);
   void SetForceMaximizeOnFirstRun(bool maximize) {
     force_maximize_on_first_run_ = maximize;
   }
diff --git a/base/metrics/statistics_recorder.cc b/base/metrics/statistics_recorder.cc
index 6b1b0bf..4828450 100644
--- a/base/metrics/statistics_recorder.cc
+++ b/base/metrics/statistics_recorder.cc
@@ -16,7 +16,6 @@
 #include "base/metrics/persistent_histogram_allocator.h"
 #include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
-#include "base/synchronization/lock.h"
 #include "base/values.h"
 
 namespace {
@@ -59,10 +58,10 @@
 StatisticsRecorder::HistogramIterator&
 StatisticsRecorder::HistogramIterator::operator++() {
   const HistogramMap::iterator histograms_end = histograms_->end();
-  if (iter_ == histograms_end || lock_ == NULL)
+  if (iter_ == histograms_end)
     return *this;
 
-  base::AutoLock auto_lock(*lock_);
+  base::AutoLock auto_lock(lock_.Get());
 
   for (;;) {
     ++iter_;
@@ -79,13 +78,12 @@
 }
 
 StatisticsRecorder::~StatisticsRecorder() {
-  DCHECK(lock_);
   DCHECK(histograms_);
   DCHECK(ranges_);
 
   // Clean out what this object created and then restore what existed before.
   Reset();
-  base::AutoLock auto_lock(*lock_);
+  base::AutoLock auto_lock(lock_.Get());
   histograms_ = existing_histograms_.release();
   callbacks_ = existing_callbacks_.release();
   ranges_ = existing_ranges_.release();
@@ -110,31 +108,26 @@
 
 // static
 bool StatisticsRecorder::IsActive() {
-  if (lock_ == NULL)
-    return false;
-  base::AutoLock auto_lock(*lock_);
-  return NULL != histograms_;
+  base::AutoLock auto_lock(lock_.Get());
+  return histograms_ != nullptr;
 }
 
 // static
 HistogramBase* StatisticsRecorder::RegisterOrDeleteDuplicate(
     HistogramBase* histogram) {
-  // As per crbug.com/79322 the histograms are intentionally leaked, so we need
-  // to annotate them. Because ANNOTATE_LEAKING_OBJECT_PTR may be used only once
-  // for an object, the duplicates should not be annotated.
-  // Callers are responsible for not calling RegisterOrDeleteDuplicate(ptr)
-  // twice if (lock_ == NULL) || (!histograms_).
-  if (lock_ == NULL) {
-    ANNOTATE_LEAKING_OBJECT_PTR(histogram);  // see crbug.com/79322
-    return histogram;
-  }
-
-  HistogramBase* histogram_to_delete = NULL;
-  HistogramBase* histogram_to_return = NULL;
+  HistogramBase* histogram_to_delete = nullptr;
+  HistogramBase* histogram_to_return = nullptr;
   {
-    base::AutoLock auto_lock(*lock_);
-    if (histograms_ == NULL) {
+    base::AutoLock auto_lock(lock_.Get());
+    if (!histograms_) {
       histogram_to_return = histogram;
+
+      // As per crbug.com/79322 the histograms are intentionally leaked, so we
+      // need to annotate them. Because ANNOTATE_LEAKING_OBJECT_PTR may be used
+      // only once for an object, the duplicates should not be annotated.
+      // Callers are responsible for not calling RegisterOrDeleteDuplicate(ptr)
+      // twice |if (!histograms_)|.
+      ANNOTATE_LEAKING_OBJECT_PTR(histogram);  // see crbug.com/79322
     } else {
       const std::string& name = histogram->histogram_name();
       HistogramMap::iterator it = histograms_->find(name);
@@ -175,13 +168,8 @@
   DCHECK(ranges->HasValidChecksum());
   std::unique_ptr<const BucketRanges> ranges_deleter;
 
-  if (lock_ == NULL) {
-    ANNOTATE_LEAKING_OBJECT_PTR(ranges);
-    return ranges;
-  }
-
-  base::AutoLock auto_lock(*lock_);
-  if (ranges_ == NULL) {
+  base::AutoLock auto_lock(lock_.Get());
+  if (!ranges_) {
     ANNOTATE_LEAKING_OBJECT_PTR(ranges);
     return ranges;
   }
@@ -278,10 +266,8 @@
 
 // static
 void StatisticsRecorder::GetHistograms(Histograms* output) {
-  if (lock_ == NULL)
-    return;
-  base::AutoLock auto_lock(*lock_);
-  if (histograms_ == NULL)
+  base::AutoLock auto_lock(lock_.Get());
+  if (!histograms_)
     return;
 
   for (const auto& entry : *histograms_) {
@@ -292,10 +278,8 @@
 // static
 void StatisticsRecorder::GetBucketRanges(
     std::vector<const BucketRanges*>* output) {
-  if (lock_ == NULL)
-    return;
-  base::AutoLock auto_lock(*lock_);
-  if (ranges_ == NULL)
+  base::AutoLock auto_lock(lock_.Get());
+  if (!ranges_)
     return;
 
   for (const auto& entry : *ranges_) {
@@ -312,15 +296,13 @@
   // will acquire the lock at that time.
   ImportGlobalPersistentHistograms();
 
-  if (lock_ == NULL)
-    return NULL;
-  base::AutoLock auto_lock(*lock_);
-  if (histograms_ == NULL)
-    return NULL;
+  base::AutoLock auto_lock(lock_.Get());
+  if (!histograms_)
+    return nullptr;
 
   HistogramMap::iterator it = histograms_->find(name);
   if (histograms_->end() == it)
-    return NULL;
+    return nullptr;
   return it->second;
 }
 
@@ -332,7 +314,7 @@
 
   HistogramMap::iterator iter_begin;
   {
-    base::AutoLock auto_lock(*lock_);
+    base::AutoLock auto_lock(lock_.Get());
     iter_begin = histograms_->begin();
   }
   return HistogramIterator(iter_begin, include_persistent);
@@ -342,7 +324,7 @@
 StatisticsRecorder::HistogramIterator StatisticsRecorder::end() {
   HistogramMap::iterator iter_end;
   {
-    base::AutoLock auto_lock(*lock_);
+    base::AutoLock auto_lock(lock_.Get());
     iter_end = histograms_->end();
   }
   return HistogramIterator(iter_end, true);
@@ -350,19 +332,18 @@
 
 // static
 void StatisticsRecorder::InitLogOnShutdown() {
-  if (lock_ == nullptr)
+  if (!histograms_)
     return;
-  base::AutoLock auto_lock(*lock_);
+
+  base::AutoLock auto_lock(lock_.Get());
   g_statistics_recorder_.Get().InitLogOnShutdownWithoutLock();
 }
 
 // static
 void StatisticsRecorder::GetSnapshot(const std::string& query,
                                      Histograms* snapshot) {
-  if (lock_ == NULL)
-    return;
-  base::AutoLock auto_lock(*lock_);
-  if (histograms_ == NULL)
+  base::AutoLock auto_lock(lock_.Get());
+  if (!histograms_)
     return;
 
   for (const auto& entry : *histograms_) {
@@ -376,10 +357,8 @@
     const std::string& name,
     const StatisticsRecorder::OnSampleCallback& cb) {
   DCHECK(!cb.is_null());
-  if (lock_ == NULL)
-    return false;
-  base::AutoLock auto_lock(*lock_);
-  if (histograms_ == NULL)
+  base::AutoLock auto_lock(lock_.Get());
+  if (!histograms_)
     return false;
 
   if (ContainsKey(*callbacks_, name))
@@ -395,10 +374,8 @@
 
 // static
 void StatisticsRecorder::ClearCallback(const std::string& name) {
-  if (lock_ == NULL)
-    return;
-  base::AutoLock auto_lock(*lock_);
-  if (histograms_ == NULL)
+  base::AutoLock auto_lock(lock_.Get());
+  if (!histograms_)
     return;
 
   callbacks_->erase(name);
@@ -412,10 +389,8 @@
 // static
 StatisticsRecorder::OnSampleCallback StatisticsRecorder::FindCallback(
     const std::string& name) {
-  if (lock_ == NULL)
-    return OnSampleCallback();
-  base::AutoLock auto_lock(*lock_);
-  if (histograms_ == NULL)
+  base::AutoLock auto_lock(lock_.Get());
+  if (!histograms_)
     return OnSampleCallback();
 
   auto callback_iterator = callbacks_->find(name);
@@ -425,10 +400,7 @@
 
 // static
 size_t StatisticsRecorder::GetHistogramCount() {
-  if (!lock_)
-    return 0;
-
-  base::AutoLock auto_lock(*lock_);
+  base::AutoLock auto_lock(lock_.Get());
   if (!histograms_)
     return 0;
   return histograms_->size();
@@ -449,7 +421,7 @@
 // static
 void StatisticsRecorder::UninitializeForTesting() {
   // Stop now if it's never been initialized.
-  if (lock_ == NULL || histograms_ == NULL)
+  if (!histograms_)
     return;
 
   // Get the global instance and destruct it. It's held in static memory so
@@ -465,7 +437,7 @@
 
 // static
 void StatisticsRecorder::ImportGlobalPersistentHistograms() {
-  if (lock_ == NULL)
+  if (!histograms_)
     return;
 
   // Import histograms from known persistent storage. Histograms could have
@@ -481,17 +453,7 @@
 // of main(), and hence it is not thread safe.  It initializes globals to
 // provide support for all future calls.
 StatisticsRecorder::StatisticsRecorder() {
-  if (lock_ == NULL) {
-    // This will leak on purpose. It's the only way to make sure we won't race
-    // against the static uninitialization of the module while one of our
-    // static methods relying on the lock get called at an inappropriate time
-    // during the termination phase. Since it's a static data member, we will
-    // leak one per process, which would be similar to the instance allocated
-    // during static initialization and released only on  process termination.
-    lock_ = new base::Lock;
-  }
-
-  base::AutoLock auto_lock(*lock_);
+  base::AutoLock auto_lock(lock_.Get());
 
   existing_histograms_.reset(histograms_);
   existing_callbacks_.reset(callbacks_);
@@ -513,23 +475,18 @@
 
 // static
 void StatisticsRecorder::Reset() {
-  // If there's no lock then there is nothing to reset.
-  if (!lock_)
-    return;
 
   std::unique_ptr<HistogramMap> histograms_deleter;
   std::unique_ptr<CallbackMap> callbacks_deleter;
   std::unique_ptr<RangesMap> ranges_deleter;
-  // We don't delete lock_ on purpose to avoid having to properly protect
-  // against it going away after we checked for NULL in the static methods.
   {
-    base::AutoLock auto_lock(*lock_);
+    base::AutoLock auto_lock(lock_.Get());
     histograms_deleter.reset(histograms_);
     callbacks_deleter.reset(callbacks_);
     ranges_deleter.reset(ranges_);
-    histograms_ = NULL;
-    callbacks_ = NULL;
-    ranges_ = NULL;
+    histograms_ = nullptr;
+    callbacks_ = nullptr;
+    ranges_ = nullptr;
   }
   // We are going to leak the histograms and the ranges.
 }
@@ -543,12 +500,13 @@
 
 
 // static
-StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL;
+StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = nullptr;
 // static
-StatisticsRecorder::CallbackMap* StatisticsRecorder::callbacks_ = NULL;
+StatisticsRecorder::CallbackMap* StatisticsRecorder::callbacks_ = nullptr;
 // static
-StatisticsRecorder::RangesMap* StatisticsRecorder::ranges_ = NULL;
+StatisticsRecorder::RangesMap* StatisticsRecorder::ranges_ = nullptr;
 // static
-base::Lock* StatisticsRecorder::lock_ = NULL;
+base::LazyInstance<base::Lock>::Leaky StatisticsRecorder::lock_ =
+    LAZY_INSTANCE_INITIALIZER;
 
 }  // namespace base
diff --git a/base/metrics/statistics_recorder.h b/base/metrics/statistics_recorder.h
index b4dae87..6deddae 100644
--- a/base/metrics/statistics_recorder.h
+++ b/base/metrics/statistics_recorder.h
@@ -25,11 +25,11 @@
 #include "base/macros.h"
 #include "base/metrics/histogram_base.h"
 #include "base/strings/string_piece.h"
+#include "base/synchronization/lock.h"
 
 namespace base {
 
 class BucketRanges;
-class Lock;
 
 class BASE_EXPORT StatisticsRecorder {
  public:
@@ -230,8 +230,11 @@
   static CallbackMap* callbacks_;
   static RangesMap* ranges_;
 
-  // Lock protects access to above maps.
-  static base::Lock* lock_;
+  // Lock protects access to above maps. This is a LazyInstance to avoid races
+  // when the above methods are used before Initialize(). Previously each method
+  // would do |if (!lock_) return;| which would race with
+  // |lock_ = new Lock;| in StatisticsRecorder(). http://crbug.com/672852.
+  static base::LazyInstance<base::Lock>::Leaky lock_;
 
   DISALLOW_COPY_AND_ASSIGN(StatisticsRecorder);
 };
diff --git a/base/numerics/safe_conversions_impl.h b/base/numerics/safe_conversions_impl.h
index 33d86bc..c4d96365 100644
--- a/base/numerics/safe_conversions_impl.h
+++ b/base/numerics/safe_conversions_impl.h
@@ -54,7 +54,7 @@
 template <typename T>
 constexpr T SafeUnsignedAbsImpl(T value, T sign_mask) {
   static_assert(!std::is_signed<T>::value, "Types must be unsigned.");
-  return (value + sign_mask) ^ sign_mask;
+  return (value ^ sign_mask) - sign_mask;
 }
 
 template <typename T,
diff --git a/build/android/resource_sizes.py b/build/android/resource_sizes.py
index 56e5a496..6df35fd 100755
--- a/build/android/resource_sizes.py
+++ b/build/android/resource_sizes.py
@@ -184,7 +184,8 @@
     return len(self._zip_infos)
 
   def FindByPattern(self, pattern):
-    return next(i for i in self._zip_infos if re.match(pattern, i.filename))
+    return next((i for i in self._zip_infos if re.match(pattern, i.filename)),
+                None)
 
   def FindLargest(self):
     return max(self._zip_infos, key=lambda i: i.file_size)
@@ -366,6 +367,9 @@
   print 'Total uncompressed size: %s' % _FormatBytes(total_file_size)
   print
 
+  if not paks:
+    return
+
   # Output the table of details about all pak files.
   print '%25s%11s%21s%21s' % (
       'FILENAME', 'RESOURCES', 'COMPRESSED SIZE', 'UNCOMPRESSED SIZE')
diff --git a/build/config/BUILD.gn b/build/config/BUILD.gn
index 6cb4134..17e1a61 100644
--- a/build/config/BUILD.gn
+++ b/build/config/BUILD.gn
@@ -136,9 +136,6 @@
   if (!enable_nacl) {
     defines += [ "DISABLE_NACL" ]
   }
-  if (enable_rlz) {
-    defines += [ "ENABLE_RLZ" ]
-  }
   if (enable_wayland_server) {
     defines += [ "ENABLE_WAYLAND_SERVER=1" ]
   }
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index fae310a..f3a6962 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -840,6 +840,11 @@
     }
 
     cflags += [
+      # Assume UTF-8 by default to avoid code page dependencies.
+      "/utf-8",
+    ]
+
+    cflags += [
       # Warnings permanently disabled:
 
       # C4091: 'typedef ': ignored on left of 'X' when no variable is
@@ -1070,9 +1075,6 @@
 config("chromium_code") {
   if (is_win) {
     cflags = [ "/W4" ]  # Warning level 4.
-
-    # Assume UTF-8 by default to avoid code page dependencies.
-    cflags += [ "/utf-8" ]
   } else {
     cflags = [ "-Wall" ]
     if (treat_warnings_as_errors) {
diff --git a/build/config/features.gni b/build/config/features.gni
index 9128af4..44fa391 100644
--- a/build/config/features.gni
+++ b/build/config/features.gni
@@ -79,11 +79,6 @@
 
 # Additional dependent variables -----------------------------------------------
 
-# Whether we are using the rlz library or not.  Platforms like Android send
-# rlz codes for searches but do not use the library.
-enable_rlz_support = is_win || is_mac || is_ios || is_chromeos
-enable_rlz = is_chrome_branded && enable_rlz_support
-
 # Chrome OS: whether to also build the upcoming version of
 # ChromeVox, which can then be enabled via a command-line switch.
 enable_chromevox_next = false
diff --git a/cc/output/overlay_candidate.cc b/cc/output/overlay_candidate.cc
index b528488..64ee2a5 100644
--- a/cc/output/overlay_candidate.cc
+++ b/cc/output/overlay_candidate.cc
@@ -335,4 +335,9 @@
 OverlayCandidateList& OverlayCandidateList::operator=(
     OverlayCandidateList&& other) = default;
 
+void OverlayCandidateList::AddPromotionHint(const OverlayCandidate& candidate) {
+  promotion_hint_info_map_[candidate.resource_id] =
+      candidate.display_rect.origin();
+}
+
 }  // namespace cc
diff --git a/cc/output/overlay_candidate.h b/cc/output/overlay_candidate.h
index 68d62e3..e35299ded 100644
--- a/cc/output/overlay_candidate.h
+++ b/cc/output/overlay_candidate.h
@@ -5,6 +5,7 @@
 #ifndef CC_OUTPUT_OVERLAY_CANDIDATE_H_
 #define CC_OUTPUT_OVERLAY_CANDIDATE_H_
 
+#include <map>
 #include <vector>
 
 #include "cc/base/cc_export.h"
@@ -114,9 +115,15 @@
   OverlayCandidateList& operator=(const OverlayCandidateList&);
   OverlayCandidateList& operator=(OverlayCandidateList&&);
 
+  // [id] == origin of candidate's |display_rect| for all promotable resources.
+  using PromotionHintInfoMap = std::map<ResourceId, gfx::PointF>;
+
   // For android, this provides a set of resources that could be promoted to
   // overlay, if one backs them with a SurfaceView.
-  ResourceIdSet promotable_resource_hints_;
+  PromotionHintInfoMap promotion_hint_info_map_;
+
+  // Helper to insert |candidate| into |promotion_hint_info_|.
+  void AddPromotionHint(const OverlayCandidate& candidate);
 };
 
 }  // namespace cc
diff --git a/cc/output/overlay_processor.cc b/cc/output/overlay_processor.cc
index 472b0c2..88523d6 100644
--- a/cc/output/overlay_processor.cc
+++ b/cc/output/overlay_processor.cc
@@ -24,7 +24,7 @@
       : resource_provider_(resource_provider), candidates_(candidates) {}
   ~SendPromotionHintsBeforeReturning() {
     resource_provider_->SendPromotionHints(
-        candidates_->promotable_resource_hints_);
+        candidates_->promotion_hint_info_map_);
   }
 
  private:
diff --git a/cc/output/overlay_strategy_underlay.cc b/cc/output/overlay_strategy_underlay.cc
index e509189..e08c40d 100644
--- a/cc/output/overlay_strategy_underlay.cc
+++ b/cc/output/overlay_strategy_underlay.cc
@@ -52,14 +52,14 @@
       // we can only promote a single quad.  Otherwise, somebody might try to
       // back one of the promotable quads with a SurfaceView, and either it or
       // |candidate| would have to fall back to a texture.
-      candidate_list->promotable_resource_hints_.clear();
-      candidate_list->promotable_resource_hints_.insert(candidate.resource_id);
+      candidate_list->promotion_hint_info_map_.clear();
+      candidate_list->AddPromotionHint(candidate);
       return true;
     } else {
       // If |candidate| should get a promotion hint, then rememeber that now.
-      candidate_list->promotable_resource_hints_.insert(
-          new_candidate_list.promotable_resource_hints_.begin(),
-          new_candidate_list.promotable_resource_hints_.end());
+      candidate_list->promotion_hint_info_map_.insert(
+          new_candidate_list.promotion_hint_info_map_.begin(),
+          new_candidate_list.promotion_hint_info_map_.end());
     }
   }
 
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc
index b5ee7a99..6547109d 100644
--- a/cc/resources/resource_provider.cc
+++ b/cc/resources/resource_provider.cc
@@ -1677,18 +1677,30 @@
 
 #if defined(OS_ANDROID)
 void ResourceProvider::SendPromotionHints(
-    const ResourceIdSet& promotable_hints) {
+    const OverlayCandidateList::PromotionHintInfoMap& promotion_hints) {
+  GLES2Interface* gl = ContextGL();
+  if (!gl)
+    return;
+
   for (const auto& id : wants_promotion_hints_set_) {
+    const ResourceMap::iterator it = resources_.find(id);
+    if (it == resources_.end())
+      continue;
+
+    if (it->second.marked_for_deletion)
+      continue;
+
     const Resource* resource = LockForRead(id);
     DCHECK(resource->wants_promotion_hint);
 
     // Insist that this is backed by a GPU texture.
     if (IsGpuResourceType(resource->type)) {
       DCHECK(resource->gl_id);
-      // TODO(liberato): Here we would either construct a set to send all at
-      // once, or send the promotion hint individually to resource->gl_id, based
-      // on whether promtable_hints.count(it->first) > 0 .
-      // crbug.com/671357
+      auto iter = promotion_hints.find(id);
+      bool promotable = iter != promotion_hints.end();
+      gl->OverlayPromotionHintCHROMIUM(resource->gl_id, promotable,
+                                       promotable ? iter->second.x() : 0,
+                                       promotable ? iter->second.y() : 0);
     }
     UnlockForRead(id);
   }
diff --git a/cc/resources/resource_provider.h b/cc/resources/resource_provider.h
index 5d7ae6f..a9834ca 100644
--- a/cc/resources/resource_provider.h
+++ b/cc/resources/resource_provider.h
@@ -208,10 +208,11 @@
 
 #if defined(OS_ANDROID)
   // Send an overlay promotion hint to all resources that requested it via
-  // |want_promotion_hint|.  |promotable_hints| contains all the resources that
-  // should be told that they're promotable.  Others will be told that they're
-  // not promotable right now.
-  void SendPromotionHints(const ResourceIdSet& promotable_hints);
+  // |wants_promotion_hints_set_|.  |promotable_hints| contains all the
+  // resources that should be told that they're promotable.  Others will be told
+  // that they're not promotable right now.
+  void SendPromotionHints(
+      const OverlayCandidateList::PromotionHintInfoMap& promotion_hints);
 #endif
 
   // The following lock classes are part of the ResourceProvider API and are
diff --git a/cc/tiles/picture_layer_tiling.cc b/cc/tiles/picture_layer_tiling.cc
index 74804dc..d582cb86 100644
--- a/cc/tiles/picture_layer_tiling.cc
+++ b/cc/tiles/picture_layer_tiling.cc
@@ -156,17 +156,14 @@
     SetLiveTilesRect(pending_twin->live_tiles_rect());
   }
 
-  if (tiles_.empty()) {
-    tiles_.swap(pending_twin->tiles_);
-    all_tiles_done_ = pending_twin->all_tiles_done_;
-  } else {
-    while (!pending_twin->tiles_.empty()) {
-      auto pending_iter = pending_twin->tiles_.begin();
-      tiles_[pending_iter->first] = std::move(pending_iter->second);
-      pending_twin->tiles_.erase(pending_iter);
-    }
-    all_tiles_done_ &= pending_twin->all_tiles_done_;
+  while (!pending_twin->tiles_.empty()) {
+    auto pending_iter = pending_twin->tiles_.begin();
+    pending_iter->second->set_tiling(this);
+    tiles_[pending_iter->first] = std::move(pending_iter->second);
+    pending_twin->tiles_.erase(pending_iter);
   }
+  all_tiles_done_ &= pending_twin->all_tiles_done_;
+
   DCHECK(pending_twin->tiles_.empty());
   pending_twin->all_tiles_done_ = true;
 
@@ -323,7 +320,7 @@
   tile_rect.set_size(tiling_data_.max_texture_size());
   gfx::Rect enclosing_layer_rect = gfx::ScaleToEnclosingRect(
       tile_rect, 1.f / raster_scales_.width(), 1.f / raster_scales_.height());
-  return Tile::CreateInfo(i, j, enclosing_layer_rect, tile_rect,
+  return Tile::CreateInfo(this, i, j, enclosing_layer_rect, tile_rect,
                           raster_scales_);
 }
 
diff --git a/cc/tiles/picture_layer_tiling_unittest.cc b/cc/tiles/picture_layer_tiling_unittest.cc
index 3291a33e..a861e87 100644
--- a/cc/tiles/picture_layer_tiling_unittest.cc
+++ b/cc/tiles/picture_layer_tiling_unittest.cc
@@ -1062,5 +1062,32 @@
   VerifyTilesExactlyCoverRect(dest_scale, gfx::Rect(10001, 2));
 }
 
+TEST_F(PictureLayerTilingIteratorTest, TilesStoreTilings) {
+  gfx::Size bounds(200, 200);
+  Initialize(gfx::Size(100, 100), 1.f, bounds);
+  SetLiveRectAndVerifyTiles(gfx::Rect(bounds));
+
+  // Get all tiles and ensure they are associated with |tiling_|.
+  std::vector<Tile*> tiles = tiling_->AllTilesForTesting();
+  EXPECT_TRUE(tiles.size());
+  for (const auto* tile : tiles) {
+    EXPECT_EQ(tile->tiling(), tiling_.get());
+  }
+
+  // Create an active tiling, transfer tiles to that tiling, and ensure that
+  // the tiles have their tiling updated.
+  scoped_refptr<FakeRasterSource> raster_source =
+      FakeRasterSource::CreateFilled(bounds);
+  auto active_tiling = TestablePictureLayerTiling::Create(
+      ACTIVE_TREE, 1.f, raster_source, &client_, LayerTreeSettings());
+  active_tiling->set_resolution(HIGH_RESOLUTION);
+
+  active_tiling->TakeTilesAndPropertiesFrom(tiling_.get(),
+                                            Region(gfx::Rect(bounds)));
+  for (const auto* tile : tiles) {
+    EXPECT_EQ(tile->tiling(), active_tiling.get());
+  }
+}
+
 }  // namespace
 }  // namespace cc
diff --git a/cc/tiles/tile.cc b/cc/tiles/tile.cc
index 1ed26bb4..0dbee11 100644
--- a/cc/tiles/tile.cc
+++ b/cc/tiles/tile.cc
@@ -23,6 +23,7 @@
            int source_frame_number,
            int flags)
     : tile_manager_(tile_manager),
+      tiling_(info.tiling),
       content_rect_(info.content_rect),
       enclosing_layer_rect_(info.enclosing_layer_rect),
       raster_scales_(info.raster_scales),
diff --git a/cc/tiles/tile.h b/cc/tiles/tile.h
index 8da46d6..aecd220b2 100644
--- a/cc/tiles/tile.h
+++ b/cc/tiles/tile.h
@@ -17,6 +17,7 @@
 
 namespace cc {
 
+class PictureLayerTiling;
 class TileManager;
 
 class CC_EXPORT Tile {
@@ -28,18 +29,21 @@
 
   class CC_EXPORT CreateInfo {
    public:
+    const PictureLayerTiling* tiling;
     int tiling_i_index;
     int tiling_j_index;
     gfx::Rect enclosing_layer_rect;
     gfx::Rect content_rect;
     gfx::SizeF raster_scales;
 
-    CreateInfo(int tiling_i_index,
+    CreateInfo(const PictureLayerTiling* tiling,
+               int tiling_i_index,
                int tiling_j_index,
                const gfx::Rect& enclosing_layer_rect,
                const gfx::Rect& content_rect,
                const gfx::SizeF& raster_scales)
-        : tiling_i_index(tiling_i_index),
+        : tiling(tiling),
+          tiling_i_index(tiling_i_index),
           tiling_j_index(tiling_j_index),
           enclosing_layer_rect(enclosing_layer_rect),
           content_rect(content_rect),
@@ -113,6 +117,9 @@
     return is_solid_color_analysis_performed_;
   }
 
+  const PictureLayerTiling* tiling() const { return tiling_; }
+  void set_tiling(const PictureLayerTiling* tiling) { tiling_ = tiling; }
+
  private:
   friend class TileManager;
   friend class FakeTileManager;
@@ -127,6 +134,7 @@
   ~Tile();
 
   TileManager* const tile_manager_;
+  const PictureLayerTiling* tiling_;
   const gfx::Rect content_rect_;
   const gfx::Rect enclosing_layer_rect_;
   const gfx::SizeF raster_scales_;
diff --git a/cc/tiles/tile_manager.cc b/cc/tiles/tile_manager.cc
index 08796a3..5a9d737 100644
--- a/cc/tiles/tile_manager.cc
+++ b/cc/tiles/tile_manager.cc
@@ -1071,7 +1071,10 @@
   // have to iterate the queue to check whether the required tiles are ready to
   // draw.
   for (; !raster_priority_queue->IsEmpty(); raster_priority_queue->Pop()) {
-    if (!raster_priority_queue->Top().tile()->draw_info().IsReadyToDraw())
+    const auto& prioritized_tile = raster_priority_queue->Top();
+    // TODO(vmpstr): Check to debug crbug.com/622080. Remove when fixed.
+    CHECK_EQ(prioritized_tile.priority().priority_bin, TilePriority::NOW);
+    if (!prioritized_tile.tile()->draw_info().IsReadyToDraw())
       return false;
   }
 
diff --git a/chrome/VERSION b/chrome/VERSION
index c9e16c40..5a8746b 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=57
 MINOR=0
-BUILD=2950
+BUILD=2951
 PATCH=0
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml
index 019ff6dd..02ecd0d 100644
--- a/chrome/android/java/AndroidManifest.xml
+++ b/chrome/android/java/AndroidManifest.xml
@@ -847,7 +847,7 @@
             {{sandboxed_service_extra_flags|default('')}} />
         {% endfor %}
 
-        {% set num_privileged_services = 20 %}
+        {% set num_privileged_services = 3 %}
         <meta-data android:name="org.chromium.content.browser.NUM_PRIVILEGED_SERVICES"
             android:value="{{ num_privileged_services }}"/>
         {% for i in range(num_privileged_services) %}
diff --git a/chrome/android/java/res/layout/history_header.xml b/chrome/android/java/res/layout/history_header.xml
new file mode 100644
index 0000000..3b9e28b
--- /dev/null
+++ b/chrome/android/java/res/layout/history_header.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical" >
+
+    <TextView
+        android:id="@+id/signed_in_not_synced"
+        style="@style/PrivacyDisclaimerText" />
+
+   <TextView
+        android:id="@+id/signed_in_synced"
+        style="@style/PrivacyDisclaimerText" />
+
+   <TextView
+        android:id="@+id/other_forms_of_browsing_history"
+        style="@style/PrivacyDisclaimerText"  />
+
+    <Button
+        android:id="@+id/clear_browsing_data_button"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="16dp"
+        style="@style/ButtonCompatBorderless"
+        android:paddingTop="16dp"
+        android:paddingBottom="16dp"
+        android:paddingStart="16dp"
+        android:paddingEnd="16dp"
+        android:gravity="center_vertical|start"
+        android:text="@string/open_clear_browsing_data_dialog_button"
+        android:textAllCaps="true"
+        android:textColor="@color/light_active_color"
+        android:textSize="16sp" />
+</LinearLayout>
\ No newline at end of file
diff --git a/chrome/android/java/res/values-v17/styles.xml b/chrome/android/java/res/values-v17/styles.xml
index a7605df..4c19ba9 100644
--- a/chrome/android/java/res/values-v17/styles.xml
+++ b/chrome/android/java/res/values-v17/styles.xml
@@ -582,6 +582,15 @@
         <item name="android:textColor">@android:color/white</item>
         <item name="android:textSize">20sp</item>
     </style>
+    <style name="PrivacyDisclaimerText">
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:layout_marginTop">16dp</item>
+        <item name="android:paddingStart">16dp</item>
+        <item name="android:paddingEnd">16dp</item>
+        <item name="android:textSize">16sp</item>
+        <item name="android:visibility">gone</item>
+    </style>
 
     <!-- New tab page RecyclerView overscroll color -->
     <style name="NewTabPageRecyclerView">
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java
index d28f6f4..ad559ad 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java
@@ -60,6 +60,7 @@
 import org.chromium.chrome.browser.tabmodel.document.DocumentTabModelSelector;
 import org.chromium.chrome.browser.tabmodel.document.StorageDelegate;
 import org.chromium.chrome.browser.tabmodel.document.TabDelegate;
+import org.chromium.chrome.browser.webapps.GooglePlayWebApkInstallDelegate;
 import org.chromium.components.signin.AccountManagerDelegate;
 import org.chromium.components.signin.SystemAccountManagerDelegate;
 import org.chromium.content.app.ContentApplication;
@@ -391,8 +392,13 @@
         return null;
     }
 
+    /** Returns the singleton instance of GooglePlayWebApkInstallDelegate. */
+    public GooglePlayWebApkInstallDelegate getGooglePlayWebApkInstallDelegate() {
+        return null;
+    }
+
     /**
-     * Returns the Singleton instance of the DocumentTabModelSelector.
+     * Returns the singleton instance of the DocumentTabModelSelector.
      * TODO(dfalcantara): Find a better place for this once we differentiate between activity and
      *                    application-level TabModelSelectors.
      * @return The DocumentTabModelSelector for the application.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index 853aabd..2a09616 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -369,7 +369,7 @@
             ChromePreferenceManager preferenceManager = ChromePreferenceManager.getInstance(this);
             // Promos can only be shown when we start with ACTION_MAIN intent and
             // after FRE is complete.
-            if (!mIntentWithEffect && FirstRunStatus.getFirstRunFlowComplete(this)) {
+            if (!mIntentWithEffect && FirstRunStatus.getFirstRunFlowComplete()) {
                 // Only show promos on the second oppurtunity. This is because we show FRE on the
                 // first oppurtunity, and we don't want to show such content back to back.
                 if (preferenceManager.getPromosSkippedOnFirstStart()) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/EmbedContentViewActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/EmbedContentViewActivity.java
index b6f5918..73601036 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/EmbedContentViewActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/EmbedContentViewActivity.java
@@ -86,7 +86,7 @@
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
         boolean retVal = super.onCreateOptionsMenu(menu);
-        if (!FirstRunStatus.getFirstRunFlowComplete(this)) return retVal;
+        if (!FirstRunStatus.getFirstRunFlowComplete()) return retVal;
         return true;
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillKeyboardAccessoryBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillKeyboardAccessoryBridge.java
index a01f2f7..a2109ba 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillKeyboardAccessoryBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillKeyboardAccessoryBridge.java
@@ -144,13 +144,15 @@
      *                 empty too.
      * @param iconId The resource ID for the icon associated with the suggestion, or 0 for no icon.
      * @param suggestionId Identifier for the suggestion type.
+     * @param isDeletable Whether the item can be deleted by the user.
      */
     @CalledByNative
     private static void addToAutofillSuggestionArray(AutofillSuggestion[] array, int index,
-            String label, String sublabel, int iconId, int suggestionId, boolean deletable) {
+            String label, String sublabel, int iconId, int suggestionId, boolean isDeletable) {
         int drawableId = iconId == 0 ? DropdownItem.NO_ICON : ResourceId.mapToDrawableId(iconId);
-        array[index] =
-                new AutofillSuggestion(label, sublabel, drawableId, suggestionId, deletable, false);
+        array[index] = new AutofillSuggestion(label, sublabel, drawableId,
+                false /* isIconAtStart */, suggestionId, isDeletable, false /* isMultilineLabel */,
+                false /* isBoldLabel */);
     }
 
     private native void nativeViewDismissed(long nativeAutofillKeyboardAccessoryView);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java
index 8266579..b5adb643 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java
@@ -92,10 +92,19 @@
     /**
      * Shows an Autofill popup with specified suggestions.
      * @param suggestions Autofill suggestions to be displayed.
+     * @param isRtl @code true if right-to-left text.
+     * @param backgroundColor popup background color, or {@code Color.TRANSPARENT} if not specified
+     * in experiment.
+     * @param dividerColor color for divider between popup items, or {@code Color.TRANSPARENT} if
+     * not specified in experiment.
+     * @param dropdownItemHeight height of each dropdown item in dimension independent pixel units,
+     * 0 if not specified in experiment.
      */
     @CalledByNative
-    private void show(AutofillSuggestion[] suggestions, boolean isRtl) {
-        if (mAutofillPopup != null) mAutofillPopup.filterAndShow(suggestions, isRtl);
+    private void show(AutofillSuggestion[] suggestions, boolean isRtl, int backgroundColor,
+            int dividerColor, int dropdownItemHeight) {
+        if (mAutofillPopup != null) mAutofillPopup.filterAndShow(suggestions, isRtl,
+                backgroundColor, dividerColor, dropdownItemHeight);
     }
 
     @CalledByNative
@@ -122,17 +131,20 @@
      * @param label First line of the suggestion.
      * @param sublabel Second line of the suggestion.
      * @param iconId The resource ID for the icon associated with the suggestion, or 0 for no icon.
+     * @param isIconAtStart {@code true} if {@param iconId} is displayed before {@param label}.
      * @param suggestionId Identifier for the suggestion type.
-     * @param deletable Whether this item is deletable.
+     * @param isDeletable Whether the item can be deleted by the user.
      * @param isLabelMultiline Whether the label should be should over multiple lines.
+     * @param isLabelBold true if {@param label} should be displayed in {@code Typeface.BOLD},
+     * false if {@param label} should be displayed in {@code Typeface.NORMAL}.
      */
     @CalledByNative
     private static void addToAutofillSuggestionArray(AutofillSuggestion[] array, int index,
-            String label, String sublabel, int iconId, int suggestionId, boolean deletable,
-            boolean isLabelMultiline) {
+            String label, String sublabel, int iconId, boolean isIconAtStart,
+            int suggestionId, boolean isDeletable, boolean isLabelMultiline, boolean isLabelBold) {
         int drawableId = iconId == 0 ? DropdownItem.NO_ICON : ResourceId.mapToDrawableId(iconId);
-        array[index] = new AutofillSuggestion(
-                label, sublabel, drawableId, suggestionId, deletable, isLabelMultiline);
+        array[index] = new AutofillSuggestion(label, sublabel, drawableId, isIconAtStart,
+                suggestionId, isDeletable, isLabelMultiline, isLabelBold);
     }
 
     private native void nativeSuggestionSelected(long nativeAutofillPopupViewAndroid,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/StaticLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/StaticLayout.java
index da3aef700..d3234658 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/StaticLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/StaticLayout.java
@@ -233,8 +233,8 @@
         LayoutTab layoutTab = tabs[0];
         final float dpToPx = getContext().getResources().getDisplayMetrics().density;
 
-        mSceneLayer.update(dpToPx, contentViewport, layerTitleCache, tabContentManager,
-                fullscreenManager, layoutTab);
+        mSceneLayer.update(
+                dpToPx, layerTitleCache, tabContentManager, fullscreenManager, layoutTab);
 
         // TODO(dtrainor): Find the best way to properly track this metric for cold starts.
         // We should probably erase the thumbnail when we select a tab that we need to restore.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/StaticTabSceneLayer.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/StaticTabSceneLayer.java
index 20f5212..647c584 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/StaticTabSceneLayer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/StaticTabSceneLayer.java
@@ -4,8 +4,6 @@
 
 package org.chromium.chrome.browser.compositor.scene_layer;
 
-import android.graphics.RectF;
-
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.chrome.browser.compositor.LayerTitleCache;
 import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab;
@@ -37,7 +35,7 @@
      * @param fullscreenManager The FullscreenManager.
      * @param layoutTab         The LayoutTab.
      */
-    public void update(float dpToPx, RectF contentViewport, LayerTitleCache layerTitleCache,
+    public void update(float dpToPx, LayerTitleCache layerTitleCache,
             TabContentManager tabContentManager, ChromeFullscreenManager fullscreenManager,
             LayoutTab layoutTab) {
         if (layoutTab == null) {
@@ -46,16 +44,13 @@
 
         float contentOffset =
                 fullscreenManager != null ? fullscreenManager.getContentOffset() : 0.f;
+        float x = layoutTab.getRenderX() * dpToPx;
+        float y = contentOffset + layoutTab.getRenderY() * dpToPx;
 
-        // TODO(dtrainor, clholgat): remove "* dpToPx" once the native part is fully supporting dp.
-        nativeUpdateTabLayer(mNativePtr, contentViewport.left, contentViewport.top,
-                contentViewport.width(), contentViewport.height(), tabContentManager,
-                layoutTab.getId(), mResToolbarControlContainer, layoutTab.canUseLiveTexture(),
-                layoutTab.getBackgroundColor(), layoutTab.getRenderX() * dpToPx,
-                layoutTab.getRenderY() * dpToPx, layoutTab.getScaledContentWidth() * dpToPx,
-                layoutTab.getScaledContentHeight() * dpToPx, contentOffset,
-                layoutTab.getStaticToViewBlend(), layoutTab.getSaturation(),
-                layoutTab.getBrightness());
+        nativeUpdateTabLayer(mNativePtr, tabContentManager, layoutTab.getId(),
+                mResToolbarControlContainer, layoutTab.canUseLiveTexture(),
+                layoutTab.getBackgroundColor(), x, y, layoutTab.getStaticToViewBlend(),
+                layoutTab.getSaturation(), layoutTab.getBrightness());
     }
 
     @Override
@@ -73,10 +68,8 @@
     }
 
     private native long nativeInit();
-    private native void nativeUpdateTabLayer(long nativeStaticTabSceneLayer, float contentViewportX,
-            float contentViewportY, float contentViewportWidth, float contentViewportHeight,
+    private native void nativeUpdateTabLayer(long nativeStaticTabSceneLayer,
             TabContentManager tabContentManager, int id, int toolbarResourceId,
-            boolean canUseLiveLayer, int backgroundColor, float x, float y, float width,
-            float height, float contentOffsetY, float staticToViewBlend, float saturation,
-            float brightness);
+            boolean canUseLiveLayer, int backgroundColor, float x, float y, float staticToViewBlend,
+            float saturation, float brightness);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapter.java
index 43f99ff..3dbf079 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapter.java
@@ -340,6 +340,7 @@
         mRegularDownloadItems.filter(mFilter, mFilteredItems);
         mIncognitoDownloadItems.filter(mFilter, mFilteredItems);
         mOfflinePageItems.filter(mFilter, mFilteredItems);
+        clear(false);
         loadItems(mFilteredItems);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java
index 0f669c0..9b4b03b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java
@@ -260,7 +260,7 @@
         UmaUtils.recordForegroundStartTime();
         stopProgressionIfNotAcceptedTermsOfService();
         if (!mFreProperties.getBoolean(EXTRA_USE_FRE_FLOW_SEQUENCER)) {
-            if (FirstRunStatus.getFirstRunFlowComplete(this)) {
+            if (FirstRunStatus.getFirstRunFlowComplete()) {
                 // This is a parallel flow that needs to be refreshed/re-fired.
                 // Signal the FRE flow completion and re-launch the original intent.
                 completeFirstRunExperience();
@@ -403,7 +403,7 @@
         // If default is true then it corresponds to opt-out and false corresponds to opt-in.
         UmaUtils.recordMetricsReportingDefaultOptIn(!DEFAULT_METRICS_AND_CRASH_REPORTING);
         sGlue.acceptTermsOfService(allowCrashUpload);
-        FirstRunStatus.setSkipWelcomePage(FirstRunActivity.this, true);
+        FirstRunStatus.setSkipWelcomePage(true);
         flushPersistentData();
         stopProgressionIfNotAcceptedTermsOfService();
         jumpToPage(mPager.getCurrentItem() + 1);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java
index 452f352b..84a67b82 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java
@@ -86,7 +86,7 @@
 
     @VisibleForTesting
     protected boolean isFirstRunFlowComplete() {
-        return FirstRunStatus.getFirstRunFlowComplete(mActivity);
+        return FirstRunStatus.getFirstRunFlowComplete();
     }
 
     @VisibleForTesting
@@ -263,13 +263,13 @@
                 fromIntent != null && TextUtils.equals(fromIntent.getAction(), Intent.ACTION_MAIN);
         if (!fromChromeIcon && ToSAckedReceiver.checkAnyUserHasSeenToS(context)) return null;
 
-        final boolean baseFreComplete = FirstRunStatus.getFirstRunFlowComplete(context);
+        final boolean baseFreComplete = FirstRunStatus.getFirstRunFlowComplete();
         if (!baseFreComplete) {
             if (forLightweightFre
                     && CommandLine.getInstance().hasSwitch(
                                ChromeSwitches.ENABLE_LIGHTWEIGHT_FIRST_RUN_EXPERIENCE)) {
-                if (!FirstRunStatus.shouldSkipWelcomePage(context)
-                        && !FirstRunStatus.getLightweightFirstRunFlowComplete(context)) {
+                if (!FirstRunStatus.shouldSkipWelcomePage()
+                        && !FirstRunStatus.getLightweightFirstRunFlowComplete()) {
                     return createLightweightFirstRunIntent(context, fromChromeIcon);
                 }
             } else {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunSignInProcessor.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunSignInProcessor.java
index 47d230ac..b5237c5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunSignInProcessor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunSignInProcessor.java
@@ -58,7 +58,7 @@
         SigninManager signinManager = SigninManager.get(activity.getApplicationContext());
         signinManager.onFirstRunCheckDone();
 
-        boolean firstRunFlowComplete = FirstRunStatus.getFirstRunFlowComplete(activity);
+        boolean firstRunFlowComplete = FirstRunStatus.getFirstRunFlowComplete();
         // We skip signin and the FRE if
         // - FRE is disabled, or
         // - FRE hasn't been completed, but the user has already seen the ToS in the Setup Wizard.
@@ -129,7 +129,7 @@
         Log.e(TAG, "Attempt to pass-through without completed FRE");
 
         // Things went wrong -- we want the user to go through the full FRE.
-        FirstRunStatus.setFirstRunFlowComplete(activity, false);
+        FirstRunStatus.setFirstRunFlowComplete(false);
         setFirstRunFlowSignInComplete(activity, false);
         setFirstRunFlowSignInAccountName(activity, null);
         setFirstRunFlowSignInSetup(activity, false);
@@ -207,7 +207,7 @@
      * @param data Resulting FRE properties bundle
      */
     public static void finalizeFirstRunFlowState(Context context, Bundle data) {
-        FirstRunStatus.setFirstRunFlowComplete(context, true);
+        FirstRunStatus.setFirstRunFlowComplete(true);
         setFirstRunFlowSignInAccountName(context,
                     data.getString(FirstRunActivity.RESULT_SIGNIN_ACCOUNT_NAME));
         setFirstRunFlowSignInSetup(
@@ -221,7 +221,7 @@
     public static void updateSigninManagerFirstRunCheckDone(Context context) {
         SigninManager manager = SigninManager.get(context);
         if (manager.isSignInAllowed()) return;
-        if (!FirstRunStatus.getFirstRunFlowComplete(context)) return;
+        if (!FirstRunStatus.getFirstRunFlowComplete()) return;
         if (!getFirstRunFlowSignInComplete(context)) return;
         manager.onFirstRunCheckDone();
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunStatus.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunStatus.java
index e62fdea0..7558603 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunStatus.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunStatus.java
@@ -4,8 +4,6 @@
 
 package org.chromium.chrome.browser.firstrun;
 
-import android.content.Context;
-
 import org.chromium.base.ContextUtils;
 
 /**
@@ -21,10 +19,9 @@
 
     /**
      * Sets the "main First Run Experience flow complete" preference.
-     * @param context Any context
      * @param isComplete Whether the main First Run Experience flow is complete
      */
-    public static void setFirstRunFlowComplete(Context context, boolean isComplete) {
+    public static void setFirstRunFlowComplete(boolean isComplete) {
         ContextUtils.getAppSharedPreferences()
                 .edit()
                 .putBoolean(FIRST_RUN_FLOW_COMPLETE, isComplete)
@@ -35,35 +32,38 @@
      * Returns whether the main First Run Experience flow is complete.
      * Note: that might NOT include "intro"/"what's new" pages, but it always
      * includes ToS and Sign In pages if necessary.
-     * @param context Any context
      */
-    public static boolean getFirstRunFlowComplete(Context context) {
+    public static boolean getFirstRunFlowComplete() {
         return ContextUtils.getAppSharedPreferences()
                 .getBoolean(FIRST_RUN_FLOW_COMPLETE, false);
     }
 
+    // TODO(tedchoc): Remove once downstream callers migrate to non-param version.
+    public static boolean getFirstRunFlowComplete(
+            @SuppressWarnings("unused") android.content.Context context) {
+        return getFirstRunFlowComplete();
+    }
+
     /**
     * Sets the preference to skip the welcome page from the main First Run Experience.
-    * @param context Any context
-    * @param isSkip Whether the welcome page should be skpped
+     * @param isSkip Whether the welcome page should be skpped
     */
-    public static void setSkipWelcomePage(Context context, boolean isSkip) {
+    public static void setSkipWelcomePage(boolean isSkip) {
         ContextUtils.getAppSharedPreferences().edit().putBoolean(SKIP_WELCOME_PAGE, isSkip).apply();
     }
 
     /**
     * Checks whether the welcome page should be skipped from the main First Run Experience.
     */
-    public static boolean shouldSkipWelcomePage(Context context) {
+    public static boolean shouldSkipWelcomePage() {
         return ContextUtils.getAppSharedPreferences().getBoolean(SKIP_WELCOME_PAGE, false);
     }
 
     /**
      * Sets the "lightweight First Run Experience flow complete" preference.
-     * @param context Any context
      * @param isComplete Whether the lightweight First Run Experience flow is complete
      */
-    public static void setLightweightFirstRunFlowComplete(Context context, boolean isComplete) {
+    public static void setLightweightFirstRunFlowComplete(boolean isComplete) {
         ContextUtils.getAppSharedPreferences()
                 .edit()
                 .putBoolean(LIGHTWEIGHT_FIRST_RUN_FLOW_COMPLETE, isComplete)
@@ -72,9 +72,8 @@
 
     /**
      * Returns whether the "lightweight First Run Experience flow" is complete.
-     * @param context Any context
      */
-    public static boolean getLightweightFirstRunFlowComplete(Context context) {
+    public static boolean getLightweightFirstRunFlowComplete() {
         return ContextUtils.getAppSharedPreferences().getBoolean(
                 LIGHTWEIGHT_FIRST_RUN_FLOW_COMPLETE, false);
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/LightweightFirstRunActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/LightweightFirstRunActivity.java
index a0cba00a..9e03c148 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/LightweightFirstRunActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/LightweightFirstRunActivity.java
@@ -78,7 +78,7 @@
 
     @Override
     public void completeFirstRunExperience() {
-        FirstRunStatus.setLightweightFirstRunFlowComplete(LightweightFirstRunActivity.this, true);
+        FirstRunStatus.setLightweightFirstRunFlowComplete(true);
         Intent intent = new Intent();
         intent.putExtras(mFreProperties);
         finishAllTheActivities(getLocalClassName(), Activity.RESULT_OK, intent);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ToSAndUMAFirstRunFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ToSAndUMAFirstRunFragment.java
index 870b82b9..b44518a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ToSAndUMAFirstRunFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ToSAndUMAFirstRunFragment.java
@@ -104,6 +104,6 @@
 
     @Override
     public boolean shouldSkipPageOnCreate(Context appContext) {
-        return FirstRunStatus.shouldSkipWelcomePage(appContext);
+        return FirstRunStatus.shouldSkipWelcomePage();
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/BrowsingHistoryBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/history/BrowsingHistoryBridge.java
index 3bf3d55b..f044d02 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/BrowsingHistoryBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/BrowsingHistoryBridge.java
@@ -30,6 +30,14 @@
          * via this method.
          */
         public void onHistoryDeleted();
+
+        /**
+         * Called after querying history to indicate whether other forms of browsing history were
+         * found.
+         * @param hasOtherForms Whether other forms of browsing history were found.
+         * @param hasSyncedResults Whether synced results were found.
+         */
+        public void hasOtherFormsOfBrowsingData(boolean hasOtherForms, boolean hasSyncedResults);
     }
 
     private final BrowsingHistoryObserver mObserver;
@@ -114,6 +122,11 @@
         mObserver.onHistoryDeleted();
     }
 
+    @CalledByNative
+    public void hasOtherFormsOfBrowsingData(boolean hasOtherForms, boolean hasSyncedResults) {
+        mObserver.hasOtherFormsOfBrowsingData(hasOtherForms, hasSyncedResults);
+    }
+
     private native long nativeInit(Profile profile);
     private native void nativeDestroy(long nativeBrowsingHistoryBridge);
     private native void nativeQueryHistory(long nativeBrowsingHistoryBridge,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java
index 5ad87ce..6d53e979 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java
@@ -5,28 +5,48 @@
 package org.chromium.chrome.browser.history;
 
 import android.support.v7.widget.RecyclerView.ViewHolder;
+import android.text.SpannableString;
+import android.text.method.LinkMovementMethod;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.View.OnClickListener;
 import android.view.ViewGroup;
+import android.widget.TextView;
 
+import org.chromium.base.ContextUtils;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.history.BrowsingHistoryBridge.BrowsingHistoryObserver;
 import org.chromium.chrome.browser.widget.DateDividedAdapter;
 import org.chromium.chrome.browser.widget.selection.SelectableItemViewHolder;
 import org.chromium.chrome.browser.widget.selection.SelectionDelegate;
+import org.chromium.components.signin.ChromeSigninController;
+import org.chromium.ui.text.NoUnderlineClickableSpan;
+import org.chromium.ui.text.SpanApplier;
 
 import java.util.List;
+import java.util.Locale;
 
 /**
  * Bridges the user's browsing history and the UI used to display it.
  */
 public class HistoryAdapter extends DateDividedAdapter implements BrowsingHistoryObserver {
     private static final String EMPTY_QUERY = "";
+    private static final String LEARN_MORE_LINK =
+            "https://support.google.com/chrome/?p=sync_history&amp;hl="
+                    + Locale.getDefault().toString();
+    private static final String GOOGLE_HISTORY_LINK = "history.google.com";
 
     private final SelectionDelegate<HistoryItem> mSelectionDelegate;
     private final BrowsingHistoryBridge mBridge;
     private final HistoryManager mManager;
 
+    private TextView mSignedInNotSyncedTextView;
+    private TextView mSignedInSyncedTextView;
+    private TextView mOtherFormsOfBrowsingHistoryTextView;
+
+    private boolean mHasOtherFormsOfBrowsingData;
+    private boolean mHasSyncedData;
+    private boolean mHeaderInflated;
     private boolean mDestroyed;
 
     public HistoryAdapter(SelectionDelegate<HistoryItem> delegate, HistoryManager manager) {
@@ -101,7 +121,11 @@
         // destroyed to avoid unnecessary work.
         if (mDestroyed) return;
 
-        loadItems(items);
+        clear(true);
+        if (items.size() > 0) {
+            addHeader();
+            loadItems(items);
+        }
     }
 
     @Override
@@ -111,4 +135,69 @@
         //                    This currently removes all items and re-issues a query.
         initialize();
     }
+
+    @Override
+    public void hasOtherFormsOfBrowsingData(boolean hasOtherForms, boolean hasSyncedResults) {
+        mHasOtherFormsOfBrowsingData = hasOtherForms;
+        mHasSyncedData = hasSyncedResults;
+        setPrivacyDisclaimerVisibility();
+    }
+
+    @Override
+    protected HeaderViewHolder createHeader(ViewGroup parent) {
+        ViewGroup v = (ViewGroup) LayoutInflater.from(parent.getContext()).inflate(
+                R.layout.history_header, parent, false);
+        mHeaderInflated = true;
+
+        View cbdButton = v.findViewById(R.id.clear_browsing_data_button);
+        cbdButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                mManager.openClearBrowsingDataPreference();
+            }
+        });
+
+        mSignedInNotSyncedTextView = (TextView) v.findViewById(R.id.signed_in_not_synced);
+        setPrivacyDisclaimerText(mSignedInNotSyncedTextView,
+                R.string.android_history_no_synced_results, LEARN_MORE_LINK);
+
+        mSignedInSyncedTextView = (TextView) v.findViewById(R.id.signed_in_synced);
+        setPrivacyDisclaimerText(mSignedInSyncedTextView,
+                R.string.android_history_has_synced_results, LEARN_MORE_LINK);
+
+        mOtherFormsOfBrowsingHistoryTextView = (TextView) v.findViewById(
+                R.id.other_forms_of_browsing_history);
+        setPrivacyDisclaimerText(mOtherFormsOfBrowsingHistoryTextView,
+                R.string.android_history_other_forms_of_history, GOOGLE_HISTORY_LINK);
+
+        setPrivacyDisclaimerVisibility();
+
+        return new HeaderViewHolder(v);
+    }
+
+    private void setPrivacyDisclaimerText(TextView view, int stringId, final  String url) {
+        NoUnderlineClickableSpan link = new NoUnderlineClickableSpan() {
+            @Override
+            public void onClick(View view) {
+                mManager.openUrl(url, null, true);
+            }
+        };
+        SpannableString spannable = SpanApplier.applySpans(
+                view.getResources().getString(stringId),
+                new SpanApplier.SpanInfo("<link>", "</link>", link));
+        view.setText(spannable);
+        view.setMovementMethod(LinkMovementMethod.getInstance());
+    }
+
+    private void setPrivacyDisclaimerVisibility() {
+        if (!mHeaderInflated) return;
+
+        boolean isSignedIn =
+                ChromeSigninController.get(ContextUtils.getApplicationContext()).isSignedIn();
+        mSignedInNotSyncedTextView.setVisibility(
+                !mHasSyncedData && isSignedIn ? View.VISIBLE : View.GONE);
+        mSignedInSyncedTextView.setVisibility(mHasSyncedData ? View.VISIBLE : View.GONE);
+        mOtherFormsOfBrowsingHistoryTextView.setVisibility(
+                mHasOtherFormsOfBrowsingData ? View.VISIBLE : View.GONE);
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryItem.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryItem.java
index 8649a27..55263e1e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryItem.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryItem.java
@@ -85,7 +85,7 @@
      * Navigates a tab to this item's URL.
      */
     public void open() {
-        if (mManager != null) mManager.openItem(mUrl, null, false);
+        if (mManager != null) mManager.openUrl(mUrl, null, false);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java
index f2738ad..8a662f0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java
@@ -17,6 +17,8 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.document.ChromeLauncherActivity;
+import org.chromium.chrome.browser.preferences.PreferencesLauncher;
+import org.chromium.chrome.browser.preferences.privacy.ClearBrowsingDataPreferences;
 import org.chromium.chrome.browser.util.IntentUtils;
 import org.chromium.chrome.browser.widget.TintedDrawable;
 import org.chromium.chrome.browser.widget.selection.SelectableListLayout;
@@ -114,14 +116,14 @@
     }
 
     /**
-     * Open the history item.
-     * @param url The URL of the history item.
-     * @param isIncognito Whether to open the history item in an incognito tab. If null, the tab
+     * Open the provided url.
+     * @param url The url to open.
+     * @param isIncognito Whether to open the url in an incognito tab. If null, the tab
      *                    will open in the current tab model.
      * @param createNewTab Whether a new tab should be created. If false, the item will clobber the
      *                     the current tab.
      */
-    public void openItem(String url, Boolean isIncognito, boolean createNewTab) {
+    public void openUrl(String url, Boolean isIncognito, boolean createNewTab) {
         // Construct basic intent.
         Intent viewIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
         viewIntent.putExtra(Browser.EXTRA_APPLICATION_ID,
@@ -151,9 +153,18 @@
         IntentHandler.startActivityForTrustedIntent(viewIntent, mActivity);
     }
 
+    /**
+     * Opens the clear browsing data preference.
+     */
+    public void openClearBrowsingDataPreference() {
+        Intent intent = PreferencesLauncher.createIntentForSettingsPage(mActivity,
+                ClearBrowsingDataPreferences.class.getName());
+        IntentUtils.safeStartActivity(mActivity, intent);
+    }
+
     private void openItemsInNewTabs(List<HistoryItem> items, boolean isIncognito) {
         for (HistoryItem item : items) {
-            openItem(item.getUrl(), isIncognito, true);
+            openUrl(item.getUrl(), isIncognito, true);
         }
     }
 }
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
index 450ca24..461fd50 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
@@ -68,7 +68,7 @@
     private final Intent mEnterVRIntent;
 
     private boolean mVrAvailable;
-    private boolean mDaydreamReadyDevice;
+    private boolean mCardboardSupportOnly;
     private Boolean mVrShellEnabled;
 
     private VrClassesBuilder mVrClassesBuilder;
@@ -90,30 +90,42 @@
     public VrShellDelegate(ChromeTabbedActivity activity) {
         mActivity = activity;
 
-        mVrAvailable = createVrClassesBuilder() && isVrCoreCompatible() && createVrDaydreamApi()
-                && mVrDaydreamApi.isDaydreamReadyDevice();
-        if (mVrAvailable) {
-            mEnterVRIntent = mVrDaydreamApi.createVrIntent(
-                    new ComponentName(mActivity, VR_ACTIVITY_ALIAS));
+        // TODO(bshe): refactor code so that mCardboardSupportOnly does not depend on mVrAvailable
+        // and mVrAvailable does not depend on createVrDaydreamApi.
+        mVrAvailable = createVrClassesBuilder() && isVrCoreCompatible() && createVrDaydreamApi();
+        // Make sure mVrDaydreamApi is created as createVrDaydreamApi might not get called above.
+        if (mVrDaydreamApi == null) createVrDaydreamApi();
+        // Only Cardboard mode is supported on non-daydream devices.
+        mCardboardSupportOnly = !mVrDaydreamApi.isDaydreamReadyDevice();
+
+        if (mVrAvailable && !mCardboardSupportOnly) {
+            mEnterVRIntent =
+                    mVrDaydreamApi.createVrIntent(new ComponentName(mActivity, VR_ACTIVITY_ALIAS));
         } else {
             mEnterVRIntent = null;
         }
-        mTabObserver = new EmptyTabObserver() {
-            @Override
-            public void onContentChanged(Tab tab) {
-                if (tab.getNativePage() != null || tab.isShowingSadTab()) {
-                    // For now we don't handle native pages. crbug.com/661609
-                    shutdownVR(false, true);
+        if (mVrAvailable) {
+            mTabObserver = new EmptyTabObserver() {
+                @Override
+                public void onContentChanged(Tab tab) {
+                    if (tab.getNativePage() != null || tab.isShowingSadTab()) {
+                        // For now we don't handle native pages. crbug.com/661609.
+                        shutdownVR(false, !mCardboardSupportOnly /* showTransition */);
+                    }
                 }
-            }
 
-            @Override
-            public void onWebContentsSwapped(Tab tab, boolean didStartLoad, boolean didFinishLoad) {
-                // TODO(mthiesse): Update the native WebContents pointer and compositor. This
-                // doesn't seem to get triggered in VR Shell currently, but that's likely to change
-                // when we have omnibar navigation.
-            }
-        };
+                @Override
+                public void onWebContentsSwapped(
+                        Tab tab, boolean didStartLoad, boolean didFinishLoad) {
+                    // TODO(mthiesse): Update the native WebContents pointer and compositor. This
+                    // doesn't seem to get triggered in VR Shell currently, but that's likely to
+                    // change
+                    // when we have omnibar navigation.
+                }
+            };
+        } else {
+            mTabObserver = null;
+        }
     }
 
     /**
@@ -149,7 +161,8 @@
      * Handle a VR intent, entering VR in the process unless we're unable to.
      */
     public void enterVRFromIntent(Intent intent) {
-        if (!mVrAvailable) return;
+        // Vr Intent is only used on Daydream devices.
+        if (!mVrAvailable || mCardboardSupportOnly) return;
         assert isVrIntent(intent);
         if (mListeningForWebVrActivateBeforePause && !mRequestedWebVR) {
             nativeDisplayActivate(mNativeVrShellDelegate);
@@ -269,7 +282,7 @@
         if (mInVr) return ENTER_VR_NOT_NECESSARY;
         if (!canEnterVR(mActivity.getActivityTab())) return ENTER_VR_CANCELLED;
 
-        if (!mVrDaydreamApi.isDaydreamCurrentViewer()) {
+        if (mCardboardSupportOnly || !mVrDaydreamApi.isDaydreamCurrentViewer()) {
             // Avoid using launchInVr which would trigger DON flow regardless current viewer type
             // due to the lack of support for unexported activities.
             return enterVR() ? ENTER_VR_SUCCEEDED : ENTER_VR_CANCELLED;
@@ -283,10 +296,16 @@
     private boolean exitWebVR() {
         if (!mInVr) return false;
         mVrShell.setWebVrModeEnabledOnUI(false);
-        // TODO(bajones): Once VR Shell can be invoked outside of WebVR this
-        // should no longer exit the shell outright. Need a way to determine
-        // how VrShell was created.
-        shutdownVR(false, !isVrShellEnabled());
+        if (mCardboardSupportOnly) {
+            // Transition screen is not available for Cardboard only (non-Daydream) devices.
+            // TODO(bshe): Fix this once b/33490788 is fixed.
+            shutdownVR(false, false);
+        } else {
+            // TODO(bajones): Once VR Shell can be invoked outside of WebVR this
+            // should no longer exit the shell outright. Need a way to determine
+            // how VrShell was created.
+            shutdownVR(false, !isVrShellEnabled());
+        }
         return true;
     }
 
@@ -300,7 +319,8 @@
      */
     public void maybeResumeVR() {
         if (!mVrAvailable) return;
-        if (isVrShellEnabled() || mListeningForWebVrActivateBeforePause) {
+        if ((isVrShellEnabled() || mListeningForWebVrActivateBeforePause)
+                && !mCardboardSupportOnly) {
             registerDaydreamIntent();
         }
         // If this is still set, it means the user backed out of the DON flow, and we won't be
@@ -334,7 +354,7 @@
             } finally {
                 StrictMode.setThreadPolicy(oldPolicy);
             }
-        } else if (mVrDaydreamApi.isDaydreamCurrentViewer()
+        } else if (!mCardboardSupportOnly && mVrDaydreamApi.isDaydreamCurrentViewer()
                 && mLastVRExit + REENTER_VR_TIMEOUT_MS > SystemClock.uptimeMillis()) {
             enterVRIfNecessary();
         }
@@ -345,16 +365,19 @@
      */
     public void maybePauseVR() {
         if (!mVrAvailable) return;
-        unregisterDaydreamIntent();
 
-        // When the active web page has a vrdisplayactivate event handler,
-        // mListeningForWebVrActivate should be set to true, which means a vrdisplayactive event
-        // should be fired once DON flow finished. However, DON flow will pause our activity, which
-        // makes the active page becomes invisible. And the event fires before the active page
-        // becomes visible again after DON finished. So here we remember the value of
-        // mListeningForWebVrActivity before pause and use this value to decide if vrdisplayactivate
-        // event should be dispatched in enterVRFromIntent.
-        mListeningForWebVrActivateBeforePause = mListeningForWebVrActivate;
+        if (!mCardboardSupportOnly) {
+            unregisterDaydreamIntent();
+
+            // When the active web page has a vrdisplayactivate event handler,
+            // mListeningForWebVrActivate should be set to true, which means a vrdisplayactive event
+            // should be fired once DON flow finished. However, DON flow will pause our activity,
+            // which makes the active page becomes invisible. And the event fires before the active
+            // page becomes visible again after DON finished. So here we remember the value of
+            // mListeningForWebVrActivity before pause and use this value to decide if
+            // vrdisplayactivate event should be dispatched in enterVRFromIntent.
+            mListeningForWebVrActivateBeforePause = mListeningForWebVrActivate;
+        }
         if (mNonPresentingGvrContext != null) {
             mNonPresentingGvrContext.pause();
         }
@@ -422,7 +445,9 @@
 
     @CalledByNative
     private void setListeningForWebVrActivate(boolean listening) {
-        if (!mVrAvailable) return;
+        // Non-Daydream devices may not have the concept of display activate. So disable
+        // mListeningForWebVrActivate for them.
+        if (!mVrAvailable || mCardboardSupportOnly) return;
         mListeningForWebVrActivate = listening;
         if (listening) {
             registerDaydreamIntent();
@@ -548,10 +573,13 @@
      * @return Whether or not VR Shell is currently enabled.
      */
     public boolean isVrShellEnabled() {
+        // Disable VR Shell for Cardboard only (non-Daydream) devices.
+        // TODO(amp|bshe): Investigate if removing LibraryLoader.isInitialized from the check is
+        // possible.
+        if (!mVrAvailable || mCardboardSupportOnly || !LibraryLoader.isInitialized()) {
+            return false;
+        }
         if (mVrShellEnabled == null) {
-            if (!LibraryLoader.isInitialized()) {
-                return false;
-            }
             mVrShellEnabled = ChromeFeatureList.isEnabled(ChromeFeatureList.VR_SHELL);
         }
         return mVrShellEnabled;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/ChromeWebApkHost.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/ChromeWebApkHost.java
index 1cba919..e315d325 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/ChromeWebApkHost.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/ChromeWebApkHost.java
@@ -10,6 +10,7 @@
 import android.os.StrictMode;
 import android.provider.Settings;
 import android.support.v7.app.AlertDialog;
+import android.text.TextUtils;
 
 import org.chromium.base.CommandLine;
 import org.chromium.base.ContextUtils;
@@ -20,12 +21,16 @@
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.ChromeVersionInfo;
 import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
+import org.chromium.components.variations.VariationsAssociatedData;
 import org.chromium.webapk.lib.client.WebApkValidator;
 
 /**
  * Contains functionality needed for Chrome to host WebAPKs.
  */
 public class ChromeWebApkHost {
+    /** Flag to enable installing WebAPKs using Google Play. */
+    private static final String PLAY_INSTALL = "play_install";
+
     private static final String TAG = "ChromeWebApkHost";
 
     private static Boolean sEnabledForTesting;
@@ -44,15 +49,21 @@
         return isEnabledInPrefs();
     }
 
+    /** Return whether installing WebAPKs using Google Play is enabled. */
+    public static boolean canUseGooglePlayToInstallWebApk() {
+        if (!isEnabled()) return false;
+        return TextUtils.equals(VariationsAssociatedData.getVariationParamValue(
+                ChromeFeatureList.WEBAPKS, PLAY_INSTALL), "true");
+    }
+
     @CalledByNative
     private static boolean areWebApkEnabled() {
         return ChromeWebApkHost.isEnabled();
     }
 
     /**
-     * Check the cached value to figure out if the feature is enabled. We have
-     * to use the cached value because native library may not yet been loaded.
-     *
+     * Check the cached value to figure out if the feature is enabled. We have to use the cached
+     * value because native library may not yet been loaded.
      * @return Whether the feature is enabled.
      */
     private static boolean isEnabledInPrefs() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/GooglePlayWebApkInstallDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/GooglePlayWebApkInstallDelegate.java
new file mode 100644
index 0000000..5bcfc29
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/GooglePlayWebApkInstallDelegate.java
@@ -0,0 +1,54 @@
+// 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.
+
+package org.chromium.chrome.browser.webapps;
+
+import android.support.annotation.IntDef;
+
+import org.chromium.base.Callback;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Defines an interface for installing WebAPKs via Google Play.
+ */
+public interface GooglePlayWebApkInstallDelegate {
+    /**
+     * The app state transitions provided by Google Play during download and installation process.
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({INVALID, DOWNLOAD_PENDING, DOWNLOADING, DOWNLOAD_CANCELLED, DOWNLOAD_ERROR,
+             INSTALLING, INSTALL_ERROR, INSTALLED})
+    public @interface InstallerPackageEvent {}
+    public static final int INVALID = -1;
+    public static final int DOWNLOAD_PENDING = 0;
+    public static final int DOWNLOADING = 1;
+    public static final int DOWNLOAD_CANCELLED = 2;
+    public static final int DOWNLOAD_ERROR = 3;
+    public static final int INSTALLING = 4;
+    public static final int INSTALL_ERROR = 5;
+    public static final int INSTALLED = 6;
+
+    /**
+     * Uses Google Play to install WebAPK asynchronously.
+     * @param packageName The package name of WebAPK to install.
+     * @param version The version of WebAPK to install.
+     * @param title The title of the WebAPK to display during installation.
+     * @param token The token from WebAPK Minter Server.
+     * @param url The start URL of the WebAPK to install.
+     * @param callback The callback to invoke when the install is either completed or failed.
+     * @return True if the install was started. A "true" value does not guarantee that the install
+     *         succeeds.
+     */
+    boolean installAsync(String packageName, int version, String title, String token,
+            String url, Callback<Boolean> callback);
+
+    /**
+     * Calls the callback once the installation either succeeded or failed.
+     * @param packageName The package name of WebAPK for the installation.
+     * @param event The result of the install.
+     */
+    void onGotInstallEvent(String packageName, @InstallerPackageEvent int event);
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInstaller.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInstaller.java
index 2b3a2c9..149a3e2c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInstaller.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInstaller.java
@@ -13,9 +13,11 @@
 
 import org.chromium.base.ApplicationState;
 import org.chromium.base.ApplicationStatus;
+import org.chromium.base.Callback;
 import org.chromium.base.ContentUriUtils;
 import org.chromium.base.ContextUtils;
 import org.chromium.base.annotations.CalledByNative;
+import org.chromium.chrome.browser.ChromeApplication;
 import org.chromium.chrome.browser.ShortcutHelper;
 import org.chromium.chrome.browser.banners.InstallerDelegate;
 import org.chromium.chrome.browser.util.IntentUtils;
@@ -45,8 +47,13 @@
     /** Weak pointer to the native WebApkInstaller. */
     private long mNativePointer;
 
+    /** Talks to Google Play to install WebAPKs. */
+    private GooglePlayWebApkInstallDelegate mGooglePlayWebApkInstallDelegate;
+
     private WebApkInstaller(long nativePtr) {
         mNativePointer = nativePtr;
+        ChromeApplication application = (ChromeApplication) ContextUtils.getApplicationContext();
+        mGooglePlayWebApkInstallDelegate = application.getGooglePlayWebApkInstallDelegate();
     }
 
     @CalledByNative
@@ -55,8 +62,16 @@
     }
 
     @CalledByNative
+    private boolean hasGooglePlayWebApkInstallDelegate() {
+        return mGooglePlayWebApkInstallDelegate != null;
+    }
+
+    @CalledByNative
     private void destroy() {
-        ApplicationStatus.unregisterApplicationStateListener(mListener);
+        if (mListener != null) {
+            ApplicationStatus.unregisterApplicationStateListener(mListener);
+        }
+        mListener = null;
         mNativePointer = 0;
     }
 
@@ -86,7 +101,67 @@
     }
 
     /**
-     * Send intent to Android to show prompt and install downloaded WebAPK.
+     * Installs a WebAPK from Google Play and monitors the installation.
+     * @param packageName The package name of the WebAPK to install.
+     * @param version The version of WebAPK to install.
+     * @param title The title of the WebAPK to display during installation.
+     * @param token The token from WebAPK Server.
+     * @param url The start URL of the WebAPK to install.
+     * @return True if the install was started. A "true" return value does not guarantee that the
+     *         install succeeds.
+     */
+    @CalledByNative
+    private boolean installWebApkFromGooglePlayAsync(String packageName, int version, String title,
+            String token, String url) {
+        if (mGooglePlayWebApkInstallDelegate == null) return false;
+
+        Callback<Boolean> callback = new Callback<Boolean>() {
+            @Override
+            public void onResult(Boolean success) {
+                if (mNativePointer != 0) {
+                    nativeOnInstallFinished(mNativePointer, success);
+                }
+            }
+        };
+        return mGooglePlayWebApkInstallDelegate.installAsync(packageName, version, title, token,
+                url, callback);
+    }
+
+    /**
+     * Updates a WebAPK.
+     * @param filePath File to update.
+     * @return True if the update was started. A "true" return value does not guarantee that the
+     *         update succeeds.
+     */
+    @CalledByNative
+    private boolean updateAsyncFromNative(String filePath) {
+        mIsInstall = false;
+        return installDownloadedWebApk(filePath);
+    }
+
+    /**
+     * Updates a WebAPK using Google Play.
+     * @param packageName The package name of the WebAPK to install.
+     * @param version The version of WebAPK to install.
+     * @param title The title of the WebAPK to display during installation.
+     * @param token The token from WebAPK Server.
+     * @param url The start URL of the WebAPK to install.
+     * @return True if the update was started. A "true" return value does not guarantee that the
+     *         update succeeds.
+     */
+    @CalledByNative
+    private boolean updateAsyncFromGooglePlay(String packageName, int version, String title,
+            String token, String url) {
+        if (mGooglePlayWebApkInstallDelegate == null) return false;
+
+        // TODO(hanxi):crbug.com/634499. Adds a callback to show an infobar after the update
+        // succeeded.
+        return mGooglePlayWebApkInstallDelegate.installAsync(packageName, version, title, token,
+                url, null);
+    }
+
+    /**
+     * Sends intent to Android to show prompt and install downloaded WebAPK.
      * @param filePath File to install.
      */
     private boolean installDownloadedWebApk(String filePath) {
@@ -132,18 +207,6 @@
         }
     }
 
-    /**
-     * Updates a WebAPK.
-     * @param filePath File to update.
-     * @return True if the update was started. A "true" return value does not guarantee that the
-     *         update succeeds.
-     */
-    @CalledByNative
-    private boolean updateAsyncFromNative(String filePath) {
-        mIsInstall = false;
-        return installDownloadedWebApk(filePath);
-    }
-
     private ApplicationStatus.ApplicationStateListener createApplicationStateListener() {
         return new ApplicationStatus.ApplicationStateListener() {
             @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/DateDividedAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/DateDividedAdapter.java
index 003498df..82b34141 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/DateDividedAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/DateDividedAdapter.java
@@ -105,6 +105,12 @@
         }
     }
 
+    protected static class HeaderViewHolder extends RecyclerView.ViewHolder {
+        public HeaderViewHolder(View itemView) {
+            super(itemView);
+        }
+    }
+
     /**
      * A bucket of items with the same date.
      */
@@ -116,16 +122,16 @@
         private int mIndex;
 
         private boolean mIsSorted;
+        private boolean mIsListHeader;
 
-        public ItemGroup(TimedItem item) {
-            mDate = new Date(item.getTimestamp());
-            mItems.add(item);
+        public ItemGroup(long timestamp) {
+            mDate = new Date(timestamp);
             mIsSorted = true;
         }
 
         public void addItem(TimedItem item) {
             mItems.add(item);
-            mIsSorted = false;
+            mIsSorted = mItems.size() == 1;
         }
 
         public void removeItem(TimedItem item) {
@@ -161,13 +167,15 @@
          * @return The size of this group.
          */
         public int size() {
+            if (mIsListHeader) return 1;
+
             // Plus 1 to account for the date header.
             return mItems.size() + 1;
         }
 
         public TimedItem getItemAt(int index) {
-            // 0 is allocated to the date header.
-            if (index == 0) return null;
+            // 0 is allocated to the date header. The list header has no items.
+            if (index == 0 || mIsListHeader) return null;
 
             sortIfNeeded();
             return mItems.get(index - 1);
@@ -203,10 +211,12 @@
     private static final AsyncTask<Void, Void, Calendar> sCal1 = createCalendar();
     private static final AsyncTask<Void, Void, Calendar> sCal2 = createCalendar();
 
+    public static final int TYPE_HEADER = -1;
     public static final int TYPE_DATE = 0;
     public static final int TYPE_NORMAL = 1;
 
     private int mSize;
+    private boolean mHasListHeader;
     private SortedSet<ItemGroup> mGroups = new TreeSet<>(new Comparator<ItemGroup>() {
         @Override
         public int compare(ItemGroup lhs, ItemGroup rhs) {
@@ -221,6 +231,14 @@
     protected abstract ViewHolder createViewHolder(ViewGroup parent);
 
     /**
+     * Creates a {@link HeaderViewHolder} in the given parent.
+     * @see #onCreateViewHolder(ViewGroup, int)
+     */
+    protected HeaderViewHolder createHeader(ViewGroup parent) {
+        return null;
+    }
+
+    /**
      * Binds the {@link ViewHolder} with the given {@link TimedItem}.
      * @see #onBindViewHolder(ViewHolder, int)
      */
@@ -233,15 +251,10 @@
     protected abstract int getTimedItemViewResId();
 
     /**
-     * Loads a list of {@link TimedItem}s to this adapter. Any previous data will be removed.
+     * Loads a list of {@link TimedItem}s to this adapter. Previous data will not be removed. Call
+     * {@link #clear(boolean)} to remove previous items.
      */
     public void loadItems(List<? extends TimedItem> timedItems) {
-        mSize = 0;
-
-        // Unset the positions of all items in the list.
-        for (ItemGroup group : mGroups) group.resetPosition();
-        mGroups.clear();
-
         for (TimedItem timedItem : timedItems) {
             Date date = new Date(timedItem.getTimestamp());
             boolean found = false;
@@ -256,7 +269,9 @@
             if (!found) {
                 // Create a new ItemGroup with the date for the new item. This increases the
                 // size by two because we add new views for the date and the item itself.
-                mGroups.add(new ItemGroup(timedItem));
+                ItemGroup newGroup = new ItemGroup(timedItem.getTimestamp());
+                newGroup.addItem(timedItem);
+                mGroups.add(newGroup);
                 mSize += 2;
             }
         }
@@ -272,12 +287,32 @@
     }
 
     /**
-     * Removes all items from this adapter.
+     * Adds a header as the first group in this adapter.
      */
-    public void clear() {
+    public void addHeader() {
+        assert mSize == 0;
+
+        ItemGroup header = new ItemGroup(Long.MAX_VALUE);
+        header.mIsListHeader = true;
+
+        mGroups.add(header);
+        mSize++;
+        mHasListHeader = true;
+    }
+
+    /**
+     * Removes all items from this adapter.
+     * @param notifyDataSetChanged Whether to notify that the data set has been changed.
+     */
+    public void clear(boolean notifyDataSetChanged) {
         mSize = 0;
+        mHasListHeader = false;
+
+        // Unset the positions of all items in the list.
+        for (ItemGroup group : mGroups) group.resetPosition();
         mGroups.clear();
-        notifyDataSetChanged();
+
+        if (notifyDataSetChanged) notifyDataSetChanged();
     }
 
     @Override
@@ -289,8 +324,8 @@
     }
 
     /**
-     * Gets the item at the given position. For date headers, {@link TimedItem} will be null; for
-     * normal items, {@link Date} will be null.
+     * Gets the item at the given position. For date headers and the list header, {@link TimedItem}
+     * will be null; for normal items, {@link Date} will be null.
      */
     public Pair<Date, TimedItem> getItemAt(int position) {
         Pair<ItemGroup, Integer> pair = getGroupAt(position);
@@ -301,7 +336,13 @@
     @Override
     public final int getItemViewType(int position) {
         Pair<ItemGroup, Integer> pair = getGroupAt(position);
-        return pair.second == 0 ? TYPE_DATE : TYPE_NORMAL;
+        if (pair.second == TYPE_HEADER) {
+            return TYPE_HEADER;
+        } else if (pair.second == 0) {
+            return TYPE_DATE;
+        } else {
+            return TYPE_NORMAL;
+        }
     }
 
     @Override
@@ -311,7 +352,10 @@
                     getTimedItemViewResId(), parent, false));
         } else if (viewType == TYPE_NORMAL) {
             return createViewHolder(parent);
+        } else if (viewType == TYPE_HEADER) {
+            return createHeader(parent);
         }
+        assert false;
         return null;
     }
 
@@ -320,7 +364,7 @@
         Pair<Date, TimedItem> pair = getItemAt(position);
         if (holder instanceof DateViewHolder) {
             ((DateViewHolder) holder).setDate(pair.first);
-        } else {
+        } else if (!(holder instanceof HeaderViewHolder)) {
             bindViewHolderForTimedItem(holder, pair.second);
         }
     }
@@ -335,6 +379,10 @@
      */
     protected Pair<ItemGroup, Integer> getGroupAt(int position) {
         // TODO(ianwen): Optimize the performance if the number of groups becomes too large.
+        if (mHasListHeader && position == 0) {
+            return new Pair<>(mGroups.first(), TYPE_HEADER);
+        }
+
         int i = position;
         for (ItemGroup group : mGroups) {
             if (i >= group.size()) {
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index 381b9a8..0a89154 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -537,6 +537,18 @@
       <message name="IDS_CLEAR_BROWSING_DATA_IMPORTANT_DIALOG_BUTTON" desc="The text of the button to perform the clear action in the dialog presenting the user with 'important' sites that they can exclude from clearing.">
         Clear
       </message>
+      <message name="IDS_OPEN_CLEAR_BROWSING_DATA_DIALOG_BUTTON" desc="Title of the button that will open the clear browsing data dialog.">
+        Clear browsing data…
+      </message>
+      <message name="IDS_ANDROID_HISTORY_NO_SYNCED_RESULTS" desc="The notification at the top of the history page indicating that it does not include visits from other devices.">
+        Showing history from this device. <ph name="BEGIN_LINK">&lt;link&gt;</ph>Learn more<ph name="END_LINK">&lt;/link&gt;</ph>.
+      </message>
+      <message name="IDS_ANDROID_HISTORY_HAS_SYNCED_RESULTS" desc="The notification at the top of the history page indicating that it is showing visits synced from other devices.">
+        Showing history from your signed-in devices. <ph name="BEGIN_LINK">&lt;link&gt;</ph>Learn more<ph name="END_LINK">&lt;/link&gt;</ph>.
+      </message>
+      <message name="IDS_ANDROID_HISTORY_OTHER_FORMS_OF_HISTORY" desc="The notification at the top of the history page indicating that deleting Chrome browsing history will not delete other forms of history stored at Google My Activity.">
+        Your Google Account may have other forms of browsing history at <ph name="BEGIN_LINK">&lt;link&gt;</ph>history.google.com<ph name="END_LINK">&lt;/link&gt;</ph>.
+      </message>
 
       <message name="IDS_USAGE_AND_CRASH_REPORTS_TITLE" desc="Title for 'Usage and crash reports' preference">
         Usage and crash reports
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index 6ee404fe..c132208c 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -1031,6 +1031,7 @@
   "java/src/org/chromium/chrome/browser/webapps/ChromeWebApkHost.java",
   "java/src/org/chromium/chrome/browser/webapps/FullScreenActivity.java",
   "java/src/org/chromium/chrome/browser/webapps/FullScreenDelegateFactory.java",
+  "java/src/org/chromium/chrome/browser/webapps/GooglePlayWebApkInstallDelegate.java",
   "java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java",
   "java/src/org/chromium/chrome/browser/webapps/WebApkActivity0.java",
   "java/src/org/chromium/chrome/browser/webapps/WebApkActivity1.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillTest.java
index 3fa8f6b..3a73a3c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillTest.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.autofill;
 
+import android.graphics.Color;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.view.View;
 
@@ -67,7 +68,9 @@
 
                 mWindowAndroid = new ActivityWindowAndroid(activity);
                 mAutofillPopup = new AutofillPopup(activity, anchorView, mMockAutofillCallback);
-                mAutofillPopup.filterAndShow(new AutofillSuggestion[0], false);
+                mAutofillPopup.filterAndShow(new AutofillSuggestion[0], false /* isRtl */,
+                        Color.TRANSPARENT /* backgroundColor */,
+                        Color.TRANSPARENT /* dividerColor */, 0 /* dropdownItemHeight */);
             }
         });
     }
@@ -107,21 +110,24 @@
     private AutofillSuggestion[] createTwoAutofillSuggestionArray() {
         return new AutofillSuggestion[] {
                 new AutofillSuggestion("Sherlock Holmes", "221B Baker Street", DropdownItem.NO_ICON,
-                        42, false, false),
-                new AutofillSuggestion(
-                        "Arthur Dent", "West Country", DropdownItem.NO_ICON, 43, false, false),
+                        false, 42, false, false, false),
+                new AutofillSuggestion("Arthur Dent", "West Country", DropdownItem.NO_ICON,
+                        false, 43, false, false, false),
         };
     }
 
     private AutofillSuggestion[] createFiveAutofillSuggestionArray() {
         return new AutofillSuggestion[] {
                 new AutofillSuggestion("Sherlock Holmes", "221B Baker Street", DropdownItem.NO_ICON,
-                        42, false, false),
-                new AutofillSuggestion(
-                        "Arthur Dent", "West Country", DropdownItem.NO_ICON, 43, false, false),
-                new AutofillSuggestion("Arthos", "France", DropdownItem.NO_ICON, 44, false, false),
-                new AutofillSuggestion("Porthos", "France", DropdownItem.NO_ICON, 45, false, false),
-                new AutofillSuggestion("Aramis", "France", DropdownItem.NO_ICON, 46, false, false),
+                        false, 42, false, false, false),
+                new AutofillSuggestion("Arthur Dent", "West Country", DropdownItem.NO_ICON,
+                        false, 43, false, false, false),
+                new AutofillSuggestion("Arthos", "France", DropdownItem.NO_ICON,
+                        false, 44, false, false, false),
+                new AutofillSuggestion("Porthos", "France", DropdownItem.NO_ICON,
+                        false, 45, false, false, false),
+                new AutofillSuggestion("Aramis", "France", DropdownItem.NO_ICON,
+                        false, 46, false, false, false),
         };
     }
 
@@ -130,7 +136,9 @@
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mAutofillPopup.filterAndShow(suggestions, false);
+                mAutofillPopup.filterAndShow(suggestions, false /* isRtl */,
+                        Color.TRANSPARENT /* backgroundColor */,
+                        Color.TRANSPARENT /* dividerColor */, 0 /* dropdownItemHeight */);
             }
         });
         CriteriaHelper.pollInstrumentationThread(new Criteria() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageSavePageLaterEvaluationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageSavePageLaterEvaluationTest.java
index 5382500a..c7f087e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageSavePageLaterEvaluationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageSavePageLaterEvaluationTest.java
@@ -119,6 +119,7 @@
         ThreadUtils.runOnUiThread(new Runnable() {
             @Override
             public void run() {
+                assert mBridge != null;
                 mBridge.getRequestsInQueue(new Callback<SavePageRequest[]>() {
                     @Override
                     public void onResult(SavePageRequest[] results) {
@@ -481,6 +482,9 @@
             Log.e(TAG, e.getMessage(), e);
             fail(String.format(
                     "Config file %s is not found, aborting the test.", CONFIG_FILE_PATH));
+        } catch (NumberFormatException e) {
+            Log.e(TAG, e.getMessage(), e);
+            fail("Error parsing config file, aborting test.");
         } finally {
             if (inputStream != null) {
                 inputStream.close();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteContactDetailsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteContactDetailsTest.java
index 850d402..5cc6612a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteContactDetailsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteContactDetailsTest.java
@@ -8,6 +8,7 @@
 import android.test.suitebuilder.annotation.MediumTest;
 
 import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.FlakyTest;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
@@ -40,7 +41,11 @@
     }
 
     /** Attempt to update the contact information with invalid data and cancel the transaction. */
-    @MediumTest
+    /*
+     * @MediumTest
+     * Bug=crbug.com/673299
+     */
+    @FlakyTest
     @Feature({"Payments"})
     public void testEditIncompleteContactAndCancel()
             throws InterruptedException, ExecutionException, TimeoutException {
diff --git a/chrome/app/chrome_main.cc b/chrome/app/chrome_main.cc
index 57dfdaf..4e69259 100644
--- a/chrome/app/chrome_main.cc
+++ b/chrome/app/chrome_main.cc
@@ -94,6 +94,7 @@
         *base::CommandLine::ForCurrentProcess();
     if (command_line.HasSwitch("mash"))
       return MashMain();
+    WaitForMashDebuggerIfNecessary();
   }
 #endif  // BUILDFLAG(ENABLE_PACKAGE_MASH_SERVICES)
 
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 7f16b62..d8f0e647 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -2164,6 +2164,9 @@
   <message name="IDS_KIOSK_APPS_BUTTON" desc="Text shown on a button that brings up the kiosk apps menu on login screen">
     Apps
   </message>
+  <message name="IDS_LOCK_SCREEN_TASK_MANAGER_NAME" desc="The name of the lock screen as it appears in the task manager. This will be prefixed with another string, such as 'Extension: ' (see IDS_TASK_MANAGER_EXTENSION_PREFIX)">
+    Lock Screen
+  </message>
   <message name="IDS_LOGIN_USER_ADDING_BANNER" desc="Text shown on a banner in user adding screen.">
     Add an account to multiple sign-in. All signed-in accounts can be accessed without a password, so this feature should only be used with trusted accounts.
   </message>
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 82f34fa7..c0b27d3 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -7767,24 +7767,9 @@
 
         <!-- Import progress popup -->
         <if expr="is_macosx">
-          <message name="IDS_IMPORT_PROGRESS_TITLE" desc="Title for the importing progress dialog">
-            Importing
-          </message>
           <message name="IDS_IMPORT_SETTINGS_MENU_MAC" desc="The text label for the Import menu item.">
             Import Bookmarks and Settings...
           </message>
-          <message name="IDS_IMPORT_PROGRESS_STATUS_BOOKMARKS" desc="Import status for bookmarks">
-            Favorites/Bookmarks
-          </message>
-          <message name="IDS_IMPORT_PROGRESS_STATUS_SEARCH" desc="Import status for search engines">
-            Search settings
-          </message>
-          <message name="IDS_IMPORT_PROGRESS_STATUS_PASSWORDS" desc="Import status for passwords">
-            Saved passwords
-          </message>
-          <message name="IDS_IMPORT_PROGRESS_STATUS_HISTORY" desc="Import status for history">
-            Browsing history
-          </message>
         </if> <!-- is_macosx -->
       </if> <!-- not is_android -->
 
diff --git a/chrome/app/mash/mash_runner.cc b/chrome/app/mash/mash_runner.cc
index ddcb260..acd09ca 100644
--- a/chrome/app/mash/mash_runner.cc
+++ b/chrome/app/mash/mash_runner.cc
@@ -5,6 +5,8 @@
 #include "chrome/app/mash/mash_runner.h"
 
 #include "base/at_exit.h"
+#include "base/base_paths.h"
+#include "base/base_switches.h"
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/debug/debugger.h"
@@ -13,7 +15,9 @@
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
+#include "base/path_service.h"
 #include "base/process/launch.h"
+#include "base/process/process.h"
 #include "base/run_loop.h"
 #include "base/task_scheduler/task_scheduler.h"
 #include "base/threading/sequenced_worker_pool.h"
@@ -34,6 +38,7 @@
 #include "services/service_manager/public/cpp/service_context.h"
 #include "services/service_manager/public/cpp/standalone_service/standalone_service.h"
 #include "services/service_manager/public/interfaces/service_factory.mojom.h"
+#include "services/service_manager/runner/common/client_util.h"
 #include "services/service_manager/runner/common/switches.h"
 #include "services/service_manager/runner/init.h"
 #include "services/service_manager/standalone/context.h"
@@ -94,8 +99,9 @@
       base::CommandLine* command_line) override {
     if (target.name() == kChromeMashServiceName ||
         target.name() == content::mojom::kBrowserServiceName) {
-      command_line->SetProgram(
-          base::CommandLine::ForCurrentProcess()->GetProgram());
+      base::FilePath exe_path;
+      base::PathService::Get(base::FILE_EXE, &exe_path);
+      command_line->SetProgram(exe_path);
     }
     if (target.name() != content::mojom::kBrowserServiceName) {
       // If running anything other than the browser process, launch a mash
@@ -239,3 +245,23 @@
   MashRunner mash_runner;
   return mash_runner.Run();
 }
+
+void WaitForMashDebuggerIfNecessary() {
+  if (!service_manager::ServiceManagerIsRemote())
+    return;
+
+  const base::CommandLine* command_line =
+      base::CommandLine::ForCurrentProcess();
+  const std::string service_name =
+      command_line->GetSwitchValueASCII(switches::kProcessServiceName);
+  if (service_name !=
+      command_line->GetSwitchValueASCII(switches::kWaitForDebugger)) {
+    return;
+  }
+
+  // Include the pid as logging may not have been initialized yet (the pid
+  // printed out by logging is wrong).
+  LOG(WARNING) << "waiting for debugger to attach for service " << service_name
+               << " pid=" << base::Process::Current().Pid();
+  base::debug::WaitForDebugger(120, true);
+}
diff --git a/chrome/app/mash/mash_runner.h b/chrome/app/mash/mash_runner.h
index 813daa0e..bf0bf5fd 100644
--- a/chrome/app/mash/mash_runner.h
+++ b/chrome/app/mash/mash_runner.h
@@ -40,4 +40,8 @@
 
 int MashMain();
 
+// Called if the command line isn't mash to potentially wait for a debugger
+// to attach.
+void WaitForMashDebuggerIfNecessary();
+
 #endif  // CHROME_APP_MASH_MASH_RUNNER_H_
diff --git a/chrome/app/nibs/BUILD.gn b/chrome/app/nibs/BUILD.gn
index 614be03..744ef8c0 100644
--- a/chrome/app/nibs/BUILD.gn
+++ b/chrome/app/nibs/BUILD.gn
@@ -36,7 +36,6 @@
   "FirstRunDialog.xib",
   "HttpAuthLoginSheet.xib",
   "HungRendererDialog.xib",
-  "ImportProgressDialog.xib",
   "MainMenu.xib",
   "OneClickSigninBubble.xib",
   "OneClickSigninDialog.xib",
@@ -50,7 +49,6 @@
   "FindBar.xib",
   "GlobalErrorBubble.xib",
   "InfoBar.xib",
-  "Panel.xib",
 ]
 
 mac_xib_bundle_data("chrome_xibs") {
diff --git a/chrome/app/nibs/ImportProgressDialog.xib b/chrome/app/nibs/ImportProgressDialog.xib
deleted file mode 100644
index 62e174c..0000000
--- a/chrome/app/nibs/ImportProgressDialog.xib
+++ /dev/null
@@ -1,161 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="5056" systemVersion="13F1077" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
-    <dependencies>
-        <deployment version="1090" identifier="macosx"/>
-        <development version="5100" identifier="xcode"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="5056"/>
-    </dependencies>
-    <objects>
-        <customObject id="-2" userLabel="File's Owner" customClass="ImportProgressDialogController">
-            <connections>
-                <outlet property="window" destination="1" id="25"/>
-            </connections>
-        </customObject>
-        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
-        <customObject id="-3" userLabel="Application"/>
-        <window title="^IDS_IMPORT_PROGRESS_TITLE" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" id="1">
-            <windowStyleMask key="styleMask" titled="YES"/>
-            <windowPositionMask key="initialPositionMask" leftStrut="YES" bottomStrut="YES"/>
-            <rect key="contentRect" x="196" y="308" width="508" height="202"/>
-            <rect key="screenRect" x="0.0" y="0.0" width="1680" height="1028"/>
-            <view key="contentView" id="2">
-                <rect key="frame" x="0.0" y="0.0" width="508" height="202"/>
-                <autoresizingMask key="autoresizingMask"/>
-                <subviews>
-                    <textField verticalHuggingPriority="750" id="3">
-                        <rect key="frame" x="17" y="165" width="475" height="17"/>
-                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
-                        <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="summary" id="4">
-                            <font key="font" metaFont="system"/>
-                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
-                            <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
-                        </textFieldCell>
-                        <connections>
-                            <binding destination="-2" name="value" keyPath="explanatoryText" id="38"/>
-                        </connections>
-                    </textField>
-                    <textField verticalHuggingPriority="750" id="5">
-                        <rect key="frame" x="29" y="56" width="227" height="17"/>
-                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
-                        <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="^IDS_IMPORT_PROGRESS_STATUS_BOOKMARKS" id="6">
-                            <font key="font" metaFont="system"/>
-                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
-                            <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
-                        </textFieldCell>
-                        <connections>
-                            <binding destination="-2" name="textColor" keyPath="favoritesImportEnabled" id="51"/>
-                        </connections>
-                    </textField>
-                    <textField verticalHuggingPriority="750" id="7">
-                        <rect key="frame" x="29" y="106" width="227" height="17"/>
-                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
-                        <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="^IDS_IMPORT_PROGRESS_STATUS_SEARCH" id="8">
-                            <font key="font" metaFont="system"/>
-                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
-                            <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
-                        </textFieldCell>
-                        <connections>
-                            <binding destination="-2" name="textColor" keyPath="searchImportEnabled" id="53"/>
-                        </connections>
-                    </textField>
-                    <textField verticalHuggingPriority="750" id="9">
-                        <rect key="frame" x="29" y="81" width="227" height="17"/>
-                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
-                        <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="^IDS_IMPORT_PROGRESS_STATUS_PASSWORDS" id="10">
-                            <font key="font" metaFont="system"/>
-                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
-                            <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
-                        </textFieldCell>
-                        <connections>
-                            <binding destination="-2" name="textColor" keyPath="passwordImportEnabled" id="55"/>
-                        </connections>
-                    </textField>
-                    <textField verticalHuggingPriority="750" id="11">
-                        <rect key="frame" x="29" y="131" width="227" height="17"/>
-                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
-                        <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="^IDS_IMPORT_PROGRESS_STATUS_HISTORY" id="12">
-                            <font key="font" metaFont="system"/>
-                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
-                            <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
-                        </textFieldCell>
-                        <connections>
-                            <binding destination="-2" name="textColor" keyPath="historyImportEnabled" id="56"/>
-                        </connections>
-                    </textField>
-                    <textField verticalHuggingPriority="750" id="16">
-                        <rect key="frame" x="258" y="56" width="234" height="17"/>
-                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
-                        <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="status" id="17">
-                            <font key="font" metaFont="systemBold"/>
-                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
-                            <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
-                        </textFieldCell>
-                        <connections>
-                            <binding destination="-2" name="value" keyPath="favoritesStatusText" id="29"/>
-                        </connections>
-                    </textField>
-                    <textField verticalHuggingPriority="750" id="18">
-                        <rect key="frame" x="258" y="81" width="234" height="17"/>
-                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
-                        <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="status" id="19">
-                            <font key="font" metaFont="systemBold"/>
-                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
-                            <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
-                        </textFieldCell>
-                        <connections>
-                            <binding destination="-2" name="value" keyPath="savedPasswordStatusText" id="35"/>
-                        </connections>
-                    </textField>
-                    <textField verticalHuggingPriority="750" id="20">
-                        <rect key="frame" x="258" y="106" width="234" height="17"/>
-                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
-                        <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="status" id="21">
-                            <font key="font" metaFont="systemBold"/>
-                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
-                            <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
-                        </textFieldCell>
-                        <connections>
-                            <binding destination="-2" name="value" keyPath="searchStatusText" id="30"/>
-                        </connections>
-                    </textField>
-                    <textField verticalHuggingPriority="750" id="22">
-                        <rect key="frame" x="258" y="131" width="234" height="17"/>
-                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
-                        <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="status" id="23">
-                            <font key="font" metaFont="systemBold"/>
-                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
-                            <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
-                        </textFieldCell>
-                        <connections>
-                            <binding destination="-2" name="value" keyPath="historyStatusText" id="34"/>
-                        </connections>
-                    </textField>
-                    <customView id="62" customClass="GTMWidthBasedTweaker">
-                        <rect key="frame" x="356" y="0.0" width="124" height="48"/>
-                        <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
-                        <subviews>
-                            <button verticalHuggingPriority="750" id="13">
-                                <rect key="frame" x="14" y="12" width="96" height="32"/>
-                                <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
-                                <buttonCell key="cell" type="push" title="^IDS_CANCEL" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="14">
-                                    <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
-                                    <font key="font" metaFont="system"/>
-                                </buttonCell>
-                                <connections>
-                                    <action selector="cancel:" target="-2" id="24"/>
-                                </connections>
-                            </button>
-                        </subviews>
-                    </customView>
-                </subviews>
-            </view>
-        </window>
-        <customObject id="57" customClass="ChromeUILocalizer"/>
-        <customObject id="59" customClass="GTMUILocalizerAndLayoutTweaker">
-            <connections>
-                <outlet property="localizer_" destination="57" id="60"/>
-                <outlet property="uiObject_" destination="1" id="61"/>
-            </connections>
-        </customObject>
-    </objects>
-</document>
diff --git a/chrome/app/nibs/Panel.xib b/chrome/app/nibs/Panel.xib
deleted file mode 100644
index c455c18..0000000
--- a/chrome/app/nibs/Panel.xib
+++ /dev/null
@@ -1,100 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="5056" systemVersion="13F1077" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
-    <dependencies>
-        <deployment version="1090" identifier="macosx"/>
-        <development version="5100" identifier="xcode"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="5056"/>
-    </dependencies>
-    <objects>
-        <customObject id="-2" userLabel="File's Owner" customClass="PanelWindowControllerCocoa">
-            <connections>
-                <outlet property="titlebar_view_" destination="6" id="8"/>
-                <outlet property="window" destination="1" id="28"/>
-            </connections>
-        </customObject>
-        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
-        <customObject id="-3" userLabel="Application"/>
-        <window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" id="1" customClass="PanelWindowCocoaImpl">
-            <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" texturedBackground="YES"/>
-            <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
-            <rect key="contentRect" x="196" y="240" width="480" height="270"/>
-            <rect key="screenRect" x="0.0" y="0.0" width="1680" height="1028"/>
-            <view key="contentView" id="2">
-                <rect key="frame" x="0.0" y="0.0" width="480" height="270"/>
-                <autoresizingMask key="autoresizingMask"/>
-            </view>
-            <connections>
-                <outlet property="delegate" destination="-2" id="29"/>
-            </connections>
-        </window>
-        <customView id="6" userLabel="PanelTitlebarView" customClass="PanelTitlebarViewCocoa">
-            <rect key="frame" x="0.0" y="0.0" width="300" height="22"/>
-            <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
-            <subviews>
-                <imageView id="19">
-                    <rect key="frame" x="126" y="3" width="14" height="14"/>
-                    <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
-                    <imageCell key="cell" controlSize="small" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" id="20"/>
-                </imageView>
-                <textField verticalHuggingPriority="750" id="10">
-                    <rect key="frame" x="26" y="1" width="248" height="17"/>
-                    <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
-                    <textFieldCell key="cell" lineBreakMode="truncatingTail" allowsUndo="NO" sendsActionOnEndEditing="YES" alignment="left" bezelStyle="round" id="11">
-                        <font key="font" metaFont="system"/>
-                        <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
-                        <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
-                    </textFieldCell>
-                </textField>
-                <button id="30" customClass="HoverImageButton">
-                    <rect key="frame" x="0.0" y="0.0" width="16" height="16"/>
-                    <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
-                    <buttonCell key="cell" type="square" title="Minimize" bezelStyle="shadowlessSquare" imagePosition="only" alignment="center" imageScaling="proportionallyDown" inset="2" id="31">
-                        <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
-                        <font key="font" metaFont="system"/>
-                    </buttonCell>
-                    <connections>
-                        <action selector="onMinimizeButtonClick:" target="6" id="35"/>
-                    </connections>
-                </button>
-                <button id="32" customClass="HoverImageButton">
-                    <rect key="frame" x="0.0" y="0.0" width="16" height="16"/>
-                    <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
-                    <buttonCell key="cell" type="square" title="Restore" bezelStyle="shadowlessSquare" imagePosition="only" alignment="center" imageScaling="proportionallyDown" inset="2" id="33">
-                        <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
-                        <font key="font" metaFont="system"/>
-                    </buttonCell>
-                    <connections>
-                        <action selector="onRestoreButtonClick:" target="6" id="37"/>
-                    </connections>
-                </button>
-                <button id="38" customClass="HoverImageButton">
-                    <rect key="frame" x="5" y="-5" width="16" height="16"/>
-                    <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
-                    <buttonCell key="cell" type="square" title="Close" bezelStyle="shadowlessSquare" alignment="center" imageScaling="proportionallyDown" inset="2" id="39">
-                        <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
-                        <font key="font" metaFont="system"/>
-                    </buttonCell>
-                    <connections>
-                        <action selector="onCloseButtonClick:" target="6" id="41"/>
-                    </connections>
-                </button>
-                <customView id="24" customClass="PanelTitlebarOverlayView">
-                    <rect key="frame" x="0.0" y="0.0" width="300" height="22"/>
-                    <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
-                    <connections>
-                        <outlet property="controller_" destination="-2" id="27"/>
-                    </connections>
-                </customView>
-            </subviews>
-            <connections>
-                <outlet property="controller_" destination="-2" id="9"/>
-                <outlet property="customCloseButton_" destination="38" id="42"/>
-                <outlet property="icon_" destination="19" id="21"/>
-                <outlet property="minimizeButton_" destination="30" id="34"/>
-                <outlet property="overlay_" destination="24" id="25"/>
-                <outlet property="restoreButton_" destination="32" id="36"/>
-                <outlet property="title_" destination="10" id="17"/>
-            </connections>
-        </customView>
-    </objects>
-</document>
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 098a818..57ad06f 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -86,6 +86,15 @@
     <message name="IDS_SETTINGS_ABOUT_PAGE_UNSTABLE_WARNING_TITLE" desc="The title of the warning about switching to developer (unstable) channel.">
       Warning: you are switching to developer channel
     </message>
+    <message name="IDS_SETTINGS_ABOUT_PAGE_DIALOG_CHANNEL_STABLE" desc="The stable option in the channel select.">
+      Stable
+    </message>
+    <message name="IDS_SETTINGS_ABOUT_PAGE_DIALOG_CHANNEL_BETA" desc="The beta option in the channel select.">
+      Beta
+    </message>
+    <message name="IDS_SETTINGS_ABOUT_PAGE_DIALOG_CHANNEL_DEV" desc="The development option in the channel select.">
+      Developer - unstable
+    </message>
   </if>
   <if expr="not chromeos">
     <message name="IDS_SETTINGS_ABOUT_PAGE_RELAUNCH" desc="The label for the relaunch button that relaunches the browser once update is complete">
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index f59ef26..49460e6 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -15,6 +15,7 @@
 import("//net/features.gni")
 import("//ppapi/features/features.gni")
 import("//printing/features/features.gni")
+import("//rlz/features/features.gni")
 import("//sandbox/features.gni")
 import("//third_party/protobuf/proto_library.gni")
 import("//ui/base/ui_features.gni")
@@ -1510,6 +1511,7 @@
     "//net:net_with_v8",
     "//ppapi/features",
     "//printing/features",
+    "//rlz/features",
     "//services/image_decoder/public/cpp",
     "//services/service_manager/public/cpp",
     "//skia",
@@ -4209,6 +4211,8 @@
     # "Safe Browsing Basic" files used for safe browsing in full mode
     # (safe_browsing=1) and mobile (=2)
     sources += [
+      "safe_browsing/certificate_reporting_service_test_utils.cc",
+      "safe_browsing/certificate_reporting_service_test_utils.h",
       "safe_browsing/mock_permission_report_sender.cc",
       "safe_browsing/mock_permission_report_sender.h",
     ]
diff --git a/chrome/browser/android/compositor/layer/content_layer.cc b/chrome/browser/android/compositor/layer/content_layer.cc
index ec014ec..67f0057 100644
--- a/chrome/browser/android/compositor/layer/content_layer.cc
+++ b/chrome/browser/android/compositor/layer/content_layer.cc
@@ -7,6 +7,7 @@
 #include "base/lazy_instance.h"
 #include "cc/layers/layer.h"
 #include "cc/layers/layer_collections.h"
+#include "cc/output/filter_operations.h"
 #include "chrome/browser/android/compositor/layer/thumbnail_layer.h"
 #include "chrome/browser/android/compositor/tab_content_manager.h"
 #include "content/public/browser/android/compositor.h"
@@ -61,85 +62,53 @@
                                  bool should_override_content_alpha,
                                  float content_alpha_override,
                                  float saturation,
-                                 const gfx::Rect& desired_bounds,
-                                 const gfx::Size& content_size) {
+                                 bool should_clip,
+                                 const gfx::Rect& clip) {
   scoped_refptr<cc::Layer> content_layer =
       tab_content_manager_->GetLiveLayer(id);
-  ClipContentLayer(content_layer, desired_bounds);
   bool content_layer_draws = DoesLeafDrawContents(content_layer);
 
   scoped_refptr<ThumbnailLayer> static_layer =
       tab_content_manager_->GetStaticLayer(
           id, !(can_use_live_layer && content_layer_draws));
 
-  ClipStaticLayer(static_layer, desired_bounds);
+  float content_opacity =
+      should_override_content_alpha ? content_alpha_override : 1.0f;
+  float static_opacity =
+      should_override_content_alpha ? content_alpha_override : 1.0f;
+  if (content_layer.get() && can_use_live_layer && content_layer_draws)
+    static_opacity = static_to_view_blend;
+  if (!can_use_live_layer)
+    content_opacity = 0.0f;
 
-  // Reset the attachment logic if the number of children doesn't match the
-  // boolean flags. At some point while a tab is in the background one or more
-  // layers may be removed from this tree.
-  // Note that this needs to be checked *after* we access TabContentManager, as
-  // that class might remove layers internally, messing up our own tracking.
-  unsigned int expected_layers = 0;
-  expected_layers += content_attached_ ? 1 : 0;
-  expected_layers += static_attached_ ? 1 : 0;
-  if (layer_->children().size() != expected_layers) {
-    content_attached_ = false;
-    static_attached_ = false;
-    const cc::LayerList& layer_children = layer_->children();
-    for (unsigned i = 0; i < layer_children.size(); i++)
-      layer_children[i]->RemoveFromParent();
+  const cc::LayerList& layer_children = layer_->children();
+  for (unsigned i = 0; i < layer_children.size(); i++)
+    layer_children[i]->RemoveFromParent();
+
+  if (content_layer.get()) {
+    content_layer->SetMasksToBounds(should_clip);
+    content_layer->SetBounds(clip.size());
+    SetOpacityOnLeaf(content_layer, content_opacity);
+
+    layer_->AddChild(content_layer);
   }
-
-  gfx::Size content_bounds(0, 0);
-  if (!content_layer.get() || !can_use_live_layer) {
-    SetContentLayer(nullptr);
-    SetStaticLayer(static_layer);
-    if (static_layer.get())
-      content_bounds = static_layer->layer()->bounds();
-    else
-      content_bounds.set_width(content_size.width());
-  } else {
-    SetContentLayer(content_layer);
-    content_bounds = content_layer->bounds();
-
-    if (static_to_view_blend == 0.0f && !content_layer_draws)
-      static_to_view_blend = 1.0f;
-
-    if (static_to_view_blend != 0.0f && static_layer.get()) {
-      static_layer->layer()->SetOpacity(static_to_view_blend);
-      SetStaticLayer(static_layer);
-      if (content_bounds.GetArea() == 0 || !content_layer_draws)
-        content_bounds = static_layer->layer()->bounds();
-    } else {
-      SetStaticLayer(nullptr);
-    }
-  }
-
-  if (should_override_content_alpha) {
-    for (unsigned int i = 0; i < layer_->children().size(); ++i)
-      SetOpacityOnLeaf(layer_->children()[i], content_alpha_override);
-  }
-
-  if (!content_layer_draws && !static_attached_)
-    content_bounds = gfx::Size(0, 0);
-
-  layer_->SetBounds(content_bounds);
-
-  // Only worry about saturation on the static layer.
   if (static_layer.get()) {
-    static_filter_operations_.Clear();
+    static_layer->layer()->SetIsDrawable(true);
+    if (should_clip)
+      static_layer->Clip(clip);
+    else
+      static_layer->ClearClip();
+    SetOpacityOnLeaf(static_layer->layer(), static_opacity);
+
+    cc::FilterOperations static_filter_operations;
     if (saturation < 1.0f) {
-      static_filter_operations_.Append(
+      static_filter_operations.Append(
           cc::FilterOperation::CreateSaturateFilter(saturation));
     }
-    static_layer->layer()->SetFilters(static_filter_operations_);
-  }
-}
+    static_layer->layer()->SetFilters(static_filter_operations);
 
-gfx::Size ContentLayer::GetContentSize() {
-  if (content_attached_ && DoesLeafDrawContents(layer()->children()[0]))
-    return layer_->children()[0]->bounds();
-  return gfx::Size(0, 0);
+    layer_->AddChild(static_layer->layer());
+  }
 }
 
 scoped_refptr<cc::Layer> ContentLayer::layer() {
@@ -148,81 +117,9 @@
 
 ContentLayer::ContentLayer(TabContentManager* tab_content_manager)
     : layer_(cc::Layer::Create()),
-      content_attached_(false),
-      static_attached_(false),
       tab_content_manager_(tab_content_manager) {}
 
 ContentLayer::~ContentLayer() {
 }
 
-void ContentLayer::SetContentLayer(scoped_refptr<cc::Layer> layer) {
-  // Check indices
-  // content_attached_, expect at least 1 child.
-  DCHECK(!content_attached_ || layer_->children().size() > 0);
-
-  if (!layer.get()) {
-    if (content_attached_)
-      layer_->child_at(0)->RemoveFromParent();
-    content_attached_ = false;
-    return;
-  }
-
-  bool new_layer = false;
-  if (content_attached_ && layer_->child_at(0)->id() != layer->id()) {
-    layer_->ReplaceChild(layer_->child_at(0), layer);
-    new_layer = true;
-  } else if (!content_attached_) {
-    layer_->InsertChild(layer, 0);
-    new_layer = true;
-  }
-
-  // If this is a new layer, reset it's opacity.
-  if (new_layer)
-    SetOpacityOnLeaf(layer, 1.0f);
-
-  content_attached_ = true;
-}
-
-void ContentLayer::SetStaticLayer(
-    scoped_refptr<ThumbnailLayer> new_static_layer) {
-  // Make sure child access will be valid.
-  // !content_attached_ AND !static_attached_, expect 0 children.
-  // content_attached_ XOR static_attached_, expect 1 child.
-  // content_attached_ AND static_attached_, expect 2 children.
-  DCHECK((!content_attached_ && !static_attached_) ||
-         (content_attached_ != static_attached_ &&
-          layer_->children().size() >= 1) ||
-         (content_attached_ && static_attached_ &&
-          layer_->children().size() >= 2));
-
-  if (!new_static_layer.get()) {
-    if (static_layer_.get()) {
-      static_layer_->layer()->RemoveFromParent();
-      static_layer_ = nullptr;
-    }
-    static_attached_ = false;
-    return;
-  }
-  static_layer_ = new_static_layer;
-  static_layer_->AddSelfToParentOrReplaceAt(layer_, content_attached_ ? 1 : 0);
-  static_layer_->layer()->SetIsDrawable(true);
-  static_attached_ = true;
-}
-
-void ContentLayer::ClipContentLayer(scoped_refptr<cc::Layer> content_layer,
-                                    gfx::Rect clipping) {
-  if (!content_layer.get())
-    return;
-
-  content_layer->SetMasksToBounds(true);
-  content_layer->SetBounds(clipping.size());
-}
-
-void ContentLayer::ClipStaticLayer(scoped_refptr<ThumbnailLayer> static_layer,
-                                   gfx::Rect clipping) {
-  if (!static_layer.get())
-    return;
-  static_layer->Clip(clipping);
-}
-
 }  //  namespace android
diff --git a/chrome/browser/android/compositor/layer/content_layer.h b/chrome/browser/android/compositor/layer/content_layer.h
index 0a894e1..6736063 100644
--- a/chrome/browser/android/compositor/layer/content_layer.h
+++ b/chrome/browser/android/compositor/layer/content_layer.h
@@ -8,7 +8,6 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "cc/output/filter_operations.h"
 #include "chrome/browser/android/compositor/layer/layer.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
@@ -36,10 +35,8 @@
                      bool should_override_content_alpha,
                      float content_alpha_override,
                      float saturation,
-                     const gfx::Rect& desired_bounds,
-                     const gfx::Size& content_size);
-  bool ShowingLiveLayer() { return !static_attached_ && content_attached_; }
-  gfx::Size GetContentSize();
+                     bool should_clip,
+                     const gfx::Rect& clip);
 
   scoped_refptr<cc::Layer> layer() override;
 
@@ -50,18 +47,11 @@
  private:
   void SetContentLayer(scoped_refptr<cc::Layer> layer);
   void SetStaticLayer(scoped_refptr<ThumbnailLayer> layer);
-  void ClipContentLayer(scoped_refptr<cc::Layer> content_layer,
-                        gfx::Rect clipping);
-  void ClipStaticLayer(scoped_refptr<ThumbnailLayer> static_layer,
-                       gfx::Rect clipping);
 
+  // This is an intermediate shim layer whose children are
+  // both the static and content layers (or either, or none, depending on which
+  // is available).
   scoped_refptr<cc::Layer> layer_;
-  scoped_refptr<ThumbnailLayer> static_layer_;
-  bool content_attached_;
-  bool static_attached_;
-
-  cc::FilterOperations static_filter_operations_;
-  cc::FilterOperations content_filter_operations_;
 
   TabContentManager* tab_content_manager_;
 
diff --git a/chrome/browser/android/compositor/layer/tab_layer.cc b/chrome/browser/android/compositor/layer/tab_layer.cc
index b3c9464..3deedae 100644
--- a/chrome/browser/android/compositor/layer/tab_layer.cc
+++ b/chrome/browser/android/compositor/layer/tab_layer.cc
@@ -453,8 +453,7 @@
 
     content_->SetProperties(id, can_use_live_layer, static_to_view_blend,
                             true, alpha, saturation,
-                            rounded_descaled_content_area,
-                            gfx::Size(content_width, content_height));
+                            true, rounded_descaled_content_area);
   } else if (back_logo_resource) {
     back_logo_->SetUIResourceId(back_logo_resource->ui_resource->id());
   }
diff --git a/chrome/browser/android/compositor/layer/thumbnail_layer.cc b/chrome/browser/android/compositor/layer/thumbnail_layer.cc
index 169f26c..1d90eca 100644
--- a/chrome/browser/android/compositor/layer/thumbnail_layer.cc
+++ b/chrome/browser/android/compositor/layer/thumbnail_layer.cc
@@ -23,6 +23,8 @@
 
 void ThumbnailLayer::Clip(const gfx::Rect& clipping) {
   last_clipping_ = clipping;
+  clipped_ = true;
+
   gfx::Size clipped_content = gfx::Size(content_size_.width() - clipping.x(),
                                         content_size_.height() - clipping.y());
   clipped_content.SetToMin(clipping.size());
@@ -36,6 +38,12 @@
           (clipping.y() + clipped_content.height()) / resource_size_.height()));
 }
 
+void ThumbnailLayer::ClearClip() {
+  layer_->SetUV(gfx::PointF(0.f, 0.f), gfx::PointF(1.f, 1.f));
+  layer_->SetBounds(gfx::Size(content_size_.width(), content_size_.height()));
+  clipped_ = false;
+}
+
 void ThumbnailLayer::AddSelfToParentOrReplaceAt(scoped_refptr<cc::Layer> parent,
                                                 size_t index) {
   if (index >= parent->children().size())
@@ -60,7 +68,10 @@
   if (content_size != content_size_ || resource_size != resource_size_) {
     content_size_ = content_size;
     resource_size_ = resource_size;
-    Clip(last_clipping_);
+    if (clipped_)
+      Clip(last_clipping_);
+    else
+      ClearClip();
   }
 }
 
diff --git a/chrome/browser/android/compositor/layer/thumbnail_layer.h b/chrome/browser/android/compositor/layer/thumbnail_layer.h
index ef8fd6d..5537059 100644
--- a/chrome/browser/android/compositor/layer/thumbnail_layer.h
+++ b/chrome/browser/android/compositor/layer/thumbnail_layer.h
@@ -32,6 +32,7 @@
   void SetThumbnail(Thumbnail* thumbnail);
   // Clip the thumbnail to the given |clipping|.
   void Clip(const gfx::Rect& clipping);
+  void ClearClip();
   // Add self to |parent| or replace self at |index| if there already is an
   // instance with the same ID at |index|.
   void AddSelfToParentOrReplaceAt(scoped_refptr<cc::Layer> parent,
@@ -51,6 +52,7 @@
   scoped_refptr<cc::UIResourceLayer> layer_;
   gfx::SizeF content_size_;
   gfx::Rect last_clipping_;
+  bool clipped_ = false;
   gfx::SizeF resource_size_;
 
   DISALLOW_COPY_AND_ASSIGN(ThumbnailLayer);
diff --git a/chrome/browser/android/compositor/scene_layer/static_tab_scene_layer.cc b/chrome/browser/android/compositor/scene_layer/static_tab_scene_layer.cc
index e407884..948126e 100644
--- a/chrome/browser/android/compositor/scene_layer/static_tab_scene_layer.cc
+++ b/chrome/browser/android/compositor/scene_layer/static_tab_scene_layer.cc
@@ -39,10 +39,6 @@
 void StaticTabSceneLayer::UpdateTabLayer(
     JNIEnv* env,
     const JavaParamRef<jobject>& jobj,
-    jfloat content_viewport_x,
-    jfloat content_viewport_y,
-    jfloat content_viewport_width,
-    jfloat content_viewport_height,
     const JavaParamRef<jobject>& jtab_content_manager,
     jint id,
     jint toolbar_resource_id,
@@ -50,16 +46,10 @@
     jint default_background_color,
     jfloat x,
     jfloat y,
-    jfloat width,
-    jfloat height,
-    jfloat content_offset_y,
     jfloat static_to_view_blend,
     jfloat saturation,
     jfloat brightness) {
   background_color_ = default_background_color;
-  gfx::Size content_viewport_size(content_viewport_width,
-                                  content_viewport_height);
-  gfx::Point content_viewport_offset(content_viewport_x, content_viewport_y);
   if (!content_layer_.get()) {
     android::TabContentManager* tab_content_manager =
         android::TabContentManager::FromJavaObject(jtab_content_manager);
@@ -73,40 +63,10 @@
   bool should_override_content_alpha = last_set_tab_id_ != id;
   last_set_tab_id_ = id;
 
-  // Set up the content layer and move it to the proper position.
-  content_layer_->layer()->SetBounds(gfx::Size(width, height));
-  content_layer_->layer()->SetPosition(gfx::PointF(x, y));
   content_layer_->SetProperties(
       id, can_use_live_layer, static_to_view_blend,
       should_override_content_alpha, content_alpha_override, saturation,
-      gfx::Rect(content_viewport_size), content_viewport_size);
-
-  gfx::Size content_bounds(0, 0);
-  content_bounds = content_layer_->layer()->bounds();
-
-  gfx::Size actual_content_size(content_layer_->GetContentSize());
-
-  bool view_and_content_have_same_orientation =
-      (content_viewport_size.width() > content_viewport_size.height()) ==
-          (actual_content_size.width() > actual_content_size.height()) &&
-      actual_content_size.width() > 0 && actual_content_size.height() > 0 &&
-      content_viewport_size.width() > 0 && content_viewport_size.height() > 0;
-
-  // This may not be true for frames during rotation.
-  bool content_has_consistent_width =
-      actual_content_size.width() == content_bounds.width() &&
-      actual_content_size.width() == content_viewport_size.width();
-
-  if (view_and_content_have_same_orientation ||
-      (content_has_consistent_width && content_layer_->ShowingLiveLayer())) {
-    y += content_offset_y;
-  } else {
-    // If our orientations are off and we have a static texture, or if we have
-    // a live layer of an unexpected width, move the texture in by the
-    // appropriate amount.
-    x += content_viewport_offset.x();
-    y += content_viewport_offset.y();
-  }
+      false, gfx::Rect());
 
   content_layer_->layer()->SetPosition(gfx::PointF(x, y));
   content_layer_->layer()->SetIsDrawable(true);
diff --git a/chrome/browser/android/compositor/scene_layer/static_tab_scene_layer.h b/chrome/browser/android/compositor/scene_layer/static_tab_scene_layer.h
index 912a04ca..e8495f1 100644
--- a/chrome/browser/android/compositor/scene_layer/static_tab_scene_layer.h
+++ b/chrome/browser/android/compositor/scene_layer/static_tab_scene_layer.h
@@ -40,10 +40,6 @@
   void UpdateTabLayer(
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& jobj,
-      jfloat content_viewport_x,
-      jfloat content_viewport_y,
-      jfloat content_viewport_width,
-      jfloat content_viewport_height,
       const base::android::JavaParamRef<jobject>& jtab_content_manager,
       jint id,
       jint toolbar_resource_id,
@@ -51,9 +47,6 @@
       jint default_background_color,
       jfloat x,
       jfloat y,
-      jfloat width,
-      jfloat height,
-      jfloat content_offset_y,
       jfloat static_to_view_blend,
       jfloat saturation,
       jfloat brightness);
diff --git a/chrome/browser/android/history/browsing_history_bridge.cc b/chrome/browser/android/history/browsing_history_bridge.cc
index 9db2b17..220fe9f 100644
--- a/chrome/browser/android/history/browsing_history_bridge.cc
+++ b/chrome/browser/android/history/browsing_history_bridge.cc
@@ -43,7 +43,11 @@
 
   history::QueryOptions options;
   options.max_count = kMaxQueryCount;
-  options.end_time = base::Time::FromJavaTime(j_query_end_time);
+  if (j_query_end_time == 0) {
+    options.end_time = base::Time();
+  } else {
+    options.end_time = base::Time::FromJavaTime(j_query_end_time);
+  }
   options.duplicate_policy = history::QueryOptions::REMOVE_DUPLICATES_PER_DAY;
 
   browsing_history_service_->QueryHistory(
@@ -138,7 +142,9 @@
 
 void BrowsingHistoryBridge::HasOtherFormsOfBrowsingHistory(
     bool has_other_forms, bool has_synced_results) {
-  // TODO(twellington): implement
+  JNIEnv* env = base::android::AttachCurrentThread();
+  Java_BrowsingHistoryBridge_hasOtherFormsOfBrowsingData(
+      env, j_history_service_obj_.obj(), has_other_forms, has_synced_results);
 }
 
 bool RegisterBrowsingHistoryBridge(JNIEnv* env) {
diff --git a/chrome/browser/android/offline_pages/evaluation/run_offline_page_evaluation_test.py b/chrome/browser/android/offline_pages/evaluation/run_offline_page_evaluation_test.py
index bb231a6..dafd009 100755
--- a/chrome/browser/android/offline_pages/evaluation/run_offline_page_evaluation_test.py
+++ b/chrome/browser/android/offline_pages/evaluation/run_offline_page_evaluation_test.py
@@ -89,6 +89,7 @@
       output_dir=os.path.expanduser('~/offline_eval_output'),
       user_request=DEFAULT_USER_REQUEST,
       user_test_scheduler=DEFAULT_USE_TEST_SCHEDULER,
+      schedule_batch_size=DEFAULT_BATCH_SIZE,
       verbose=DEFAULT_VERBOSE)
 
   def get_adb_command(args):
diff --git a/chrome/browser/android/webapk/webapk.proto b/chrome/browser/android/webapk/webapk.proto
index 4a18b4cc..90b171e 100644
--- a/chrome/browser/android/webapk/webapk.proto
+++ b/chrome/browser/android/webapk/webapk.proto
@@ -19,7 +19,10 @@
   // URL to download WebAPK.
   optional string signed_download_url = 3;
 
-  reserved 4;
+  // Unique id identifying session with WebAPK server.
+  optional string token = 6;
+
+  reserved 4, 5;
 }
 
 // Sent as part of request to create or update a WebAPK.
diff --git a/chrome/browser/android/webapk/webapk_installer.cc b/chrome/browser/android/webapk/webapk_installer.cc
index 348c336c..840e1147 100644
--- a/chrome/browser/android/webapk/webapk_installer.cc
+++ b/chrome/browser/android/webapk/webapk_installer.cc
@@ -13,6 +13,7 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
@@ -315,6 +316,39 @@
       env, java_ref_, java_file_path);
 }
 
+bool WebApkInstaller::HasGooglePlayWebApkInstallDelegate() {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  return Java_WebApkInstaller_hasGooglePlayWebApkInstallDelegate(
+      env, java_ref_);
+}
+
+bool WebApkInstaller::InstallOrUpdateWebApkFromGooglePlay(
+    const std::string& package_name,
+    int version,
+    const std::string& token) {
+  webapk_package_ = package_name;
+
+  JNIEnv* env = base::android::AttachCurrentThread();
+  base::android::ScopedJavaLocalRef<jstring> java_webapk_package =
+      base::android::ConvertUTF8ToJavaString(env, webapk_package_);
+  base::android::ScopedJavaLocalRef<jstring> java_title =
+      base::android::ConvertUTF16ToJavaString(env, shortcut_info_.user_title);
+  base::android::ScopedJavaLocalRef<jstring> java_token =
+      base::android::ConvertUTF8ToJavaString(env, token);
+  base::android::ScopedJavaLocalRef<jstring> java_url =
+      base::android::ConvertUTF8ToJavaString(env, shortcut_info_.url.spec());
+
+  if (task_type_ == WebApkInstaller::INSTALL) {
+    return Java_WebApkInstaller_installWebApkFromGooglePlayAsync(
+        env, java_ref_, java_webapk_package, version, java_title, java_token,
+        java_url);
+  } else {
+    return Java_WebApkInstaller_updateAsyncFromGooglePlay(
+        env, java_ref_, java_webapk_package, version, java_title, java_token,
+        java_url);
+  }
+}
+
 void WebApkInstaller::OnURLFetchComplete(const net::URLFetcher* source) {
   timer_.Stop();
 
@@ -339,6 +373,17 @@
     OnFailure();
     return;
   }
+
+  if (HasGooglePlayWebApkInstallDelegate()) {
+    int version = 1;
+    base::StringToInt(response->version(), &version);
+    if (!InstallOrUpdateWebApkFromGooglePlay(
+        response->package_name(), version, response->token())) {
+      OnFailure();
+    }
+    return;
+  }
+
   OnGotWebApkDownloadUrl(signed_download_url, response->package_name());
 }
 
diff --git a/chrome/browser/android/webapk/webapk_installer.h b/chrome/browser/android/webapk/webapk_installer.h
index c24a6688..052f988e0 100644
--- a/chrome/browser/android/webapk/webapk_installer.h
+++ b/chrome/browser/android/webapk/webapk_installer.h
@@ -105,6 +105,18 @@
       JNIEnv* env,
       const base::android::ScopedJavaLocalRef<jstring>& java_file_path);
 
+  // Returns whether the Google Play install delegate is available.
+  // Note: it is possible that this delegate is null even when installing
+  // WebAPKs using Google Play is enabled.
+  virtual bool HasGooglePlayWebApkInstallDelegate();
+
+  // Called when the package name of the WebAPK is available and the install
+  // or update request is handled by Google Play.
+  virtual bool InstallOrUpdateWebApkFromGooglePlay(
+      const std::string& package_name,
+      int version,
+      const std::string& token);
+
   // Called when the request to install the WebAPK is sent to Google Play.
   void OnSuccess();
 
diff --git a/chrome/browser/android/webapk/webapk_installer_unittest.cc b/chrome/browser/android/webapk/webapk_installer_unittest.cc
index 10021ff9..0734459e 100644
--- a/chrome/browser/android/webapk/webapk_installer_unittest.cc
+++ b/chrome/browser/android/webapk/webapk_installer_unittest.cc
@@ -52,12 +52,17 @@
 
 // WebApkInstaller subclass where
 // WebApkInstaller::StartInstallingDownloadedWebApk() and
-// WebApkInstaller::StartUpdateUsingDownloadedWebApk() are stubbed out.
+// WebApkInstaller::StartUpdateUsingDownloadedWebApk() and
+// WebApkInstaller::HasGooglePlayWebApkInstallDelegate() and
+// WebApkInstaller::InstallOrUpdateWebApkFromGooglePlay() are stubbed out.
 class TestWebApkInstaller : public WebApkInstaller {
  public:
   TestWebApkInstaller(const ShortcutInfo& shortcut_info,
-                      const SkBitmap& shortcut_icon)
-      : WebApkInstaller(shortcut_info, shortcut_icon) {}
+                      const SkBitmap& shortcut_icon,
+                      bool has_google_play_webapk_install_delegate)
+      : WebApkInstaller(shortcut_info, shortcut_icon),
+        has_google_play_webapk_install_delegate_(
+            has_google_play_webapk_install_delegate) {}
 
   bool StartInstallingDownloadedWebApk(
       JNIEnv* env,
@@ -73,6 +78,17 @@
     return true;
   }
 
+  bool HasGooglePlayWebApkInstallDelegate() override {
+    return has_google_play_webapk_install_delegate_;
+  }
+
+  bool InstallOrUpdateWebApkFromGooglePlay(const std::string& package_name,
+                                           int version,
+                                           const std::string& token) override {
+    PostTaskToRunSuccessCallback();
+    return true;
+  }
+
   void PostTaskToRunSuccessCallback() {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE,
@@ -80,6 +96,9 @@
   }
 
  private:
+  // Whether the Google Play install delegate is available.
+  bool has_google_play_webapk_install_delegate_;
+
   DISALLOW_COPY_AND_ASSIGN(TestWebApkInstaller);
 };
 
@@ -89,9 +108,15 @@
   explicit WebApkInstallerRunner(const GURL& best_icon_url)
       : url_request_context_getter_(new net::TestURLRequestContextGetter(
             base::ThreadTaskRunnerHandle::Get())),
-        best_icon_url_(best_icon_url) {}
+        best_icon_url_(best_icon_url),
+        has_google_play_webapk_install_delegate_(false) {}
+
   ~WebApkInstallerRunner() {}
 
+  void SetHasGooglePlayWebApkInstallDelegate(bool has_delegate) {
+    has_google_play_webapk_install_delegate_ = has_delegate;
+  }
+
   void RunInstallWebApk() {
     WebApkInstaller* installer = CreateWebApkInstaller();
 
@@ -123,7 +148,8 @@
     info.best_icon_url = best_icon_url_;
 
     // WebApkInstaller owns itself.
-    WebApkInstaller* installer = new TestWebApkInstaller(info, SkBitmap());
+    WebApkInstaller* installer = new TestWebApkInstaller(
+        info, SkBitmap(), has_google_play_webapk_install_delegate_);
     installer->SetTimeoutMs(100);
     return installer;
   }
@@ -154,6 +180,9 @@
   // Whether the installation process succeeded.
   bool success_;
 
+  // Whether the Google Play install delegate is available.
+  bool has_google_play_webapk_install_delegate_;
+
   DISALLOW_COPY_AND_ASSIGN(WebApkInstallerRunner);
 };
 
@@ -331,3 +360,11 @@
   runner->RunUpdateWebApk();
   EXPECT_TRUE(runner->success());
 }
+
+// Test installation succeeds using Google Play.
+TEST_F(WebApkInstallerTest, InstallFromGooglePlaySuccess) {
+  std::unique_ptr<WebApkInstallerRunner> runner = CreateWebApkInstallerRunner();
+  runner->SetHasGooglePlayWebApkInstallDelegate(true);
+  runner->RunInstallWebApk();
+  EXPECT_TRUE(runner->success());
+}
diff --git a/chrome/browser/browser_shutdown.cc b/chrome/browser/browser_shutdown.cc
index cf324c8..33c5ee6 100644
--- a/chrome/browser/browser_shutdown.cc
+++ b/chrome/browser/browser_shutdown.cc
@@ -38,6 +38,7 @@
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/tracing_controller.h"
 #include "printing/features/features.h"
+#include "rlz/features/features.h"
 
 #if defined(OS_WIN)
 #include "chrome/browser/first_run/upgrade_util_win.h"
@@ -52,7 +53,7 @@
 #include "chrome/browser/background/background_mode_manager.h"
 #endif
 
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
 #include "components/rlz/rlz_tracker.h"
 #endif
 
@@ -175,7 +176,7 @@
 
   prefs->CommitPendingWrite();
 
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
   // Cleanup any statics created by RLZ. Must be done before NotificationService
   // is destroyed.
   rlz::RLZTracker::CleanupRlz();
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index dcf863d..ab34cda 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -163,6 +163,7 @@
 #include "net/http/http_stream_factory.h"
 #include "net/url_request/url_request.h"
 #include "printing/features/features.h"
+#include "rlz/features/features.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/layout.h"
 #include "ui/base/material_design/material_design_controller.h"
@@ -246,10 +247,10 @@
 #include "printing/printed_document.h"
 #endif  // BUILDFLAG(ENABLE_PRINT_PREVIEW) && !defined(OFFICIAL_BUILD)
 
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
 #include "chrome/browser/rlz/chrome_rlz_tracker_delegate.h"
 #include "components/rlz/rlz_tracker.h"
-#endif  // defined(ENABLE_RLZ)
+#endif  // BUILDFLAG(ENABLE_RLZ)
 
 #if BUILDFLAG(ENABLE_WEBRTC)
 #include "chrome/browser/media/webrtc/webrtc_log_util.h"
@@ -1708,7 +1709,7 @@
   }
 #endif  // defined(OS_WIN)
 
-#if defined(ENABLE_RLZ) && !defined(OS_CHROMEOS)
+#if BUILDFLAG(ENABLE_RLZ) && !defined(OS_CHROMEOS)
   // Init the RLZ library. This just binds the dll and schedules a task on the
   // file thread to be run sometime later. If this is the first run we record
   // the installation event.
@@ -1725,7 +1726,7 @@
       ChromeRLZTrackerDelegate::IsGoogleDefaultSearch(profile_),
       ChromeRLZTrackerDelegate::IsGoogleHomepage(profile_),
       ChromeRLZTrackerDelegate::IsGoogleInStartpages(profile_));
-#endif  // defined(ENABLE_RLZ) && !defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(ENABLE_RLZ) && !defined(OS_CHROMEOS)
 
   // Configure modules that need access to resources.
   net::NetModule::SetResourceProvider(chrome_common_net::NetResourceProvider);
diff --git a/chrome/browser/chrome_browser_main_extra_parts_exo.cc b/chrome/browser/chrome_browser_main_extra_parts_exo.cc
index 01df0be..af9342b 100644
--- a/chrome/browser/chrome_browser_main_extra_parts_exo.cc
+++ b/chrome/browser/chrome_browser_main_extra_parts_exo.cc
@@ -131,6 +131,7 @@
   display_ =
       base::MakeUnique<exo::Display>(arc_notification_surface_manager_.get());
   wayland_server_ = exo::wayland::Server::Create(display_.get());
+  // Wayland server creation can fail if XDG_RUNTIME_DIR is not set correctly.
   if (wayland_server_)
     wayland_watcher_ = base::MakeUnique<WaylandWatcher>(wayland_server_.get());
 }
diff --git a/chrome/browser/chrome_content_browser_manifest_overlay.json b/chrome/browser/chrome_content_browser_manifest_overlay.json
index 0ff06ab9..d066222 100644
--- a/chrome/browser/chrome_content_browser_manifest_overlay.json
+++ b/chrome/browser/chrome_content_browser_manifest_overlay.json
@@ -20,9 +20,11 @@
         "ash": [
           // Under classic ash the browser provides some of the ash interfaces
           // to itself.
+          "app_list::mojom::AppList",
           "ash::mojom::AcceleratorController",
           "ash::mojom::CastConfig",
           "ash::mojom::LocaleNotificationController",
+          "ash::mojom::MediaController",
           "ash::mojom::NewWindowController",
           "ash::mojom::SessionController",
           "ash::mojom::ShelfController",
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 85b53d1..e04aed9 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -877,14 +877,22 @@
     "login/ui/models/user_board_model.cc",
     "login/ui/models/user_board_model.h",
     "login/ui/proxy_settings_dialog.cc",
+    "login/ui/shared_web_view.cc",
+    "login/ui/shared_web_view.h",
+    "login/ui/shared_web_view_factory.cc",
+    "login/ui/shared_web_view_factory.h",
     "login/ui/simple_web_view_dialog.cc",
     "login/ui/simple_web_view_dialog.h",
     "login/ui/user_adding_screen.cc",
     "login/ui/user_adding_screen.h",
     "login/ui/user_adding_screen_input_methods_controller.cc",
     "login/ui/user_adding_screen_input_methods_controller.h",
+    "login/ui/web_contents_forced_title.cc",
+    "login/ui/web_contents_forced_title.h",
     "login/ui/web_contents_set_background_color.cc",
     "login/ui/web_contents_set_background_color.h",
+    "login/ui/web_view_handle.cc",
+    "login/ui/web_view_handle.h",
     "login/ui/webui_login_display.cc",
     "login/ui/webui_login_display.h",
     "login/ui/webui_login_view.cc",
diff --git a/chrome/browser/chromeos/arc/arc_service_launcher.cc b/chrome/browser/chromeos/arc/arc_service_launcher.cc
index af50b1ae..be75eba 100644
--- a/chrome/browser/chromeos/arc/arc_service_launcher.cc
+++ b/chrome/browser/chromeos/arc/arc_service_launcher.cc
@@ -36,7 +36,6 @@
 #include "components/arc/obb_mounter/arc_obb_mounter_bridge.h"
 #include "components/arc/power/arc_power_bridge.h"
 #include "components/arc/storage_manager/arc_storage_manager.h"
-#include "components/arc/user_data/arc_user_data_service.h"
 #include "components/prefs/pref_member.h"
 #include "content/public/browser/browser_thread.h"
 #include "ui/arc/notification/arc_notification_manager.h"
diff --git a/chrome/browser/chromeos/arc/enterprise/arc_enterprise_reporting_service.cc b/chrome/browser/chromeos/arc/enterprise/arc_enterprise_reporting_service.cc
index 7c005ffb..ea63ad1 100644
--- a/chrome/browser/chromeos/arc/enterprise/arc_enterprise_reporting_service.cc
+++ b/chrome/browser/chromeos/arc/enterprise/arc_enterprise_reporting_service.cc
@@ -11,7 +11,6 @@
 #include "chrome/browser/chromeos/arc/arc_session_manager.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_service_manager.h"
-#include "components/arc/user_data/arc_user_data_service.h"
 
 namespace arc {
 
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
index 3e74f47..4b3e12bf 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -148,12 +148,13 @@
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "printing/backend/print_backend.h"
+#include "rlz/features/features.h"
 #include "ui/base/ime/chromeos/ime_keyboard.h"
 #include "ui/base/ime/chromeos/input_method_manager.h"
 #include "ui/base/touch/touch_device.h"
 #include "ui/events/event_utils.h"
 
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
 #include "components/rlz/rlz_tracker.h"
 #endif
 
diff --git a/chrome/browser/chromeos/chrome_interface_factory.cc b/chrome/browser/chromeos/chrome_interface_factory.cc
index 559d52a..865092c 100644
--- a/chrome/browser/chromeos/chrome_interface_factory.cc
+++ b/chrome/browser/chromeos/chrome_interface_factory.cc
@@ -16,7 +16,6 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/ui/ash/app_list/app_list_presenter_service.h"
 #include "chrome/browser/ui/ash/ash_util.h"
 #include "chrome/browser/ui/ash/keyboard_ui_service.h"
 #include "chrome/browser/ui/browser_commands.h"
@@ -26,7 +25,6 @@
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/service_manager/public/cpp/connection.h"
 #include "services/service_manager/public/cpp/interface_registry.h"
-#include "ui/app_list/presenter/app_list_presenter.mojom.h"
 #include "ui/keyboard/keyboard.mojom.h"
 
 namespace chromeos {
@@ -113,21 +111,11 @@
     launchable_->ProcessRequest(std::move(request));
   }
 
-  void BindRequest(app_list::mojom::AppListPresenterRequest request) {
-    if (!app_list_presenter_service_)
-      app_list_presenter_service_ = base::MakeUnique<AppListPresenterService>();
-    app_list_presenter_bindings_.AddBinding(app_list_presenter_service_.get(),
-                                            std::move(request));
-  }
-
   static base::LazyInstance<std::unique_ptr<FactoryImpl>>::Leaky factory_;
 
   std::unique_ptr<KeyboardUIService> keyboard_ui_service_;
   mojo::BindingSet<keyboard::mojom::Keyboard> keyboard_bindings_;
   std::unique_ptr<ChromeLaunchable> launchable_;
-  std::unique_ptr<AppListPresenterService> app_list_presenter_service_;
-  mojo::BindingSet<app_list::mojom::AppListPresenter>
-      app_list_presenter_bindings_;
 
   DISALLOW_COPY_AND_ASSIGN(FactoryImpl);
 };
@@ -153,8 +141,6 @@
                                                      main_thread_task_runner_);
   FactoryImpl::AddFactory<mash::mojom::Launchable>(registry,
                                                    main_thread_task_runner_);
-  FactoryImpl::AddFactory<app_list::mojom::AppListPresenter>(
-      registry, main_thread_task_runner_);
 
   // In classic ash, the browser process provides ash services to itself.
   if (!chrome::IsRunningInMash()) {
diff --git a/chrome/browser/chromeos/login/lock/webui_screen_locker.cc b/chrome/browser/chromeos/login/lock/webui_screen_locker.cc
index f962b73..4a7aa6d 100644
--- a/chrome/browser/chromeos/login/lock/webui_screen_locker.cc
+++ b/chrome/browser/chromeos/login/lock/webui_screen_locker.cc
@@ -61,7 +61,8 @@
 // WebUIScreenLocker implementation.
 
 WebUIScreenLocker::WebUIScreenLocker(ScreenLocker* screen_locker)
-    : screen_locker_(screen_locker),
+    : WebUILoginView(WebViewSettings()),
+      screen_locker_(screen_locker),
       network_state_helper_(new login::NetworkStateHelper),
       weak_factory_(this) {
   set_should_emit_login_prompt_visible(false);
@@ -88,7 +89,7 @@
   }
   // If LockScreen() was called, we need to clear the signin screen handler
   // delegate set in ShowSigninScreen so that it no longer points to us.
-  if (login_display_.get())
+  if (login_display_.get() && GetOobeUI())
     GetOobeUI()->ResetSigninScreenHandlerDelegate();
 
   if (keyboard::KeyboardController::GetInstance() && is_observing_keyboard_) {
@@ -107,7 +108,7 @@
   lock_window_->AddObserver(this);
 
   Init();
-  content::WebContentsObserver::Observe(webui_login_->GetWebContents());
+  content::WebContentsObserver::Observe(web_view()->GetWebContents());
 
   lock_window_->SetContentsView(this);
   lock_window_->SetBounds(bounds);
@@ -171,7 +172,7 @@
 void WebUIScreenLocker::FocusUserPod() {
   if (!webui_ready_)
     return;
-  webui_login_->RequestFocus();
+  web_view()->RequestFocus();
   GetWebUI()->CallJavascriptFunctionUnsafe(
       "cr.ui.Oobe.forceLockedUserPodFocus");
 }
diff --git a/chrome/browser/chromeos/login/login_utils_browsertest.cc b/chrome/browser/chromeos/login/login_utils_browsertest.cc
index c50687b..b8730021 100644
--- a/chrome/browser/chromeos/login/login_utils_browsertest.cc
+++ b/chrome/browser/chromeos/login/login_utils_browsertest.cc
@@ -27,8 +27,9 @@
 #include "google_apis/gaia/gaia_urls.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/embedded_test_server/http_response.h"
+#include "rlz/features/features.h"
 
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
 #include "components/rlz/rlz_tracker.h"
 #endif
 
@@ -36,7 +37,7 @@
 
 namespace {
 
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
 void GetAccessPointRlzInBackgroundThread(rlz_lib::AccessPoint point,
                                          base::string16* rlz) {
   ASSERT_FALSE(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
@@ -81,7 +82,7 @@
   DISALLOW_COPY_AND_ASSIGN(LoginUtilsTest);
 };
 
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
 IN_PROC_BROWSER_TEST_F(LoginUtilsTest, RlzInitialized) {
   WaitForSigninScreen();
 
diff --git a/chrome/browser/chromeos/login/screens/user_selection_screen.cc b/chrome/browser/chromeos/login/screens/user_selection_screen.cc
index 9ebe8f3..e5e2949 100644
--- a/chrome/browser/chromeos/login/screens/user_selection_screen.cc
+++ b/chrome/browser/chromeos/login/screens/user_selection_screen.cc
@@ -269,6 +269,13 @@
 
 void UserSelectionScreen::SetHandler(LoginDisplayWebUIHandler* handler) {
   handler_ = handler;
+
+  if (handler_) {
+    // Forcibly refresh all of the user images, as the |handler_| instance may
+    // have been reused.
+    for (user_manager::User* user : users_)
+      handler_->OnUserImageChanged(*user);
+  }
 }
 
 void UserSelectionScreen::SetView(UserBoardView* view) {
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc
index e6956a98..581a1c1 100644
--- a/chrome/browser/chromeos/login/session/user_session_manager.cc
+++ b/chrome/browser/chromeos/login/session/user_session_manager.cc
@@ -114,11 +114,12 @@
 #include "content/public/browser/storage_partition.h"
 #include "content/public/common/content_switches.h"
 #include "net/cert/sth_distributor.h"
+#include "rlz/features/features.h"
 #include "ui/base/ime/chromeos/input_method_descriptor.h"
 #include "ui/base/ime/chromeos/input_method_manager.h"
 #include "url/gurl.h"
 
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
 #include "chrome/browser/rlz/chrome_rlz_tracker_delegate.h"
 #include "components/rlz/rlz_tracker.h"
 #endif
@@ -242,7 +243,7 @@
   prefs->SetBoolean(prefs::kLanguageShouldMergeInputMethods, true);
 }
 
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
 // Flag file that disables RLZ tracking, when present.
 const base::FilePath::CharType kRLZDisabledFlagName[] =
     FILE_PATH_LITERAL(".rlz_disabled");
@@ -555,7 +556,7 @@
 }
 
 void UserSessionManager::InitRlz(Profile* profile) {
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
   if (!g_browser_process->local_state()->HasPrefPath(prefs::kRLZBrand)) {
     // Read brand code asynchronously from an OEM data and repost ourselves.
     google_brand::chromeos::InitBrand(
@@ -1354,7 +1355,7 @@
 }
 
 void UserSessionManager::InitRlzImpl(Profile* profile, bool disabled) {
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
   PrefService* local_state = g_browser_process->local_state();
   if (disabled) {
     // Empty brand code means an organic install (no RLZ pings are sent).
diff --git a/chrome/browser/chromeos/login/signin_screen_controller.h b/chrome/browser/chromeos/login/signin_screen_controller.h
index 6b95adc..b60cb2f5 100644
--- a/chrome/browser/chromeos/login/signin_screen_controller.h
+++ b/chrome/browser/chromeos/login/signin_screen_controller.h
@@ -23,6 +23,10 @@
 
 // Class that manages control flow between wizard screens. Wizard controller
 // interacts with screen controllers to move the user between screens.
+//
+// This class is allocated when the signin or lock screen is actually visible to
+// the user. It is a 'per-session' class; SignInScreenHandler, in comparsion, is
+// tied to the WebContents lifetime and therefore may live beyond this class.
 class SignInScreenController : public user_manager::RemoveUserDelegate,
                                public content::NotificationObserver {
  public:
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_impl.cc b/chrome/browser/chromeos/login/ui/login_display_host_impl.cc
index c8bb5f6..2b6122d 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host_impl.cc
+++ b/chrome/browser/chromeos/login/ui/login_display_host_impl.cc
@@ -1141,7 +1141,7 @@
   params.delegate = new LoginWidgetDelegate(login_window_);
   login_window_->Init(params);
 
-  login_view_ = new WebUILoginView();
+  login_view_ = new WebUILoginView(WebUILoginView::WebViewSettings());
   login_view_->Init();
   if (login_view_->webui_visible())
     OnLoginPromptVisible();
diff --git a/chrome/browser/chromeos/login/ui/shared_web_view.cc b/chrome/browser/chromeos/login/ui/shared_web_view.cc
new file mode 100644
index 0000000..e2d14be4
--- /dev/null
+++ b/chrome/browser/chromeos/login/ui/shared_web_view.cc
@@ -0,0 +1,81 @@
+// 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/chromeos/login/ui/shared_web_view.h"
+
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/chromeos/login/ui/web_view_handle.h"
+#include "chrome/browser/profiles/profile.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_widget_host.h"
+#include "content/public/browser/web_contents.h"
+#include "ui/views/controls/webview/webview.h"
+
+namespace chromeos {
+
+SharedWebView::SharedWebView(Profile* profile) : profile_(profile) {
+  registrar_.Add(this, chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST,
+                 content::NotificationService::AllSources());
+  memory_pressure_listener_ = base::MakeUnique<base::MemoryPressureListener>(
+      base::Bind(&SharedWebView::OnMemoryPressure, base::Unretained(this)));
+}
+
+SharedWebView::~SharedWebView() {}
+
+void SharedWebView::Shutdown() {
+  web_view_handle_ = nullptr;
+}
+
+bool SharedWebView::Get(const GURL& url,
+                        scoped_refptr<WebViewHandle>* out_handle) {
+  // At the moment only one shared WebView instance is supported per profile.
+  DCHECK(web_view_url_.is_empty() || web_view_url_ == url);
+  web_view_url_ = url;
+
+  // Ensure the WebView is not being reused simultaneously.
+  DCHECK(!web_view_handle_ || web_view_handle_->HasOneRef());
+
+  // Clear cached reference if it is no longer valid (ie, destroyed in task
+  // manager).
+  if (web_view_handle_ &&
+      !web_view_handle_->web_view()
+           ->GetWebContents()
+           ->GetRenderViewHost()
+           ->GetWidget()
+           ->GetView()) {
+    web_view_handle_ = nullptr;
+  }
+
+  // Create WebView if needed.
+  bool reused = true;
+  if (!web_view_handle_) {
+    web_view_handle_ = new WebViewHandle(profile_);
+    reused = false;
+  }
+
+  *out_handle = web_view_handle_;
+  return reused;
+}
+
+void SharedWebView::Observe(int type,
+                            const content::NotificationSource& source,
+                            const content::NotificationDetails& details) {
+  DCHECK_EQ(chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST, type);
+  web_view_handle_ = nullptr;
+}
+
+void SharedWebView::OnMemoryPressure(
+    base::MemoryPressureListener::MemoryPressureLevel level) {
+  switch (level) {
+    case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
+      break;
+    case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
+    case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
+      web_view_handle_ = nullptr;
+      break;
+  }
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/ui/shared_web_view.h b/chrome/browser/chromeos/login/ui/shared_web_view.h
new file mode 100644
index 0000000..abe936f8
--- /dev/null
+++ b/chrome/browser/chromeos/login/ui/shared_web_view.h
@@ -0,0 +1,70 @@
+// 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_CHROMEOS_LOGIN_UI_SHARED_WEB_VIEW_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_UI_SHARED_WEB_VIEW_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/memory/memory_pressure_listener.h"
+#include "base/memory/ref_counted.h"
+#include "components/keyed_service/core/keyed_service.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+#include "url/gurl.h"
+
+class Profile;
+
+namespace chromeos {
+
+class WebViewHandle;
+
+// Stores and fetches a views::WebView instance that is ulimately owned by the
+// signin profile. This allows for a WebView to be reused over time or
+// preloaded. Use SharedWebViewFactory to get an instance of this class.
+class SharedWebView : public KeyedService,
+                      public content::NotificationObserver {
+ public:
+  explicit SharedWebView(Profile* profile);
+  ~SharedWebView() override;
+  void Shutdown() override;
+
+  // Stores a webview instance inside of |out_handle|. |url| is the initial
+  // URL that the webview stores (note: this function does not perform the
+  // navigation). This returns true if the webview was reused, false if it
+  // was freshly created.
+  bool Get(const GURL& url, scoped_refptr<WebViewHandle>* out_handle);
+
+ private:
+  // content::NotificationObserver:
+  void Observe(int type,
+               const content::NotificationSource& source,
+               const content::NotificationDetails& details) override;
+
+  // Called when there is a memory pressure event.
+  void OnMemoryPressure(
+      base::MemoryPressureListener::MemoryPressureLevel level);
+
+  content::NotificationRegistrar registrar_;
+
+  // Profile used for creating the views::WebView instance.
+  Profile* const profile_;
+
+  // Cached URL that the |web_view_| instance should point to used for
+  // validation.
+  GURL web_view_url_;
+
+  // Shared web-view instance. Callers may take a reference on the handle so it
+  // could outlive this class.
+  scoped_refptr<WebViewHandle> web_view_handle_;
+
+  std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
+
+  DISALLOW_COPY_AND_ASSIGN(SharedWebView);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_UI_SHARED_WEB_VIEW_H_
diff --git a/chrome/browser/chromeos/login/ui/shared_web_view_factory.cc b/chrome/browser/chromeos/login/ui/shared_web_view_factory.cc
new file mode 100644
index 0000000..a42a30b3f
--- /dev/null
+++ b/chrome/browser/chromeos/login/ui/shared_web_view_factory.cc
@@ -0,0 +1,48 @@
+// 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/chromeos/login/ui/shared_web_view_factory.h"
+
+#include "chrome/browser/chromeos/login/ui/shared_web_view.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/profiles/incognito_helpers.h"
+#include "chrome/browser/profiles/profile.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+
+namespace chromeos {
+
+// static
+SharedWebView* SharedWebViewFactory::GetForProfile(Profile* profile) {
+  auto result = static_cast<SharedWebView*>(
+      GetInstance()->GetServiceForBrowserContext(profile, true));
+  return result;
+}
+
+// static
+SharedWebViewFactory* SharedWebViewFactory::GetInstance() {
+  return base::Singleton<SharedWebViewFactory>::get();
+}
+
+SharedWebViewFactory::SharedWebViewFactory()
+    : BrowserContextKeyedServiceFactory(
+          "SharedWebViewFactory",
+          BrowserContextDependencyManager::GetInstance()) {}
+
+SharedWebViewFactory::~SharedWebViewFactory() {}
+
+content::BrowserContext* SharedWebViewFactory::GetBrowserContextToUse(
+    content::BrowserContext* context) const {
+  // Make sure that only the SigninProfile is using a shared webview.
+  if (Profile::FromBrowserContext(context) != ProfileHelper::GetSigninProfile())
+    return nullptr;
+
+  return context;
+}
+
+KeyedService* SharedWebViewFactory::BuildServiceInstanceFor(
+    content::BrowserContext* context) const {
+  return new SharedWebView(Profile::FromBrowserContext(context));
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/ui/shared_web_view_factory.h b/chrome/browser/chromeos/login/ui/shared_web_view_factory.h
new file mode 100644
index 0000000..7386b5e
--- /dev/null
+++ b/chrome/browser/chromeos/login/ui/shared_web_view_factory.h
@@ -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.
+
+#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_UI_SHARED_WEB_VIEW_FACTORY_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_UI_SHARED_WEB_VIEW_FACTORY_H_
+
+#include "base/macros.h"
+#include "base/memory/singleton.h"
+#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+
+class Profile;
+
+namespace chromeos {
+
+class SharedWebView;
+
+// Fetches a SharedWebView instance for the signin profile.
+class SharedWebViewFactory : public BrowserContextKeyedServiceFactory {
+ public:
+  static SharedWebView* GetForProfile(Profile* profile);
+
+  static SharedWebViewFactory* GetInstance();
+
+ private:
+  friend struct base::DefaultSingletonTraits<SharedWebViewFactory>;
+
+  SharedWebViewFactory();
+  ~SharedWebViewFactory() override;
+
+  // BrowserContextKeyedServiceFactory:
+  content::BrowserContext* GetBrowserContextToUse(
+      content::BrowserContext* context) const override;
+  KeyedService* BuildServiceInstanceFor(
+      content::BrowserContext* profile) const override;
+
+  DISALLOW_COPY_AND_ASSIGN(SharedWebViewFactory);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_UI_SHARED_WEB_VIEW_FACTORY_H_
diff --git a/chrome/browser/chromeos/login/ui/web_contents_forced_title.cc b/chrome/browser/chromeos/login/ui/web_contents_forced_title.cc
new file mode 100644
index 0000000..51dbef2
--- /dev/null
+++ b/chrome/browser/chromeos/login/ui/web_contents_forced_title.cc
@@ -0,0 +1,39 @@
+// 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/chromeos/login/ui/web_contents_forced_title.h"
+
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/web_contents.h"
+
+DEFINE_WEB_CONTENTS_USER_DATA_KEY(chromeos::WebContentsForcedTitle);
+
+namespace chromeos {
+
+// static
+void WebContentsForcedTitle::CreateForWebContentsWithTitle(
+    content::WebContents* web_contents,
+    const base::string16& title) {
+  if (FromWebContents(web_contents))
+    return;
+
+  web_contents->UpdateTitleForEntry(nullptr, title);
+  web_contents->SetUserData(UserDataKey(),
+                            new WebContentsForcedTitle(web_contents, title));
+}
+
+WebContentsForcedTitle::WebContentsForcedTitle(
+    content::WebContents* web_contents,
+    const base::string16& title)
+    : content::WebContentsObserver(web_contents), title_(title) {}
+
+WebContentsForcedTitle::~WebContentsForcedTitle() {}
+
+void WebContentsForcedTitle::TitleWasSet(content::NavigationEntry* entry,
+                                         bool explicit_set) {
+  if (!entry || entry->GetTitle() != title_)
+    web_contents()->UpdateTitleForEntry(entry, title_);
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/ui/web_contents_forced_title.h b/chrome/browser/chromeos/login/ui/web_contents_forced_title.h
new file mode 100644
index 0000000..b12ebd2
--- /dev/null
+++ b/chrome/browser/chromeos/login/ui/web_contents_forced_title.h
@@ -0,0 +1,39 @@
+// 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_CHROMEOS_LOGIN_UI_WEB_CONTENTS_FORCED_TITLE_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_UI_WEB_CONTENTS_FORCED_TITLE_H_
+
+#include "base/strings/string16.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/browser/web_contents_user_data.h"
+
+namespace chromeos {
+
+// Ensures that the title of the WebContents instance this object is attached
+// to is always set to the given title value.
+class WebContentsForcedTitle
+    : public content::WebContentsObserver,
+      public content::WebContentsUserData<WebContentsForcedTitle> {
+ public:
+  static void CreateForWebContentsWithTitle(content::WebContents* web_contents,
+                                            const base::string16& title);
+
+  ~WebContentsForcedTitle() override;
+
+ private:
+  WebContentsForcedTitle(content::WebContents* web_contents,
+                         const base::string16& title);
+
+  // content::WebContentsObserver:
+  void TitleWasSet(content::NavigationEntry* entry, bool explicit_set) override;
+
+  base::string16 title_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebContentsForcedTitle);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_UI_WEB_CONTENTS_FORCED_TITLE_H_
diff --git a/chrome/browser/chromeos/login/ui/web_view_handle.cc b/chrome/browser/chromeos/login/ui/web_view_handle.cc
new file mode 100644
index 0000000..45165abd
--- /dev/null
+++ b/chrome/browser/chromeos/login/ui/web_view_handle.cc
@@ -0,0 +1,19 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/login/ui/web_view_handle.h"
+
+#include "chrome/browser/profiles/profile.h"
+#include "ui/views/controls/webview/webview.h"
+
+namespace chromeos {
+
+WebViewHandle::WebViewHandle(Profile* profile)
+    : web_view_(base::MakeUnique<views::WebView>(profile)) {
+  web_view_->set_owned_by_client();
+}
+
+WebViewHandle::~WebViewHandle() {}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/ui/web_view_handle.h b/chrome/browser/chromeos/login/ui/web_view_handle.h
new file mode 100644
index 0000000..856abfc
--- /dev/null
+++ b/chrome/browser/chromeos/login/ui/web_view_handle.h
@@ -0,0 +1,41 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_UI_WEB_VIEW_HANDLE_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_UI_WEB_VIEW_HANDLE_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+
+class Profile;
+
+namespace views {
+class WebView;
+}
+
+namespace chromeos {
+
+// Owns a views::WebView instance. Any caller actively using the views::WebView
+// instance should increase/decrease the refcount.
+class WebViewHandle : public base::RefCounted<WebViewHandle> {
+ public:
+  explicit WebViewHandle(Profile* profile);
+
+  // Returns an unowned pointer to the stored |web_view| instance.
+  views::WebView* web_view() { return web_view_.get(); }
+
+ private:
+  friend class base::RefCounted<WebViewHandle>;
+  ~WebViewHandle();
+
+  std::unique_ptr<views::WebView> web_view_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebViewHandle);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_UI_WEB_VIEW_HANDLE_H_
diff --git a/chrome/browser/chromeos/login/ui/webui_login_view.cc b/chrome/browser/chromeos/login/ui/webui_login_view.cc
index a9d53c9..3cc07a5 100644
--- a/chrome/browser/chromeos/login/ui/webui_login_view.cc
+++ b/chrome/browser/chromeos/login/ui/webui_login_view.cc
@@ -22,7 +22,11 @@
 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
 #include "chrome/browser/chromeos/login/ui/proxy_settings_dialog.h"
+#include "chrome/browser/chromeos/login/ui/shared_web_view.h"
+#include "chrome/browser/chromeos/login/ui/shared_web_view_factory.h"
+#include "chrome/browser/chromeos/login/ui/web_contents_forced_title.h"
 #include "chrome/browser/chromeos/login/ui/web_contents_set_background_color.h"
+#include "chrome/browser/chromeos/login/ui/web_view_handle.h"
 #include "chrome/browser/chromeos/login/ui/webui_login_display.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
@@ -176,7 +180,8 @@
 
 // WebUILoginView public: ------------------------------------------------------
 
-WebUILoginView::WebUILoginView() {
+WebUILoginView::WebUILoginView(const WebViewSettings& settings)
+    : settings_(settings) {
   registrar_.Add(this,
                  chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
                  content::NotificationService::AllSources());
@@ -252,15 +257,28 @@
   } else {
     NOTIMPLEMENTED();
   }
+
+  // If the WebView is going to be reused, make sure we call teardown.
+  if (!webui_login_->HasOneRef())
+    GetWebUI()->CallJavascriptFunctionUnsafe("cr.ui.Oobe.teardown");
+
+  // Clear any delegates we have set on the WebView.
+  WebContents* web_contents = web_view()->GetWebContents();
+  WebContentsModalDialogManager::FromWebContents(web_contents)
+      ->SetDelegate(nullptr);
+  web_contents->SetDelegate(nullptr);
 }
 
-void WebUILoginView::Init() {
-  Profile* signin_profile = ProfileHelper::GetSigninProfile();
-  webui_login_ = new views::WebView(signin_profile);
-  webui_login_->set_allow_accelerators(true);
-  AddChildView(webui_login_);
+// static
+void WebUILoginView::InitializeWebView(views::WebView* web_view,
+                                       const base::string16& title) {
+  WebContents* web_contents = web_view->GetWebContents();
 
-  WebContents* web_contents = webui_login_->GetWebContents();
+  if (!title.empty())
+    WebContentsForcedTitle::CreateForWebContentsWithTitle(web_contents, title);
+
+  WebContentsSetBackgroundColor::CreateForWebContentsWithColor(
+      web_contents, SK_ColorTRANSPARENT);
 
   // Ensure that the login UI has a tab ID, which will allow the GAIA auth
   // extension's background script to tell it apart from a captive portal window
@@ -274,16 +292,38 @@
 
   // LoginHandlerViews uses a constrained window for the password manager view.
   WebContentsModalDialogManager::CreateForWebContents(web_contents);
-  WebContentsModalDialogManager::FromWebContents(web_contents)->
-      SetDelegate(this);
 
-  web_contents->SetDelegate(this);
   extensions::SetViewType(web_contents, extensions::VIEW_TYPE_COMPONENT);
   extensions::ChromeExtensionWebContentsObserver::CreateForWebContents(
       web_contents);
   content::RendererPreferences* prefs = web_contents->GetMutableRendererPrefs();
   renderer_preferences_util::UpdateFromSystemSettings(
-      prefs, signin_profile, web_contents);
+      prefs, ProfileHelper::GetSigninProfile(), web_contents);
+}
+
+void WebUILoginView::Init() {
+  Profile* signin_profile = ProfileHelper::GetSigninProfile();
+
+  if (!settings_.preloaded_url.is_empty()) {
+    SharedWebView* shared_web_view =
+        SharedWebViewFactory::GetForProfile(signin_profile);
+    is_reusing_webview_ =
+        shared_web_view->Get(settings_.preloaded_url, &webui_login_);
+  } else {
+    webui_login_ = new WebViewHandle(signin_profile);
+    is_reusing_webview_ = false;
+  }
+
+  WebContents* web_contents = web_view()->GetWebContents();
+  if (!is_reusing_webview_)
+    InitializeWebView(web_view(), settings_.web_view_title);
+
+  web_view()->set_allow_accelerators(true);
+  AddChildView(web_view());
+
+  WebContentsModalDialogManager::FromWebContents(web_contents)
+      ->SetDelegate(this);
+  web_contents->SetDelegate(this);
 
   status_area_widget_host_ = new views::View;
   AddChildView(status_area_widget_host_);
@@ -294,7 +334,7 @@
 }
 
 void WebUILoginView::RequestFocus() {
-  webui_login_->RequestFocus();
+  web_view()->RequestFocus();
 }
 
 web_modal::WebContentsModalDialogHost*
@@ -334,7 +374,7 @@
   if (entry == accel_map_.end())
     return false;
 
-  if (!webui_login_)
+  if (!web_view())
     return true;
 
   content::WebUI* web_ui = GetWebUI();
@@ -351,12 +391,15 @@
   return GetWidget()->GetNativeWindow();
 }
 
-void WebUILoginView::LoadURL(const GURL & url) {
-  webui_login_->LoadInitialURL(url);
-  webui_login_->RequestFocus();
+void WebUILoginView::LoadURL(const GURL& url) {
+  // If a preloaded_url is provided then |url| must match it.
+  DCHECK(settings_.preloaded_url.is_empty() || url == settings_.preloaded_url);
 
-  WebContentsSetBackgroundColor::CreateForWebContentsWithColor(
-      GetWebContents(), SK_ColorTRANSPARENT);
+  if (is_reusing_webview_ && !settings_.preloaded_url.is_empty())
+    GetWebUI()->CallJavascriptFunctionUnsafe("cr.ui.Oobe.reload");
+  else
+    web_view()->LoadInitialURL(url);
+  web_view()->RequestFocus();
 
   // There is no Shell instance while running in mash.
   if (chrome::IsRunningInMash())
@@ -373,14 +416,17 @@
 }
 
 content::WebUI* WebUILoginView::GetWebUI() {
-  return webui_login_->web_contents()->GetWebUI();
+  return web_view()->web_contents()->GetWebUI();
 }
 
 content::WebContents* WebUILoginView::GetWebContents() {
-  return webui_login_->web_contents();
+  return web_view()->web_contents();
 }
 
 OobeUI* WebUILoginView::GetOobeUI() {
+  if (!GetWebUI())
+    return nullptr;
+
   return static_cast<OobeUI*>(GetWebUI()->GetController());
 }
 
@@ -442,8 +488,8 @@
 // WebUILoginView protected: ---------------------------------------------------
 
 void WebUILoginView::Layout() {
-  DCHECK(webui_login_);
-  webui_login_->SetBoundsRect(bounds());
+  DCHECK(web_view());
+  web_view()->SetBoundsRect(bounds());
 
   for (auto& observer : observer_list_)
     observer.OnPositionRequiresUpdate();
@@ -459,9 +505,9 @@
 
 void WebUILoginView::AboutToRequestFocusFromTabTraversal(bool reverse) {
   // Return the focus to the web contents.
-  webui_login_->web_contents()->FocusThroughTabTraversal(reverse);
+  web_view()->web_contents()->FocusThroughTabTraversal(reverse);
   GetWidget()->Activate();
-  webui_login_->web_contents()->Focus();
+  web_view()->web_contents()->Focus();
 }
 
 void WebUILoginView::Observe(int type,
@@ -479,6 +525,10 @@
   }
 }
 
+views::WebView* WebUILoginView::web_view() {
+  return webui_login_->web_view();
+}
+
 // WebUILoginView private: -----------------------------------------------------
 
 bool WebUILoginView::HandleContextMenu(
diff --git a/chrome/browser/chromeos/login/ui/webui_login_view.h b/chrome/browser/chromeos/login/ui/webui_login_view.h
index 5fbd2c7..c3f3bb2 100644
--- a/chrome/browser/chromeos/login/ui/webui_login_view.h
+++ b/chrome/browser/chromeos/login/ui/webui_login_view.h
@@ -9,6 +9,7 @@
 #include <string>
 
 #include "base/macros.h"
+#include "base/memory/ref_counted.h"
 #include "base/observer_list.h"
 #include "chrome/browser/ui/chrome_web_modal_dialog_manager_delegate.h"
 #include "components/web_modal/web_contents_modal_dialog_host.h"
@@ -18,8 +19,7 @@
 #include "ui/views/controls/webview/unhandled_keyboard_event_handler.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_delegate.h"
-
-class GURL;
+#include "url/gurl.h"
 
 namespace content {
 class WebUI;
@@ -34,6 +34,7 @@
 namespace chromeos {
 
 class OobeUI;
+class WebViewHandle;
 
 // View used to render a WebUI supporting Widget. This widget is used for the
 // WebUI based start up and lock screens. It contains a WebView.
@@ -43,10 +44,19 @@
                        public ChromeWebModalDialogManagerDelegate,
                        public web_modal::WebContentsModalDialogHost {
  public:
+  struct WebViewSettings {
+    // URL of the WebView to preload and reuse across WebUILoginView instances.
+    GURL preloaded_url;
+
+    // Title of the web contents. This will be shown in the task manager. If
+    // empty, the default webview title will be used.
+    base::string16 web_view_title;
+  };
+
   // Internal class name.
   static const char kViewClassName[];
 
-  WebUILoginView();
+  explicit WebUILoginView(const WebViewSettings& settings);
   ~WebUILoginView() override;
 
   // Initializes the webui login view.
@@ -105,6 +115,9 @@
   }
 
  protected:
+  static void InitializeWebView(views::WebView* web_view,
+                                const base::string16& title);
+
   // Overridden from views::View:
   void Layout() override;
   void OnLocaleChanged() override;
@@ -116,8 +129,7 @@
                const content::NotificationSource& source,
                const content::NotificationDetails& details) override;
 
-  // WebView for rendering a webpage as a webui login.
-  views::WebView* webui_login_ = nullptr;
+  views::WebView* web_view();
 
  private:
   // Map type for the accelerator-to-identifier map.
@@ -148,6 +160,15 @@
 
   content::NotificationRegistrar registrar_;
 
+  // WebView configuration options.
+  const WebViewSettings settings_;
+
+  // WebView for rendering a webpage as a webui login.
+  scoped_refptr<WebViewHandle> webui_login_;
+
+  // True if the current webview instance (ie, GetWebUI()) has been reused.
+  bool is_reusing_webview_ = false;
+
   // Converts keyboard events on the WebContents to accelerators.
   views::UnhandledKeyboardEventHandler unhandled_keyboard_event_handler_;
 
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn
index afc16da..4398018 100644
--- a/chrome/browser/extensions/BUILD.gn
+++ b/chrome/browser/extensions/BUILD.gn
@@ -7,6 +7,7 @@
 import("//chrome/common/features.gni")
 import("//extensions/features/features.gni")
 import("//media/media_options.gni")
+import("//rlz/features/features.gni")
 
 assert(enable_extensions)
 
@@ -897,6 +898,7 @@
     "//net",
     "//ppapi/features",
     "//printing/features",
+    "//rlz/features",
     "//skia",
     "//sql",
     "//storage/browser",
diff --git a/chrome/browser/extensions/api/music_manager_private/device_id_win.cc b/chrome/browser/extensions/api/music_manager_private/device_id_win.cc
index 90814d7..6455e9a 100644
--- a/chrome/browser/extensions/api/music_manager_private/device_id_win.cc
+++ b/chrome/browser/extensions/api/music_manager_private/device_id_win.cc
@@ -25,8 +25,9 @@
 #include "base/threading/thread_restrictions.h"
 #include "base/win/windows_version.h"
 #include "content/public/browser/browser_thread.h"
+#include "rlz/features/features.h"
 
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
 #include "rlz/lib/machine_id.h"
 #endif
 
@@ -183,13 +184,13 @@
 }
 
 std::string GetRlzMachineId() {
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
   std::string machine_id;
   if (!rlz_lib::GetMachineId(&machine_id))
-    return "";
+    return std::string();
   return machine_id;
 #else
-  return "";
+  return std::string();
 #endif
 }
 
diff --git a/chrome/browser/extensions/api/music_manager_private/music_manager_private_browsertest.cc b/chrome/browser/extensions/api/music_manager_private/music_manager_private_browsertest.cc
index 27e7bc9..40a360b 100644
--- a/chrome/browser/extensions/api/music_manager_private/music_manager_private_browsertest.cc
+++ b/chrome/browser/extensions/api/music_manager_private/music_manager_private_browsertest.cc
@@ -5,9 +5,10 @@
 #include "build/build_config.h"
 #include "chrome/browser/apps/app_browsertest_util.h"
 #include "extensions/test/extension_test_message_listener.h"
+#include "rlz/features/features.h"
 
 // Supported on all platforms, but on Windows only if RLZ is enabled.
-#if !defined(OS_WIN) || defined(ENABLE_RLZ)
+#if !defined(OS_WIN) || BUILDFLAG(ENABLE_RLZ)
 
 class MusicManagerPrivateTest : public extensions::PlatformAppBrowserTest {
 };
diff --git a/chrome/browser/extensions/install_signer.cc b/chrome/browser/extensions/install_signer.cc
index a7a085af..bc584ad 100644
--- a/chrome/browser/extensions/install_signer.cc
+++ b/chrome/browser/extensions/install_signer.cc
@@ -34,9 +34,10 @@
 #include "net/url_request/url_fetcher_delegate.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "net/url_request/url_request_status.h"
+#include "rlz/features/features.h"
 #include "url/gurl.h"
 
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
 #include "rlz/lib/machine_id.h"
 #endif
 
@@ -84,7 +85,7 @@
 // |result|.
 bool HashWithMachineId(const std::string& salt, std::string* result) {
   std::string machine_id;
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
   if (!rlz_lib::GetMachineId(&machine_id))
     return false;
 #else
diff --git a/chrome/browser/mac/exception_processor_unittest.mm b/chrome/browser/mac/exception_processor_unittest.mm
index 74c1128..0e8460b 100644
--- a/chrome/browser/mac/exception_processor_unittest.mm
+++ b/chrome/browser/mac/exception_processor_unittest.mm
@@ -95,7 +95,7 @@
   CFRunLoopRef run_loop = CFRunLoopGetCurrent();
 
   CFRunLoopPerformBlock(run_loop, kCFRunLoopCommonModes, ^{
-    [NSException raise:@"ThrowExceptionInRunLoop" format:nil];
+    [NSException raise:@"ThrowExceptionInRunLoop" format:@""];
   });
   CFRunLoopPerformBlock(run_loop, kCFRunLoopCommonModes, ^{
     CFRunLoopStop(run_loop);
@@ -129,7 +129,7 @@
   CFRunLoopRef run_loop = CFRunLoopGetCurrent();
   CFRunLoopPerformBlock(run_loop, kCFRunLoopCommonModes, ^{
     @try {
-      [NSException raise:@"ObjcExceptionPreprocessCaught" format:nil];
+      [NSException raise:@"ObjcExceptionPreprocessCaught" format:@""];
     } @catch (id exception) {
     }
   });
diff --git a/chrome/browser/media/cast_remoting_connector_messaging.cc b/chrome/browser/media/cast_remoting_connector_messaging.cc
index 40682e37..d55d6a5 100644
--- a/chrome/browser/media/cast_remoting_connector_messaging.cc
+++ b/chrome/browser/media/cast_remoting_connector_messaging.cc
@@ -50,10 +50,9 @@
   start += specifier.size();
   if (start + 1 >= message.size())
     return -1; // Must be at least one hex digit following the specifier.
+  const auto length = message.find(kMessageFieldSeparator, start) - start;
   int parsed_value;
-  if (!base::HexStringToInt(
-          message.substr(start, message.find(kMessageFieldSeparator, start)),
-          &parsed_value) ||
+  if (!base::HexStringToInt(message.substr(start, length), &parsed_value) ||
       parsed_value < 0 ||
       parsed_value > std::numeric_limits<int32_t>::max()) {
     return -1; // Non-hex digits, or outside valid range.
diff --git a/chrome/browser/ntp_snippets/download_suggestions_provider.cc b/chrome/browser/ntp_snippets/download_suggestions_provider.cc
index b1e5fac..86155a2e 100644
--- a/chrome/browser/ntp_snippets/download_suggestions_provider.cc
+++ b/chrome/browser/ntp_snippets/download_suggestions_provider.cc
@@ -17,6 +17,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
+#include "base/values.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/ntp_snippets/features.h"
@@ -29,6 +30,7 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/image/image.h"
 
+using base::ContainsValue;
 using content::DownloadItem;
 using content::DownloadManager;
 using ntp_snippets::Category;
@@ -49,6 +51,9 @@
 
 const char* kMaxSuggestionsCountParamName = "downloads_max_count";
 
+// Maximal number of dismissed asset download IDs stored at any time.
+const int kMaxDismissedIdCount = 100;
+
 bool CompareOfflinePagesMostRecentlyCreatedFirst(const OfflinePageItem& left,
                                                  const OfflinePageItem& right) {
   return left.creation_time > right.creation_time;
@@ -186,12 +191,8 @@
 void DownloadSuggestionsProvider::DismissSuggestion(
     const ContentSuggestion::ID& suggestion_id) {
   DCHECK_EQ(provided_category_, suggestion_id.category());
-  std::set<std::string> dismissed_ids =
-      ReadDismissedIDsFromPrefs(CorrespondsToOfflinePage(suggestion_id));
-  dismissed_ids.insert(suggestion_id.id_within_category());
-  StoreDismissedIDsToPrefs(CorrespondsToOfflinePage(suggestion_id),
-                           dismissed_ids);
 
+  AddToDismissedStorageIfNeeded(suggestion_id);
   RemoveSuggestionFromCacheAndRetrieveMoreIfNeeded(suggestion_id);
 }
 
@@ -262,7 +263,7 @@
 void DownloadSuggestionsProvider::ClearDismissedSuggestionsForDebugging(
     Category category) {
   DCHECK_EQ(provided_category_, category);
-  StoreAssetDismissedIDsToPrefs(std::set<std::string>());
+  StoreAssetDismissedIDsToPrefs(std::vector<std::string>());
   StoreOfflinePageDismissedIDsToPrefs(std::set<std::string>());
   AsynchronouslyFetchAllDownloadsAndSubmitSuggestions();
 }
@@ -274,6 +275,10 @@
   registry->RegisterListPref(kDismissedOfflinePageDownloadSuggestions);
 }
 
+int DownloadSuggestionsProvider::GetMaxDismissedCountForTesting() {
+  return kMaxDismissedIdCount;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Private methods
 
@@ -281,10 +286,12 @@
     GetPagesMatchingQueryCallbackForGetDismissedSuggestions(
         const ntp_snippets::DismissedSuggestionsCallback& callback,
         const std::vector<OfflinePageItem>& offline_pages) const {
-  std::set<std::string> dismissed_ids = ReadOfflinePageDismissedIDsFromPrefs();
+  std::set<std::string> dismissed_offline_ids =
+      ReadOfflinePageDismissedIDsFromPrefs();
   std::vector<ContentSuggestion> suggestions;
   for (const OfflinePageItem& item : offline_pages) {
-    if (dismissed_ids.count(GetOfflinePagePerCategoryID(item.offline_id))) {
+    if (dismissed_offline_ids.count(
+            GetOfflinePagePerCategoryID(item.offline_id))) {
       suggestions.push_back(ConvertOfflinePage(item));
     }
   }
@@ -293,10 +300,12 @@
     std::vector<DownloadItem*> all_downloads;
     download_manager_->GetAllDownloads(&all_downloads);
 
-    dismissed_ids = ReadAssetDismissedIDsFromPrefs();
+    std::vector<std::string> dismissed_asset_ids =
+        ReadAssetDismissedIDsFromPrefs();
 
     for (const DownloadItem* item : all_downloads) {
-      if (dismissed_ids.count(GetAssetDownloadPerCategoryID(item->GetId()))) {
+      if (ContainsValue(dismissed_asset_ids,
+                        GetAssetDownloadPerCategoryID(item->GetId()))) {
         suggestions.push_back(ConvertDownloadItem(*item));
       }
     }
@@ -369,7 +378,7 @@
 }
 
 void DownloadSuggestionsProvider::OnDownloadUpdated(DownloadItem* item) {
-  if (base::ContainsValue(cached_asset_downloads_, item)) {
+  if (ContainsValue(cached_asset_downloads_, item)) {
     if (item->GetFileExternallyRemoved()) {
       InvalidateSuggestion(GetAssetDownloadPerCategoryID(item->GetId()));
     } else {
@@ -450,25 +459,23 @@
 
   std::vector<DownloadItem*> all_downloads;
   download_manager_->GetAllDownloads(&all_downloads);
-  std::set<std::string> old_dismissed_ids = ReadAssetDismissedIDsFromPrefs();
-  std::set<std::string> retained_dismissed_ids;
+  std::vector<std::string> old_dismissed_ids = ReadAssetDismissedIDsFromPrefs();
   cached_asset_downloads_.clear();
   for (const DownloadItem* item : all_downloads) {
     std::string within_category_id =
         GetAssetDownloadPerCategoryID(item->GetId());
-    if (!old_dismissed_ids.count(within_category_id)) {
+    if (!ContainsValue(old_dismissed_ids, within_category_id)) {
       if (IsDownloadCompleted(*item)) {
         cached_asset_downloads_.push_back(item);
       }
-    } else {
-      retained_dismissed_ids.insert(within_category_id);
     }
   }
 
-  if (old_dismissed_ids.size() != retained_dismissed_ids.size()) {
-    StoreAssetDismissedIDsToPrefs(retained_dismissed_ids);
-  }
-
+  // We do not prune dismissed IDs, because it is not possible to ensure that
+  // the list of downloads is complete (i.e. DownloadManager has finished
+  // reading them).
+  // TODO(vitaliii): Prune dismissed IDs once the |OnLoaded| notification is
+  // provided. See crbug.com/672758.
   const int max_suggestions_count = GetMaxSuggestionsCount();
   if (static_cast<int>(cached_asset_downloads_.size()) >
       max_suggestions_count) {
@@ -566,12 +573,13 @@
     return false;
   }
 
-  if (base::ContainsValue(cached_asset_downloads_, item)) {
+  if (ContainsValue(cached_asset_downloads_, item)) {
     return false;
   }
 
-  std::set<std::string> dismissed_ids = ReadAssetDismissedIDsFromPrefs();
-  if (dismissed_ids.count(GetAssetDownloadPerCategoryID(item->GetId()))) {
+  std::vector<std::string> dismissed_ids = ReadAssetDismissedIDsFromPrefs();
+  if (ContainsValue(dismissed_ids,
+                    GetAssetDownloadPerCategoryID(item->GetId()))) {
     return false;
   }
 
@@ -709,31 +717,38 @@
   ContentSuggestion::ID suggestion_id(provided_category_, id_within_category);
   observer()->OnSuggestionInvalidated(this, suggestion_id);
 
-  std::set<std::string> dismissed_ids =
-      ReadDismissedIDsFromPrefs(CorrespondsToOfflinePage(suggestion_id));
-  auto it = dismissed_ids.find(id_within_category);
-  if (it != dismissed_ids.end()) {
-    dismissed_ids.erase(it);
-    StoreDismissedIDsToPrefs(CorrespondsToOfflinePage(suggestion_id),
-                             dismissed_ids);
-  }
-
+  RemoveFromDismissedStorageIfNeeded(suggestion_id);
   RemoveSuggestionFromCacheAndRetrieveMoreIfNeeded(suggestion_id);
 }
 
-std::set<std::string>
+// TODO(vitaliii): Do not use std::vector, when we ensure that pruning happens
+// at the right time (crbug.com/672758).
+std::vector<std::string>
 DownloadSuggestionsProvider::ReadAssetDismissedIDsFromPrefs() const {
-  return ntp_snippets::prefs::ReadDismissedIDsFromPrefs(
-      *pref_service_, kDismissedAssetDownloadSuggestions);
+  std::vector<std::string> dismissed_ids;
+  const base::ListValue* list =
+      pref_service_->GetList(kDismissedAssetDownloadSuggestions);
+  for (const std::unique_ptr<base::Value>& value : *list) {
+    std::string dismissed_id;
+    bool success = value->GetAsString(&dismissed_id);
+    DCHECK(success) << "Failed to parse dismissed id from prefs param "
+                    << kDismissedAssetDownloadSuggestions << " into string.";
+    dismissed_ids.push_back(dismissed_id);
+  }
+  return dismissed_ids;
 }
 
 void DownloadSuggestionsProvider::StoreAssetDismissedIDsToPrefs(
-    const std::set<std::string>& dismissed_ids) {
+    const std::vector<std::string>& dismissed_ids) {
   DCHECK(std::all_of(
       dismissed_ids.begin(), dismissed_ids.end(),
       [](const std::string& id) { return id[0] == kAssetDownloadsPrefix; }));
-  ntp_snippets::prefs::StoreDismissedIDsToPrefs(
-      pref_service_, kDismissedAssetDownloadSuggestions, dismissed_ids);
+
+  base::ListValue list;
+  for (const std::string& dismissed_id : dismissed_ids) {
+    list.AppendString(dismissed_id);
+  }
+  pref_service_->Set(kDismissedAssetDownloadSuggestions, list);
 }
 
 std::set<std::string>
@@ -752,22 +767,45 @@
       pref_service_, kDismissedOfflinePageDownloadSuggestions, dismissed_ids);
 }
 
-std::set<std::string> DownloadSuggestionsProvider::ReadDismissedIDsFromPrefs(
-    bool for_offline_page_downloads) const {
-  if (for_offline_page_downloads) {
-    return ReadOfflinePageDismissedIDsFromPrefs();
-  }
-  return ReadAssetDismissedIDsFromPrefs();
-}
-
-// TODO(vitaliii): Store one set instead of two. See crbug.com/656024.
-void DownloadSuggestionsProvider::StoreDismissedIDsToPrefs(
-    bool for_offline_page_downloads,
-    const std::set<std::string>& dismissed_ids) {
-  if (for_offline_page_downloads) {
+void DownloadSuggestionsProvider::AddToDismissedStorageIfNeeded(
+    const ContentSuggestion::ID& suggestion_id) {
+  if (CorrespondsToOfflinePage(suggestion_id)) {
+    std::set<std::string> dismissed_ids =
+        ReadOfflinePageDismissedIDsFromPrefs();
+    dismissed_ids.insert(suggestion_id.id_within_category());
     StoreOfflinePageDismissedIDsToPrefs(dismissed_ids);
   } else {
-    StoreAssetDismissedIDsToPrefs(dismissed_ids);
+    std::vector<std::string> dismissed_ids = ReadAssetDismissedIDsFromPrefs();
+    // The suggestion may be double dismissed from previously opened NTPs.
+    if (!ContainsValue(dismissed_ids, suggestion_id.id_within_category())) {
+      dismissed_ids.push_back(suggestion_id.id_within_category());
+      // TODO(vitaliii): Remove this workaround once the dismissed ids are
+      // pruned. See crbug.com/672758.
+      while (dismissed_ids.size() > kMaxDismissedIdCount) {
+        dismissed_ids.erase(dismissed_ids.begin());
+      }
+      StoreAssetDismissedIDsToPrefs(dismissed_ids);
+    }
+  }
+}
+
+void DownloadSuggestionsProvider::RemoveFromDismissedStorageIfNeeded(
+    const ContentSuggestion::ID& suggestion_id) {
+  if (CorrespondsToOfflinePage(suggestion_id)) {
+    std::set<std::string> dismissed_ids =
+        ReadOfflinePageDismissedIDsFromPrefs();
+    if (dismissed_ids.count(suggestion_id.id_within_category())) {
+      dismissed_ids.erase(suggestion_id.id_within_category());
+      StoreOfflinePageDismissedIDsToPrefs(dismissed_ids);
+    }
+  } else {
+    std::vector<std::string> dismissed_ids = ReadAssetDismissedIDsFromPrefs();
+    auto it = std::find(dismissed_ids.begin(), dismissed_ids.end(),
+                        suggestion_id.id_within_category());
+    if (it != dismissed_ids.end()) {
+      dismissed_ids.erase(it);
+      StoreAssetDismissedIDsToPrefs(dismissed_ids);
+    }
   }
 }
 
diff --git a/chrome/browser/ntp_snippets/download_suggestions_provider.h b/chrome/browser/ntp_snippets/download_suggestions_provider.h
index 9b7cdb2..a98dc97 100644
--- a/chrome/browser/ntp_snippets/download_suggestions_provider.h
+++ b/chrome/browser/ntp_snippets/download_suggestions_provider.h
@@ -75,6 +75,8 @@
 
   static void RegisterProfilePrefs(PrefRegistrySimple* registry);
 
+  static int GetMaxDismissedCountForTesting();
+
  private:
   friend class DownloadSuggestionsProviderTest;
 
@@ -171,11 +173,11 @@
   void InvalidateSuggestion(const std::string& id_within_category);
 
   // Reads dismissed IDs related to asset downloads from prefs.
-  std::set<std::string> ReadAssetDismissedIDsFromPrefs() const;
+  std::vector<std::string> ReadAssetDismissedIDsFromPrefs() const;
 
   // Writes |dismissed_ids| into prefs for asset downloads.
   void StoreAssetDismissedIDsToPrefs(
-      const std::set<std::string>& dismissed_ids);
+      const std::vector<std::string>& dismissed_ids);
 
   // Reads dismissed IDs related to offline page downloads from prefs.
   std::set<std::string> ReadOfflinePageDismissedIDsFromPrefs() const;
@@ -184,15 +186,15 @@
   void StoreOfflinePageDismissedIDsToPrefs(
       const std::set<std::string>& dismissed_ids);
 
-  // Reads from prefs dismissed IDs related to either offline page or asset
-  // downloads (given by |for_offline_page_downloads|).
-  std::set<std::string> ReadDismissedIDsFromPrefs(
-      bool for_offline_page_downloads) const;
+  // Adds a suggestion ID to the dismissed list in prefs, if it is not there.
+  // Works for both Offline Page and Asset downloads.
+  void AddToDismissedStorageIfNeeded(
+      const ntp_snippets::ContentSuggestion::ID& suggestion_id);
 
-  // Writes |dismissed_ids| into prefs for either offline page or asset
-  // downloads (given by |for_offline_page_downloads|).
-  void StoreDismissedIDsToPrefs(bool for_offline_page_downloads,
-                                const std::set<std::string>& dismissed_ids);
+  // Removes a suggestion ID from the dismissed list in prefs, if it is there.
+  // Works for both Offline Page and Asset downloads.
+  void RemoveFromDismissedStorageIfNeeded(
+      const ntp_snippets::ContentSuggestion::ID& suggestion_id);
 
   void UnregisterDownloadItemObservers();
 
diff --git a/chrome/browser/ntp_snippets/download_suggestions_provider_unittest.cc b/chrome/browser/ntp_snippets/download_suggestions_provider_unittest.cc
index c68d1d3c..90f654f 100644
--- a/chrome/browser/ntp_snippets/download_suggestions_provider_unittest.cc
+++ b/chrome/browser/ntp_snippets/download_suggestions_provider_unittest.cc
@@ -38,12 +38,12 @@
 using testing::AnyNumber;
 using testing::ElementsAre;
 using testing::IsEmpty;
+using testing::Lt;
 using testing::Mock;
 using testing::Return;
 using testing::SizeIs;
 using testing::StrictMock;
 using testing::UnorderedElementsAre;
-using testing::Lt;
 
 namespace ntp_snippets {
 // These functions are implicitly used to print out values during the tests.
@@ -926,3 +926,87 @@
                                             HasUrl("http://download.com/2"))));
   CreateProvider(/*show_assets=*/true, /*show_offline_pages=*/false);
 }
+
+TEST_F(DownloadSuggestionsProviderTest,
+       ShouldNotPruneDismissedSuggestionsOnStartup) {
+  IgnoreOnCategoryStatusChangedToAvailable();
+  IgnoreOnSuggestionInvalidated();
+
+  // We dismiss an item to store it in the list of dismissed items.
+  *(downloads_manager()->mutable_items()) = CreateDummyAssetDownloads({1});
+  EXPECT_CALL(*observer(), OnNewSuggestions(_, downloads_category(), _));
+  CreateProvider(/*show_assets=*/true, /*show_offline_pages=*/false);
+  provider()->DismissSuggestion(
+      GetDummySuggestionId(1, /*is_offline_page=*/false));
+  DestroyProvider();
+
+  // We simulate current DownloadManager behaviour;
+  // The download manager has not started reading the list yet, so it is empty.
+  downloads_manager()->mutable_items()->clear();
+  EXPECT_CALL(*observer(), OnNewSuggestions(_, downloads_category(), _));
+  CreateProvider(/*show_assets=*/true, /*show_offline_pages=*/false);
+  Mock::VerifyAndClearExpectations(observer());
+
+  // The first download is being read.
+  *(downloads_manager()->mutable_items()) = CreateDummyAssetDownloads({1});
+  EXPECT_CALL(*observer(), OnNewSuggestions(_, downloads_category(), _))
+      .Times(0);
+  FireDownloadCreated(downloads_manager()->items()[0].get());
+  // The first download should not be reported, because it is dismissed.
+}
+
+TEST_F(DownloadSuggestionsProviderTest, ShouldStoreDismissedSuggestions) {
+  IgnoreOnCategoryStatusChangedToAvailable();
+  IgnoreOnSuggestionInvalidated();
+
+  // Dismiss items to store them in the list of dismissed items.
+  *(offline_pages_model()->mutable_items()) = CreateDummyOfflinePages({1});
+  *(downloads_manager()->mutable_items()) = CreateDummyAssetDownloads({1});
+  EXPECT_CALL(*observer(), OnNewSuggestions(_, downloads_category(), _));
+  CreateProvider(/*show_assets=*/true, /*show_offline_pages=*/true);
+  provider()->DismissSuggestion(
+      GetDummySuggestionId(1, /*is_offline_page=*/true));
+  provider()->DismissSuggestion(
+      GetDummySuggestionId(1, /*is_offline_page=*/false));
+  // Destroy and create provider to simulate turning off Chrome.
+  DestroyProvider();
+
+  EXPECT_CALL(*observer(), OnNewSuggestions(_, downloads_category(), _));
+  CreateProvider(/*show_assets=*/true, /*show_offline_pages=*/true);
+  EXPECT_THAT(GetDismissedSuggestions(),
+              UnorderedElementsAre(HasUrl("http://dummy.com/1"),
+                                   HasUrl("http://download.com/1")));
+}
+
+// TODO(vitaliii): Remove this test once the dismissed ids are pruned. See
+// crbug.com/672758.
+TEST_F(DownloadSuggestionsProviderTest, ShouldRemoveOldDismissedIdsIfTooMany) {
+  IgnoreOnCategoryStatusChangedToAvailable();
+  IgnoreOnSuggestionInvalidated();
+
+  const int kMaxDismissedIdCount =
+      DownloadSuggestionsProvider::GetMaxDismissedCountForTesting();
+  std::vector<int> ids;
+  for (int i = 0; i < kMaxDismissedIdCount + 1; ++i) {
+    ids.push_back(i);
+  }
+
+  *(downloads_manager()->mutable_items()) = CreateDummyAssetDownloads(ids);
+  EXPECT_CALL(*observer(), OnNewSuggestions(_, downloads_category(), _));
+  CreateProvider(/*show_assets=*/true, /*show_offline_pages=*/false);
+
+  for (int i = 0; i < static_cast<int>(ids.size()); ++i) {
+    provider()->DismissSuggestion(
+        GetDummySuggestionId(i, /*is_offline_page=*/false));
+  }
+
+  EXPECT_THAT(GetDismissedSuggestions(), SizeIs(kMaxDismissedIdCount));
+  DestroyProvider();
+  // The oldest dismissed suggestion must become undismissed now. This is a
+  // temporary workaround and not what we want in long term. This test must be
+  // removed once we start pruning dismissed asset downloads on startup.
+  EXPECT_CALL(*observer(),
+              OnNewSuggestions(_, downloads_category(),
+                               ElementsAre(HasUrl("http://download.com/0"))));
+  CreateProvider(/*show_assets=*/true, /*show_offline_pages=*/false);
+}
diff --git a/chrome/browser/predictors/resource_prefetch_predictor_browsertest.cc b/chrome/browser/predictors/resource_prefetch_predictor_browsertest.cc
index c47ea93c..3016a1e 100644
--- a/chrome/browser/predictors/resource_prefetch_predictor_browsertest.cc
+++ b/chrome/browser/predictors/resource_prefetch_predictor_browsertest.cc
@@ -112,6 +112,19 @@
   navigation_id->main_frame_url = GURL("http://127.0.0.1");
 }
 
+void ModifySubresourceForComparison(URLRequestSummary* subresource,
+                                    bool match_navigation_id) {
+  if (!match_navigation_id)
+    SetValidNavigationID(&subresource->navigation_id);
+  if (subresource->resource_type == content::RESOURCE_TYPE_IMAGE &&
+      subresource->priority == net::LOWEST) {
+    // Fuzzy comparison for images because an image priority can be
+    // boosted during layout via
+    // ResourceFetcher::updateAllImageResourcePriorities().
+    subresource->priority = net::MEDIUM;
+  }
+}
+
 // Does a custom comparison of subresources of URLRequestSummary
 // and fail the test if the expectation is not met.
 void CompareSubresources(std::vector<URLRequestSummary> actual_subresources,
@@ -121,12 +134,11 @@
   // ResourcePrefetchPredictor only cares about the first occurrence of each.
   RemoveDuplicateSubresources(&actual_subresources);
 
-  if (!match_navigation_id) {
-    for (auto& subresource : actual_subresources)
-      SetValidNavigationID(&subresource.navigation_id);
-    for (auto& subresource : expected_subresources)
-      SetValidNavigationID(&subresource.navigation_id);
-  }
+  for (auto& subresource : actual_subresources)
+    ModifySubresourceForComparison(&subresource, match_navigation_id);
+  for (auto& subresource : expected_subresources)
+    ModifySubresourceForComparison(&subresource, match_navigation_id);
+
   EXPECT_THAT(actual_subresources,
               testing::UnorderedElementsAreArray(expected_subresources));
 }
@@ -456,8 +468,9 @@
   NavigateToURLAndCheckSubresources(GetURL(kHtmlDocumentWritePath));
 }
 
+// Disabled due to flakiness (crbug.com/673028).
 IN_PROC_BROWSER_TEST_F(ResourcePrefetchPredictorBrowserTest,
-                       LearningJavascriptAppendChild) {
+                       DISABLED_LearningJavascriptAppendChild) {
   auto externalScript =
       AddExternalResource(GetURL(kScriptAppendChildPath),
                           content::RESOURCE_TYPE_SCRIPT, net::MEDIUM);
diff --git a/chrome/browser/prefs/chrome_pref_service_factory.cc b/chrome/browser/prefs/chrome_pref_service_factory.cc
index 0c761e6..0b72728 100644
--- a/chrome/browser/prefs/chrome_pref_service_factory.cc
+++ b/chrome/browser/prefs/chrome_pref_service_factory.cc
@@ -59,6 +59,7 @@
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
 #include "extensions/features/features.h"
+#include "rlz/features/features.h"
 #include "sql/error_delegate_util.h"
 #include "ui/base/resource/resource_bundle.h"
 
@@ -72,9 +73,9 @@
 
 #if defined(OS_WIN)
 #include "base/win/win_util.h"
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
 #include "rlz/lib/machine_id.h"
-#endif  // defined(ENABLE_RLZ)
+#endif  // BUILDFLAG(ENABLE_RLZ)
 #endif  // defined(OS_WIN)
 
 using content::BrowserContext;
@@ -399,7 +400,7 @@
 std::unique_ptr<ProfilePrefStoreManager> CreateProfilePrefStoreManager(
     const base::FilePath& profile_path) {
   std::string device_id;
-#if defined(OS_WIN) && defined(ENABLE_RLZ)
+#if defined(OS_WIN) && BUILDFLAG(ENABLE_RLZ)
   // This is used by
   // chrome/browser/extensions/api/music_manager_private/device_id_win.cc
   // but that API is private (http://crbug.com/276485) and other platforms are
diff --git a/chrome/browser/renderer_host/pepper/device_id_fetcher.cc b/chrome/browser/renderer_host/pepper/device_id_fetcher.cc
index fabd784e..ddca7f8 100644
--- a/chrome/browser/renderer_host/pepper/device_id_fetcher.cc
+++ b/chrome/browser/renderer_host/pepper/device_id_fetcher.cc
@@ -11,9 +11,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
 #include "components/prefs/pref_service.h"
-#if defined(OS_CHROMEOS)
-#include "chromeos/cryptohome/system_salt_getter.h"
-#endif
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_ppapi_host.h"
@@ -23,7 +20,13 @@
 #include "crypto/random.h"
 #include "crypto/sha2.h"
 #include "ppapi/c/pp_errors.h"
-#if defined(ENABLE_RLZ)
+#include "rlz/features/features.h"
+
+#if defined(OS_CHROMEOS)
+#include "chromeos/cryptohome/system_salt_getter.h"
+#endif
+
+#if BUILDFLAG(ENABLE_RLZ)
 #include "rlz/lib/machine_id.h"
 #endif
 
@@ -41,7 +44,7 @@
 
 void GetMachineIDAsync(
     const base::Callback<void(const std::string&)>& callback) {
-#if defined(OS_WIN) && defined(ENABLE_RLZ)
+#if defined(OS_WIN) && BUILDFLAG(ENABLE_RLZ)
   std::string result;
   rlz_lib::GetMachineId(&result);
   callback.Run(result);
diff --git a/chrome/browser/resources/bluetooth_internals/adapter_broker.js b/chrome/browser/resources/bluetooth_internals/adapter_broker.js
index 7aab614..c1cf8fa 100644
--- a/chrome/browser/resources/bluetooth_internals/adapter_broker.js
+++ b/chrome/browser/resources/bluetooth_internals/adapter_broker.js
@@ -46,7 +46,7 @@
         }
 
         return interfaces.Connection.bindHandleToProxy(
-            response.device,
+            response.device.ptr.passInterface().handle,
             interfaces.BluetoothDevice.Device);
       });
     },
@@ -56,8 +56,12 @@
      * @param {!interfaces.BluetoothAdapter.AdapterClient} adapterClient
      */
     setClient: function(adapterClient) {
-      this.adapter_.setClient(interfaces.Connection.bindStubDerivedImpl(
-          adapterClient));
+      adapterClient.binding = new interfaces.Bindings.Binding(
+          interfaces.BluetoothAdapter.AdapterClient,
+          adapterClient);
+
+      this.adapter_.setClient(
+          adapterClient.binding.createInterfacePtrAndBind());
     },
 
     /**
@@ -153,12 +157,12 @@
       // Get an Adapter service.
       return adapterFactory.getAdapter();
     }).then(function(response) {
-      if (!response.adapter) {
+      if (!response.adapter.ptr.isBound()) {
         throw new Error('Bluetooth Not Supported on this platform.');
       }
 
       var adapter = interfaces.Connection.bindHandleToProxy(
-          response.adapter,
+          response.adapter.ptr.passInterface().handle,
           interfaces.BluetoothAdapter.Adapter);
 
       adapterBroker = new AdapterBroker(adapter);
diff --git a/chrome/browser/resources/bluetooth_internals/interfaces.js b/chrome/browser/resources/bluetooth_internals/interfaces.js
index 063cbe7..0bbe9cb 100644
--- a/chrome/browser/resources/bluetooth_internals/interfaces.js
+++ b/chrome/browser/resources/bluetooth_internals/interfaces.js
@@ -25,11 +25,13 @@
         'content/public/renderer/frame_interfaces',
         'device/bluetooth/public/interfaces/adapter.mojom',
         'device/bluetooth/public/interfaces/device.mojom',
+        'mojo/public/js/bindings',
         'mojo/public/js/connection',
       ]).then(function([frameInterfaces, bluetoothAdapter, bluetoothDevice,
-          connection]) {
+          bindings, connection]) {
         interfaces.BluetoothAdapter = bluetoothAdapter;
         interfaces.BluetoothDevice = bluetoothDevice;
+        interfaces.Bindings = bindings;
         interfaces.Connection = connection;
         interfaces.FrameInterfaces = frameInterfaces;
       });
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/automation_predicate.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/automation_predicate.js
index 7be6f0c..3fe675a 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/automation_predicate.js
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/automation_predicate.js
@@ -57,7 +57,8 @@
 };
 
 /** @type {AutomationPredicate.Unary} */
-AutomationPredicate.checkBox = AutomationPredicate.roles([Role.checkBox]);
+AutomationPredicate.checkBox =
+    AutomationPredicate.roles([Role.checkBox, Role.switch]);
 /** @type {AutomationPredicate.Unary} */
 AutomationPredicate.comboBox = AutomationPredicate.roles(
     [Role.comboBox, Role.popUpButton, Role.menuListPopup]);
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs
index 99c957d..1fab64c 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs
@@ -997,7 +997,7 @@
     };
 
     mockFeedback.call(doCmd('nextEditText'))
-        .expectSpeech('Top News')
+        .expectSpeech('Top News Most Popular Sports')
         .call(doCmd('nextHeading'))
         .expectSpeech('Top News')
         .call(assertRangeHasText('Top News'))
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/live_regions.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/live_regions.js
index 29a9c6f..7c0eb03 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/live_regions.js
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/live_regions.js
@@ -134,6 +134,10 @@
       return;
     }
 
+    // Alerts should be announced as a result of focus.
+    if (node.role == RoleType.alert)
+      return;
+
     var range = cursors.Range.fromNode(node);
     var output = new Output();
     if (opt_prependFormatStr)
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/live_regions_test.extjs b/chrome/browser/resources/chromeos/chromevox/cvox2/background/live_regions_test.extjs
index d2bc87d..88d7d53a 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/live_regions_test.extjs
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/live_regions_test.extjs
@@ -109,9 +109,7 @@
     function(rootNode) {
       var go = rootNode.find({ role: RoleType.button });
       mockFeedback.call(go.doDefault.bind(go))
-          .expectCategoryFlushSpeech('Alpha')
-          .expectQueuedSpeech('Bravo')
-          .expectQueuedSpeech('Charlie');
+          .expectCategoryFlushSpeech('Alpha Bravo Charlie')
       mockFeedback.replay();
     });
 });
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js
index bb8767b..1d12d9d 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js
@@ -397,11 +397,12 @@
       leave: '@exited_container($role)'
     },
     alert: {
-      speak: '$earcon(ALERT_NONMODAL) $role $descendants $state'
+      enter: '$name $role $state',
+      speak: '$earcon(ALERT_NONMODAL) $role $nameOrTextContent $state'
     },
     alertDialog: {
       enter: '$earcon(ALERT_MODAL) $name $state',
-      speak: '$earcon(ALERT_MODAL) $name $descendants $state $role'
+      speak: '$earcon(ALERT_MODAL) $name $nameOrTextContent $state $role'
     },
     cell: {
       enter: '@cell_summary($tableCellRowIndex, $tableCellColumnIndex) ' +
@@ -524,7 +525,7 @@
       enter: '$node(tableRowHeader)'
     },
     rowHeader: {
-      speak: '$descendants $state'
+      speak: '$nameOrTextContent $state'
     },
     slider: {
       speak: '$earcon(SLIDER) @describe_slider($value, $name) $description ' +
@@ -547,7 +548,7 @@
           '$node(tableHeader)'
     },
     tableHeaderContainer: {
-      speak: '$descendants $state $description'
+      speak: '$nameOrTextContent $state $description'
     },
     textField: {
       speak: '$name $value $if($multiline, @tag_textarea, $if(' +
@@ -601,7 +602,7 @@
   alert: {
     default: {
       speak: '$earcon(ALERT_NONMODAL) @role_alert ' +
-          '$if($name, $name, $descendants) $description'
+          '$nameOrTextContent $description'
     }
   }
 };
@@ -1236,11 +1237,14 @@
                 Dir.FORWARD,
                 {visit: AutomationPredicate.leafOrStaticText,
                  leaf: AutomationPredicate.leafOrStaticText});
+            var outputStrings = [];
             while (walker.next().node &&
                 walker.phase == AutomationTreeWalkerPhase.DESCENDANT) {
               if (walker.node.name)
-                this.append_(buff, walker.node.name, options);
+                outputStrings.push(walker.node.name);
             }
+            var joinedOutput = outputStrings.join(' ');
+            this.append_(buff, joinedOutput, options);
           }
         } else if (node[token] !== undefined) {
           options.annotation.push(token);
diff --git a/chrome/browser/resources/chromeos/chromevox/host/chrome/tts_background.js b/chrome/browser/resources/chromeos/chromevox/host/chrome/tts_background.js
index be031a9..d4d3704 100644
--- a/chrome/browser/resources/chromeos/chromevox/host/chrome/tts_background.js
+++ b/chrome/browser/resources/chromeos/chromevox/host/chrome/tts_background.js
@@ -303,19 +303,6 @@
   // Next, add the new utterance to the queue.
   this.utteranceQueue_.push(utterance);
 
-  // Update the caption panel.
-  if (utterance.properties &&
-      utterance.properties['pitch'] &&
-      utterance.properties['pitch'] < this.ttsProperties['pitch']) {
-    (new PanelCommand(
-        PanelCommandType.ADD_ANNOTATION_SPEECH,
-        utterance.textString)).send();
-  } else {
-    (new PanelCommand(
-        PanelCommandType.ADD_NORMAL_SPEECH,
-        utterance.textString)).send();
-  }
-
   // Now start speaking the next item in the queue.
   this.startSpeakingNextItemInQueue_();
 };
@@ -342,9 +329,10 @@
   }
 
   this.currentUtterance_ = this.utteranceQueue_.shift();
-  var utteranceId = this.currentUtterance_.id;
+  var utterance = this.currentUtterance_;
+  var utteranceId = utterance.id;
 
-  this.currentUtterance_.properties['onEvent'] = goog.bind(function(event) {
+  utterance.properties['onEvent'] = goog.bind(function(event) {
             this.onTtsEvent_(event, utteranceId);
           },
   this);
@@ -352,13 +340,25 @@
   var validatedProperties = {};
   for (var i = 0; i < cvox.TtsBackground.ALLOWED_PROPERTIES_.length; i++) {
     var p = cvox.TtsBackground.ALLOWED_PROPERTIES_[i];
-    if (this.currentUtterance_.properties[p]) {
-      validatedProperties[p] = this.currentUtterance_.properties[p];
+    if (utterance.properties[p]) {
+      validatedProperties[p] = utterance.properties[p];
     }
   }
 
-  chrome.tts.speak(this.currentUtterance_.textString,
-                   validatedProperties);
+  // Update the caption panel.
+  if (utterance.properties &&
+      utterance.properties['pitch'] &&
+      utterance.properties['pitch'] < this.ttsProperties['pitch']) {
+    (new PanelCommand(
+        PanelCommandType.ADD_ANNOTATION_SPEECH,
+        utterance.textString)).send();
+  } else {
+    (new PanelCommand(
+        PanelCommandType.ADD_NORMAL_SPEECH,
+        utterance.textString)).send();
+  }
+
+  chrome.tts.speak(utterance.textString, validatedProperties);
 };
 
 /**
diff --git a/chrome/browser/resources/chromeos/login/lock.js b/chrome/browser/resources/chromeos/login/lock.js
index ad5919ce..4028f54 100644
--- a/chrome/browser/resources/chromeos/login/lock.js
+++ b/chrome/browser/resources/chromeos/login/lock.js
@@ -66,6 +66,39 @@
       chrome.send('screenStateInitialize');
     },
 
+    /**
+     * Notification from the host that the PIN keyboard will be used in the
+     * lock session so it should also get preloaded.
+     */
+    preloadPinKeyboard: function() {
+      showPinKeyboardAsync();
+    },
+
+    /**
+     * Called when a preloaded webview (this) instance is being reused to
+     * display a new lock screen session. This will also be called when a
+     * lock screen has been preloaded and is being displayed for the first
+     * time.
+     */
+    reload: function() {
+      // Sending accountPickerReady displays the webui. Wait for the next
+      // animation frame so the user does not see any state from the previous
+      // instance.
+      requestAnimationFrame(function() {
+        chrome.send('accountPickerReady');
+      });
+    },
+
+    /**
+     * Called when the lock screen has been dismissed but this webview will stay
+     * in memory. The webview will be reused when Oobe.reload() is called.
+     */
+    teardown: function() {
+      // The PIN keyboard will disable the virtual keyboard. Make sure to
+      // revert the force disable when hiding the lock screen.
+      chrome.send('setForceDisableVirtualKeyboard', [false]);
+    },
+
     // Dummy Oobe functions not present with stripped login UI.
     initializeA11yMenu: function(e) {},
     handleAccessibilityLinkClick: function(e) {},
diff --git a/chrome/browser/resources/md_downloads/vulcanized.html b/chrome/browser/resources/md_downloads/vulcanized.html
index 50e3c7a..282db70 100644
--- a/chrome/browser/resources/md_downloads/vulcanized.html
+++ b/chrome/browser/resources/md_downloads/vulcanized.html
@@ -34,7 +34,8 @@
 :root {
   /* This is a custom, Chrome-specific color that does not have a --paper or
    * --google equivalent. */
-  --md-background-color: rgb(241, 241, 241);
+  --md-background-color: #f1f1f1;
+  --md-loading-message-color: #6e6e6e;
   /* This is --google-blue-700, rewritten as a native custom property for speed.
    */
   --md-toolbar-color: rgb(51, 103, 214);
@@ -3028,7 +3029,7 @@
 }
 
 :host(:not([narrow]):not([showing-search])) #icon, :host(:not([narrow])) #prompt {
-  opacity: 0.6;
+  opacity: 0.7;
 }
 
 :host([narrow]:not([showing-search])) #searchTerm {
@@ -3296,7 +3297,8 @@
 :root {
   /* This is a custom, Chrome-specific color that does not have a --paper or
    * --google equivalent. */
-  --md-background-color: rgb(241, 241, 241);
+  --md-background-color: #f1f1f1;
+  --md-loading-message-color: #6e6e6e;
   /* This is --google-blue-700, rewritten as a native custom property for speed.
    */
   --md-toolbar-color: rgb(51, 103, 214);
diff --git a/chrome/browser/resources/md_history/app.crisper.js b/chrome/browser/resources/md_history/app.crisper.js
index a5a250e..299b3ab 100644
--- a/chrome/browser/resources/md_history/app.crisper.js
+++ b/chrome/browser/resources/md_history/app.crisper.js
@@ -13,13 +13,11 @@
 // 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.
-cr.define("cr.ui",function(){function KeyboardShortcut(shortcut){var mods={};var ident="";shortcut.split("|").forEach(function(part){var partLc=part.toLowerCase();switch(partLc){case"alt":case"ctrl":case"meta":case"shift":mods[partLc+"Key"]=true;break;default:if(ident)throw Error("Invalid shortcut");ident=part}});this.ident_=ident;this.mods_=mods}KeyboardShortcut.prototype={matchesEvent:function(e){if(e.key==this.ident_){var mods=this.mods_;return["altKey","ctrlKey","metaKey","shiftKey"].every(function(k){return e[k]==!!mods[k]})}return false}};var Command=cr.ui.define("command");Command.prototype={__proto__:HTMLElement.prototype,decorate:function(){CommandManager.init(assert(this.ownerDocument));if(this.hasAttribute("shortcut"))this.shortcut=this.getAttribute("shortcut")},execute:function(opt_element){if(this.disabled)return;var doc=this.ownerDocument;if(doc.activeElement){var e=new Event("command",{bubbles:true});e.command=this;(opt_element||doc.activeElement).dispatchEvent(e)}},canExecuteChange:function(opt_node){dispatchCanExecuteEvent(this,opt_node||this.ownerDocument.activeElement)},shortcut_:"",get shortcut(){return this.shortcut_},set shortcut(shortcut){var oldShortcut=this.shortcut_;if(shortcut!==oldShortcut){this.keyboardShortcuts_=shortcut.split(/\s+/).map(function(shortcut){return new KeyboardShortcut(shortcut)});this.shortcut_=shortcut;cr.dispatchPropertyChange(this,"shortcut",this.shortcut_,oldShortcut)}},matchesEvent:function(e){if(!this.keyboardShortcuts_)return false;return this.keyboardShortcuts_.some(function(keyboardShortcut){return keyboardShortcut.matchesEvent(e)})}};cr.defineProperty(Command,"label",cr.PropertyKind.ATTR);cr.defineProperty(Command,"disabled",cr.PropertyKind.BOOL_ATTR);cr.defineProperty(Command,"hidden",cr.PropertyKind.BOOL_ATTR);cr.defineProperty(Command,"checked",cr.PropertyKind.BOOL_ATTR);cr.defineProperty(Command,"hideShortcutText",cr.PropertyKind.BOOL_ATTR);function dispatchCanExecuteEvent(command,target){var e=new CanExecuteEvent(command);target.dispatchEvent(e);command.disabled=!e.canExecute}var commandManagers={};function CommandManager(doc){doc.addEventListener("focus",this.handleFocus_.bind(this),true);doc.addEventListener("keydown",this.handleKeyDown_.bind(this),false)}CommandManager.init=function(doc){var uid=cr.getUid(doc);if(!(uid in commandManagers)){commandManagers[uid]=new CommandManager(doc)}};CommandManager.prototype={handleFocus_:function(e){var target=e.target;if(target.menu||target.command)return;var commands=Array.prototype.slice.call(target.ownerDocument.querySelectorAll("command"));commands.forEach(function(command){dispatchCanExecuteEvent(command,target)})},handleKeyDown_:function(e){var target=e.target;var commands=Array.prototype.slice.call(target.ownerDocument.querySelectorAll("command"));for(var i=0,command;command=commands[i];i++){if(command.matchesEvent(e)){command.canExecuteChange();if(!command.disabled){e.preventDefault();e.stopPropagation();command.execute();return}}}}};function CanExecuteEvent(command){var e=new Event("canExecute",{bubbles:true,cancelable:true});e.__proto__=CanExecuteEvent.prototype;e.command=command;return e}CanExecuteEvent.prototype={__proto__:Event.prototype,command:null,canExecute_:false,get canExecute(){return this.canExecute_},set canExecute(canExecute){this.canExecute_=!!canExecute;this.stopPropagation();this.preventDefault()}};return{Command:Command,CanExecuteEvent:CanExecuteEvent}});Polymer({is:"iron-media-query",properties:{queryMatches:{type:Boolean,value:false,readOnly:true,notify:true},query:{type:String,observer:"queryChanged"},full:{type:Boolean,value:false},_boundMQHandler:{value:function(){return this.queryHandler.bind(this)}},_mq:{value:null}},attached:function(){this.style.display="none";this.queryChanged()},detached:function(){this._remove()},_add:function(){if(this._mq){this._mq.addListener(this._boundMQHandler)}},_remove:function(){if(this._mq){this._mq.removeListener(this._boundMQHandler)}this._mq=null},queryChanged:function(){this._remove();var query=this.query;if(!query){return}if(!this.full&&query[0]!=="("){query="("+query+")"}this._mq=window.matchMedia(query);this._add();this.queryHandler(this._mq)},queryHandler:function(mq){this._setQueryMatches(mq.matches)}});Polymer.IronResizableBehavior={properties:{_parentResizable:{type:Object,observer:"_parentResizableChanged"},_notifyingDescendant:{type:Boolean,value:false}},listeners:{"iron-request-resize-notifications":"_onIronRequestResizeNotifications"},created:function(){this._interestedResizables=[];this._boundNotifyResize=this.notifyResize.bind(this)},attached:function(){this.fire("iron-request-resize-notifications",null,{node:this,bubbles:true,cancelable:true});if(!this._parentResizable){window.addEventListener("resize",this._boundNotifyResize);this.notifyResize()}},detached:function(){if(this._parentResizable){this._parentResizable.stopResizeNotificationsFor(this)}else{window.removeEventListener("resize",this._boundNotifyResize)}this._parentResizable=null},notifyResize:function(){if(!this.isAttached){return}this._interestedResizables.forEach(function(resizable){if(this.resizerShouldNotify(resizable)){this._notifyDescendant(resizable)}},this);this._fireResize()},assignParentResizable:function(parentResizable){this._parentResizable=parentResizable},stopResizeNotificationsFor:function(target){var index=this._interestedResizables.indexOf(target);if(index>-1){this._interestedResizables.splice(index,1);this.unlisten(target,"iron-resize","_onDescendantIronResize")}},resizerShouldNotify:function(element){return true},_onDescendantIronResize:function(event){if(this._notifyingDescendant){event.stopPropagation();return}if(!Polymer.Settings.useShadow){this._fireResize()}},_fireResize:function(){this.fire("iron-resize",null,{node:this,bubbles:false})},_onIronRequestResizeNotifications:function(event){var target=event.path?event.path[0]:event.target;if(target===this){return}if(this._interestedResizables.indexOf(target)===-1){this._interestedResizables.push(target);this.listen(target,"iron-resize","_onDescendantIronResize")}target.assignParentResizable(this);this._notifyDescendant(target);event.stopPropagation()},_parentResizableChanged:function(parentResizable){if(parentResizable){window.removeEventListener("resize",this._boundNotifyResize)}},_notifyDescendant:function(descendant){if(!this.isAttached){return}this._notifyingDescendant=true;descendant.notifyResize();this._notifyingDescendant=false}};Polymer.IronSelection=function(selectCallback){this.selection=[];this.selectCallback=selectCallback};Polymer.IronSelection.prototype={get:function(){return this.multi?this.selection.slice():this.selection[0]},clear:function(excludes){this.selection.slice().forEach(function(item){if(!excludes||excludes.indexOf(item)<0){this.setItemSelected(item,false)}},this)},isSelected:function(item){return this.selection.indexOf(item)>=0},setItemSelected:function(item,isSelected){if(item!=null){if(isSelected!==this.isSelected(item)){if(isSelected){this.selection.push(item)}else{var i=this.selection.indexOf(item);if(i>=0){this.selection.splice(i,1)}}if(this.selectCallback){this.selectCallback(item,isSelected)}}}},select:function(item){if(this.multi){this.toggle(item)}else if(this.get()!==item){this.setItemSelected(this.get(),false);this.setItemSelected(item,true)}},toggle:function(item){this.setItemSelected(item,!this.isSelected(item))}};Polymer.IronSelectableBehavior={properties:{attrForSelected:{type:String,value:null},selected:{type:String,notify:true},selectedItem:{type:Object,readOnly:true,notify:true},activateEvent:{type:String,value:"tap",observer:"_activateEventChanged"},selectable:String,selectedClass:{type:String,value:"iron-selected"},selectedAttribute:{type:String,value:null},fallbackSelection:{type:String,value:null},items:{type:Array,readOnly:true,notify:true,value:function(){return[]}},_excludedLocalNames:{type:Object,value:function(){return{template:1}}}},observers:["_updateAttrForSelected(attrForSelected)","_updateSelected(selected)","_checkFallback(fallbackSelection)"],created:function(){this._bindFilterItem=this._filterItem.bind(this);this._selection=new Polymer.IronSelection(this._applySelection.bind(this))},attached:function(){this._observer=this._observeItems(this);this._updateItems();if(!this._shouldUpdateSelection){this._updateSelected()}this._addListener(this.activateEvent)},detached:function(){if(this._observer){Polymer.dom(this).unobserveNodes(this._observer)}this._removeListener(this.activateEvent)},indexOf:function(item){return this.items.indexOf(item)},select:function(value){this.selected=value},selectPrevious:function(){var length=this.items.length;var index=(Number(this._valueToIndex(this.selected))-1+length)%length;this.selected=this._indexToValue(index)},selectNext:function(){var index=(Number(this._valueToIndex(this.selected))+1)%this.items.length;this.selected=this._indexToValue(index)},selectIndex:function(index){this.select(this._indexToValue(index))},forceSynchronousItemUpdate:function(){this._updateItems()},get _shouldUpdateSelection(){return this.selected!=null},_checkFallback:function(){if(this._shouldUpdateSelection){this._updateSelected()}},_addListener:function(eventName){this.listen(this,eventName,"_activateHandler")},_removeListener:function(eventName){this.unlisten(this,eventName,"_activateHandler")},_activateEventChanged:function(eventName,old){this._removeListener(old);this._addListener(eventName)},_updateItems:function(){var nodes=Polymer.dom(this).queryDistributedElements(this.selectable||"*");nodes=Array.prototype.filter.call(nodes,this._bindFilterItem);this._setItems(nodes)},_updateAttrForSelected:function(){if(this._shouldUpdateSelection){this.selected=this._indexToValue(this.indexOf(this.selectedItem))}},_updateSelected:function(){this._selectSelected(this.selected)},_selectSelected:function(selected){this._selection.select(this._valueToItem(this.selected));if(this.fallbackSelection&&this.items.length&&this._selection.get()===undefined){this.selected=this.fallbackSelection}},_filterItem:function(node){return!this._excludedLocalNames[node.localName]},_valueToItem:function(value){return value==null?null:this.items[this._valueToIndex(value)]},_valueToIndex:function(value){if(this.attrForSelected){for(var i=0,item;item=this.items[i];i++){if(this._valueForItem(item)==value){return i}}}else{return Number(value)}},_indexToValue:function(index){if(this.attrForSelected){var item=this.items[index];if(item){return this._valueForItem(item)}}else{return index}},_valueForItem:function(item){var propValue=item[Polymer.CaseMap.dashToCamelCase(this.attrForSelected)];return propValue!=undefined?propValue:item.getAttribute(this.attrForSelected)},_applySelection:function(item,isSelected){if(this.selectedClass){this.toggleClass(this.selectedClass,isSelected,item)}if(this.selectedAttribute){this.toggleAttribute(this.selectedAttribute,isSelected,item)}this._selectionChange();this.fire("iron-"+(isSelected?"select":"deselect"),{item:item})},_selectionChange:function(){this._setSelectedItem(this._selection.get())},_observeItems:function(node){return Polymer.dom(node).observeNodes(function(mutation){this._updateItems();if(this._shouldUpdateSelection){this._updateSelected()}this.fire("iron-items-changed",mutation,{bubbles:false,cancelable:false})})},_activateHandler:function(e){var t=e.target;var items=this.items;while(t&&t!=this){var i=items.indexOf(t);if(i>=0){var value=this._indexToValue(i);this._itemActivate(value,t);return}t=t.parentNode}},_itemActivate:function(value,item){if(!this.fire("iron-activate",{selected:value,item:item},{cancelable:true}).defaultPrevented){this.select(value)}}};Polymer({is:"iron-pages",behaviors:[Polymer.IronResizableBehavior,Polymer.IronSelectableBehavior],properties:{activateEvent:{type:String,value:null}},observers:["_selectedPageChanged(selected)"],_selectedPageChanged:function(selected,old){this.async(this.notifyResize)}});Polymer.IronScrollTargetBehavior={properties:{scrollTarget:{type:HTMLElement,value:function(){return this._defaultScrollTarget}}},observers:["_scrollTargetChanged(scrollTarget, isAttached)"],_shouldHaveListener:true,_scrollTargetChanged:function(scrollTarget,isAttached){var eventTarget;if(this._oldScrollTarget){this._toggleScrollListener(false,this._oldScrollTarget);this._oldScrollTarget=null}if(!isAttached){return}if(scrollTarget==="document"){this.scrollTarget=this._doc}else if(typeof scrollTarget==="string"){this.scrollTarget=this.domHost?this.domHost.$[scrollTarget]:Polymer.dom(this.ownerDocument).querySelector("#"+scrollTarget)}else if(this._isValidScrollTarget()){this._boundScrollHandler=this._boundScrollHandler||this._scrollHandler.bind(this);this._oldScrollTarget=scrollTarget;this._toggleScrollListener(this._shouldHaveListener,scrollTarget)}},_scrollHandler:function scrollHandler(){},get _defaultScrollTarget(){return this._doc},get _doc(){return this.ownerDocument.documentElement},get _scrollTop(){if(this._isValidScrollTarget()){return this.scrollTarget===this._doc?window.pageYOffset:this.scrollTarget.scrollTop}return 0},get _scrollLeft(){if(this._isValidScrollTarget()){return this.scrollTarget===this._doc?window.pageXOffset:this.scrollTarget.scrollLeft}return 0},set _scrollTop(top){if(this.scrollTarget===this._doc){window.scrollTo(window.pageXOffset,top)}else if(this._isValidScrollTarget()){this.scrollTarget.scrollTop=top}},set _scrollLeft(left){if(this.scrollTarget===this._doc){window.scrollTo(left,window.pageYOffset)}else if(this._isValidScrollTarget()){this.scrollTarget.scrollLeft=left}},scroll:function(left,top){if(this.scrollTarget===this._doc){window.scrollTo(left,top)}else if(this._isValidScrollTarget()){this.scrollTarget.scrollLeft=left;this.scrollTarget.scrollTop=top}},get _scrollTargetWidth(){if(this._isValidScrollTarget()){return this.scrollTarget===this._doc?window.innerWidth:this.scrollTarget.offsetWidth}return 0},get _scrollTargetHeight(){if(this._isValidScrollTarget()){return this.scrollTarget===this._doc?window.innerHeight:this.scrollTarget.offsetHeight}return 0},_isValidScrollTarget:function(){return this.scrollTarget instanceof HTMLElement},_toggleScrollListener:function(yes,scrollTarget){if(!this._boundScrollHandler){return}var eventTarget=scrollTarget===this._doc?window:scrollTarget;if(yes){eventTarget.addEventListener("scroll",this._boundScrollHandler)}else{eventTarget.removeEventListener("scroll",this._boundScrollHandler)}},toggleScrollListener:function(yes){this._shouldHaveListener=yes;this._toggleScrollListener(yes,this.scrollTarget)}};(function(){var metaDatas={};var metaArrays={};var singleton=null;Polymer.IronMeta=Polymer({is:"iron-meta",properties:{type:{type:String,value:"default",observer:"_typeChanged"},key:{type:String,observer:"_keyChanged"},value:{type:Object,notify:true,observer:"_valueChanged"},self:{type:Boolean,observer:"_selfChanged"},list:{type:Array,notify:true}},hostAttributes:{hidden:true},factoryImpl:function(config){if(config){for(var n in config){switch(n){case"type":case"key":case"value":this[n]=config[n];break}}}},created:function(){this._metaDatas=metaDatas;this._metaArrays=metaArrays},_keyChanged:function(key,old){this._resetRegistration(old)},_valueChanged:function(value){this._resetRegistration(this.key)},_selfChanged:function(self){if(self){this.value=this}},_typeChanged:function(type){this._unregisterKey(this.key);if(!metaDatas[type]){metaDatas[type]={}}this._metaData=metaDatas[type];if(!metaArrays[type]){metaArrays[type]=[]}this.list=metaArrays[type];this._registerKeyValue(this.key,this.value)},byKey:function(key){return this._metaData&&this._metaData[key]},_resetRegistration:function(oldKey){this._unregisterKey(oldKey);this._registerKeyValue(this.key,this.value)},_unregisterKey:function(key){this._unregister(key,this._metaData,this.list)},_registerKeyValue:function(key,value){this._register(key,value,this._metaData,this.list)},_register:function(key,value,data,list){if(key&&data&&value!==undefined){data[key]=value;list.push(value)}},_unregister:function(key,data,list){if(key&&data){if(key in data){var value=data[key];delete data[key];this.arrayDelete(list,value)}}}});Polymer.IronMeta.getIronMeta=function getIronMeta(){if(singleton===null){singleton=new Polymer.IronMeta}return singleton};Polymer.IronMetaQuery=Polymer({is:"iron-meta-query",properties:{type:{type:String,value:"default",observer:"_typeChanged"},key:{type:String,observer:"_keyChanged"},value:{type:Object,notify:true,readOnly:true},list:{type:Array,notify:true}},factoryImpl:function(config){if(config){for(var n in config){switch(n){case"type":case"key":this[n]=config[n];break}}}},created:function(){this._metaDatas=metaDatas;this._metaArrays=metaArrays},_keyChanged:function(key){this._setValue(this._metaData&&this._metaData[key])},_typeChanged:function(type){this._metaData=metaDatas[type];this.list=metaArrays[type];if(this.key){this._keyChanged(this.key)}},byKey:function(key){return this._metaData&&this._metaData[key]}})})();Polymer({is:"iron-icon",properties:{icon:{type:String,observer:"_iconChanged"},theme:{type:String,observer:"_updateIcon"},src:{type:String,observer:"_srcChanged"},_meta:{value:Polymer.Base.create("iron-meta",{type:"iconset"}),observer:"_updateIcon"}},_DEFAULT_ICONSET:"icons",_iconChanged:function(icon){var parts=(icon||"").split(":");this._iconName=parts.pop();this._iconsetName=parts.pop()||this._DEFAULT_ICONSET;this._updateIcon()},_srcChanged:function(src){this._updateIcon()},_usesIconset:function(){return this.icon||!this.src},_updateIcon:function(){if(this._usesIconset()){if(this._img&&this._img.parentNode){Polymer.dom(this.root).removeChild(this._img)}if(this._iconName===""){if(this._iconset){this._iconset.removeIcon(this)}}else if(this._iconsetName&&this._meta){this._iconset=this._meta.byKey(this._iconsetName);if(this._iconset){this._iconset.applyIcon(this,this._iconName,this.theme);this.unlisten(window,"iron-iconset-added","_updateIcon")}else{this.listen(window,"iron-iconset-added","_updateIcon")}}}else{if(this._iconset){this._iconset.removeIcon(this)}if(!this._img){this._img=document.createElement("img");this._img.style.width="100%";this._img.style.height="100%";this._img.draggable=false}this._img.src=this.src;Polymer.dom(this.root).appendChild(this._img)}}});(function(){"use strict";var KEY_IDENTIFIER={"U+0008":"backspace","U+0009":"tab","U+001B":"esc","U+0020":"space","U+007F":"del"};var KEY_CODE={8:"backspace",9:"tab",13:"enter",27:"esc",33:"pageup",34:"pagedown",35:"end",36:"home",32:"space",37:"left",38:"up",39:"right",40:"down",46:"del",106:"*"};var MODIFIER_KEYS={shift:"shiftKey",ctrl:"ctrlKey",alt:"altKey",meta:"metaKey"};var KEY_CHAR=/[a-z0-9*]/;var IDENT_CHAR=/U\+/;var ARROW_KEY=/^arrow/;var SPACE_KEY=/^space(bar)?/;var ESC_KEY=/^escape$/;function transformKey(key,noSpecialChars){var validKey="";if(key){var lKey=key.toLowerCase();if(lKey===" "||SPACE_KEY.test(lKey)){validKey="space"}else if(ESC_KEY.test(lKey)){validKey="esc"}else if(lKey.length==1){if(!noSpecialChars||KEY_CHAR.test(lKey)){validKey=lKey}}else if(ARROW_KEY.test(lKey)){validKey=lKey.replace("arrow","")}else if(lKey=="multiply"){validKey="*"}else{validKey=lKey}}return validKey}function transformKeyIdentifier(keyIdent){var validKey="";if(keyIdent){if(keyIdent in KEY_IDENTIFIER){validKey=KEY_IDENTIFIER[keyIdent]}else if(IDENT_CHAR.test(keyIdent)){keyIdent=parseInt(keyIdent.replace("U+","0x"),16);validKey=String.fromCharCode(keyIdent).toLowerCase()}else{validKey=keyIdent.toLowerCase()}}return validKey}function transformKeyCode(keyCode){var validKey="";if(Number(keyCode)){if(keyCode>=65&&keyCode<=90){validKey=String.fromCharCode(32+keyCode)}else if(keyCode>=112&&keyCode<=123){validKey="f"+(keyCode-112)}else if(keyCode>=48&&keyCode<=57){validKey=String(keyCode-48)}else if(keyCode>=96&&keyCode<=105){validKey=String(keyCode-96)}else{validKey=KEY_CODE[keyCode]}}return validKey}function normalizedKeyForEvent(keyEvent,noSpecialChars){if(keyEvent.key){return transformKey(keyEvent.key,noSpecialChars)}if(keyEvent.detail&&keyEvent.detail.key){return transformKey(keyEvent.detail.key,noSpecialChars)}return transformKeyIdentifier(keyEvent.keyIdentifier)||transformKeyCode(keyEvent.keyCode)||""}function keyComboMatchesEvent(keyCombo,event){var keyEvent=normalizedKeyForEvent(event,keyCombo.hasModifiers);return keyEvent===keyCombo.key&&(!keyCombo.hasModifiers||!!event.shiftKey===!!keyCombo.shiftKey&&!!event.ctrlKey===!!keyCombo.ctrlKey&&!!event.altKey===!!keyCombo.altKey&&!!event.metaKey===!!keyCombo.metaKey)}function parseKeyComboString(keyComboString){if(keyComboString.length===1){return{combo:keyComboString,key:keyComboString,event:"keydown"}}return keyComboString.split("+").reduce(function(parsedKeyCombo,keyComboPart){var eventParts=keyComboPart.split(":");var keyName=eventParts[0];var event=eventParts[1];if(keyName in MODIFIER_KEYS){parsedKeyCombo[MODIFIER_KEYS[keyName]]=true;parsedKeyCombo.hasModifiers=true}else{parsedKeyCombo.key=keyName;parsedKeyCombo.event=event||"keydown"}return parsedKeyCombo},{combo:keyComboString.split(":").shift()})}function parseEventString(eventString){return eventString.trim().split(" ").map(function(keyComboString){return parseKeyComboString(keyComboString)})}Polymer.IronA11yKeysBehavior={properties:{keyEventTarget:{type:Object,value:function(){return this}},stopKeyboardEventPropagation:{type:Boolean,value:false},_boundKeyHandlers:{type:Array,value:function(){return[]}},_imperativeKeyBindings:{type:Object,value:function(){return{}}}},observers:["_resetKeyEventListeners(keyEventTarget, _boundKeyHandlers)"],keyBindings:{},registered:function(){this._prepKeyBindings()},attached:function(){this._listenKeyEventListeners()},detached:function(){this._unlistenKeyEventListeners()},addOwnKeyBinding:function(eventString,handlerName){this._imperativeKeyBindings[eventString]=handlerName;this._prepKeyBindings();this._resetKeyEventListeners()},removeOwnKeyBindings:function(){this._imperativeKeyBindings={};this._prepKeyBindings();this._resetKeyEventListeners()},keyboardEventMatchesKeys:function(event,eventString){var keyCombos=parseEventString(eventString);for(var i=0;i<keyCombos.length;++i){if(keyComboMatchesEvent(keyCombos[i],event)){return true}}return false},_collectKeyBindings:function(){var keyBindings=this.behaviors.map(function(behavior){return behavior.keyBindings});if(keyBindings.indexOf(this.keyBindings)===-1){keyBindings.push(this.keyBindings)}return keyBindings},_prepKeyBindings:function(){this._keyBindings={};this._collectKeyBindings().forEach(function(keyBindings){for(var eventString in keyBindings){this._addKeyBinding(eventString,keyBindings[eventString])}},this);for(var eventString in this._imperativeKeyBindings){this._addKeyBinding(eventString,this._imperativeKeyBindings[eventString])}for(var eventName in this._keyBindings){this._keyBindings[eventName].sort(function(kb1,kb2){var b1=kb1[0].hasModifiers;var b2=kb2[0].hasModifiers;return b1===b2?0:b1?-1:1})}},_addKeyBinding:function(eventString,handlerName){parseEventString(eventString).forEach(function(keyCombo){this._keyBindings[keyCombo.event]=this._keyBindings[keyCombo.event]||[];this._keyBindings[keyCombo.event].push([keyCombo,handlerName])},this)},_resetKeyEventListeners:function(){this._unlistenKeyEventListeners();if(this.isAttached){this._listenKeyEventListeners()}},_listenKeyEventListeners:function(){if(!this.keyEventTarget){return}Object.keys(this._keyBindings).forEach(function(eventName){var keyBindings=this._keyBindings[eventName];var boundKeyHandler=this._onKeyBindingEvent.bind(this,keyBindings);this._boundKeyHandlers.push([this.keyEventTarget,eventName,boundKeyHandler]);this.keyEventTarget.addEventListener(eventName,boundKeyHandler)},this)},_unlistenKeyEventListeners:function(){var keyHandlerTuple;var keyEventTarget;var eventName;var boundKeyHandler;while(this._boundKeyHandlers.length){keyHandlerTuple=this._boundKeyHandlers.pop();keyEventTarget=keyHandlerTuple[0];eventName=keyHandlerTuple[1];boundKeyHandler=keyHandlerTuple[2];keyEventTarget.removeEventListener(eventName,boundKeyHandler)}},_onKeyBindingEvent:function(keyBindings,event){if(this.stopKeyboardEventPropagation){event.stopPropagation()}if(event.defaultPrevented){return}for(var i=0;i<keyBindings.length;i++){var keyCombo=keyBindings[i][0];var handlerName=keyBindings[i][1];if(keyComboMatchesEvent(keyCombo,event)){this._triggerKeyHandler(keyCombo,handlerName,event);if(event.defaultPrevented){return}}}},_triggerKeyHandler:function(keyCombo,handlerName,keyboardEvent){var detail=Object.create(keyCombo);detail.keyboardEvent=keyboardEvent;var event=new CustomEvent(keyCombo.event,{detail:detail,cancelable:true});this[handlerName].call(this,event);if(event.defaultPrevented){keyboardEvent.preventDefault()}}}})();Polymer.IronControlState={properties:{focused:{type:Boolean,value:false,notify:true,readOnly:true,reflectToAttribute:true},disabled:{type:Boolean,value:false,notify:true,observer:"_disabledChanged",reflectToAttribute:true},_oldTabIndex:{type:Number},_boundFocusBlurHandler:{type:Function,value:function(){return this._focusBlurHandler.bind(this)}}},observers:["_changedControlState(focused, disabled)"],ready:function(){this.addEventListener("focus",this._boundFocusBlurHandler,true);this.addEventListener("blur",this._boundFocusBlurHandler,true)},_focusBlurHandler:function(event){if(event.target===this){this._setFocused(event.type==="focus")}else if(!this.shadowRoot){var target=Polymer.dom(event).localTarget;if(!this.isLightDescendant(target)){this.fire(event.type,{sourceEvent:event},{node:this,bubbles:event.bubbles,cancelable:event.cancelable})}}},_disabledChanged:function(disabled,old){this.setAttribute("aria-disabled",disabled?"true":"false");this.style.pointerEvents=disabled?"none":"";if(disabled){this._oldTabIndex=this.tabIndex;this._setFocused(false);this.tabIndex=-1;this.blur()}else if(this._oldTabIndex!==undefined){this.tabIndex=this._oldTabIndex}},_changedControlState:function(){if(this._controlStateChanged){this._controlStateChanged()}}};Polymer.IronButtonStateImpl={properties:{pressed:{type:Boolean,readOnly:true,value:false,reflectToAttribute:true,observer:"_pressedChanged"},toggles:{type:Boolean,value:false,reflectToAttribute:true},active:{type:Boolean,value:false,notify:true,reflectToAttribute:true},pointerDown:{type:Boolean,readOnly:true,value:false},receivedFocusFromKeyboard:{type:Boolean,readOnly:true},ariaActiveAttribute:{type:String,value:"aria-pressed",observer:"_ariaActiveAttributeChanged"}},listeners:{down:"_downHandler",up:"_upHandler",tap:"_tapHandler"},observers:["_detectKeyboardFocus(focused)","_activeChanged(active, ariaActiveAttribute)"],keyBindings:{"enter:keydown":"_asyncClick","space:keydown":"_spaceKeyDownHandler","space:keyup":"_spaceKeyUpHandler"},_mouseEventRe:/^mouse/,_tapHandler:function(){if(this.toggles){this._userActivate(!this.active)}else{this.active=false}},_detectKeyboardFocus:function(focused){this._setReceivedFocusFromKeyboard(!this.pointerDown&&focused)},_userActivate:function(active){if(this.active!==active){this.active=active;this.fire("change")}},_downHandler:function(event){this._setPointerDown(true);this._setPressed(true);this._setReceivedFocusFromKeyboard(false)},_upHandler:function(){this._setPointerDown(false);this._setPressed(false)},_spaceKeyDownHandler:function(event){var keyboardEvent=event.detail.keyboardEvent;var target=Polymer.dom(keyboardEvent).localTarget;if(this.isLightDescendant(target))return;keyboardEvent.preventDefault();keyboardEvent.stopImmediatePropagation();this._setPressed(true)},_spaceKeyUpHandler:function(event){var keyboardEvent=event.detail.keyboardEvent;var target=Polymer.dom(keyboardEvent).localTarget;if(this.isLightDescendant(target))return;if(this.pressed){this._asyncClick()}this._setPressed(false)},_asyncClick:function(){this.async(function(){this.click()},1)},_pressedChanged:function(pressed){this._changedButtonState()},_ariaActiveAttributeChanged:function(value,oldValue){if(oldValue&&oldValue!=value&&this.hasAttribute(oldValue)){this.removeAttribute(oldValue)}},_activeChanged:function(active,ariaActiveAttribute){if(this.toggles){this.setAttribute(this.ariaActiveAttribute,active?"true":"false")}else{this.removeAttribute(this.ariaActiveAttribute)}this._changedButtonState()},_controlStateChanged:function(){if(this.disabled){this._setPressed(false)}else{this._changedButtonState()}},_changedButtonState:function(){if(this._buttonStateChanged){this._buttonStateChanged()}}};Polymer.IronButtonState=[Polymer.IronA11yKeysBehavior,Polymer.IronButtonStateImpl];(function(){var Utility={distance:function(x1,y1,x2,y2){var xDelta=x1-x2;var yDelta=y1-y2;return Math.sqrt(xDelta*xDelta+yDelta*yDelta)},now:window.performance&&window.performance.now?window.performance.now.bind(window.performance):Date.now};function ElementMetrics(element){this.element=element;this.width=this.boundingRect.width;this.height=this.boundingRect.height;this.size=Math.max(this.width,this.height)}ElementMetrics.prototype={get boundingRect(){return this.element.getBoundingClientRect()},furthestCornerDistanceFrom:function(x,y){var topLeft=Utility.distance(x,y,0,0);var topRight=Utility.distance(x,y,this.width,0);var bottomLeft=Utility.distance(x,y,0,this.height);var bottomRight=Utility.distance(x,y,this.width,this.height);return Math.max(topLeft,topRight,bottomLeft,bottomRight)}};function Ripple(element){this.element=element;this.color=window.getComputedStyle(element).color;this.wave=document.createElement("div");this.waveContainer=document.createElement("div");this.wave.style.backgroundColor=this.color;this.wave.classList.add("wave");this.waveContainer.classList.add("wave-container");Polymer.dom(this.waveContainer).appendChild(this.wave);this.resetInteractionState()}Ripple.MAX_RADIUS=300;Ripple.prototype={get recenters(){return this.element.recenters},get center(){return this.element.center},get mouseDownElapsed(){var elapsed;if(!this.mouseDownStart){return 0}elapsed=Utility.now()-this.mouseDownStart;if(this.mouseUpStart){elapsed-=this.mouseUpElapsed}return elapsed},get mouseUpElapsed(){return this.mouseUpStart?Utility.now()-this.mouseUpStart:0},get mouseDownElapsedSeconds(){return this.mouseDownElapsed/1e3},get mouseUpElapsedSeconds(){return this.mouseUpElapsed/1e3},get mouseInteractionSeconds(){return this.mouseDownElapsedSeconds+this.mouseUpElapsedSeconds},get initialOpacity(){return this.element.initialOpacity},get opacityDecayVelocity(){return this.element.opacityDecayVelocity},get radius(){var width2=this.containerMetrics.width*this.containerMetrics.width;var height2=this.containerMetrics.height*this.containerMetrics.height;var waveRadius=Math.min(Math.sqrt(width2+height2),Ripple.MAX_RADIUS)*1.1+5;var duration=1.1-.2*(waveRadius/Ripple.MAX_RADIUS);var timeNow=this.mouseInteractionSeconds/duration;var size=waveRadius*(1-Math.pow(80,-timeNow));return Math.abs(size)},get opacity(){if(!this.mouseUpStart){return this.initialOpacity}return Math.max(0,this.initialOpacity-this.mouseUpElapsedSeconds*this.opacityDecayVelocity)},get outerOpacity(){var outerOpacity=this.mouseUpElapsedSeconds*.3;var waveOpacity=this.opacity;return Math.max(0,Math.min(outerOpacity,waveOpacity))},get isOpacityFullyDecayed(){return this.opacity<.01&&this.radius>=Math.min(this.maxRadius,Ripple.MAX_RADIUS)},get isRestingAtMaxRadius(){return this.opacity>=this.initialOpacity&&this.radius>=Math.min(this.maxRadius,Ripple.MAX_RADIUS)},get isAnimationComplete(){return this.mouseUpStart?this.isOpacityFullyDecayed:this.isRestingAtMaxRadius},get translationFraction(){return Math.min(1,this.radius/this.containerMetrics.size*2/Math.sqrt(2))},get xNow(){if(this.xEnd){return this.xStart+this.translationFraction*(this.xEnd-this.xStart)}return this.xStart},get yNow(){if(this.yEnd){return this.yStart+this.translationFraction*(this.yEnd-this.yStart)}return this.yStart},get isMouseDown(){return this.mouseDownStart&&!this.mouseUpStart},resetInteractionState:function(){this.maxRadius=0;this.mouseDownStart=0;this.mouseUpStart=0;this.xStart=0;
-
-this.yStart=0;this.xEnd=0;this.yEnd=0;this.slideDistance=0;this.containerMetrics=new ElementMetrics(this.element)},draw:function(){var scale;var translateString;var dx;var dy;this.wave.style.opacity=this.opacity;scale=this.radius/(this.containerMetrics.size/2);dx=this.xNow-this.containerMetrics.width/2;dy=this.yNow-this.containerMetrics.height/2;this.waveContainer.style.webkitTransform="translate("+dx+"px, "+dy+"px)";this.waveContainer.style.transform="translate3d("+dx+"px, "+dy+"px, 0)";this.wave.style.webkitTransform="scale("+scale+","+scale+")";this.wave.style.transform="scale3d("+scale+","+scale+",1)"},downAction:function(event){var xCenter=this.containerMetrics.width/2;var yCenter=this.containerMetrics.height/2;this.resetInteractionState();this.mouseDownStart=Utility.now();if(this.center){this.xStart=xCenter;this.yStart=yCenter;this.slideDistance=Utility.distance(this.xStart,this.yStart,this.xEnd,this.yEnd)}else{this.xStart=event?event.detail.x-this.containerMetrics.boundingRect.left:this.containerMetrics.width/2;this.yStart=event?event.detail.y-this.containerMetrics.boundingRect.top:this.containerMetrics.height/2}if(this.recenters){this.xEnd=xCenter;this.yEnd=yCenter;this.slideDistance=Utility.distance(this.xStart,this.yStart,this.xEnd,this.yEnd)}this.maxRadius=this.containerMetrics.furthestCornerDistanceFrom(this.xStart,this.yStart);this.waveContainer.style.top=(this.containerMetrics.height-this.containerMetrics.size)/2+"px";this.waveContainer.style.left=(this.containerMetrics.width-this.containerMetrics.size)/2+"px";this.waveContainer.style.width=this.containerMetrics.size+"px";this.waveContainer.style.height=this.containerMetrics.size+"px"},upAction:function(event){if(!this.isMouseDown){return}this.mouseUpStart=Utility.now()},remove:function(){Polymer.dom(this.waveContainer.parentNode).removeChild(this.waveContainer)}};Polymer({is:"paper-ripple",behaviors:[Polymer.IronA11yKeysBehavior],properties:{initialOpacity:{type:Number,value:.25},opacityDecayVelocity:{type:Number,value:.8},recenters:{type:Boolean,value:false},center:{type:Boolean,value:false},ripples:{type:Array,value:function(){return[]}},animating:{type:Boolean,readOnly:true,reflectToAttribute:true,value:false},holdDown:{type:Boolean,value:false,observer:"_holdDownChanged"},noink:{type:Boolean,value:false},_animating:{type:Boolean},_boundAnimate:{type:Function,value:function(){return this.animate.bind(this)}}},get target(){return this.keyEventTarget},keyBindings:{"enter:keydown":"_onEnterKeydown","space:keydown":"_onSpaceKeydown","space:keyup":"_onSpaceKeyup"},attached:function(){if(this.parentNode.nodeType==11){this.keyEventTarget=Polymer.dom(this).getOwnerRoot().host}else{this.keyEventTarget=this.parentNode}var keyEventTarget=this.keyEventTarget;this.listen(keyEventTarget,"up","uiUpAction");this.listen(keyEventTarget,"down","uiDownAction")},detached:function(){this.unlisten(this.keyEventTarget,"up","uiUpAction");this.unlisten(this.keyEventTarget,"down","uiDownAction");this.keyEventTarget=null},get shouldKeepAnimating(){for(var index=0;index<this.ripples.length;++index){if(!this.ripples[index].isAnimationComplete){return true}}return false},simulatedRipple:function(){this.downAction(null);this.async(function(){this.upAction()},1)},uiDownAction:function(event){if(!this.noink){this.downAction(event)}},downAction:function(event){if(this.holdDown&&this.ripples.length>0){return}var ripple=this.addRipple();ripple.downAction(event);if(!this._animating){this._animating=true;this.animate()}},uiUpAction:function(event){if(!this.noink){this.upAction(event)}},upAction:function(event){if(this.holdDown){return}this.ripples.forEach(function(ripple){ripple.upAction(event)});this._animating=true;this.animate()},onAnimationComplete:function(){this._animating=false;this.$.background.style.backgroundColor=null;this.fire("transitionend")},addRipple:function(){var ripple=new Ripple(this);Polymer.dom(this.$.waves).appendChild(ripple.waveContainer);this.$.background.style.backgroundColor=ripple.color;this.ripples.push(ripple);this._setAnimating(true);return ripple},removeRipple:function(ripple){var rippleIndex=this.ripples.indexOf(ripple);if(rippleIndex<0){return}this.ripples.splice(rippleIndex,1);ripple.remove();if(!this.ripples.length){this._setAnimating(false)}},animate:function(){if(!this._animating){return}var index;var ripple;for(index=0;index<this.ripples.length;++index){ripple=this.ripples[index];ripple.draw();this.$.background.style.opacity=ripple.outerOpacity;if(ripple.isOpacityFullyDecayed&&!ripple.isRestingAtMaxRadius){this.removeRipple(ripple)}}if(!this.shouldKeepAnimating&&this.ripples.length===0){this.onAnimationComplete()}else{window.requestAnimationFrame(this._boundAnimate)}},_onEnterKeydown:function(){this.uiDownAction();this.async(this.uiUpAction,1)},_onSpaceKeydown:function(){this.uiDownAction()},_onSpaceKeyup:function(){this.uiUpAction()},_holdDownChanged:function(newVal,oldVal){if(oldVal===undefined){return}if(newVal){this.downAction()}else{this.upAction()}}})})();Polymer.PaperRippleBehavior={properties:{noink:{type:Boolean,observer:"_noinkChanged"},_rippleContainer:{type:Object}},_buttonStateChanged:function(){if(this.focused){this.ensureRipple()}},_downHandler:function(event){Polymer.IronButtonStateImpl._downHandler.call(this,event);if(this.pressed){this.ensureRipple(event)}},ensureRipple:function(optTriggeringEvent){if(!this.hasRipple()){this._ripple=this._createRipple();this._ripple.noink=this.noink;var rippleContainer=this._rippleContainer||this.root;if(rippleContainer){Polymer.dom(rippleContainer).appendChild(this._ripple)}if(optTriggeringEvent){var domContainer=Polymer.dom(this._rippleContainer||this);var target=Polymer.dom(optTriggeringEvent).rootTarget;if(domContainer.deepContains(target)){this._ripple.uiDownAction(optTriggeringEvent)}}}},getRipple:function(){this.ensureRipple();return this._ripple},hasRipple:function(){return Boolean(this._ripple)},_createRipple:function(){return document.createElement("paper-ripple")},_noinkChanged:function(noink){if(this.hasRipple()){this._ripple.noink=noink}}};Polymer.PaperInkyFocusBehaviorImpl={observers:["_focusedChanged(receivedFocusFromKeyboard)"],_focusedChanged:function(receivedFocusFromKeyboard){if(receivedFocusFromKeyboard){this.ensureRipple()}if(this.hasRipple()){this._ripple.holdDown=receivedFocusFromKeyboard}},_createRipple:function(){var ripple=Polymer.PaperRippleBehavior._createRipple();ripple.id="ink";ripple.setAttribute("center","");ripple.classList.add("circle");return ripple}};Polymer.PaperInkyFocusBehavior=[Polymer.IronButtonState,Polymer.IronControlState,Polymer.PaperRippleBehavior,Polymer.PaperInkyFocusBehaviorImpl];Polymer({is:"paper-icon-button",hostAttributes:{role:"button",tabindex:"0"},behaviors:[Polymer.PaperInkyFocusBehavior],properties:{src:{type:String},icon:{type:String},alt:{type:String,observer:"_altChanged"}},_altChanged:function(newValue,oldValue){var label=this.getAttribute("aria-label");if(!label||oldValue==label){this.setAttribute("aria-label",newValue)}}});Polymer({is:"iron-iconset-svg",properties:{name:{type:String,observer:"_nameChanged"},size:{type:Number,value:24},rtlMirroring:{type:Boolean,value:false}},_targetIsRTL:function(target){if(target&&target.nodeType!==Node.ELEMENT_NODE){target=target.host}return target&&window.getComputedStyle(target)["direction"]==="rtl"},attached:function(){this.style.display="none"},getIconNames:function(){this._icons=this._createIconMap();return Object.keys(this._icons).map(function(n){return this.name+":"+n},this)},applyIcon:function(element,iconName){element=element.root||element;this.removeIcon(element);var svg=this._cloneIcon(iconName,this.rtlMirroring&&this._targetIsRTL(element));if(svg){var pde=Polymer.dom(element);pde.insertBefore(svg,pde.childNodes[0]);return element._svgIcon=svg}return null},removeIcon:function(element){element=element.root||element;if(element._svgIcon){Polymer.dom(element).removeChild(element._svgIcon);element._svgIcon=null}},_nameChanged:function(){new Polymer.IronMeta({type:"iconset",key:this.name,value:this});this.async(function(){this.fire("iron-iconset-added",this,{node:window})})},_createIconMap:function(){var icons=Object.create(null);Polymer.dom(this).querySelectorAll("[id]").forEach(function(icon){icons[icon.id]=icon});return icons},_cloneIcon:function(id,mirrorAllowed){this._icons=this._icons||this._createIconMap();return this._prepareSvgClone(this._icons[id],this.size,mirrorAllowed)},_prepareSvgClone:function(sourceSvg,size,mirrorAllowed){if(sourceSvg){var content=sourceSvg.cloneNode(true),svg=document.createElementNS("http://www.w3.org/2000/svg","svg"),viewBox=content.getAttribute("viewBox")||"0 0 "+size+" "+size,cssText="pointer-events: none; display: block; width: 100%; height: 100%;";if(mirrorAllowed&&content.hasAttribute("mirror-in-rtl")){cssText+="-webkit-transform:scale(-1,1);transform:scale(-1,1);"}svg.setAttribute("viewBox",viewBox);svg.setAttribute("preserveAspectRatio","xMidYMid meet");svg.style.cssText=cssText;svg.appendChild(content).removeAttribute("id");return svg}return null}});
+cr.define("cr.ui",function(){function KeyboardShortcut(shortcut){var mods={};var ident="";shortcut.split("|").forEach(function(part){var partLc=part.toLowerCase();switch(partLc){case"alt":case"ctrl":case"meta":case"shift":mods[partLc+"Key"]=true;break;default:if(ident)throw Error("Invalid shortcut");ident=part}});this.ident_=ident;this.mods_=mods}KeyboardShortcut.prototype={matchesEvent:function(e){if(e.key==this.ident_){var mods=this.mods_;return["altKey","ctrlKey","metaKey","shiftKey"].every(function(k){return e[k]==!!mods[k]})}return false}};var Command=cr.ui.define("command");Command.prototype={__proto__:HTMLElement.prototype,decorate:function(){CommandManager.init(assert(this.ownerDocument));if(this.hasAttribute("shortcut"))this.shortcut=this.getAttribute("shortcut")},execute:function(opt_element){if(this.disabled)return;var doc=this.ownerDocument;if(doc.activeElement){var e=new Event("command",{bubbles:true});e.command=this;(opt_element||doc.activeElement).dispatchEvent(e)}},canExecuteChange:function(opt_node){dispatchCanExecuteEvent(this,opt_node||this.ownerDocument.activeElement)},shortcut_:"",get shortcut(){return this.shortcut_},set shortcut(shortcut){var oldShortcut=this.shortcut_;if(shortcut!==oldShortcut){this.keyboardShortcuts_=shortcut.split(/\s+/).map(function(shortcut){return new KeyboardShortcut(shortcut)});this.shortcut_=shortcut;cr.dispatchPropertyChange(this,"shortcut",this.shortcut_,oldShortcut)}},matchesEvent:function(e){if(!this.keyboardShortcuts_)return false;return this.keyboardShortcuts_.some(function(keyboardShortcut){return keyboardShortcut.matchesEvent(e)})}};cr.defineProperty(Command,"label",cr.PropertyKind.ATTR);cr.defineProperty(Command,"disabled",cr.PropertyKind.BOOL_ATTR);cr.defineProperty(Command,"hidden",cr.PropertyKind.BOOL_ATTR);cr.defineProperty(Command,"checked",cr.PropertyKind.BOOL_ATTR);cr.defineProperty(Command,"hideShortcutText",cr.PropertyKind.BOOL_ATTR);function dispatchCanExecuteEvent(command,target){var e=new CanExecuteEvent(command);target.dispatchEvent(e);command.disabled=!e.canExecute}var commandManagers={};function CommandManager(doc){doc.addEventListener("focus",this.handleFocus_.bind(this),true);doc.addEventListener("keydown",this.handleKeyDown_.bind(this),false)}CommandManager.init=function(doc){var uid=cr.getUid(doc);if(!(uid in commandManagers)){commandManagers[uid]=new CommandManager(doc)}};CommandManager.prototype={handleFocus_:function(e){var target=e.target;if(target.menu||target.command)return;var commands=Array.prototype.slice.call(target.ownerDocument.querySelectorAll("command"));commands.forEach(function(command){dispatchCanExecuteEvent(command,target)})},handleKeyDown_:function(e){var target=e.target;var commands=Array.prototype.slice.call(target.ownerDocument.querySelectorAll("command"));for(var i=0,command;command=commands[i];i++){if(command.matchesEvent(e)){command.canExecuteChange();if(!command.disabled){e.preventDefault();e.stopPropagation();command.execute();return}}}}};function CanExecuteEvent(command){var e=new Event("canExecute",{bubbles:true,cancelable:true});e.__proto__=CanExecuteEvent.prototype;e.command=command;return e}CanExecuteEvent.prototype={__proto__:Event.prototype,command:null,canExecute_:false,get canExecute(){return this.canExecute_},set canExecute(canExecute){this.canExecute_=!!canExecute;this.stopPropagation();this.preventDefault()}};return{Command:Command,CanExecuteEvent:CanExecuteEvent}});Polymer({is:"iron-media-query",properties:{queryMatches:{type:Boolean,value:false,readOnly:true,notify:true},query:{type:String,observer:"queryChanged"},full:{type:Boolean,value:false},_boundMQHandler:{value:function(){return this.queryHandler.bind(this)}},_mq:{value:null}},attached:function(){this.style.display="none";this.queryChanged()},detached:function(){this._remove()},_add:function(){if(this._mq){this._mq.addListener(this._boundMQHandler)}},_remove:function(){if(this._mq){this._mq.removeListener(this._boundMQHandler)}this._mq=null},queryChanged:function(){this._remove();var query=this.query;if(!query){return}if(!this.full&&query[0]!=="("){query="("+query+")"}this._mq=window.matchMedia(query);this._add();this.queryHandler(this._mq)},queryHandler:function(mq){this._setQueryMatches(mq.matches)}});Polymer.IronResizableBehavior={properties:{_parentResizable:{type:Object,observer:"_parentResizableChanged"},_notifyingDescendant:{type:Boolean,value:false}},listeners:{"iron-request-resize-notifications":"_onIronRequestResizeNotifications"},created:function(){this._interestedResizables=[];this._boundNotifyResize=this.notifyResize.bind(this)},attached:function(){this.fire("iron-request-resize-notifications",null,{node:this,bubbles:true,cancelable:true});if(!this._parentResizable){window.addEventListener("resize",this._boundNotifyResize);this.notifyResize()}},detached:function(){if(this._parentResizable){this._parentResizable.stopResizeNotificationsFor(this)}else{window.removeEventListener("resize",this._boundNotifyResize)}this._parentResizable=null},notifyResize:function(){if(!this.isAttached){return}this._interestedResizables.forEach(function(resizable){if(this.resizerShouldNotify(resizable)){this._notifyDescendant(resizable)}},this);this._fireResize()},assignParentResizable:function(parentResizable){this._parentResizable=parentResizable},stopResizeNotificationsFor:function(target){var index=this._interestedResizables.indexOf(target);if(index>-1){this._interestedResizables.splice(index,1);this.unlisten(target,"iron-resize","_onDescendantIronResize")}},resizerShouldNotify:function(element){return true},_onDescendantIronResize:function(event){if(this._notifyingDescendant){event.stopPropagation();return}if(!Polymer.Settings.useShadow){this._fireResize()}},_fireResize:function(){this.fire("iron-resize",null,{node:this,bubbles:false})},_onIronRequestResizeNotifications:function(event){var target=event.path?event.path[0]:event.target;if(target===this){return}if(this._interestedResizables.indexOf(target)===-1){this._interestedResizables.push(target);this.listen(target,"iron-resize","_onDescendantIronResize")}target.assignParentResizable(this);this._notifyDescendant(target);event.stopPropagation()},_parentResizableChanged:function(parentResizable){if(parentResizable){window.removeEventListener("resize",this._boundNotifyResize)}},_notifyDescendant:function(descendant){if(!this.isAttached){return}this._notifyingDescendant=true;descendant.notifyResize();this._notifyingDescendant=false}};Polymer.IronSelection=function(selectCallback){this.selection=[];this.selectCallback=selectCallback};Polymer.IronSelection.prototype={get:function(){return this.multi?this.selection.slice():this.selection[0]},clear:function(excludes){this.selection.slice().forEach(function(item){if(!excludes||excludes.indexOf(item)<0){this.setItemSelected(item,false)}},this)},isSelected:function(item){return this.selection.indexOf(item)>=0},setItemSelected:function(item,isSelected){if(item!=null){if(isSelected!==this.isSelected(item)){if(isSelected){this.selection.push(item)}else{var i=this.selection.indexOf(item);if(i>=0){this.selection.splice(i,1)}}if(this.selectCallback){this.selectCallback(item,isSelected)}}}},select:function(item){if(this.multi){this.toggle(item)}else if(this.get()!==item){this.setItemSelected(this.get(),false);this.setItemSelected(item,true)}},toggle:function(item){this.setItemSelected(item,!this.isSelected(item))}};Polymer.IronSelectableBehavior={properties:{attrForSelected:{type:String,value:null},selected:{type:String,notify:true},selectedItem:{type:Object,readOnly:true,notify:true},activateEvent:{type:String,value:"tap",observer:"_activateEventChanged"},selectable:String,selectedClass:{type:String,value:"iron-selected"},selectedAttribute:{type:String,value:null},fallbackSelection:{type:String,value:null},items:{type:Array,readOnly:true,notify:true,value:function(){return[]}},_excludedLocalNames:{type:Object,value:function(){return{template:1}}}},observers:["_updateAttrForSelected(attrForSelected)","_updateSelected(selected)","_checkFallback(fallbackSelection)"],created:function(){this._bindFilterItem=this._filterItem.bind(this);this._selection=new Polymer.IronSelection(this._applySelection.bind(this))},attached:function(){this._observer=this._observeItems(this);this._updateItems();if(!this._shouldUpdateSelection){this._updateSelected()}this._addListener(this.activateEvent)},detached:function(){if(this._observer){Polymer.dom(this).unobserveNodes(this._observer)}this._removeListener(this.activateEvent)},indexOf:function(item){return this.items.indexOf(item)},select:function(value){this.selected=value},selectPrevious:function(){var length=this.items.length;var index=(Number(this._valueToIndex(this.selected))-1+length)%length;this.selected=this._indexToValue(index)},selectNext:function(){var index=(Number(this._valueToIndex(this.selected))+1)%this.items.length;this.selected=this._indexToValue(index)},selectIndex:function(index){this.select(this._indexToValue(index))},forceSynchronousItemUpdate:function(){this._updateItems()},get _shouldUpdateSelection(){return this.selected!=null},_checkFallback:function(){if(this._shouldUpdateSelection){this._updateSelected()}},_addListener:function(eventName){this.listen(this,eventName,"_activateHandler")},_removeListener:function(eventName){this.unlisten(this,eventName,"_activateHandler")},_activateEventChanged:function(eventName,old){this._removeListener(old);this._addListener(eventName)},_updateItems:function(){var nodes=Polymer.dom(this).queryDistributedElements(this.selectable||"*");nodes=Array.prototype.filter.call(nodes,this._bindFilterItem);this._setItems(nodes)},_updateAttrForSelected:function(){if(this._shouldUpdateSelection){this.selected=this._indexToValue(this.indexOf(this.selectedItem))}},_updateSelected:function(){this._selectSelected(this.selected)},_selectSelected:function(selected){this._selection.select(this._valueToItem(this.selected));if(this.fallbackSelection&&this.items.length&&this._selection.get()===undefined){this.selected=this.fallbackSelection}},_filterItem:function(node){return!this._excludedLocalNames[node.localName]},_valueToItem:function(value){return value==null?null:this.items[this._valueToIndex(value)]},_valueToIndex:function(value){if(this.attrForSelected){for(var i=0,item;item=this.items[i];i++){if(this._valueForItem(item)==value){return i}}}else{return Number(value)}},_indexToValue:function(index){if(this.attrForSelected){var item=this.items[index];if(item){return this._valueForItem(item)}}else{return index}},_valueForItem:function(item){var propValue=item[Polymer.CaseMap.dashToCamelCase(this.attrForSelected)];return propValue!=undefined?propValue:item.getAttribute(this.attrForSelected)},_applySelection:function(item,isSelected){if(this.selectedClass){this.toggleClass(this.selectedClass,isSelected,item)}if(this.selectedAttribute){this.toggleAttribute(this.selectedAttribute,isSelected,item)}this._selectionChange();this.fire("iron-"+(isSelected?"select":"deselect"),{item:item})},_selectionChange:function(){this._setSelectedItem(this._selection.get())},_observeItems:function(node){return Polymer.dom(node).observeNodes(function(mutation){this._updateItems();if(this._shouldUpdateSelection){this._updateSelected()}this.fire("iron-items-changed",mutation,{bubbles:false,cancelable:false})})},_activateHandler:function(e){var t=e.target;var items=this.items;while(t&&t!=this){var i=items.indexOf(t);if(i>=0){var value=this._indexToValue(i);this._itemActivate(value,t);return}t=t.parentNode}},_itemActivate:function(value,item){if(!this.fire("iron-activate",{selected:value,item:item},{cancelable:true}).defaultPrevented){this.select(value)}}};Polymer({is:"iron-pages",behaviors:[Polymer.IronResizableBehavior,Polymer.IronSelectableBehavior],properties:{activateEvent:{type:String,value:null}},observers:["_selectedPageChanged(selected)"],_selectedPageChanged:function(selected,old){this.async(this.notifyResize)}});Polymer.IronScrollTargetBehavior={properties:{scrollTarget:{type:HTMLElement,value:function(){return this._defaultScrollTarget}}},observers:["_scrollTargetChanged(scrollTarget, isAttached)"],_shouldHaveListener:true,_scrollTargetChanged:function(scrollTarget,isAttached){var eventTarget;if(this._oldScrollTarget){this._toggleScrollListener(false,this._oldScrollTarget);this._oldScrollTarget=null}if(!isAttached){return}if(scrollTarget==="document"){this.scrollTarget=this._doc}else if(typeof scrollTarget==="string"){this.scrollTarget=this.domHost?this.domHost.$[scrollTarget]:Polymer.dom(this.ownerDocument).querySelector("#"+scrollTarget)}else if(this._isValidScrollTarget()){this._boundScrollHandler=this._boundScrollHandler||this._scrollHandler.bind(this);this._oldScrollTarget=scrollTarget;this._toggleScrollListener(this._shouldHaveListener,scrollTarget)}},_scrollHandler:function scrollHandler(){},get _defaultScrollTarget(){return this._doc},get _doc(){return this.ownerDocument.documentElement},get _scrollTop(){if(this._isValidScrollTarget()){return this.scrollTarget===this._doc?window.pageYOffset:this.scrollTarget.scrollTop}return 0},get _scrollLeft(){if(this._isValidScrollTarget()){return this.scrollTarget===this._doc?window.pageXOffset:this.scrollTarget.scrollLeft}return 0},set _scrollTop(top){if(this.scrollTarget===this._doc){window.scrollTo(window.pageXOffset,top)}else if(this._isValidScrollTarget()){this.scrollTarget.scrollTop=top}},set _scrollLeft(left){if(this.scrollTarget===this._doc){window.scrollTo(left,window.pageYOffset)}else if(this._isValidScrollTarget()){this.scrollTarget.scrollLeft=left}},scroll:function(left,top){if(this.scrollTarget===this._doc){window.scrollTo(left,top)}else if(this._isValidScrollTarget()){this.scrollTarget.scrollLeft=left;this.scrollTarget.scrollTop=top}},get _scrollTargetWidth(){if(this._isValidScrollTarget()){return this.scrollTarget===this._doc?window.innerWidth:this.scrollTarget.offsetWidth}return 0},get _scrollTargetHeight(){if(this._isValidScrollTarget()){return this.scrollTarget===this._doc?window.innerHeight:this.scrollTarget.offsetHeight}return 0},_isValidScrollTarget:function(){return this.scrollTarget instanceof HTMLElement},_toggleScrollListener:function(yes,scrollTarget){if(!this._boundScrollHandler){return}var eventTarget=scrollTarget===this._doc?window:scrollTarget;if(yes){eventTarget.addEventListener("scroll",this._boundScrollHandler)}else{eventTarget.removeEventListener("scroll",this._boundScrollHandler)}},toggleScrollListener:function(yes){this._shouldHaveListener=yes;this._toggleScrollListener(yes,this.scrollTarget)}};(function(){var metaDatas={};var metaArrays={};var singleton=null;Polymer.IronMeta=Polymer({is:"iron-meta",properties:{type:{type:String,value:"default",observer:"_typeChanged"},key:{type:String,observer:"_keyChanged"},value:{type:Object,notify:true,observer:"_valueChanged"},self:{type:Boolean,observer:"_selfChanged"},list:{type:Array,notify:true}},hostAttributes:{hidden:true},factoryImpl:function(config){if(config){for(var n in config){switch(n){case"type":case"key":case"value":this[n]=config[n];break}}}},created:function(){this._metaDatas=metaDatas;this._metaArrays=metaArrays},_keyChanged:function(key,old){this._resetRegistration(old)},_valueChanged:function(value){this._resetRegistration(this.key)},_selfChanged:function(self){if(self){this.value=this}},_typeChanged:function(type){this._unregisterKey(this.key);if(!metaDatas[type]){metaDatas[type]={}}this._metaData=metaDatas[type];if(!metaArrays[type]){metaArrays[type]=[]}this.list=metaArrays[type];this._registerKeyValue(this.key,this.value)},byKey:function(key){return this._metaData&&this._metaData[key]},_resetRegistration:function(oldKey){this._unregisterKey(oldKey);this._registerKeyValue(this.key,this.value)},_unregisterKey:function(key){this._unregister(key,this._metaData,this.list)},_registerKeyValue:function(key,value){this._register(key,value,this._metaData,this.list)},_register:function(key,value,data,list){if(key&&data&&value!==undefined){data[key]=value;list.push(value)}},_unregister:function(key,data,list){if(key&&data){if(key in data){var value=data[key];delete data[key];this.arrayDelete(list,value)}}}});Polymer.IronMeta.getIronMeta=function getIronMeta(){if(singleton===null){singleton=new Polymer.IronMeta}return singleton};Polymer.IronMetaQuery=Polymer({is:"iron-meta-query",properties:{type:{type:String,value:"default",observer:"_typeChanged"},key:{type:String,observer:"_keyChanged"},value:{type:Object,notify:true,readOnly:true},list:{type:Array,notify:true}},factoryImpl:function(config){if(config){for(var n in config){switch(n){case"type":case"key":this[n]=config[n];break}}}},created:function(){this._metaDatas=metaDatas;this._metaArrays=metaArrays},_keyChanged:function(key){this._setValue(this._metaData&&this._metaData[key])},_typeChanged:function(type){this._metaData=metaDatas[type];this.list=metaArrays[type];if(this.key){this._keyChanged(this.key)}},byKey:function(key){return this._metaData&&this._metaData[key]}})})();Polymer({is:"iron-icon",properties:{icon:{type:String,observer:"_iconChanged"},theme:{type:String,observer:"_updateIcon"},src:{type:String,observer:"_srcChanged"},_meta:{value:Polymer.Base.create("iron-meta",{type:"iconset"}),observer:"_updateIcon"}},_DEFAULT_ICONSET:"icons",_iconChanged:function(icon){var parts=(icon||"").split(":");this._iconName=parts.pop();this._iconsetName=parts.pop()||this._DEFAULT_ICONSET;this._updateIcon()},_srcChanged:function(src){this._updateIcon()},_usesIconset:function(){return this.icon||!this.src},_updateIcon:function(){if(this._usesIconset()){if(this._img&&this._img.parentNode){Polymer.dom(this.root).removeChild(this._img)}if(this._iconName===""){if(this._iconset){this._iconset.removeIcon(this)}}else if(this._iconsetName&&this._meta){this._iconset=this._meta.byKey(this._iconsetName);if(this._iconset){this._iconset.applyIcon(this,this._iconName,this.theme);this.unlisten(window,"iron-iconset-added","_updateIcon")}else{this.listen(window,"iron-iconset-added","_updateIcon")}}}else{if(this._iconset){this._iconset.removeIcon(this)}if(!this._img){this._img=document.createElement("img");this._img.style.width="100%";this._img.style.height="100%";this._img.draggable=false}this._img.src=this.src;Polymer.dom(this.root).appendChild(this._img)}}});Polymer({is:"iron-iconset-svg",properties:{name:{type:String,observer:"_nameChanged"},size:{type:Number,value:24},rtlMirroring:{type:Boolean,value:false}},_targetIsRTL:function(target){if(target&&target.nodeType!==Node.ELEMENT_NODE){target=target.host}return target&&window.getComputedStyle(target)["direction"]==="rtl"},attached:function(){this.style.display="none"},getIconNames:function(){this._icons=this._createIconMap();return Object.keys(this._icons).map(function(n){return this.name+":"+n},this)},applyIcon:function(element,iconName){element=element.root||element;this.removeIcon(element);var svg=this._cloneIcon(iconName,this.rtlMirroring&&this._targetIsRTL(element));if(svg){var pde=Polymer.dom(element);pde.insertBefore(svg,pde.childNodes[0]);return element._svgIcon=svg}return null},removeIcon:function(element){element=element.root||element;if(element._svgIcon){Polymer.dom(element).removeChild(element._svgIcon);element._svgIcon=null}},_nameChanged:function(){new Polymer.IronMeta({type:"iconset",key:this.name,value:this});this.async(function(){this.fire("iron-iconset-added",this,{node:window})})},_createIconMap:function(){var icons=Object.create(null);Polymer.dom(this).querySelectorAll("[id]").forEach(function(icon){icons[icon.id]=icon});return icons},_cloneIcon:function(id,mirrorAllowed){this._icons=this._icons||this._createIconMap();return this._prepareSvgClone(this._icons[id],this.size,mirrorAllowed)},_prepareSvgClone:function(sourceSvg,size,mirrorAllowed){if(sourceSvg){var content=sourceSvg.cloneNode(true),svg=document.createElementNS("http://www.w3.org/2000/svg","svg"),viewBox=content.getAttribute("viewBox")||"0 0 "+size+" "+size,cssText="pointer-events: none; display: block; width: 100%; height: 100%;";if(mirrorAllowed&&content.hasAttribute("mirror-in-rtl")){cssText+="-webkit-transform:scale(-1,1);transform:scale(-1,1);"}svg.setAttribute("viewBox",viewBox);svg.setAttribute("preserveAspectRatio","xMidYMid meet");svg.style.cssText=cssText;svg.appendChild(content).removeAttribute("id");return svg}return null}});
 // 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:"cr-lazy-render","extends":"template",behaviors:[Polymer.Templatizer],child_:null,get:function(){if(!this.child_)this.render_();return this.child_},getIfExists:function(){return this.child_},render_:function(){if(!this.ctor)this.templatize(this);var parentNode=this.parentNode;if(parentNode&&!this.child_){var instance=this.stamp({});this.child_=instance.root.firstElementChild;parentNode.insertBefore(instance.root,this)}},_forwardParentProp:function(prop,value){if(this.child_)this.child_._templateInstance[prop]=value},_forwardParentPath:function(path,value){if(this.child_)this.child_._templateInstance.notifyPath(path,value,true)}});Polymer.PaperSpinnerBehavior={listeners:{animationend:"__reset",webkitAnimationEnd:"__reset"},properties:{active:{type:Boolean,value:false,reflectToAttribute:true,observer:"__activeChanged"},alt:{type:String,value:"loading",observer:"__altChanged"},__coolingDown:{type:Boolean,value:false}},__computeContainerClasses:function(active,coolingDown){return[active||coolingDown?"active":"",coolingDown?"cooldown":""].join(" ")},__activeChanged:function(active,old){this.__setAriaHidden(!active);this.__coolingDown=!active&&old},__altChanged:function(alt){if(alt===this.getPropertyInfo("alt").value){this.alt=this.getAttribute("aria-label")||alt}else{this.__setAriaHidden(alt==="");this.setAttribute("aria-label",alt)}},__setAriaHidden:function(hidden){var attr="aria-hidden";if(hidden){this.setAttribute(attr,"true")}else{this.removeAttribute(attr)}},__reset:function(){this.active=false;this.__coolingDown=false}};Polymer({is:"paper-spinner-lite",behaviors:[Polymer.PaperSpinnerBehavior]});
+Polymer({is:"cr-lazy-render","extends":"template",behaviors:[Polymer.Templatizer],child_:null,get:function(){if(!this.child_)this.render_();return this.child_},getIfExists:function(){return this.child_},render_:function(){if(!this.ctor)this.templatize(this);var parentNode=this.parentNode;if(parentNode&&!this.child_){var instance=this.stamp({});this.child_=instance.root.firstElementChild;parentNode.insertBefore(instance.root,this)}},_forwardParentProp:function(prop,value){if(this.child_)this.child_._templateInstance[prop]=value},_forwardParentPath:function(path,value){if(this.child_)this.child_._templateInstance.notifyPath(path,value,true)}});(function(){"use strict";var KEY_IDENTIFIER={"U+0008":"backspace","U+0009":"tab","U+001B":"esc","U+0020":"space","U+007F":"del"};var KEY_CODE={8:"backspace",9:"tab",13:"enter",27:"esc",33:"pageup",34:"pagedown",35:"end",36:"home",32:"space",37:"left",38:"up",39:"right",40:"down",46:"del",106:"*"};var MODIFIER_KEYS={shift:"shiftKey",ctrl:"ctrlKey",alt:"altKey",meta:"metaKey"};var KEY_CHAR=/[a-z0-9*]/;var IDENT_CHAR=/U\+/;var ARROW_KEY=/^arrow/;var SPACE_KEY=/^space(bar)?/;var ESC_KEY=/^escape$/;function transformKey(key,noSpecialChars){var validKey="";if(key){var lKey=key.toLowerCase();if(lKey===" "||SPACE_KEY.test(lKey)){validKey="space"}else if(ESC_KEY.test(lKey)){validKey="esc"}else if(lKey.length==1){if(!noSpecialChars||KEY_CHAR.test(lKey)){validKey=lKey}}else if(ARROW_KEY.test(lKey)){validKey=lKey.replace("arrow","")}else if(lKey=="multiply"){validKey="*"}else{validKey=lKey}}return validKey}function transformKeyIdentifier(keyIdent){var validKey="";if(keyIdent){if(keyIdent in KEY_IDENTIFIER){validKey=KEY_IDENTIFIER[keyIdent]}else if(IDENT_CHAR.test(keyIdent)){keyIdent=parseInt(keyIdent.replace("U+","0x"),16);validKey=String.fromCharCode(keyIdent).toLowerCase()}else{validKey=keyIdent.toLowerCase()}}return validKey}function transformKeyCode(keyCode){var validKey="";if(Number(keyCode)){if(keyCode>=65&&keyCode<=90){validKey=String.fromCharCode(32+keyCode)}else if(keyCode>=112&&keyCode<=123){validKey="f"+(keyCode-112)}else if(keyCode>=48&&keyCode<=57){validKey=String(keyCode-48)}else if(keyCode>=96&&keyCode<=105){validKey=String(keyCode-96)}else{validKey=KEY_CODE[keyCode]}}return validKey}function normalizedKeyForEvent(keyEvent,noSpecialChars){if(keyEvent.key){return transformKey(keyEvent.key,noSpecialChars)}if(keyEvent.detail&&keyEvent.detail.key){return transformKey(keyEvent.detail.key,noSpecialChars)}return transformKeyIdentifier(keyEvent.keyIdentifier)||transformKeyCode(keyEvent.keyCode)||""}function keyComboMatchesEvent(keyCombo,event){var keyEvent=normalizedKeyForEvent(event,keyCombo.hasModifiers);return keyEvent===keyCombo.key&&(!keyCombo.hasModifiers||!!event.shiftKey===!!keyCombo.shiftKey&&!!event.ctrlKey===!!keyCombo.ctrlKey&&!!event.altKey===!!keyCombo.altKey&&!!event.metaKey===!!keyCombo.metaKey)}function parseKeyComboString(keyComboString){if(keyComboString.length===1){return{combo:keyComboString,key:keyComboString,event:"keydown"}}return keyComboString.split("+").reduce(function(parsedKeyCombo,keyComboPart){var eventParts=keyComboPart.split(":");var keyName=eventParts[0];var event=eventParts[1];if(keyName in MODIFIER_KEYS){parsedKeyCombo[MODIFIER_KEYS[keyName]]=true;parsedKeyCombo.hasModifiers=true}else{parsedKeyCombo.key=keyName;parsedKeyCombo.event=event||"keydown"}return parsedKeyCombo},{combo:keyComboString.split(":").shift()})}function parseEventString(eventString){return eventString.trim().split(" ").map(function(keyComboString){return parseKeyComboString(keyComboString)})}Polymer.IronA11yKeysBehavior={properties:{keyEventTarget:{type:Object,value:function(){return this}},stopKeyboardEventPropagation:{type:Boolean,value:false},_boundKeyHandlers:{type:Array,value:function(){return[]}},_imperativeKeyBindings:{type:Object,value:function(){return{}}}},observers:["_resetKeyEventListeners(keyEventTarget, _boundKeyHandlers)"],keyBindings:{},registered:function(){this._prepKeyBindings()},attached:function(){this._listenKeyEventListeners()},detached:function(){this._unlistenKeyEventListeners()},addOwnKeyBinding:function(eventString,handlerName){this._imperativeKeyBindings[eventString]=handlerName;this._prepKeyBindings();this._resetKeyEventListeners()},removeOwnKeyBindings:function(){this._imperativeKeyBindings={};this._prepKeyBindings();this._resetKeyEventListeners()},keyboardEventMatchesKeys:function(event,eventString){var keyCombos=parseEventString(eventString);for(var i=0;i<keyCombos.length;++i){if(keyComboMatchesEvent(keyCombos[i],event)){return true}}return false},_collectKeyBindings:function(){var keyBindings=this.behaviors.map(function(behavior){return behavior.keyBindings});if(keyBindings.indexOf(this.keyBindings)===-1){keyBindings.push(this.keyBindings)}return keyBindings},_prepKeyBindings:function(){this._keyBindings={};this._collectKeyBindings().forEach(function(keyBindings){for(var eventString in keyBindings){this._addKeyBinding(eventString,keyBindings[eventString])}},this);for(var eventString in this._imperativeKeyBindings){this._addKeyBinding(eventString,this._imperativeKeyBindings[eventString])}for(var eventName in this._keyBindings){this._keyBindings[eventName].sort(function(kb1,kb2){var b1=kb1[0].hasModifiers;var b2=kb2[0].hasModifiers;return b1===b2?0:b1?-1:1})}},_addKeyBinding:function(eventString,handlerName){parseEventString(eventString).forEach(function(keyCombo){this._keyBindings[keyCombo.event]=this._keyBindings[keyCombo.event]||[];this._keyBindings[keyCombo.event].push([keyCombo,handlerName])},this)},_resetKeyEventListeners:function(){this._unlistenKeyEventListeners();if(this.isAttached){this._listenKeyEventListeners()}},_listenKeyEventListeners:function(){if(!this.keyEventTarget){return}Object.keys(this._keyBindings).forEach(function(eventName){var keyBindings=this._keyBindings[eventName];var boundKeyHandler=this._onKeyBindingEvent.bind(this,keyBindings);this._boundKeyHandlers.push([this.keyEventTarget,eventName,boundKeyHandler]);this.keyEventTarget.addEventListener(eventName,boundKeyHandler)},this)},_unlistenKeyEventListeners:function(){var keyHandlerTuple;var keyEventTarget;var eventName;var boundKeyHandler;while(this._boundKeyHandlers.length){keyHandlerTuple=this._boundKeyHandlers.pop();keyEventTarget=keyHandlerTuple[0];eventName=keyHandlerTuple[1];boundKeyHandler=keyHandlerTuple[2];keyEventTarget.removeEventListener(eventName,boundKeyHandler)}},_onKeyBindingEvent:function(keyBindings,event){if(this.stopKeyboardEventPropagation){event.stopPropagation()}if(event.defaultPrevented){return}for(var i=0;i<keyBindings.length;i++){var keyCombo=keyBindings[i][0];var handlerName=keyBindings[i][1];if(keyComboMatchesEvent(keyCombo,event)){this._triggerKeyHandler(keyCombo,handlerName,event);if(event.defaultPrevented){return}}}},_triggerKeyHandler:function(keyCombo,handlerName,keyboardEvent){var detail=Object.create(keyCombo);detail.keyboardEvent=keyboardEvent;var event=new CustomEvent(keyCombo.event,{detail:detail,cancelable:true});this[handlerName].call(this,event);if(event.defaultPrevented){keyboardEvent.preventDefault()}}}})();Polymer.IronControlState={properties:{focused:{type:Boolean,value:false,notify:true,readOnly:true,reflectToAttribute:true},disabled:{type:Boolean,value:false,notify:true,observer:"_disabledChanged",reflectToAttribute:true},_oldTabIndex:{type:Number},_boundFocusBlurHandler:{type:Function,value:function(){return this._focusBlurHandler.bind(this)}}},observers:["_changedControlState(focused, disabled)"],ready:function(){this.addEventListener("focus",this._boundFocusBlurHandler,true);this.addEventListener("blur",this._boundFocusBlurHandler,true)},_focusBlurHandler:function(event){if(event.target===this){this._setFocused(event.type==="focus")}else if(!this.shadowRoot){var target=Polymer.dom(event).localTarget;if(!this.isLightDescendant(target)){this.fire(event.type,{sourceEvent:event},{node:this,bubbles:event.bubbles,cancelable:event.cancelable})}}},_disabledChanged:function(disabled,old){this.setAttribute("aria-disabled",disabled?"true":"false");this.style.pointerEvents=disabled?"none":"";if(disabled){this._oldTabIndex=this.tabIndex;this._setFocused(false);this.tabIndex=-1;this.blur()}else if(this._oldTabIndex!==undefined){this.tabIndex=this._oldTabIndex}},_changedControlState:function(){if(this._controlStateChanged){this._controlStateChanged()}}};Polymer.IronButtonStateImpl={properties:{pressed:{type:Boolean,readOnly:true,value:false,reflectToAttribute:true,observer:"_pressedChanged"},toggles:{type:Boolean,value:false,reflectToAttribute:true},active:{type:Boolean,value:false,notify:true,reflectToAttribute:true},pointerDown:{type:Boolean,readOnly:true,value:false},receivedFocusFromKeyboard:{type:Boolean,readOnly:true},ariaActiveAttribute:{type:String,value:"aria-pressed",observer:"_ariaActiveAttributeChanged"}},listeners:{down:"_downHandler",up:"_upHandler",tap:"_tapHandler"},observers:["_detectKeyboardFocus(focused)","_activeChanged(active, ariaActiveAttribute)"],keyBindings:{"enter:keydown":"_asyncClick","space:keydown":"_spaceKeyDownHandler","space:keyup":"_spaceKeyUpHandler"},_mouseEventRe:/^mouse/,_tapHandler:function(){if(this.toggles){this._userActivate(!this.active)}else{this.active=false}},_detectKeyboardFocus:function(focused){this._setReceivedFocusFromKeyboard(!this.pointerDown&&focused)},_userActivate:function(active){if(this.active!==active){this.active=active;this.fire("change")}},_downHandler:function(event){this._setPointerDown(true);this._setPressed(true);this._setReceivedFocusFromKeyboard(false)},_upHandler:function(){this._setPointerDown(false);this._setPressed(false)},_spaceKeyDownHandler:function(event){var keyboardEvent=event.detail.keyboardEvent;var target=Polymer.dom(keyboardEvent).localTarget;if(this.isLightDescendant(target))return;keyboardEvent.preventDefault();keyboardEvent.stopImmediatePropagation();this._setPressed(true)},_spaceKeyUpHandler:function(event){var keyboardEvent=event.detail.keyboardEvent;var target=Polymer.dom(keyboardEvent).localTarget;if(this.isLightDescendant(target))return;if(this.pressed){this._asyncClick()}this._setPressed(false)},_asyncClick:function(){this.async(function(){this.click()},1)},_pressedChanged:function(pressed){this._changedButtonState()},_ariaActiveAttributeChanged:function(value,oldValue){if(oldValue&&oldValue!=value&&this.hasAttribute(oldValue)){this.removeAttribute(oldValue)}},_activeChanged:function(active,ariaActiveAttribute){if(this.toggles){this.setAttribute(this.ariaActiveAttribute,active?"true":"false")}else{this.removeAttribute(this.ariaActiveAttribute)}this._changedButtonState()},_controlStateChanged:function(){if(this.disabled){this._setPressed(false)}else{this._changedButtonState()}},_changedButtonState:function(){if(this._buttonStateChanged){this._buttonStateChanged()}}};Polymer.IronButtonState=[Polymer.IronA11yKeysBehavior,Polymer.IronButtonStateImpl];(function(){var Utility={distance:function(x1,y1,x2,y2){var xDelta=x1-x2;var yDelta=y1-y2;return Math.sqrt(xDelta*xDelta+yDelta*yDelta)},now:window.performance&&window.performance.now?window.performance.now.bind(window.performance):Date.now};function ElementMetrics(element){this.element=element;this.width=this.boundingRect.width;this.height=this.boundingRect.height;this.size=Math.max(this.width,this.height)}ElementMetrics.prototype={get boundingRect(){return this.element.getBoundingClientRect()},furthestCornerDistanceFrom:function(x,y){var topLeft=Utility.distance(x,y,0,0);var topRight=Utility.distance(x,y,this.width,0);var bottomLeft=Utility.distance(x,y,0,this.height);var bottomRight=Utility.distance(x,y,this.width,this.height);return Math.max(topLeft,topRight,bottomLeft,bottomRight)}};function Ripple(element){this.element=element;this.color=window.getComputedStyle(element).color;this.wave=document.createElement("div");this.waveContainer=document.createElement("div");this.wave.style.backgroundColor=this.color;this.wave.classList.add("wave");this.waveContainer.classList.add("wave-container");Polymer.dom(this.waveContainer).appendChild(this.wave);this.resetInteractionState()}Ripple.MAX_RADIUS=300;Ripple.prototype={get recenters(){return this.element.recenters},get center(){return this.element.center},get mouseDownElapsed(){var elapsed;if(!this.mouseDownStart){return 0}elapsed=Utility.now()-this.mouseDownStart;if(this.mouseUpStart){elapsed-=this.mouseUpElapsed}return elapsed},get mouseUpElapsed(){return this.mouseUpStart?Utility.now()-this.mouseUpStart:0},get mouseDownElapsedSeconds(){return this.mouseDownElapsed/1e3},get mouseUpElapsedSeconds(){return this.mouseUpElapsed/1e3},get mouseInteractionSeconds(){return this.mouseDownElapsedSeconds+this.mouseUpElapsedSeconds},get initialOpacity(){return this.element.initialOpacity},get opacityDecayVelocity(){return this.element.opacityDecayVelocity},get radius(){var width2=this.containerMetrics.width*this.containerMetrics.width;var height2=this.containerMetrics.height*this.containerMetrics.height;var waveRadius=Math.min(Math.sqrt(width2+height2),Ripple.MAX_RADIUS)*1.1+5;var duration=1.1-.2*(waveRadius/Ripple.MAX_RADIUS);var timeNow=this.mouseInteractionSeconds/duration;var size=waveRadius*(1-Math.pow(80,-timeNow));return Math.abs(size)},get opacity(){if(!this.mouseUpStart){return this.initialOpacity}return Math.max(0,this.initialOpacity-this.mouseUpElapsedSeconds*this.opacityDecayVelocity)},get outerOpacity(){var outerOpacity=this.mouseUpElapsedSeconds*.3;var waveOpacity=this.opacity;return Math.max(0,Math.min(outerOpacity,waveOpacity))},get isOpacityFullyDecayed(){return this.opacity<.01&&this.radius>=Math.min(this.maxRadius,Ripple.MAX_RADIUS)},get isRestingAtMaxRadius(){return this.opacity>=this.initialOpacity&&this.radius>=Math.min(this.maxRadius,Ripple.MAX_RADIUS)},get isAnimationComplete(){return this.mouseUpStart?this.isOpacityFullyDecayed:this.isRestingAtMaxRadius},get translationFraction(){return Math.min(1,this.radius/this.containerMetrics.size*2/Math.sqrt(2))},get xNow(){if(this.xEnd){return this.xStart+this.translationFraction*(this.xEnd-this.xStart)}return this.xStart},get yNow(){if(this.yEnd){return this.yStart+this.translationFraction*(this.yEnd-this.yStart)}return this.yStart},get isMouseDown(){return this.mouseDownStart&&!this.mouseUpStart},resetInteractionState:function(){this.maxRadius=0;this.mouseDownStart=0;this.mouseUpStart=0;this.xStart=0;this.yStart=0;this.xEnd=0;this.yEnd=0;this.slideDistance=0;this.containerMetrics=new ElementMetrics(this.element)},draw:function(){var scale;var translateString;var dx;var dy;this.wave.style.opacity=this.opacity;scale=this.radius/(this.containerMetrics.size/2);dx=this.xNow-this.containerMetrics.width/2;dy=this.yNow-this.containerMetrics.height/2;this.waveContainer.style.webkitTransform="translate("+dx+"px, "+dy+"px)";this.waveContainer.style.transform="translate3d("+dx+"px, "+dy+"px, 0)";this.wave.style.webkitTransform="scale("+scale+","+scale+")";this.wave.style.transform="scale3d("+scale+","+scale+",1)"},downAction:function(event){var xCenter=this.containerMetrics.width/2;var yCenter=this.containerMetrics.height/2;this.resetInteractionState();this.mouseDownStart=Utility.now();if(this.center){this.xStart=xCenter;this.yStart=yCenter;this.slideDistance=Utility.distance(this.xStart,this.yStart,this.xEnd,this.yEnd)}else{this.xStart=event?event.detail.x-this.containerMetrics.boundingRect.left:this.containerMetrics.width/2;this.yStart=event?event.detail.y-this.containerMetrics.boundingRect.top:this.containerMetrics.height/2}if(this.recenters){this.xEnd=xCenter;this.yEnd=yCenter;this.slideDistance=Utility.distance(this.xStart,this.yStart,this.xEnd,this.yEnd)}this.maxRadius=this.containerMetrics.furthestCornerDistanceFrom(this.xStart,this.yStart);this.waveContainer.style.top=(this.containerMetrics.height-this.containerMetrics.size)/2+"px";this.waveContainer.style.left=(this.containerMetrics.width-this.containerMetrics.size)/2+"px";this.waveContainer.style.width=this.containerMetrics.size+"px";this.waveContainer.style.height=this.containerMetrics.size+"px"},upAction:function(event){if(!this.isMouseDown){return}this.mouseUpStart=Utility.now()},remove:function(){Polymer.dom(this.waveContainer.parentNode).removeChild(this.waveContainer)}};Polymer({is:"paper-ripple",behaviors:[Polymer.IronA11yKeysBehavior],properties:{initialOpacity:{type:Number,value:.25},opacityDecayVelocity:{type:Number,value:.8},recenters:{type:Boolean,value:false},center:{type:Boolean,value:false},ripples:{type:Array,value:function(){return[]}},animating:{type:Boolean,readOnly:true,reflectToAttribute:true,value:false},holdDown:{type:Boolean,value:false,observer:"_holdDownChanged"},noink:{type:Boolean,value:false},_animating:{type:Boolean},_boundAnimate:{type:Function,value:function(){return this.animate.bind(this)}}},get target(){return this.keyEventTarget},keyBindings:{"enter:keydown":"_onEnterKeydown","space:keydown":"_onSpaceKeydown","space:keyup":"_onSpaceKeyup"},attached:function(){if(this.parentNode.nodeType==11){this.keyEventTarget=Polymer.dom(this).getOwnerRoot().host}else{this.keyEventTarget=this.parentNode}var keyEventTarget=this.keyEventTarget;this.listen(keyEventTarget,"up","uiUpAction");this.listen(keyEventTarget,"down","uiDownAction")},detached:function(){this.unlisten(this.keyEventTarget,"up","uiUpAction");this.unlisten(this.keyEventTarget,"down","uiDownAction");this.keyEventTarget=null},get shouldKeepAnimating(){for(var index=0;index<this.ripples.length;++index){if(!this.ripples[index].isAnimationComplete){return true}}return false},simulatedRipple:function(){this.downAction(null);this.async(function(){this.upAction()},1)},uiDownAction:function(event){if(!this.noink){this.downAction(event)}},downAction:function(event){if(this.holdDown&&this.ripples.length>0){return}var ripple=this.addRipple();ripple.downAction(event);if(!this._animating){this._animating=true;this.animate()}},uiUpAction:function(event){if(!this.noink){this.upAction(event)}},upAction:function(event){if(this.holdDown){return}this.ripples.forEach(function(ripple){ripple.upAction(event)});this._animating=true;this.animate()},onAnimationComplete:function(){this._animating=false;this.$.background.style.backgroundColor=null;this.fire("transitionend")},addRipple:function(){var ripple=new Ripple(this);Polymer.dom(this.$.waves).appendChild(ripple.waveContainer);this.$.background.style.backgroundColor=ripple.color;this.ripples.push(ripple);this._setAnimating(true);return ripple},removeRipple:function(ripple){var rippleIndex=this.ripples.indexOf(ripple);if(rippleIndex<0){return}this.ripples.splice(rippleIndex,1);ripple.remove();if(!this.ripples.length){this._setAnimating(false)}},animate:function(){if(!this._animating){return}var index;var ripple;for(index=0;index<this.ripples.length;++index){ripple=this.ripples[index];ripple.draw();this.$.background.style.opacity=ripple.outerOpacity;if(ripple.isOpacityFullyDecayed&&!ripple.isRestingAtMaxRadius){this.removeRipple(ripple)}}if(!this.shouldKeepAnimating&&this.ripples.length===0){this.onAnimationComplete()}else{window.requestAnimationFrame(this._boundAnimate)}},_onEnterKeydown:function(){this.uiDownAction();this.async(this.uiUpAction,1)},_onSpaceKeydown:function(){this.uiDownAction()},_onSpaceKeyup:function(){this.uiUpAction()},_holdDownChanged:function(newVal,oldVal){if(oldVal===undefined){return}if(newVal){this.downAction()}else{this.upAction()}}})})();Polymer.PaperRippleBehavior={properties:{noink:{type:Boolean,observer:"_noinkChanged"},_rippleContainer:{type:Object}},_buttonStateChanged:function(){if(this.focused){this.ensureRipple()}},_downHandler:function(event){Polymer.IronButtonStateImpl._downHandler.call(this,event);if(this.pressed){this.ensureRipple(event)}},ensureRipple:function(optTriggeringEvent){if(!this.hasRipple()){this._ripple=this._createRipple();this._ripple.noink=this.noink;var rippleContainer=this._rippleContainer||this.root;if(rippleContainer){Polymer.dom(rippleContainer).appendChild(this._ripple)}if(optTriggeringEvent){var domContainer=Polymer.dom(this._rippleContainer||this);var target=Polymer.dom(optTriggeringEvent).rootTarget;if(domContainer.deepContains(target)){this._ripple.uiDownAction(optTriggeringEvent)}}}},getRipple:function(){this.ensureRipple();return this._ripple},hasRipple:function(){return Boolean(this._ripple)},_createRipple:function(){return document.createElement("paper-ripple")},_noinkChanged:function(noink){if(this.hasRipple()){this._ripple.noink=noink}}};Polymer.PaperInkyFocusBehaviorImpl={observers:["_focusedChanged(receivedFocusFromKeyboard)"],_focusedChanged:function(receivedFocusFromKeyboard){if(receivedFocusFromKeyboard){this.ensureRipple()}if(this.hasRipple()){this._ripple.holdDown=receivedFocusFromKeyboard}},_createRipple:function(){var ripple=Polymer.PaperRippleBehavior._createRipple();ripple.id="ink";ripple.setAttribute("center","");ripple.classList.add("circle");return ripple}};Polymer.PaperInkyFocusBehavior=[Polymer.IronButtonState,Polymer.IronControlState,Polymer.PaperRippleBehavior,Polymer.PaperInkyFocusBehaviorImpl];Polymer({is:"paper-icon-button",hostAttributes:{role:"button",tabindex:"0"},behaviors:[Polymer.PaperInkyFocusBehavior],properties:{src:{type:String},icon:{type:String},alt:{type:String,observer:"_altChanged"}},_altChanged:function(newValue,oldValue){var label=this.getAttribute("aria-label");if(!label||oldValue==label){this.setAttribute("aria-label",newValue)}}});Polymer.PaperSpinnerBehavior={listeners:{animationend:"__reset",webkitAnimationEnd:"__reset"},properties:{active:{type:Boolean,value:false,reflectToAttribute:true,observer:"__activeChanged"},alt:{type:String,value:"loading",observer:"__altChanged"},__coolingDown:{type:Boolean,value:false}},__computeContainerClasses:function(active,coolingDown){return[active||coolingDown?"active":"",coolingDown?"cooldown":""].join(" ")},__activeChanged:function(active,old){this.__setAriaHidden(!active);this.__coolingDown=!active&&old},__altChanged:function(alt){if(alt===this.getPropertyInfo("alt").value){this.alt=this.getAttribute("aria-label")||alt}else{this.__setAriaHidden(alt==="");this.setAttribute("aria-label",alt)}},__setAriaHidden:function(hidden){var attr="aria-hidden";if(hidden){this.setAttribute(attr,"true")}else{this.removeAttribute(attr)}},__reset:function(){this.active=false;this.__coolingDown=false}};Polymer({is:"paper-spinner-lite",behaviors:[Polymer.PaperSpinnerBehavior]});
 // Copyright 2016 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
diff --git a/chrome/browser/resources/md_history/app.html b/chrome/browser/resources/md_history/app.html
index a693334..ba0d9c72 100644
--- a/chrome/browser/resources/md_history/app.html
+++ b/chrome/browser/resources/md_history/app.html
@@ -17,6 +17,7 @@
   <template>
     <style include="shared-style">
       :host {
+        color: var(--primary-text-color);
         display: block;
         height: 100%;
         overflow: hidden;
@@ -63,7 +64,7 @@
 
       #drawer-header {
         align-items: center;
-        border-bottom: 1px solid rgba(0, 0, 0, 0.08);
+        border-bottom: 1px solid var(--separator-color);
         box-sizing: border-box;
         display: flex;
         height: var(--toolbar-height);
@@ -71,7 +72,7 @@
 
       h1 {
         -webkit-padding-start: 24px;
-        color: rgb(66, 66, 66);
+        color: var(--primary-text-color);
         font-size: 123%;
         font-weight: 400;
       }
diff --git a/chrome/browser/resources/md_history/app.vulcanized.html b/chrome/browser/resources/md_history/app.vulcanized.html
index 09e4008..175133f3 100644
--- a/chrome/browser/resources/md_history/app.vulcanized.html
+++ b/chrome/browser/resources/md_history/app.vulcanized.html
@@ -31,7 +31,8 @@
 :root {
   /* This is a custom, Chrome-specific color that does not have a --paper or
    * --google equivalent. */
-  --md-background-color: rgb(241, 241, 241);
+  --md-background-color: #f1f1f1;
+  --md-loading-message-color: #6e6e6e;
   /* This is --google-blue-700, rewritten as a native custom property for speed.
    */
   --md-toolbar-color: rgb(51, 103, 214);
@@ -207,6 +208,39 @@
   </template>
 
   </dom-module>
+<iron-iconset-svg name="cr" size="24">
+  <svg>
+    <defs>
+      
+      <g id="add"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"></path></g>
+      <g id="arrow-drop-down"><path d="M7 10l5 5 5-5z"></path></g>
+      <g id="cancel"><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z"></path></g>
+<if expr="chromeos">
+      <g id="check"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"></path></g>
+</if>
+      <g id="chevron-right"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"></path></g>
+      <g id="clear"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></g>
+      <g id="close"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></g>
+      <g id="delete"><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"></path></g>
+      <g id="domain"><path d="M12 7V3H2v18h20V7H12zM6 19H4v-2h2v2zm0-4H4v-2h2v2zm0-4H4V9h2v2zm0-4H4V5h2v2zm4 12H8v-2h2v2zm0-4H8v-2h2v2zm0-4H8V9h2v2zm0-4H8V5h2v2zm10 12h-8v-2h2v-2h-2v-2h2v-2h-2V9h8v10zm-2-8h-2v2h2v-2zm0 4h-2v2h2v-2z"></path></g>
+      <g id="expand-less"><path d="M12 8l-6 6 1.41 1.41L12 10.83l4.59 4.58L18 14z"></path></g>
+      <g id="expand-more"><path d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"></path></g>
+      <g id="extension"><path d="M20.5 11H19V7c0-1.1-.9-2-2-2h-4V3.5C13 2.12 11.88 1 10.5 1S8 2.12 8 3.5V5H4c-1.1 0-1.99.9-1.99 2v3.8H3.5c1.49 0 2.7 1.21 2.7 2.7s-1.21 2.7-2.7 2.7H2V20c0 1.1.9 2 2 2h3.8v-1.5c0-1.49 1.21-2.7 2.7-2.7 1.49 0 2.7 1.21 2.7 2.7V22H17c1.1 0 2-.9 2-2v-4h1.5c1.38 0 2.5-1.12 2.5-2.5S21.88 11 20.5 11z"></path></g>
+      <g id="file-download"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"></path></g>
+      <g id="fullscreen"><path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"></path></g>
+      <g id="group"><path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"></path></g>
+      <g id="menu"><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"></path></g>
+      <g id="more-vert"><path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"></path></g>
+      <g id="open-in-new"><path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"></path></g>
+      <g id="person"><path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"></path></g>
+      <g id="print"><path d="M19 8H5c-1.66 0-3 1.34-3 3v6h4v4h12v-4h4v-6c0-1.66-1.34-3-3-3zm-3 11H8v-5h8v5zm3-7c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm-1-9H6v4h12V3z"></path></g>
+      <g id="search"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path></g>
+      <g id="settings"><path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"></path></g>
+      <g id="star"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"></path></g>
+      <g id="warning"><path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"></path></g>
+    </defs>
+  </svg>
+</iron-iconset-svg>
 <dom-module id="paper-ripple" assetpath="chrome://resources/polymer/v1_0/paper-ripple/" css-build="shadow">
 
   <template>
@@ -679,39 +713,6 @@
   </template>
 
   </dom-module>
-<iron-iconset-svg name="cr" size="24">
-  <svg>
-    <defs>
-      
-      <g id="add"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"></path></g>
-      <g id="arrow-drop-down"><path d="M7 10l5 5 5-5z"></path></g>
-      <g id="cancel"><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z"></path></g>
-<if expr="chromeos">
-      <g id="check"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"></path></g>
-</if>
-      <g id="chevron-right"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"></path></g>
-      <g id="clear"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></g>
-      <g id="close"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></g>
-      <g id="delete"><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"></path></g>
-      <g id="domain"><path d="M12 7V3H2v18h20V7H12zM6 19H4v-2h2v2zm0-4H4v-2h2v2zm0-4H4V9h2v2zm0-4H4V5h2v2zm4 12H8v-2h2v2zm0-4H8v-2h2v2zm0-4H8V9h2v2zm0-4H8V5h2v2zm10 12h-8v-2h2v-2h-2v-2h2v-2h-2V9h8v10zm-2-8h-2v2h2v-2zm0 4h-2v2h2v-2z"></path></g>
-      <g id="expand-less"><path d="M12 8l-6 6 1.41 1.41L12 10.83l4.59 4.58L18 14z"></path></g>
-      <g id="expand-more"><path d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"></path></g>
-      <g id="extension"><path d="M20.5 11H19V7c0-1.1-.9-2-2-2h-4V3.5C13 2.12 11.88 1 10.5 1S8 2.12 8 3.5V5H4c-1.1 0-1.99.9-1.99 2v3.8H3.5c1.49 0 2.7 1.21 2.7 2.7s-1.21 2.7-2.7 2.7H2V20c0 1.1.9 2 2 2h3.8v-1.5c0-1.49 1.21-2.7 2.7-2.7 1.49 0 2.7 1.21 2.7 2.7V22H17c1.1 0 2-.9 2-2v-4h1.5c1.38 0 2.5-1.12 2.5-2.5S21.88 11 20.5 11z"></path></g>
-      <g id="file-download"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"></path></g>
-      <g id="fullscreen"><path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"></path></g>
-      <g id="group"><path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"></path></g>
-      <g id="menu"><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"></path></g>
-      <g id="more-vert"><path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"></path></g>
-      <g id="open-in-new"><path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"></path></g>
-      <g id="person"><path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"></path></g>
-      <g id="print"><path d="M19 8H5c-1.66 0-3 1.34-3 3v6h4v4h12v-4h4v-6c0-1.66-1.34-3-3-3zm-3 11H8v-5h8v5zm3-7c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm-1-9H6v4h12V3z"></path></g>
-      <g id="search"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path></g>
-      <g id="settings"><path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"></path></g>
-      <g id="star"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"></path></g>
-      <g id="warning"><path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"></path></g>
-    </defs>
-  </svg>
-</iron-iconset-svg>
 <dom-module id="paper-spinner-styles" assetpath="chrome://resources/polymer/v1_0/paper-spinner/" css-build="shadow">
   <template>
     <style scope="paper-spinner-styles">:host {
@@ -1896,7 +1897,7 @@
 }
 
 :host(:not([narrow]):not([showing-search])) #icon, :host(:not([narrow])) #prompt {
-  opacity: 0.6;
+  opacity: 0.7;
 }
 
 :host([narrow]:not([showing-search])) #searchTerm {
@@ -2105,10 +2106,16 @@
     --card-padding-side: 24px;
     --card-sizing_-_margin:  0 auto; --card-sizing_-_max-width:  var(--card-max-width); --card-sizing_-_min-width:  var(--card-min-width); --card-sizing_-_padding:  0 var(--card-padding-side); --card-sizing_-_width:  calc(100% - 2 * var(--card-padding-side));;
     --first-card-padding-top: 24px;
+    --history-item-time-color: #646464;
+    --interactive-color: var(--google-blue-500);
     --item-height: 44px;
-    --primary-text-color: #333;
-    --secondary-text-color: #757575;
+    --link-color: var(--google-blue-700);
+    --primary-text-color: var(--paper-grey-800);
+    --secondary-text-color: var(--paper-grey-600);
+    --separator-color: rgba(0, 0, 0, 0.08);
     --side-bar-width: 256px;
+    --sidebar-footer-text-color: #6e6e6e;
+    --sidebar-unselected-color: #5a5a5a;
     --toolbar-grouped-height: 101px;
     --toolbar-height: 56px;
 }
@@ -2120,11 +2127,14 @@
   display: none !important;
 }
 
+a {
+  color: var(--link-color);
+}
+
 .card-title {
   align-items: center;
         border-bottom: 1px solid var(--card-border-color);
         border-radius: 2px 2px 0 0;
-        color: var(--primary-text-color);
         display: flex;
         font-size: 14px;
         font-weight: 500;
@@ -2138,7 +2148,7 @@
 
 .centered-message {
   align-items: center;
-        color: #b4b4b4;
+        color: var(--md-loading-message-color);
         display: flex;
         flex: 1;
         font-size: 14px;
@@ -2179,8 +2189,7 @@
 }
 
 button.icon-button iron-icon {
-  color: var(--secondary-text-color);
-        height: 20px;
+  height: 20px;
         width: 20px;
 }
 
@@ -2209,11 +2218,14 @@
   display: none !important;
 }
 
+a {
+  color: var(--link-color);
+}
+
 .card-title {
   align-items: center;
         border-bottom: 1px solid var(--card-border-color);
         border-radius: 2px 2px 0 0;
-        color: var(--primary-text-color);
         display: flex;
         font-size: 14px;
         font-weight: 500;
@@ -2227,7 +2239,7 @@
 
 .centered-message {
   align-items: center;
-        color: #b4b4b4;
+        color: var(--md-loading-message-color);
         display: flex;
         flex: 1;
         font-size: 14px;
@@ -2268,8 +2280,7 @@
 }
 
 button.icon-button iron-icon {
-  color: var(--secondary-text-color);
-        height: 20px;
+  height: 20px;
         width: 20px;
 }
 
@@ -2301,7 +2312,7 @@
 }
 
 :host([items-selected_]) {
-  background: rgb(68, 136, 255);
+  background: var(--interactive-color);
 }
 
 #toolbar-container {
@@ -2350,7 +2361,7 @@
   box-shadow: var(--shadow-elevation-2dp_-_box-shadow);
         background-color: white;
         border-radius: 2px;
-        color: var(--paper-grey-800);
+        color: var(--primary-text-color);
         overflow: hidden;
         padding: 12px 20px;
 }
@@ -2376,15 +2387,13 @@
 #cancel-icon-button {
   -webkit-margin-end: 24px;
         -webkit-margin-start: 2px;
-        height: 36px;
-        min-width: 36px;
-        width: 36px;
 }
 
-#grouped-nav-container paper-icon-button {
-  --paper-icon-button-ink-color: rgba(255, 255, 255, 0.4);
-        -webkit-margin-start: 24px;
-        flex: 0 0 auto;
+paper-tabs {
+  --paper-tabs-selection-bar-color: #fff;
+        -webkit-margin-start: 32px;
+        height: calc(var(--toolbar-grouped-height) - var(--toolbar-height));
+        min-width: 300px;
 }
 
 paper-tab {
@@ -2393,23 +2402,13 @@
         text-transform: uppercase;
 }
 
-paper-tabs {
-  --paper-tabs-selection-bar-color: var(--google-blue-500);
-        height: calc(var(--toolbar-grouped-height) - var(--toolbar-height));
-        min-width: 300px;
-}
-
 #grouped-buttons-container {
   align-items: center;
         display: flex;
 }
 
-#grouped-range-buttons {
-  -webkit-margin-start: 32px;
-}
-
 #grouped-nav-container {
-  -webkit-margin-end: 24px;
+  -webkit-margin-end: 16px;
         align-items: center;
         display: flex;
         flex: 1;
@@ -2424,7 +2423,8 @@
 }
 
 #grouped-date {
-  flex: 0 1 auto;
+  -webkit-margin-end: 8px;
+        flex: 0 1 auto;
         opacity: 0.7;
         overflow: hidden;
         text-align: right;
@@ -2432,6 +2432,15 @@
         white-space: nowrap;
 }
 
+#grouped-nav-container button {
+  -webkit-margin-start: 8px;
+        flex: 0 0 auto;
+}
+
+#grouped-nav-container button[disabled] {
+  color: rgba(255, 255, 255, 0.5);
+}
+
 :host-context([dir=rtl]) .rtl-reversible {
   transform: rotate(180deg);
 }
@@ -2458,8 +2467,9 @@
       <template is="dom-if" if="[[itemsSelected_]]">
         <div id="overlay-wrapper" hidden$="[[!itemsSelected_]]">
           <div id="overlay-buttons">
-            <paper-icon-button icon="cr:clear" id="cancel-icon-button" on-tap="onClearSelectionTap_" title="$i18n{cancel}">
-            </paper-icon-button>
+            <button is="paper-icon-button-light" id="cancel-icon-button" class="icon-button" on-tap="onClearSelectionTap_" title="$i18n{cancel}">
+              <iron-icon icon="cr:clear"></iron-icon>
+            </button>
             <div id="number-selected">[[numberOfItemsSelected_(count)]]</div>
             <paper-button id="cancel-button" on-tap="onClearSelectionTap_">
               $i18n{cancel}
@@ -2473,7 +2483,7 @@
     </div>
     <template is="dom-if" if="[[isGroupedMode]]">
       <div id="grouped-buttons-container">
-        <paper-tabs attr-for-selected="value" selected="{{groupedRange}}" id="grouped-range-buttons">
+        <paper-tabs attr-for-selected="value" selected="{{groupedRange}}">
           <paper-tab value="0">$i18n{rangeAllTime}</paper-tab>
           <paper-tab value="1">$i18n{rangeWeek}</paper-tab>
           <paper-tab value="2">$i18n{rangeMonth}</paper-tab>
@@ -2482,9 +2492,15 @@
           <span id="grouped-date">
             {{getHistoryInterval_(queryStartTime, queryEndTime)}}
           </span>
-          <paper-icon-button id="today-button" icon="history:today" alt="$i18n{rangeToday}" title="$i18n{rangeToday}" on-tap="onTodayTap_" disabled="[[isToday_(groupedOffset)]]"></paper-icon-button>
-          <paper-icon-button id="prev-button" icon="history:chevron-left" alt="$i18n{rangePrevious}" title="$i18n{rangePrevious}" class="rtl-reversible" on-tap="onPrevTap_" disabled="[[!hasMoreResults]]"></paper-icon-button>
-          <paper-icon-button id="next-button" icon="cr:chevron-right" alt="$i18n{rangeNext}" title="$i18n{rangeNext}" class="rtl-reversible" on-tap="onNextTap_" disabled="[[isToday_(groupedOffset)]]"></paper-icon-button>
+          <button is="paper-icon-button-light" id="today-button" class="icon-button" title="$i18n{rangeToday}" on-tap="onTodayTap_" disabled="[[isToday_(groupedOffset)]]">
+            <iron-icon icon="history:today"></iron-icon>
+          </button>
+          <button is="paper-icon-button-light" id="prev-button" title="$i18n{rangePrevious}" class="icon-button rtl-reversible" on-tap="onPrevTap_" disabled="[[!hasMoreResults]]">
+            <iron-icon icon="history:chevron-left"></iron-icon>
+          </button>
+          <button is="paper-icon-button-light" id="next-button" title="$i18n{rangeNext}" class="icon-button rtl-reversible" on-tap="onNextTap_" disabled="[[isToday_(groupedOffset)]]">
+            <iron-icon icon="cr:chevron-right"></iron-icon>
+          </button>
         </div>
       </div>
     </template>
@@ -2694,11 +2710,14 @@
   display: none !important;
 }
 
+a {
+  color: var(--link-color);
+}
+
 .card-title {
   align-items: center;
         border-bottom: 1px solid var(--card-border-color);
         border-radius: 2px 2px 0 0;
-        color: var(--primary-text-color);
         display: flex;
         font-size: 14px;
         font-weight: 500;
@@ -2712,7 +2731,7 @@
 
 .centered-message {
   align-items: center;
-        color: #b4b4b4;
+        color: var(--md-loading-message-color);
         display: flex;
         flex: 1;
         font-size: 14px;
@@ -2753,8 +2772,7 @@
 }
 
 button.icon-button iron-icon {
-  color: var(--secondary-text-color);
-        height: 20px;
+  height: 20px;
         width: 20px;
 }
 
@@ -2773,8 +2791,7 @@
 }
 
 :host {
-  --checked-color: rgb(68, 136, 255);
-        display: block;
+  display: block;
         outline: none;
         pointer-events: none;
 }
@@ -2837,7 +2854,7 @@
 }
 
 :host([selected]) #checkbox {
-  color: var(--checked-color);
+  color: var(--interactive-color);
 }
 
 #checkmark {
@@ -2865,8 +2882,8 @@
 }
 
 :host([selected]) #checkmark {
-  background: var(--checked-color);
-        border-color: var(--checked-color);
+  background: var(--interactive-color);
+        border-color: var(--interactive-color);
 }
 
 :host([selected]) #checkmark::after {
@@ -2877,7 +2894,7 @@
 }
 
 #time-accessed {
-  color: #646464;
+  color: var(--history-item-time-color);
         min-width: 96px;
 }
 
@@ -2898,7 +2915,7 @@
 }
 
 #bookmark-star {
-  color: var(--checked-color);
+  color: var(--interactive-color);
         height: 32px;
         width: 32px;
 }
@@ -3005,11 +3022,14 @@
   display: none !important;
 }
 
+a {
+  color: var(--link-color);
+}
+
 .card-title {
   align-items: center;
         border-bottom: 1px solid var(--card-border-color);
         border-radius: 2px 2px 0 0;
-        color: var(--primary-text-color);
         display: flex;
         font-size: 14px;
         font-weight: 500;
@@ -3023,7 +3043,7 @@
 
 .centered-message {
   align-items: center;
-        color: #b4b4b4;
+        color: var(--md-loading-message-color);
         display: flex;
         flex: 1;
         font-size: 14px;
@@ -3064,8 +3084,7 @@
 }
 
 button.icon-button iron-icon {
-  color: var(--secondary-text-color);
-        height: 20px;
+  height: 20px;
         width: 20px;
 }
 
@@ -3116,11 +3135,14 @@
   display: none !important;
 }
 
+a {
+  color: var(--link-color);
+}
+
 .card-title {
   align-items: center;
         border-bottom: 1px solid var(--card-border-color);
         border-radius: 2px 2px 0 0;
-        color: var(--primary-text-color);
         display: flex;
         font-size: 14px;
         font-weight: 500;
@@ -3134,7 +3156,7 @@
 
 .centered-message {
   align-items: center;
-        color: #b4b4b4;
+        color: var(--md-loading-message-color);
         display: flex;
         flex: 1;
         font-size: 14px;
@@ -3175,8 +3197,7 @@
 }
 
 button.icon-button iron-icon {
-  color: var(--secondary-text-color);
-        height: 20px;
+  height: 20px;
         width: 20px;
 }
 
@@ -3399,11 +3420,14 @@
   display: none !important;
 }
 
+a {
+  color: var(--link-color);
+}
+
 .card-title {
   align-items: center;
         border-bottom: 1px solid var(--card-border-color);
         border-radius: 2px 2px 0 0;
-        color: var(--primary-text-color);
         display: flex;
         font-size: 14px;
         font-weight: 500;
@@ -3417,7 +3441,7 @@
 
 .centered-message {
   align-items: center;
-        color: #b4b4b4;
+        color: var(--md-loading-message-color);
         display: flex;
         flex: 1;
         font-size: 14px;
@@ -3458,8 +3482,7 @@
 }
 
 button.icon-button iron-icon {
-  color: var(--secondary-text-color);
-        height: 20px;
+  height: 20px;
         width: 20px;
 }
 
@@ -3490,7 +3513,7 @@
 }
 
 div.separator {
-  background-color: rgba(0, 0, 0, 0.08);
+  background-color: var(--separator-color);
         flex-shrink: 0;
         height: 1px;
         margin: 8px 0;
@@ -3512,7 +3535,7 @@
 iron-selector {
   -webkit-user-select: none;
         background-color: transparent;
-        color: #5a5a5a;
+        color: var(--sidebar-unselected-color);
         display: flex;
         flex: 1;
         flex-direction: column;
@@ -3537,7 +3560,7 @@
 }
 
 iron-selector > a.iron-selected {
-  color: var(--google-blue-500);
+  color: var(--link-color);
 }
 
 #spacer {
@@ -3545,7 +3568,7 @@
 }
 
 #footer {
-  color: var(--paper-grey-600);
+  color: var(--sidebar-footer-text-color);
         width: var(--side-bar-width);
 }
 
@@ -3557,8 +3580,7 @@
 }
 
 #footer a {
-  color: var(--google-blue-700);
-        text-decoration: none;
+  text-decoration: none;
 }
 
 </style>
@@ -3592,11 +3614,14 @@
   display: none !important;
 }
 
+a {
+  color: var(--link-color);
+}
+
 .card-title {
   align-items: center;
         border-bottom: 1px solid var(--card-border-color);
         border-radius: 2px 2px 0 0;
-        color: var(--primary-text-color);
         display: flex;
         font-size: 14px;
         font-weight: 500;
@@ -3610,7 +3635,7 @@
 
 .centered-message {
   align-items: center;
-        color: #b4b4b4;
+        color: var(--md-loading-message-color);
         display: flex;
         flex: 1;
         font-size: 14px;
@@ -3651,8 +3676,7 @@
 }
 
 button.icon-button iron-icon {
-  color: var(--secondary-text-color);
-        height: 20px;
+  height: 20px;
         width: 20px;
 }
 
@@ -3671,7 +3695,8 @@
 }
 
 :host {
-  display: block;
+  color: var(--primary-text-color);
+        display: block;
         height: 100%;
         overflow: hidden;
         z-index: 0;
@@ -3714,7 +3739,7 @@
 
 #drawer-header {
   align-items: center;
-        border-bottom: 1px solid rgba(0, 0, 0, 0.08);
+        border-bottom: 1px solid var(--separator-color);
         box-sizing: border-box;
         display: flex;
         height: var(--toolbar-height);
@@ -3722,7 +3747,7 @@
 
 h1 {
   -webkit-padding-start: 24px;
-        color: rgb(66, 66, 66);
+        color: var(--primary-text-color);
         font-size: 123%;
         font-weight: 400;
 }
diff --git a/chrome/browser/resources/md_history/grouped_list.html b/chrome/browser/resources/md_history/grouped_list.html
index 557ec95..9986263 100644
--- a/chrome/browser/resources/md_history/grouped_list.html
+++ b/chrome/browser/resources/md_history/grouped_list.html
@@ -32,7 +32,7 @@
       }
 
       .domain-count {
-        color: rgb(151, 156, 160);
+        color: var(--secondary-text-color);
         padding-left: 10px;
       }
 
diff --git a/chrome/browser/resources/md_history/history.html b/chrome/browser/resources/md_history/history.html
index 6d3ea11..604407d6b 100644
--- a/chrome/browser/resources/md_history/history.html
+++ b/chrome/browser/resources/md_history/history.html
@@ -53,7 +53,7 @@
 
     #loading-message {
       align-items: center;
-      color: #b4b4b4;
+      color: var(--md-loading-message-color);
       flex: 1;
       font-weight: 500;
       justify-content: center;
diff --git a/chrome/browser/resources/md_history/history_item.html b/chrome/browser/resources/md_history/history_item.html
index 87bc8b1..cbbd233a 100644
--- a/chrome/browser/resources/md_history/history_item.html
+++ b/chrome/browser/resources/md_history/history_item.html
@@ -16,7 +16,6 @@
   <template>
     <style include="shared-style">
       :host {
-        --checked-color: rgb(68, 136, 255);
         display: block;
         outline: none;
         pointer-events: none;
@@ -81,7 +80,7 @@
       }
 
       :host([selected]) #checkbox {
-        color: var(--checked-color);
+        color: var(--interactive-color);
       }
 
       #checkmark {
@@ -109,8 +108,8 @@
       }
 
       :host([selected]) #checkmark {
-        background: var(--checked-color);
-        border-color: var(--checked-color);
+        background: var(--interactive-color);
+        border-color: var(--interactive-color);
       }
 
       :host([selected]) #checkmark::after {
@@ -121,7 +120,7 @@
       }
 
       #time-accessed {
-        color: #646464;
+        color: var(--history-item-time-color);
         min-width: 96px;
       }
 
@@ -142,7 +141,7 @@
       }
 
       #bookmark-star {
-        color: var(--checked-color);
+        color: var(--interactive-color);
         height: 32px;
         width: 32px;
       }
diff --git a/chrome/browser/resources/md_history/history_toolbar.html b/chrome/browser/resources/md_history/history_toolbar.html
index c5a31c3..a534da4 100644
--- a/chrome/browser/resources/md_history/history_toolbar.html
+++ b/chrome/browser/resources/md_history/history_toolbar.html
@@ -1,6 +1,5 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_toolbar/cr_toolbar.html">
@@ -21,6 +20,8 @@
         width: 100%;
       }
 
+      /* General toolbar layout. */
+
       cr-toolbar,
       #overlay-buttons,
       #overlay-wrapper,
@@ -31,7 +32,7 @@
       }
 
       :host([items-selected_]) {
-        background: rgb(68, 136, 255);
+        background: var(--interactive-color);
       }
 
       #toolbar-container {
@@ -62,6 +63,8 @@
         -webkit-margin-end: 12px;
       }
 
+      /* Info button and dropdown. */
+
       #info-button {
         /* Additional styles for unresolved <button>. */
         background: none;
@@ -87,11 +90,13 @@
         @apply(--shadow-elevation-2dp);
         background-color: white;
         border-radius: 2px;
-        color: var(--paper-grey-800);
+        color: var(--primary-text-color);
         overflow: hidden;
         padding: 12px 20px;
       }
 
+      /* Selection overlay. */
+
       :host(:not([has-drawer])) #overlay-wrapper {
         -webkit-margin-start: var(--side-bar-width);
       }
@@ -113,15 +118,16 @@
       #cancel-icon-button {
         -webkit-margin-end: 24px;
         -webkit-margin-start: 2px;
-        height: 36px;
-        min-width: 36px;
-        width: 36px;
       }
 
-      #grouped-nav-container paper-icon-button {
-        --paper-icon-button-ink-color: rgba(255, 255, 255, 0.4);
-        -webkit-margin-start: 24px;
-        flex: 0 0 auto;
+      /* Grouped toolbar. */
+
+      paper-tabs {
+        /* TODO(tsergeant): Align tabs with cards. */
+        --paper-tabs-selection-bar-color: #fff;
+        -webkit-margin-start: 32px;
+        height: calc(var(--toolbar-grouped-height) - var(--toolbar-height));
+        min-width: 300px;
       }
 
       paper-tab {
@@ -130,23 +136,13 @@
         text-transform: uppercase;
       }
 
-      paper-tabs {
-        --paper-tabs-selection-bar-color: var(--google-blue-500);
-        height: calc(var(--toolbar-grouped-height) - var(--toolbar-height));
-        min-width: 300px;
-      }
-
       #grouped-buttons-container {
         align-items: center;
         display: flex;
       }
 
-      #grouped-range-buttons {
-        -webkit-margin-start: 32px;
-      }
-
       #grouped-nav-container {
-        -webkit-margin-end: 24px;
+        -webkit-margin-end: 16px;
         align-items: center;
         display: flex;
         flex: 1;
@@ -161,6 +157,7 @@
       }
 
       #grouped-date {
+        -webkit-margin-end: 8px;
         flex: 0 1 auto;
         opacity: 0.7;
         overflow: hidden;
@@ -169,6 +166,15 @@
         white-space: nowrap;
       }
 
+      #grouped-nav-container button {
+        -webkit-margin-start: 8px;
+        flex: 0 0 auto;
+      }
+
+      #grouped-nav-container button[disabled] {
+        color: rgba(255, 255, 255, 0.5);
+      }
+
       :host-context([dir=rtl]) .rtl-reversible {
         transform: rotate(180deg);
       }
@@ -208,9 +214,13 @@
       <template is="dom-if" if="[[itemsSelected_]]">
         <div id="overlay-wrapper" hidden$="[[!itemsSelected_]]">
           <div id="overlay-buttons">
-            <paper-icon-button icon="cr:clear" id="cancel-icon-button"
-                on-tap="onClearSelectionTap_" title="$i18n{cancel}">
-            </paper-icon-button>
+            <button is="paper-icon-button-light"
+                id="cancel-icon-button"
+                class="icon-button"
+                on-tap="onClearSelectionTap_"
+                title="$i18n{cancel}">
+              <iron-icon icon="cr:clear"></iron-icon>
+            </button>
             <div id="number-selected">[[numberOfItemsSelected_(count)]]</div>
             <paper-button id="cancel-button" on-tap="onClearSelectionTap_">
               $i18n{cancel}
@@ -224,8 +234,7 @@
     </div>
     <template is="dom-if" if="[[isGroupedMode]]">
       <div id="grouped-buttons-container">
-        <paper-tabs attr-for-selected="value" selected="{{groupedRange}}"
-            id="grouped-range-buttons">
+        <paper-tabs attr-for-selected="value" selected="{{groupedRange}}">
           <paper-tab value="0">$i18n{rangeAllTime}</paper-tab>
           <paper-tab value="1">$i18n{rangeWeek}</paper-tab>
           <paper-tab value="2">$i18n{rangeMonth}</paper-tab>
@@ -234,23 +243,30 @@
           <span id="grouped-date">
             {{getHistoryInterval_(queryStartTime, queryEndTime)}}
           </span>
-          <paper-icon-button id="today-button" icon="history:today"
-              alt="$i18n{rangeToday}"
+          <button is="paper-icon-button-light"
+              id="today-button"
+              class="icon-button"
               title="$i18n{rangeToday}"
               on-tap="onTodayTap_"
-              disabled="[[isToday_(groupedOffset)]]"></paper-icon-button>
-          <paper-icon-button id="prev-button" icon="history:chevron-left"
-              alt="$i18n{rangePrevious}"
+              disabled="[[isToday_(groupedOffset)]]">
+            <iron-icon icon="history:today"></iron-icon>
+          </button>
+          <button is="paper-icon-button-light"
+              id="prev-button"
               title="$i18n{rangePrevious}"
-              class="rtl-reversible"
+              class="icon-button rtl-reversible"
               on-tap="onPrevTap_"
-              disabled="[[!hasMoreResults]]"></paper-icon-button>
-          <paper-icon-button id="next-button" icon="cr:chevron-right"
-              alt="$i18n{rangeNext}"
+              disabled="[[!hasMoreResults]]">
+            <iron-icon icon="history:chevron-left"></iron-icon>
+          </button>
+          <button is="paper-icon-button-light"
+              id="next-button"
               title="$i18n{rangeNext}"
-              class="rtl-reversible"
+              class="icon-button rtl-reversible"
               on-tap="onNextTap_"
-              disabled="[[isToday_(groupedOffset)]]"></paper-icon-button>
+              disabled="[[isToday_(groupedOffset)]]">
+            <iron-icon icon="cr:chevron-right"></iron-icon>
+          </button>
         </div>
       </div>
     </template>
diff --git a/chrome/browser/resources/md_history/lazy_load.vulcanized.html b/chrome/browser/resources/md_history/lazy_load.vulcanized.html
index 9c958e04..3154e4b 100644
--- a/chrome/browser/resources/md_history/lazy_load.vulcanized.html
+++ b/chrome/browser/resources/md_history/lazy_load.vulcanized.html
@@ -48,11 +48,14 @@
   display: none !important;
 }
 
+a {
+  color: var(--link-color);
+}
+
 .card-title {
   align-items: center;
         border-bottom: 1px solid var(--card-border-color);
         border-radius: 2px 2px 0 0;
-        color: var(--primary-text-color);
         display: flex;
         font-size: 14px;
         font-weight: 500;
@@ -66,7 +69,7 @@
 
 .centered-message {
   align-items: center;
-        color: #b4b4b4;
+        color: var(--md-loading-message-color);
         display: flex;
         flex: 1;
         font-size: 14px;
@@ -107,8 +110,7 @@
 }
 
 button.icon-button iron-icon {
-  color: var(--secondary-text-color);
-        height: 20px;
+  height: 20px;
         width: 20px;
 }
 
@@ -148,7 +150,7 @@
 }
 
 .domain-count {
-  color: rgb(151, 156, 160);
+  color: var(--secondary-text-color);
         padding-left: 10px;
 }
 
@@ -599,11 +601,14 @@
   display: none !important;
 }
 
+a {
+  color: var(--link-color);
+}
+
 .card-title {
   align-items: center;
         border-bottom: 1px solid var(--card-border-color);
         border-radius: 2px 2px 0 0;
-        color: var(--primary-text-color);
         display: flex;
         font-size: 14px;
         font-weight: 500;
@@ -617,7 +622,7 @@
 
 .centered-message {
   align-items: center;
-        color: #b4b4b4;
+        color: var(--md-loading-message-color);
         display: flex;
         flex: 1;
         font-size: 14px;
@@ -658,8 +663,7 @@
 }
 
 button.icon-button iron-icon {
-  color: var(--secondary-text-color);
-        height: 20px;
+  height: 20px;
         width: 20px;
 }
 
@@ -711,6 +715,7 @@
 
 #right-buttons {
   -webkit-margin-end: 4px;
+        color: var(--secondary-text-color);
 }
 
 #menu-button {
@@ -786,11 +791,14 @@
   display: none !important;
 }
 
+a {
+  color: var(--link-color);
+}
+
 .card-title {
   align-items: center;
         border-bottom: 1px solid var(--card-border-color);
         border-radius: 2px 2px 0 0;
-        color: var(--primary-text-color);
         display: flex;
         font-size: 14px;
         font-weight: 500;
@@ -804,7 +812,7 @@
 
 .centered-message {
   align-items: center;
-        color: #b4b4b4;
+        color: var(--md-loading-message-color);
         display: flex;
         flex: 1;
         font-size: 14px;
@@ -845,8 +853,7 @@
 }
 
 button.icon-button iron-icon {
-  color: var(--secondary-text-color);
-        height: 20px;
+  height: 20px;
         width: 20px;
 }
 
@@ -960,13 +967,12 @@
 }
 
 #sign-in-promo {
-  color: var(--primary-text-color);
-        font-size: 215%;
+  font-size: 215%;
         margin-top: 40px;
 }
 
 #sign-in-promo-desc {
-  color: #848484;
+  color: var(--secondary-text-color);
         font-size: 123%;
         margin-top: 10px;
 }
diff --git a/chrome/browser/resources/md_history/shared_style.html b/chrome/browser/resources/md_history/shared_style.html
index 9c6d07c..8e4e8c6 100644
--- a/chrome/browser/resources/md_history/shared_style.html
+++ b/chrome/browser/resources/md_history/shared_style.html
@@ -7,11 +7,14 @@
         display: none !important;
       }
 
+      a {
+        color: var(--link-color);
+      }
+
       .card-title {
         align-items: center;
         border-bottom: 1px solid var(--card-border-color);
         border-radius: 2px 2px 0 0;
-        color: var(--primary-text-color);
         display: flex;
         font-size: 14px;
         font-weight: 500;
@@ -25,7 +28,7 @@
 
       .centered-message {
         align-items: center;
-        color: #b4b4b4;
+        color: var(--md-loading-message-color);
         display: flex;
         flex: 1;
         font-size: 14px;
@@ -66,7 +69,6 @@
       }
 
       button.icon-button iron-icon {
-        color: var(--secondary-text-color);
         height: 20px;
         width: 20px;
       }
diff --git a/chrome/browser/resources/md_history/shared_vars.html b/chrome/browser/resources/md_history/shared_vars.html
index 967e990..68bf438f 100644
--- a/chrome/browser/resources/md_history/shared_vars.html
+++ b/chrome/browser/resources/md_history/shared_vars.html
@@ -1,3 +1,6 @@
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/default-theme.html">
+
 <style is="custom-style">
   :root {
     --card-border-color: rgba(0, 0, 0, 0.14);
@@ -14,10 +17,16 @@
       width: calc(100% - 2 * var(--card-padding-side));
     };
     --first-card-padding-top: 24px;
+    --history-item-time-color: #646464;
+    --interactive-color: var(--google-blue-500);
     --item-height: 44px;
-    --primary-text-color: #333;
-    --secondary-text-color: #757575;
+    --link-color: var(--google-blue-700);
+    --primary-text-color: var(--paper-grey-800);
+    --secondary-text-color: var(--paper-grey-600);
+    --separator-color: rgba(0, 0, 0, 0.08);
     --side-bar-width: 256px;
+    --sidebar-footer-text-color: #6e6e6e;
+    --sidebar-unselected-color: #5a5a5a;
     --toolbar-grouped-height: 101px;
     --toolbar-height: 56px;
   }
diff --git a/chrome/browser/resources/md_history/side_bar.html b/chrome/browser/resources/md_history/side_bar.html
index c4c8254..226ee403 100644
--- a/chrome/browser/resources/md_history/side_bar.html
+++ b/chrome/browser/resources/md_history/side_bar.html
@@ -23,7 +23,7 @@
       }
 
       div.separator {
-        background-color: rgba(0, 0, 0, 0.08);
+        background-color: var(--separator-color);
         flex-shrink: 0;
         height: 1px;
         margin: 8px 0;
@@ -45,7 +45,7 @@
       iron-selector {
         -webkit-user-select: none;
         background-color: transparent;
-        color: #5a5a5a;
+        color: var(--sidebar-unselected-color);
         display: flex;
         flex: 1;
         flex-direction: column;
@@ -70,7 +70,7 @@
       }
 
       iron-selector > a.iron-selected {
-        color: var(--google-blue-500);
+        color: var(--link-color);
       }
 
       #spacer {
@@ -78,7 +78,7 @@
       }
 
       #footer {
-        color: var(--paper-grey-600);
+        color: var(--sidebar-footer-text-color);
         width: var(--side-bar-width);
       }
 
@@ -90,7 +90,6 @@
       }
 
       #footer a {
-        color: var(--google-blue-700);
         text-decoration: none;
       }
     </style>
diff --git a/chrome/browser/resources/md_history/synced_device_card.html b/chrome/browser/resources/md_history/synced_device_card.html
index c7fa695c..e36c0e0 100644
--- a/chrome/browser/resources/md_history/synced_device_card.html
+++ b/chrome/browser/resources/md_history/synced_device_card.html
@@ -48,6 +48,7 @@
 
       #right-buttons {
         -webkit-margin-end: 4px;
+        color: var(--secondary-text-color);
       }
 
       #menu-button {
diff --git a/chrome/browser/resources/md_history/synced_device_manager.html b/chrome/browser/resources/md_history/synced_device_manager.html
index a685a1e..2673eb0d 100644
--- a/chrome/browser/resources/md_history/synced_device_manager.html
+++ b/chrome/browser/resources/md_history/synced_device_manager.html
@@ -41,13 +41,12 @@
       }
 
       #sign-in-promo {
-        color: var(--primary-text-color);
         font-size: 215%;
         margin-top: 40px;
       }
 
       #sign-in-promo-desc {
-        color: #848484;
+        color: var(--secondary-text-color);
         font-size: 123%;
         margin-top: 10px;
       }
diff --git a/chrome/browser/resources/omnibox/omnibox.js b/chrome/browser/resources/omnibox/omnibox.js
index 7fa1ef5..11c4a993 100644
--- a/chrome/browser/resources/omnibox/omnibox.js
+++ b/chrome/browser/resources/omnibox/omnibox.js
@@ -415,24 +415,26 @@
 
   function initializeProxies() {
     return importModules([
+      'mojo/public/js/bindings',
       'mojo/public/js/connection',
       'chrome/browser/ui/webui/omnibox/omnibox.mojom',
       'content/public/renderer/frame_interfaces',
     ]).then(function(modules) {
-      var connection = modules[0];
-      var mojom = modules[1];
-      var frameInterfaces = modules[2];
+      var bindings = modules[0];
+      var connection = modules[1];
+      var mojom = modules[2];
+      var frameInterfaces = modules[3];
 
       browserProxy = connection.bindHandleToProxy(
           frameInterfaces.getInterface(mojom.OmniboxPageHandler.name),
           mojom.OmniboxPageHandler);
 
       /** @constructor */
-      var OmniboxPageImpl = function() {};
+      var OmniboxPageImpl = function() {
+        this.binding = new bindings.Binding(mojom.OmniboxPage, this);
+      };
 
       OmniboxPageImpl.prototype = {
-        __proto__: mojom.OmniboxPage.stubClass.prototype,
-
         /** @override */
         handleNewAutocompleteResult: function(result) {
           progressiveAutocompleteResults.push(result);
@@ -441,12 +443,7 @@
       };
 
       pageImpl = new OmniboxPageImpl();
-
-      // Create a message pipe, with one end of the pipe already connected to
-      // JS.
-      var handle = connection.bindStubDerivedImpl(pageImpl);
-      // Send the other end of the pipe to C++.
-      browserProxy.setClientPage(handle);
+      browserProxy.setClientPage(pageImpl.binding.createInterfacePtrAndBind());
     });
   }
 
diff --git a/chrome/browser/resources/plugins.js b/chrome/browser/resources/plugins.js
index 8acef3c7..bffd6bb 100644
--- a/chrome/browser/resources/plugins.js
+++ b/chrome/browser/resources/plugins.js
@@ -227,35 +227,33 @@
 
 function initializeProxies() {
   return importModules([
+    'mojo/public/js/bindings',
     'mojo/public/js/connection',
     'chrome/browser/ui/webui/plugins/plugins.mojom',
     'content/public/renderer/frame_interfaces',
   ]).then(function(modules) {
-    var connection = modules[0];
-    var pluginsMojom = modules[1];
-    var frameInterfaces = modules[2];
+    var bindings = modules[0];
+    var connection = modules[1];
+    var pluginsMojom = modules[2];
+    var frameInterfaces = modules[3];
 
     browserProxy = connection.bindHandleToProxy(
         frameInterfaces.getInterface(pluginsMojom.PluginsPageHandler.name),
         pluginsMojom.PluginsPageHandler);
 
     /** @constructor */
-    var PluginsPageImpl = function() {};
+    var PluginsPageImpl = function() {
+      this.binding = new bindings.Binding(pluginsMojom.PluginsPage, this);
+    };
 
     PluginsPageImpl.prototype = {
-      __proto__: pluginsMojom.PluginsPage.stubClass.prototype,
-
       /** @override */
       onPluginsUpdated: function(plugins) {
         returnPluginsData({plugins: plugins});
       },
     };
     pageImpl = new PluginsPageImpl();
-
-    // Create a message pipe, with one end of the pipe already connected to JS.
-    var handle = connection.bindStubDerivedImpl(pageImpl);
-    // Send the other end of the pipe to C++.
-    browserProxy.setClientPage(handle);
+    browserProxy.setClientPage(pageImpl.binding.createInterfacePtrAndBind());
   });
 }
 
diff --git a/chrome/browser/resources/settings/about_page/channel_switcher_dialog.html b/chrome/browser/resources/settings/about_page/channel_switcher_dialog.html
index a04b0f5ab..1edbba0 100644
--- a/chrome/browser/resources/settings/about_page/channel_switcher_dialog.html
+++ b/chrome/browser/resources/settings/about_page/channel_switcher_dialog.html
@@ -9,7 +9,11 @@
 
 <dom-module id="settings-channel-switcher-dialog">
   <template>
-    <style include="settings-shared"></style>
+    <style include="settings-shared">
+      dialog {
+        width: 600px;
+      }
+    </style>
     <dialog is="cr-dialog" id="dialog">
       <div class="title">$i18n{aboutChangeChannel}</div>
       <div class="body">
@@ -19,13 +23,13 @@
         <paper-radio-group
             on-paper-radio-group-changed="onChannelSelectionChanged_">
           <paper-radio-button name="[[browserChannelEnum_.STABLE]]">
-            $i18n{aboutChannelStable}
+            $i18n{aboutChannelDialogStable}
           </paper-radio-button>
           <paper-radio-button name="[[browserChannelEnum_.BETA]]">
-            $i18n{aboutChannelBeta}
+            $i18n{aboutChannelDialogBeta}
           </paper-radio-button>
           <paper-radio-button name="[[browserChannelEnum_.DEV]]">
-            $i18n{aboutChannelDev}
+            $i18n{aboutChannelDialogDev}
           </paper-radio-button>
         </paper-radio-group>
         <div id="warning" hidden="[[!shouldShowWarning_(warning_)]]">
diff --git a/chrome/browser/safe_browsing/certificate_reporting_service.cc b/chrome/browser/safe_browsing/certificate_reporting_service.cc
index 52a20c7..0a84e0e 100644
--- a/chrome/browser/safe_browsing/certificate_reporting_service.cc
+++ b/chrome/browser/safe_browsing/certificate_reporting_service.cc
@@ -2,12 +2,20 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/bind_helpers.h"
 #include "base/time/clock.h"
 #include "base/time/default_clock.h"
 #include "chrome/browser/safe_browsing/certificate_reporting_service.h"
 #include "content/public/browser/browser_thread.h"
 
 namespace {
+
+// URL to upload invalid certificate chain reports. An HTTP URL is used because
+// a client seeing an invalid cert might not be able to make an HTTPS connection
+// to report it.
+const char kExtendedReportingUploadUrl[] =
+    "http://safebrowsing.googleusercontent.com/safebrowsing/clientreport/";
+
 // Compare function that orders Reports in reverse chronological order (i.e.
 // oldest item is last).
 bool ReportCompareFunc(const CertificateReportingService::Report& item1,
@@ -57,11 +65,13 @@
     std::unique_ptr<certificate_reporting::ErrorReporter> error_reporter,
     std::unique_ptr<BoundedReportList> retry_list,
     base::Clock* clock,
-    base::TimeDelta report_ttl)
+    base::TimeDelta report_ttl,
+    bool retries_enabled)
     : error_reporter_(std::move(error_reporter)),
       retry_list_(std::move(retry_list)),
-      test_clock_(clock),
+      clock_(clock),
       report_ttl_(report_ttl),
+      retries_enabled_(retries_enabled),
       current_report_id_(0),
       weak_factory_(this) {}
 
@@ -70,15 +80,15 @@
 void CertificateReportingService::Reporter::Send(
     const std::string& serialized_report) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  base::Time now =
-      test_clock_ ? test_clock_->Now() : base::Time::NowFromSystemTime();
-  SendInternal(Report(current_report_id_++, now, serialized_report));
+  SendInternal(Report(current_report_id_++, clock_->Now(), serialized_report));
 }
 
 void CertificateReportingService::Reporter::SendPending() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  base::Time now =
-      test_clock_ ? test_clock_->Now() : base::Time::NowFromSystemTime();
+  if (!retries_enabled_) {
+    return;
+  }
+  const base::Time now = clock_->Now();
   // Copy pending reports and clear the retry list.
   std::vector<Report> items = retry_list_->items();
   retry_list_->Clear();
@@ -118,9 +128,11 @@
                                                           const GURL& url,
                                                           int error) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  auto it = inflight_reports_.find(report_id);
-  DCHECK(it != inflight_reports_.end());
-  retry_list_->Add(it->second);
+  if (retries_enabled_) {
+    auto it = inflight_reports_.find(report_id);
+    DCHECK(it != inflight_reports_.end());
+    retry_list_->Add(it->second);
+  }
   CHECK_GT(inflight_reports_.erase(report_id), 0u);
 }
 
@@ -128,3 +140,159 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   CHECK_GT(inflight_reports_.erase(report_id), 0u);
 }
+
+CertificateReportingService::CertificateReportingService(
+    scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
+    uint8_t server_public_key[/* 32 */],
+    uint32_t server_public_key_version,
+    size_t max_queued_report_count,
+    base::TimeDelta max_report_age,
+    std::unique_ptr<base::Clock> clock)
+    : enabled_(true),
+      url_request_context_(nullptr),
+      max_queued_report_count_(max_queued_report_count),
+      max_report_age_(max_report_age),
+      clock_(std::move(clock)),
+      made_send_attempt_(false),
+      server_public_key_(server_public_key),
+      server_public_key_version_(server_public_key_version) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  content::BrowserThread::PostTask(
+      content::BrowserThread::IO, FROM_HERE,
+      base::Bind(&CertificateReportingService::InitializeOnIOThread,
+                 base::Unretained(this), enabled_, url_request_context_getter,
+                 max_queued_report_count_, max_report_age_, clock_.get(),
+                 server_public_key_, server_public_key_version_));
+}
+
+CertificateReportingService::~CertificateReportingService() {
+  DCHECK(!reporter_);
+}
+
+void CertificateReportingService::Shutdown() {
+  // Shutdown will be called twice: Once after SafeBrowsing shuts down, and once
+  // when all KeyedServices shut down. All calls after the first one are no-op.
+  enabled_ = false;
+  Reset();
+}
+
+void CertificateReportingService::Send(const std::string& serialized_report) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  made_send_attempt_ = true;
+  if (!reporter_) {
+    return;
+  }
+  content::BrowserThread::PostTask(
+      content::BrowserThread::IO, FROM_HERE,
+      base::Bind(&CertificateReportingService::Reporter::Send,
+                 base::Unretained(reporter_.get()), serialized_report));
+}
+
+void CertificateReportingService::SendPending() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  made_send_attempt_ = true;
+  if (!reporter_) {
+    return;
+  }
+  content::BrowserThread::PostTask(
+      content::BrowserThread::IO, FROM_HERE,
+      base::Bind(&CertificateReportingService::Reporter::SendPending,
+                 base::Unretained(reporter_.get())));
+}
+
+void CertificateReportingService::InitializeOnIOThread(
+    bool enabled,
+    scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
+    size_t max_queued_report_count,
+    base::TimeDelta max_report_age,
+    base::Clock* clock,
+    uint8_t* server_public_key,
+    uint32_t server_public_key_version) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+  DCHECK(!url_request_context_);
+  url_request_context_ = url_request_context_getter->GetURLRequestContext();
+  ResetOnIOThread(enabled, url_request_context_, max_queued_report_count,
+                  max_report_age, clock, server_public_key,
+                  server_public_key_version);
+}
+
+void CertificateReportingService::SetEnabled(bool enabled) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  enabled_ = enabled;
+  Reset();
+}
+
+CertificateReportingService::Reporter*
+CertificateReportingService::GetReporterForTesting() const {
+  return reporter_.get();
+}
+
+void CertificateReportingService::SetMaxQueuedReportCountForTesting(
+    size_t count) {
+  DCHECK(!made_send_attempt_);
+  max_queued_report_count_ = count;
+  Reset();
+}
+
+void CertificateReportingService::SetClockForTesting(
+    std::unique_ptr<base::Clock> clock) {
+  DCHECK(!made_send_attempt_);
+  clock_ = std::move(clock);
+  Reset();
+}
+
+void CertificateReportingService::SetMaxReportAgeForTesting(
+    base::TimeDelta max_report_age) {
+  DCHECK(!made_send_attempt_);
+  max_report_age_ = max_report_age;
+  Reset();
+}
+
+// static
+GURL CertificateReportingService::GetReportingURLForTesting() {
+  return GURL(kExtendedReportingUploadUrl);
+}
+
+void CertificateReportingService::Reset() {
+  content::BrowserThread::PostTask(
+      content::BrowserThread::IO, FROM_HERE,
+      base::Bind(&CertificateReportingService::ResetOnIOThread,
+                 base::Unretained(this), enabled_, url_request_context_,
+                 max_queued_report_count_, max_report_age_, clock_.get(),
+                 server_public_key_, server_public_key_version_));
+}
+
+void CertificateReportingService::ResetOnIOThread(
+    bool enabled,
+    net::URLRequestContext* url_request_context,
+    size_t max_queued_report_count,
+    base::TimeDelta max_report_age,
+    base::Clock* clock,
+    uint8_t* const server_public_key,
+    uint32_t server_public_key_version) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+  // url_request_context_ is null during shutdown.
+  if (!enabled || !url_request_context) {
+    reporter_.reset(nullptr);
+    return;
+  }
+  std::unique_ptr<certificate_reporting::ErrorReporter> error_reporter;
+  if (server_public_key) {
+    // Only used in tests.
+    std::unique_ptr<net::ReportSender> report_sender(new net::ReportSender(
+        url_request_context, net::ReportSender::DO_NOT_SEND_COOKIES));
+    error_reporter.reset(new certificate_reporting::ErrorReporter(
+        GURL(kExtendedReportingUploadUrl), server_public_key,
+        server_public_key_version, std::move(report_sender)));
+  } else {
+    error_reporter.reset(new certificate_reporting::ErrorReporter(
+        url_request_context, GURL(kExtendedReportingUploadUrl),
+        net::ReportSender::DO_NOT_SEND_COOKIES));
+  }
+
+  reporter_.reset(
+      new Reporter(std::move(error_reporter),
+                   std::unique_ptr<BoundedReportList>(
+                       new BoundedReportList(max_queued_report_count)),
+                   clock, max_report_age, true /* retries_enabled */));
+}
diff --git a/chrome/browser/safe_browsing/certificate_reporting_service.h b/chrome/browser/safe_browsing/certificate_reporting_service.h
index 4c1e4cd2..6c45e7e 100644
--- a/chrome/browser/safe_browsing/certificate_reporting_service.h
+++ b/chrome/browser/safe_browsing/certificate_reporting_service.h
@@ -16,16 +16,31 @@
 #include "base/time/time.h"
 #include "components/certificate_reporting/error_reporter.h"
 #include "components/keyed_service/core/keyed_service.h"
+#include "net/url_request/url_request_context_getter.h"
 
 namespace base {
 class Clock;
 }
 
+namespace net {
+class URLRequestContextGetter;
+}
+
 // This service initiates uploads of invalid certificate reports and retries any
-// failed uploads.
+// failed uploads. Each report is retried until it's older than a certain time
+// to live (TTL). Reports older than this TTL are dropped and no more retried,
+// so that the retry list doesn't grow indefinitely.
+//
+// Lifetime and dependencies:
+//
+// CertificateReportingService uses the url request context from SafeBrowsing
+// service. SafeBrowsing service is created before CertificateReportingService,
+// but is also shut down before any KeyedService is shut down. This means that
+// CertificateReportingService cannot depend on SafeBrowsing's url request being
+// available at all times, and it should know when SafeBrowsing shuts down.
 class CertificateReportingService : public KeyedService {
  public:
-  // Represent a report to be sent.
+  // Represents a report to be sent.
   struct Report {
     int report_id;
     base::Time creation_time;
@@ -64,6 +79,8 @@
 
     std::vector<Report> items_;
     base::ThreadChecker thread_checker_;
+
+    DISALLOW_COPY_AND_ASSIGN(BoundedReportList);
   };
 
   // Class that handles report uploads and implements the upload retry logic.
@@ -73,7 +90,8 @@
         std::unique_ptr<certificate_reporting::ErrorReporter> error_reporter_,
         std::unique_ptr<BoundedReportList> retry_list,
         base::Clock* clock,
-        base::TimeDelta report_ttl);
+        base::TimeDelta report_ttl,
+        bool retries_enabled);
     ~Reporter();
 
     // Sends a report. If the send fails, the report will be added to the retry
@@ -96,16 +114,105 @@
 
     std::unique_ptr<certificate_reporting::ErrorReporter> error_reporter_;
     std::unique_ptr<BoundedReportList> retry_list_;
-    base::Clock* test_clock_;
+    base::Clock* clock_;
+    // Maximum age of a queued report. Reports older than this are discarded in
+    // the next SendPending() call.
     const base::TimeDelta report_ttl_;
+    const bool retries_enabled_;
+    // Current report id, starting from zero and monotonically incrementing.
     int current_report_id_;
 
     std::map<int, Report> inflight_reports_;
 
     base::WeakPtrFactory<Reporter> weak_factory_;
 
-    DISALLOW_IMPLICIT_CONSTRUCTORS(Reporter);
+    DISALLOW_COPY_AND_ASSIGN(Reporter);
   };
+
+  CertificateReportingService(
+      scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
+      uint8_t server_public_key[/* 32 */],
+      uint32_t server_public_key_version,
+      size_t max_queued_report_count,
+      base::TimeDelta max_report_age,
+      std::unique_ptr<base::Clock> clock);
+
+  ~CertificateReportingService() override;
+
+  // KeyedService implementation:
+  void Shutdown() override;
+
+  // Sends a serialized report. If the report upload fails, the upload is
+  // retried at a future time.
+  void Send(const std::string& serialized_report);
+
+  // Sends pending reports that are in the retry queue.
+  void SendPending();
+
+  // Enables or disables reporting. When disabled, pending report queue is
+  // cleared and incoming reports are ignored. Reporting is enabled by default
+  // once the service is initialized.
+  void SetEnabled(bool enabled);
+
+  // Getters and setters for testing.
+  Reporter* GetReporterForTesting() const;
+  void SetMaxQueuedReportCountForTesting(size_t max_report_count);
+  void SetClockForTesting(std::unique_ptr<base::Clock> clock);
+  void SetMaxReportAgeForTesting(base::TimeDelta max_report_age);
+
+  static GURL GetReportingURLForTesting();
+
+ private:
+  void Reset();
+
+  void InitializeOnIOThread(
+      bool enabled,
+      scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
+      size_t max_queued_report_count,
+      base::TimeDelta max_report_age,
+      base::Clock* clock,
+      uint8_t* server_public_key,
+      uint32_t server_public_key_version);
+
+  // Resets the reporter on the IO thread. Changes in SafeBrowsing or extended
+  // reporting enabled states cause the reporter to be reset.
+  // If |enabled| is false or |url_request_context_getter| is null, report is
+  // set to null, effectively cancelling all in flight uploads and clearing the
+  // pending reports queue.
+  void ResetOnIOThread(bool enabled,
+                       net::URLRequestContext* url_request_context,
+                       size_t max_queued_report_count,
+                       base::TimeDelta max_report_age,
+                       base::Clock* clock,
+                       uint8_t* server_public_key,
+                       uint32_t server_public_key_version);
+
+  // If true, reporting is enabled. When SafeBrowsing preferences change, this
+  // might be set to false.
+  bool enabled_;
+
+  net::URLRequestContext* url_request_context_;
+  std::unique_ptr<Reporter> reporter_;
+
+  // Maximum number of reports to be queued for retry.
+  size_t max_queued_report_count_;
+
+  // Maximum age of the reports to be queued for retry, from the time the
+  // certificate error was first encountered by the user. Any report older than
+  // this age is ignored and is not re-uploaded.
+  base::TimeDelta max_report_age_;
+
+  std::unique_ptr<base::Clock> clock_;
+
+  // Whether a send has ever been made. Used to verify that test setters are
+  // only called after initialization.
+  bool made_send_attempt_;
+
+  // Encryption parameters.
+  uint8_t* server_public_key_;
+  uint32_t server_public_key_version_;
+
+  DISALLOW_COPY_AND_ASSIGN(CertificateReportingService);
 };
 
 #endif  // CHROME_BROWSER_SAFE_BROWSING_CERTIFICATE_REPORTING_SERVICE_H_
diff --git a/chrome/browser/safe_browsing/certificate_reporting_service_factory.cc b/chrome/browser/safe_browsing/certificate_reporting_service_factory.cc
index bed32fd..fc1eab1 100644
--- a/chrome/browser/safe_browsing/certificate_reporting_service_factory.cc
+++ b/chrome/browser/safe_browsing/certificate_reporting_service_factory.cc
@@ -29,7 +29,8 @@
 
 KeyedService* CertificateReportingServiceFactory::BuildServiceInstanceFor(
     content::BrowserContext* profile) const {
-  return new CertificateReportingService();
+  // TODO(crbug.com/554323): Create a real CertificateReportingService here.
+  return nullptr;
 }
 
 content::BrowserContext*
diff --git a/chrome/browser/safe_browsing/certificate_reporting_service_test_utils.cc b/chrome/browser/safe_browsing/certificate_reporting_service_test_utils.cc
new file mode 100644
index 0000000..780f8d50
--- /dev/null
+++ b/chrome/browser/safe_browsing/certificate_reporting_service_test_utils.cc
@@ -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.
+
+#include "chrome/browser/safe_browsing/certificate_reporting_service_test_utils.h"
+
+#include "base/threading/thread_task_runner_handle.h"
+#include "components/certificate_reporting/encrypted_cert_logger.pb.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/test_utils.h"
+#include "crypto/curve25519.h"
+#include "net/base/upload_bytes_element_reader.h"
+#include "net/base/upload_data_stream.h"
+#include "net/test/url_request/url_request_failed_job.h"
+#include "net/test/url_request/url_request_mock_data_job.h"
+#include "net/url_request/url_request_filter.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+const uint32_t kServerPublicKeyTestVersion = 16;
+
+void SetUpURLHandlersOnIOThread(
+    std::unique_ptr<net::URLRequestInterceptor> url_request_interceptor) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+  net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance();
+  filter->AddUrlInterceptor(
+      CertificateReportingService::GetReportingURLForTesting(),
+      std::move(url_request_interceptor));
+}
+
+std::string GetUploadData(net::URLRequest* request) {
+  const net::UploadDataStream* stream = request->get_upload();
+  EXPECT_TRUE(stream);
+  EXPECT_TRUE(stream->GetElementReaders());
+  EXPECT_EQ(1u, stream->GetElementReaders()->size());
+  const net::UploadBytesElementReader* reader =
+      (*stream->GetElementReaders())[0]->AsBytesReader();
+  return std::string(reader->bytes(), reader->length());
+}
+
+std::string GetReportContents(net::URLRequest* request,
+                              const uint8_t* server_private_key) {
+  std::string serialized_report(GetUploadData(request));
+  certificate_reporting::EncryptedCertLoggerRequest encrypted_request;
+  EXPECT_TRUE(encrypted_request.ParseFromString(serialized_report));
+  EXPECT_EQ(kServerPublicKeyTestVersion,
+            encrypted_request.server_public_key_version());
+  EXPECT_EQ(certificate_reporting::EncryptedCertLoggerRequest::
+                AEAD_ECDH_AES_128_CTR_HMAC_SHA256,
+            encrypted_request.algorithm());
+  std::string decrypted_report;
+  certificate_reporting::ErrorReporter::DecryptErrorReport(
+      server_private_key, encrypted_request, &decrypted_report);
+  return decrypted_report;
+}
+
+}  // namespace
+
+namespace certificate_reporting_test_utils {
+
+DelayableCertReportURLRequestJob::DelayableCertReportURLRequestJob(
+    net::URLRequest* request,
+    net::NetworkDelegate* network_delegate)
+    : net::URLRequestJob(request, network_delegate), weak_factory_(this) {}
+
+DelayableCertReportURLRequestJob::~DelayableCertReportURLRequestJob() {}
+
+base::WeakPtr<DelayableCertReportURLRequestJob>
+DelayableCertReportURLRequestJob::GetWeakPtr() {
+  return weak_factory_.GetWeakPtr();
+}
+
+void DelayableCertReportURLRequestJob::Start() {
+  started_ = true;
+  if (delayed_) {
+    // Do nothing until Resume() is called.
+    return;
+  }
+  Resume();
+}
+
+int DelayableCertReportURLRequestJob::ReadRawData(net::IOBuffer* buf,
+                                                  int buf_size) {
+  // Report sender ignores responses. Return empty response.
+  return 0;
+}
+
+int DelayableCertReportURLRequestJob::GetResponseCode() const {
+  // Report sender ignores responses. Return empty response.
+  return 200;
+}
+
+void DelayableCertReportURLRequestJob::GetResponseInfo(
+    net::HttpResponseInfo* info) {
+  // Report sender ignores responses. Return empty response.
+}
+
+void DelayableCertReportURLRequestJob::Resume() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+  DCHECK(delayed_);
+  if (!started_) {
+    // If Start() hasn't been called yet, then unset |delayed_| so
+    // that when Start() is called, the request will begin
+    // immediately.
+    delayed_ = false;
+    return;
+  }
+  // Start reading asynchronously as would a normal network request.
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE,
+      base::Bind(&DelayableCertReportURLRequestJob::NotifyHeadersComplete,
+                 weak_factory_.GetWeakPtr()));
+}
+
+CertReportJobInterceptor::CertReportJobInterceptor(
+    ReportSendingResult expected_report_result,
+    const uint8_t* server_private_key)
+    : expected_report_result_(expected_report_result),
+      server_private_key_(server_private_key),
+      weak_factory_(this) {}
+
+CertReportJobInterceptor::~CertReportJobInterceptor() {}
+
+net::URLRequestJob* CertReportJobInterceptor::MaybeInterceptRequest(
+    net::URLRequest* request,
+    net::NetworkDelegate* network_delegate) const {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+
+  const std::string uploaded_report =
+      GetReportContents(request, server_private_key_);
+  content::BrowserThread::PostTask(
+      content::BrowserThread::UI, FROM_HERE,
+      base::Bind(&CertReportJobInterceptor::RequestCreated,
+                 weak_factory_.GetWeakPtr(), uploaded_report,
+                 expected_report_result_));
+
+  if (expected_report_result_ == REPORTS_FAIL) {
+    return new net::URLRequestFailedJob(request, network_delegate,
+                                        net::ERR_SSL_PROTOCOL_ERROR);
+  } else if (expected_report_result_ == REPORTS_DELAY) {
+    DCHECK(!delayed_request_) << "Supports only one delayed request at a time";
+    DelayableCertReportURLRequestJob* job =
+        new DelayableCertReportURLRequestJob(request, network_delegate);
+    delayed_request_ = job->GetWeakPtr();
+    return job;
+  }
+  // Successful url request job.
+  return new net::URLRequestMockDataJob(request, network_delegate, "some data",
+                                        1, false);
+}
+
+void CertReportJobInterceptor::SetFailureMode(
+    ReportSendingResult expected_report_result) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  content::BrowserThread::PostTask(
+      content::BrowserThread::IO, FROM_HERE,
+      base::Bind(&CertReportJobInterceptor::SetFailureModeOnIOThread,
+                 weak_factory_.GetWeakPtr(), expected_report_result));
+}
+
+void CertReportJobInterceptor::Resume() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  content::BrowserThread::PostTask(
+      content::BrowserThread::IO, FROM_HERE,
+      base::Bind(&CertReportJobInterceptor::ResumeOnIOThread,
+                 base::Unretained(this)));
+}
+
+const std::set<std::string>& CertReportJobInterceptor::successful_reports()
+    const {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  return successful_reports_;
+}
+
+const std::set<std::string>& CertReportJobInterceptor::failed_reports() const {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  return failed_reports_;
+}
+
+const std::set<std::string>& CertReportJobInterceptor::delayed_reports() const {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  return delayed_reports_;
+}
+
+void CertReportJobInterceptor::ClearObservedReports() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  successful_reports_.clear();
+  failed_reports_.clear();
+  delayed_reports_.clear();
+}
+
+void CertReportJobInterceptor::SetFailureModeOnIOThread(
+    ReportSendingResult expected_report_result) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+  expected_report_result_ = expected_report_result;
+}
+
+void CertReportJobInterceptor::ResumeOnIOThread() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+  EXPECT_EQ(REPORTS_DELAY, expected_report_result_);
+  if (delayed_request_)
+    delayed_request_->Resume();
+}
+
+void CertReportJobInterceptor::RequestCreated(
+    const std::string& uploaded_report,
+    ReportSendingResult expected_report_result) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  switch (expected_report_result) {
+    case REPORTS_SUCCESSFUL:
+      successful_reports_.insert(uploaded_report);
+      break;
+    case REPORTS_FAIL:
+      failed_reports_.insert(uploaded_report);
+      break;
+    case REPORTS_DELAY:
+      delayed_reports_.insert(uploaded_report);
+      break;
+  }
+}
+
+CertificateReportingServiceTestNetworkDelegate::
+    CertificateReportingServiceTestNetworkDelegate(
+        const base::Callback<void()>& url_request_destroyed_callback)
+    : url_request_destroyed_callback_(url_request_destroyed_callback) {}
+
+CertificateReportingServiceTestNetworkDelegate::
+    ~CertificateReportingServiceTestNetworkDelegate() {}
+
+void CertificateReportingServiceTestNetworkDelegate::OnURLRequestDestroyed(
+    net::URLRequest* request) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+  content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
+                                   url_request_destroyed_callback_);
+}
+
+CertificateReportingServiceTestBase::ReportExpectation::ReportExpectation() {}
+
+CertificateReportingServiceTestBase::ReportExpectation::ReportExpectation(
+    const ReportExpectation& other) = default;
+
+CertificateReportingServiceTestBase::ReportExpectation::~ReportExpectation() {}
+
+// static
+CertificateReportingServiceTestBase::ReportExpectation
+CertificateReportingServiceTestBase::ReportExpectation::Successful(
+    const std::set<std::string>& reports) {
+  ReportExpectation expectation;
+  expectation.successful_reports = reports;
+  return expectation;
+}
+
+// static
+CertificateReportingServiceTestBase::ReportExpectation
+CertificateReportingServiceTestBase::ReportExpectation::Failed(
+    const std::set<std::string>& reports) {
+  ReportExpectation expectation;
+  expectation.failed_reports = reports;
+  return expectation;
+}
+
+// static
+CertificateReportingServiceTestBase::ReportExpectation
+CertificateReportingServiceTestBase::ReportExpectation::Delayed(
+    const std::set<std::string>& reports) {
+  ReportExpectation expectation;
+  expectation.delayed_reports = reports;
+  return expectation;
+}
+
+CertificateReportingServiceTestBase::CertificateReportingServiceTestBase()
+    : num_request_deletions_to_wait_for_(0), num_deleted_requests_(0) {
+  memset(server_private_key_, 1, sizeof(server_private_key_));
+  crypto::curve25519::ScalarBaseMult(server_private_key_, server_public_key_);
+}
+
+CertificateReportingServiceTestBase::~CertificateReportingServiceTestBase() {}
+
+void CertificateReportingServiceTestBase::SetUpInterceptor() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  url_request_interceptor_ =
+      new CertReportJobInterceptor(REPORTS_FAIL, server_private_key_);
+  content::BrowserThread::PostTask(
+      content::BrowserThread::IO, FROM_HERE,
+      base::Bind(
+          &CertificateReportingServiceTestBase::SetUpInterceptorOnIOThread,
+          base::Unretained(this),
+          base::Passed(std::unique_ptr<net::URLRequestInterceptor>(
+              url_request_interceptor_))));
+}
+
+void CertificateReportingServiceTestBase::TearDownInterceptor() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  content::BrowserThread::PostTask(
+      content::BrowserThread::IO, FROM_HERE,
+      base::Bind(
+          &CertificateReportingServiceTestBase::TearDownInterceptorOnIOThread,
+          base::Unretained(this)));
+}
+
+// Changes the behavior of report uploads to fail or succeed.
+void CertificateReportingServiceTestBase::SetFailureMode(
+    ReportSendingResult expected_report_result) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  url_request_interceptor_->SetFailureMode(expected_report_result);
+}
+
+void CertificateReportingServiceTestBase::ResumeDelayedRequest() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  url_request_interceptor_->Resume();
+}
+
+void CertificateReportingServiceTestBase::WaitForRequestsDestroyed(
+    const ReportExpectation& expectation) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  DCHECK(!run_loop_);
+
+  const int num_request_deletions_to_wait_for =
+      expectation.successful_reports.size() +
+      expectation.failed_reports.size() + expectation.delayed_reports.size();
+
+  ASSERT_LE(num_deleted_requests_, num_request_deletions_to_wait_for)
+      << "Observed unexpected report";
+  if (num_deleted_requests_ < num_request_deletions_to_wait_for) {
+    num_request_deletions_to_wait_for_ = num_request_deletions_to_wait_for;
+    run_loop_.reset(new base::RunLoop());
+    run_loop_->Run();
+    run_loop_.reset(nullptr);
+    EXPECT_EQ(0, num_deleted_requests_);
+    EXPECT_EQ(0, num_request_deletions_to_wait_for_);
+  } else if (num_deleted_requests_ == num_request_deletions_to_wait_for) {
+    num_deleted_requests_ = 0;
+    num_request_deletions_to_wait_for_ = 0;
+  }
+  EXPECT_EQ(expectation.successful_reports,
+            url_request_interceptor_->successful_reports());
+  EXPECT_EQ(expectation.failed_reports,
+            url_request_interceptor_->failed_reports());
+  EXPECT_EQ(expectation.delayed_reports,
+            url_request_interceptor_->delayed_reports());
+  url_request_interceptor_->ClearObservedReports();
+}
+
+uint8_t* CertificateReportingServiceTestBase::server_public_key() {
+  return server_public_key_;
+}
+
+uint32_t CertificateReportingServiceTestBase::server_public_key_version()
+    const {
+  return kServerPublicKeyTestVersion;
+}
+
+net::NetworkDelegate* CertificateReportingServiceTestBase::network_delegate() {
+  return network_delegate_.get();
+}
+
+void CertificateReportingServiceTestBase::SetUpInterceptorOnIOThread(
+    std::unique_ptr<net::URLRequestInterceptor> url_request_interceptor) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+  network_delegate_.reset(new CertificateReportingServiceTestNetworkDelegate(
+      base::Bind(&CertificateReportingServiceTestBase::OnURLRequestDestroyed,
+                 base::Unretained(this))));
+  SetUpURLHandlersOnIOThread(std::move(url_request_interceptor));
+}
+
+void CertificateReportingServiceTestBase::TearDownInterceptorOnIOThread() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+  network_delegate_.reset(nullptr);
+}
+
+void CertificateReportingServiceTestBase::OnURLRequestDestroyed() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  num_deleted_requests_++;
+  if (!run_loop_) {
+    return;
+  }
+  EXPECT_LE(num_deleted_requests_, num_request_deletions_to_wait_for_);
+  if (num_deleted_requests_ == num_request_deletions_to_wait_for_) {
+    num_request_deletions_to_wait_for_ = 0;
+    num_deleted_requests_ = 0;
+    run_loop_->Quit();
+  }
+}
+
+}  // namespace certificate_reporting_test_utils
diff --git a/chrome/browser/safe_browsing/certificate_reporting_service_test_utils.h b/chrome/browser/safe_browsing/certificate_reporting_service_test_utils.h
new file mode 100644
index 0000000..1d2f6cc
--- /dev/null
+++ b/chrome/browser/safe_browsing/certificate_reporting_service_test_utils.h
@@ -0,0 +1,199 @@
+// 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_SAFE_BROWSING_CERTIFICATE_REPORTING_SERVICE_TEST_UTILS_H_
+#define CHROME_BROWSER_SAFE_BROWSING_CERTIFICATE_REPORTING_SERVICE_TEST_UTILS_H_
+
+#include <set>
+
+#include "base/macros.h"
+#include "base/run_loop.h"
+#include "chrome/browser/safe_browsing/certificate_reporting_service.h"
+#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "net/base/network_delegate_impl.h"
+#include "net/url_request/url_request_interceptor.h"
+#include "net/url_request/url_request_job.h"
+
+namespace net {
+class NetworkDelegate;
+}
+
+namespace certificate_reporting_test_utils {
+
+// Failure mode of the report sending attempts.
+enum ReportSendingResult {
+  // Report send attempts should be successful.
+  REPORTS_SUCCESSFUL,
+  // Report send attempts should fail.
+  REPORTS_FAIL,
+  // Report send attempts should hang until explicitly resumed.
+  REPORTS_DELAY,
+};
+
+// A URLRequestJob that can be delayed until Resume() is called. Returns an
+// empty response. If Resume() is called before a request is made, then the
+// request will not be delayed.
+class DelayableCertReportURLRequestJob : public net::URLRequestJob {
+ public:
+  DelayableCertReportURLRequestJob(net::URLRequest* request,
+                                   net::NetworkDelegate* network_delegate);
+  ~DelayableCertReportURLRequestJob() override;
+
+  base::WeakPtr<DelayableCertReportURLRequestJob> GetWeakPtr();
+
+  // net::URLRequestJob methods:
+  void Start() override;
+  int ReadRawData(net::IOBuffer* buf, int buf_size) override;
+  int GetResponseCode() const override;
+  void GetResponseInfo(net::HttpResponseInfo* info) override;
+
+  // Resumes a previously started request that was delayed. If no
+  // request has been started yet, then when Start() is called it will
+  // not delay.
+  void Resume();
+
+ private:
+  bool delayed_ = true;
+  bool started_ = false;
+  base::WeakPtrFactory<DelayableCertReportURLRequestJob> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(DelayableCertReportURLRequestJob);
+};
+
+// A job interceptor that returns a failed, succesful or delayed request job.
+// Used to simulate report uploads that fail, succeed or hang.
+class CertReportJobInterceptor : public net::URLRequestInterceptor {
+ public:
+  CertReportJobInterceptor(ReportSendingResult expected_report_result,
+                           const uint8_t* server_private_key);
+  ~CertReportJobInterceptor() override;
+
+  // net::URLRequestInterceptor method:
+  net::URLRequestJob* MaybeInterceptRequest(
+      net::URLRequest* request,
+      net::NetworkDelegate* network_delegate) const override;
+
+  // Sets the failure mode for reports. Must be called on the UI thread.
+  void SetFailureMode(ReportSendingResult expected_report_result);
+  // Resumes any hanging URL request. Must be called on the UI thread.
+  void Resume();
+
+  // These must be called on the UI thread.
+  const std::set<std::string>& successful_reports() const;
+  const std::set<std::string>& failed_reports() const;
+  const std::set<std::string>& delayed_reports() const;
+  void ClearObservedReports();
+
+ private:
+  void SetFailureModeOnIOThread(ReportSendingResult expected_report_result);
+  void ResumeOnIOThread();
+  void RequestCreated(const std::string& uploaded_report,
+                      ReportSendingResult expected_report_result);
+
+  std::set<std::string> successful_reports_;
+  std::set<std::string> failed_reports_;
+  std::set<std::string> delayed_reports_;
+
+  ReportSendingResult expected_report_result_;
+
+  // Private key to decrypt certificate reports.
+  const uint8_t* server_private_key_;
+
+  mutable base::WeakPtr<DelayableCertReportURLRequestJob> delayed_request_ =
+      nullptr;
+  mutable base::WeakPtrFactory<CertReportJobInterceptor> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(CertReportJobInterceptor);
+};
+
+// A network delegate used to observe URL request destructions. The tests check
+// that no outstanding URL request is present during tear down.
+class CertificateReportingServiceTestNetworkDelegate
+    : public net::NetworkDelegateImpl {
+ public:
+  CertificateReportingServiceTestNetworkDelegate(
+      const base::Callback<void()>& url_request_destroyed_callback);
+  ~CertificateReportingServiceTestNetworkDelegate() override;
+
+  // net::NetworkDelegate method:
+  void OnURLRequestDestroyed(net::URLRequest* request) override;
+
+ private:
+  base::Callback<void()> url_request_destroyed_callback_;
+};
+
+// Base class for CertificateReportingService tests. Sets up an interceptor to
+// keep track of reports that are being sent.
+class CertificateReportingServiceTestBase {
+ protected:
+  CertificateReportingServiceTestBase();
+  virtual ~CertificateReportingServiceTestBase();
+
+  // Syntactic sugar for wrapping report expectations in a more readable way.
+  // Passed to WaitForRequestDeletions() as input.
+  // Example:
+  // The following expects report0 and report1 to be successfully sent and their
+  // URL requests to be deleted:
+  // WaitForRequestDeletions(
+  //     ReportExpectation::Successful("report0, report1"));
+  struct ReportExpectation {
+    ReportExpectation();
+    ReportExpectation(const ReportExpectation& other);
+    ~ReportExpectation();
+    // Returns an expectation where all reports in |reports| succeed.
+    static ReportExpectation Successful(const std::set<std::string>& reports);
+    // Returns an expectation where all reports in |reports| fail.
+    static ReportExpectation Failed(const std::set<std::string>& reports);
+    // Returns an expectation where all reports in |reports| are delayed.
+    static ReportExpectation Delayed(const std::set<std::string>& reports);
+    std::set<std::string> successful_reports;
+    std::set<std::string> failed_reports;
+    std::set<std::string> delayed_reports;
+  };
+
+  void SetUpInterceptor();
+  void TearDownInterceptor();
+
+  // Changes the behavior of report uploads to fail, succeed or hang.
+  void SetFailureMode(ReportSendingResult expected_report_result);
+
+  // Resumes delayed report request. Failure mode should be REPORTS_DELAY when
+  // calling this method.
+  void ResumeDelayedRequest();
+
+  // Waits for the URL requests for the expected reports to be destroyed.
+  // Doesn't block if all requests have already been destroyed.
+  void WaitForRequestsDestroyed(const ReportExpectation& expectation);
+
+  uint8_t* server_public_key();
+  uint32_t server_public_key_version() const;
+
+  net::NetworkDelegate* network_delegate();
+
+  CertReportJobInterceptor* interceptor() { return url_request_interceptor_; }
+
+ private:
+  void SetUpInterceptorOnIOThread(
+      std::unique_ptr<net::URLRequestInterceptor> url_request_interceptor);
+  void TearDownInterceptorOnIOThread();
+  void OnURLRequestDestroyed();
+
+  CertReportJobInterceptor* url_request_interceptor_;
+
+  uint8_t server_public_key_[32];
+  uint8_t server_private_key_[32];
+
+  std::unique_ptr<CertificateReportingServiceTestNetworkDelegate>
+      network_delegate_;
+
+  int num_request_deletions_to_wait_for_;
+  int num_deleted_requests_;
+  std::unique_ptr<base::RunLoop> run_loop_;
+  DISALLOW_COPY_AND_ASSIGN(CertificateReportingServiceTestBase);
+};
+
+}  // namespace certificate_reporting_test_utils
+
+#endif  // CHROME_BROWSER_SAFE_BROWSING_CERTIFICATE_REPORTING_SERVICE_TEST_UTILS_H_
diff --git a/chrome/browser/safe_browsing/certificate_reporting_service_unittest.cc b/chrome/browser/safe_browsing/certificate_reporting_service_unittest.cc
index f7d4c8f..07de07b 100644
--- a/chrome/browser/safe_browsing/certificate_reporting_service_unittest.cc
+++ b/chrome/browser/safe_browsing/certificate_reporting_service_unittest.cc
@@ -6,18 +6,38 @@
 
 #include <string>
 
+#include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
 #include "base/test/simple_test_clock.h"
+#include "base/test/thread_test_helper.h"
 #include "base/time/clock.h"
 #include "base/time/time.h"
+#include "chrome/browser/safe_browsing/certificate_reporting_service_test_utils.h"
+#include "content/public/browser/browser_thread.h"
 #include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "net/base/network_delegate_impl.h"
 #include "net/test/url_request/url_request_failed_job.h"
 #include "net/test/url_request/url_request_mock_data_job.h"
+#include "net/url_request/url_request_filter.h"
 #include "net/url_request/url_request_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-TEST(CertificateReportingServiceTest, BoundedReportList) {
+namespace {
+
+// Maximum number of reports kept in the certificate reporting service's retry
+// queue.
+const size_t kMaxReportCountInQueue = 3;
+
+void ClearURLHandlers() {
+  net::URLRequestFilter::GetInstance()->ClearHandlers();
+}
+
+}  // namespace
+
+TEST(CertificateReportingServiceReportListTest, BoundedReportList) {
   // Create a report list with maximum of 2 items.
   CertificateReportingService::BoundedReportList list(2 /* max_size */);
   EXPECT_EQ(0u, list.items().size());
@@ -56,7 +76,8 @@
   EXPECT_EQ("report2_five_minutes_old", list.items()[1].serialized_report);
 }
 
-class CertificateReportingServiceReporterTest : public ::testing::Test {
+class CertificateReportingServiceReporterOnIOThreadTest
+    : public ::testing::Test {
  public:
   void SetUp() override {
     message_loop_.reset(new base::MessageLoopForIO());
@@ -68,6 +89,8 @@
     net::URLRequestMockDataJob::AddUrlHandler();
   }
 
+  void TearDown() override { ClearURLHandlers(); }
+
  protected:
   net::URLRequestContextGetter* url_request_context_getter() {
     return url_request_context_getter_.get();
@@ -80,7 +103,8 @@
   scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
 };
 
-TEST_F(CertificateReportingServiceReporterTest, Reporter) {
+TEST_F(CertificateReportingServiceReporterOnIOThreadTest,
+       Reporter_RetriesEnabled) {
   std::unique_ptr<base::SimpleTestClock> clock(new base::SimpleTestClock());
   base::Time reference_time = base::Time::Now();
   clock->SetNow(reference_time);
@@ -95,11 +119,13 @@
   CertificateReportingService::BoundedReportList* list =
       new CertificateReportingService::BoundedReportList(2);
 
+  // Create a reporter with retries enabled.
   CertificateReportingService::Reporter reporter(
       std::unique_ptr<certificate_reporting::ErrorReporter>(
           certificate_error_reporter),
       std::unique_ptr<CertificateReportingService::BoundedReportList>(list),
-      clock.get(), base::TimeDelta::FromSeconds(100));
+      clock.get(), base::TimeDelta::FromSeconds(100),
+      true /* retries_enabled */);
   EXPECT_EQ(0u, list->items().size());
   EXPECT_EQ(0u, reporter.inflight_report_count_for_testing());
 
@@ -172,3 +198,371 @@
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0u, list->items().size());
 }
+
+// Same as above, but retries are disabled.
+TEST_F(CertificateReportingServiceReporterOnIOThreadTest,
+       Reporter_RetriesDisabled) {
+  std::unique_ptr<base::SimpleTestClock> clock(new base::SimpleTestClock());
+  base::Time reference_time = base::Time::Now();
+  clock->SetNow(reference_time);
+
+  const GURL kFailureURL =
+      net::URLRequestFailedJob::GetMockHttpsUrl(net::ERR_SSL_PROTOCOL_ERROR);
+  certificate_reporting::ErrorReporter* certificate_error_reporter =
+      new certificate_reporting::ErrorReporter(
+          url_request_context_getter()->GetURLRequestContext(), kFailureURL,
+          net::ReportSender::DO_NOT_SEND_COOKIES);
+
+  CertificateReportingService::BoundedReportList* list =
+      new CertificateReportingService::BoundedReportList(2);
+
+  // Create a reporter with retries disabled.
+  CertificateReportingService::Reporter reporter(
+      std::unique_ptr<certificate_reporting::ErrorReporter>(
+          certificate_error_reporter),
+      std::unique_ptr<CertificateReportingService::BoundedReportList>(list),
+      clock.get(), base::TimeDelta::FromSeconds(100),
+      false /* retries_enabled */);
+  EXPECT_EQ(0u, list->items().size());
+  EXPECT_EQ(0u, reporter.inflight_report_count_for_testing());
+
+  // Sending a failed report will not put the report in the retry list.
+  reporter.Send("report1");
+  EXPECT_EQ(1u, reporter.inflight_report_count_for_testing());
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_EQ(0u, reporter.inflight_report_count_for_testing());
+  ASSERT_EQ(0u, list->items().size());
+
+  // Sending a second failed report will also not put it in the retry list.
+  clock->Advance(base::TimeDelta::FromSeconds(10));
+  reporter.Send("report2");
+  base::RunLoop().RunUntilIdle();
+  ASSERT_EQ(0u, list->items().size());
+
+  // Send pending reports. Nothing should be sent.
+  clock->Advance(base::TimeDelta::FromSeconds(10));
+  reporter.SendPending();
+  base::RunLoop().RunUntilIdle();
+  ASSERT_EQ(0u, list->items().size());
+}
+
+class CertificateReportingServiceTest
+    : public ::testing::Test,
+      public certificate_reporting_test_utils::
+          CertificateReportingServiceTestBase {
+ public:
+  CertificateReportingServiceTest()
+      : CertificateReportingServiceTestBase(),
+        thread_bundle_(content::TestBrowserThreadBundle::REAL_IO_THREAD),
+        io_task_runner_(content::BrowserThread::GetTaskRunnerForThread(
+            content::BrowserThread::IO)) {}
+
+  ~CertificateReportingServiceTest() override {}
+
+  void SetUp() override {
+    SetUpInterceptor();
+    WaitForIOThread();
+
+    content::BrowserThread::PostTask(
+        content::BrowserThread::IO, FROM_HERE,
+        base::Bind(
+            &CertificateReportingServiceTest::SetUpURLRequestContextOnIOThread,
+            base::Unretained(this)));
+    WaitForIOThread();
+
+    clock_ = new base::SimpleTestClock();
+    service_.reset(new CertificateReportingService(
+        url_request_context_getter(), server_public_key(),
+        server_public_key_version(), kMaxReportCountInQueue,
+        base::TimeDelta::FromHours(24), std::unique_ptr<base::Clock>(clock_)));
+    // Wait for service reset.
+    WaitForIOThread();
+  }
+
+  void SetUpURLRequestContextOnIOThread() {
+    std::unique_ptr<net::TestURLRequestContext> url_request_context(
+        new net::TestURLRequestContext(true));
+    url_request_context->set_network_delegate(network_delegate());
+    url_request_context->Init();
+    url_request_context_getter_ = new net::TestURLRequestContextGetter(
+        io_task_runner_, std::move(url_request_context));
+  }
+
+  void TearDown() override {
+    WaitForIOThread();
+    EXPECT_TRUE(interceptor()->successful_reports().empty());
+    EXPECT_TRUE(interceptor()->failed_reports().empty());
+    EXPECT_TRUE(interceptor()->delayed_reports().empty());
+    EXPECT_EQ(0u, service()
+                      ->GetReporterForTesting()
+                      ->inflight_report_count_for_testing());
+
+    service_->Shutdown();
+    WaitForIOThread();
+
+    service_.reset(nullptr);
+    content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
+                                     base::Bind(&ClearURLHandlers));
+    TearDownInterceptor();
+  }
+
+ protected:
+  net::URLRequestContextGetter* url_request_context_getter() {
+    return url_request_context_getter_.get();
+  }
+
+  void WaitForIOThread() {
+    scoped_refptr<base::ThreadTestHelper> io_helper(
+        new base::ThreadTestHelper(io_task_runner_));
+    ASSERT_TRUE(io_helper->Run());
+  }
+
+  // Sets service enabled state and waits for a reset event.
+  void SetServiceEnabledAndWait(bool enabled) {
+    service()->SetEnabled(enabled);
+    WaitForIOThread();
+  }
+
+  void AdvanceClock(base::TimeDelta delta) {
+    content::BrowserThread::PostTask(
+        content::BrowserThread::IO, FROM_HERE,
+        base::Bind(&base::SimpleTestClock::Advance, base::Unretained(clock_),
+                   delta));
+  }
+
+  void SetNow(base::Time now) {
+    content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
+                                     base::Bind(&base::SimpleTestClock::SetNow,
+                                                base::Unretained(clock_), now));
+  }
+
+  CertificateReportingService* service() { return service_.get(); }
+
+ private:
+  // Must be initialized before url_request_context_getter_
+  content::TestBrowserThreadBundle thread_bundle_;
+
+  scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
+  scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
+
+  std::unique_ptr<CertificateReportingService> service_;
+  base::SimpleTestClock* clock_;
+};
+
+TEST_F(CertificateReportingServiceTest, Send) {
+  WaitForIOThread();
+  // Let all reports fail.
+  SetFailureMode(
+      certificate_reporting_test_utils::ReportSendingResult::REPORTS_FAIL);
+
+  // Send two reports. Both should fail and get queued.
+  service()->Send("report0");
+  WaitForRequestsDestroyed(ReportExpectation::Failed({"report0"}));
+
+  service()->Send("report1");
+  WaitForRequestsDestroyed(ReportExpectation::Failed({"report1"}));
+
+  // Send pending reports. Previously queued reports should be observed. They
+  // will also be queued again.
+  service()->SendPending();
+  WaitForRequestsDestroyed(ReportExpectation::Failed({"report0", "report1"}));
+
+  // Let all reports succeed.
+  SetFailureMode(certificate_reporting_test_utils::ReportSendingResult::
+                     REPORTS_SUCCESSFUL);
+
+  // Send a third report. This should not be queued.
+  service()->Send("report2");
+  WaitForRequestsDestroyed(ReportExpectation::Successful({"report2"}));
+
+  // Send pending reports. Previously failed and queued two reports should be
+  // observed.
+  service()->SendPending();
+  WaitForRequestsDestroyed(
+      ReportExpectation::Successful({"report0", "report1"}));
+}
+
+TEST_F(CertificateReportingServiceTest, Disabled_ShouldNotSend) {
+  // Let all reports succeed.
+  SetFailureMode(certificate_reporting_test_utils::ReportSendingResult::
+                     REPORTS_SUCCESSFUL);
+
+  // Disable the service.
+  SetServiceEnabledAndWait(false);
+
+  // Send a report. Report attempt should be cancelled and no sent reports
+  // should be observed.
+  service()->Send("report0");
+
+  // Enable the service and send a report again.
+  SetServiceEnabledAndWait(true);
+
+  service()->Send("report1");
+  WaitForRequestsDestroyed(ReportExpectation::Successful({"report1"}));
+}
+
+TEST_F(CertificateReportingServiceTest, Disabled_ShouldClearPendingReports) {
+  // Let all reports fail.
+  SetFailureMode(
+      certificate_reporting_test_utils::ReportSendingResult::REPORTS_FAIL);
+
+  service()->Send("report0");
+  WaitForRequestsDestroyed(ReportExpectation::Failed({"report0"}));
+
+  // Disable the service.
+  SetServiceEnabledAndWait(false);
+
+  // Sending has no effect while disabled, wait for a single cancelled event.
+  service()->SendPending();
+
+  // Re-enable the service and send pending reports. Pending reports should have
+  // been cleared when the service was disabled, so no report should be seen.
+  SetServiceEnabledAndWait(true);
+
+  // Sending with empty queue has no effect.
+  service()->SendPending();
+}
+
+TEST_F(CertificateReportingServiceTest, DontSendOldReports) {
+  SetNow(base::Time::Now());
+  // Let all reports fail.
+  SetFailureMode(
+      certificate_reporting_test_utils::ReportSendingResult::REPORTS_FAIL);
+
+  // Send a report.
+  service()->Send("report0");
+  WaitForRequestsDestroyed(ReportExpectation::Failed({"report0"}));
+
+  // Advance the clock a bit and trigger another report.
+  AdvanceClock(base::TimeDelta::FromHours(5));
+
+  service()->Send("report1");
+  WaitForRequestsDestroyed(ReportExpectation::Failed({"report1"}));
+
+  // Advance the clock to 20 hours, putting it 25 hours ahead of the reference
+  // time. This makes the report0 older than max age (24 hours). The report1 is
+  // now 20 hours old.
+  AdvanceClock(base::TimeDelta::FromHours(20));
+  // Send pending reports. report0 should be discarded since it's too old.
+  // report1 should be queued again.
+  service()->SendPending();
+  WaitForRequestsDestroyed(ReportExpectation::Failed({"report1"}));
+
+  // Send a third report.
+  service()->Send("report2");
+  WaitForRequestsDestroyed(ReportExpectation::Failed({"report2"}));
+
+  // Advance the clock 5 hours. The report1 will now be 25 hours old.
+  AdvanceClock(base::TimeDelta::FromHours(5));
+  // Send pending reports. report1 should be discarded since it's too old.
+  // report2 should be queued again.
+  service()->SendPending();
+  WaitForRequestsDestroyed(ReportExpectation::Failed({"report2"}));
+
+  // Advance the clock 20 hours again so that report2 is 25 hours old and is
+  // older than max age (24 hours)
+  AdvanceClock(base::TimeDelta::FromHours(20));
+  // Send pending reports. report2 should be discarded since it's too old. No
+  // other reports remain.
+  service()->SendPending();
+}
+
+TEST_F(CertificateReportingServiceTest, DiscardOldReports) {
+  SetNow(base::Time::Now());
+  // Let all reports fail.
+  SetFailureMode(
+      certificate_reporting_test_utils::ReportSendingResult::REPORTS_FAIL);
+
+  // Send a failed report.
+  service()->Send("report0");
+  WaitForRequestsDestroyed(ReportExpectation::Failed({"report0"}));
+
+  // Send three more reports within five hours of each other. After this:
+  // report0 is 0 hours after reference time (15 hours old).
+  // report1 is 5 hours after reference time (10 hours old).
+  // report2 is 10 hours after reference time (5 hours old).
+  // report3 is 15 hours after reference time (0 hours old).
+  AdvanceClock(base::TimeDelta::FromHours(5));
+  service()->Send("report1");
+
+  AdvanceClock(base::TimeDelta::FromHours(5));
+  service()->Send("report2");
+
+  AdvanceClock(base::TimeDelta::FromHours(5));
+  service()->Send("report3");
+  WaitForRequestsDestroyed(
+      ReportExpectation::Failed({"report1", "report2", "report3"}));
+
+  // Send pending reports. Four reports were generated above, but the service
+  // only queues three reports, so the very first one should be dropped since
+  // it's the oldest.
+  service()->SendPending();
+  WaitForRequestsDestroyed(
+      ReportExpectation::Failed({"report1", "report2", "report3"}));
+
+  // Let all reports succeed.
+  SetFailureMode(certificate_reporting_test_utils::ReportSendingResult::
+                     REPORTS_SUCCESSFUL);
+
+  // Advance the clock by 15 hours. Current time is now 30 hours after reference
+  // time. The ages of reports are now as follows:
+  // report1 is 25 hours old.
+  // report2 is 20 hours old.
+  // report3 is 15 hours old.
+  AdvanceClock(base::TimeDelta::FromHours(15));
+  // Send pending reports. Only report2 and report3 should be sent, report1
+  // should be ignored because it's too old.
+  service()->SendPending();
+  WaitForRequestsDestroyed(
+      ReportExpectation::Successful({"report2", "report3"}));
+
+  // Do a final send. No reports should be sent.
+  service()->SendPending();
+}
+
+// A delayed report should successfully upload when it's resumed.
+TEST_F(CertificateReportingServiceTest, Delayed_Resumed) {
+  // Let reports hang.
+  SetFailureMode(
+      certificate_reporting_test_utils::ReportSendingResult::REPORTS_DELAY);
+  // Send a report. The report upload hangs, so no error or success callbacks
+  // should be called.
+  service()->Send("report0");
+
+  // Resume the report upload and run the callbacks. The report should be
+  // successfully sent.
+  ResumeDelayedRequest();
+  WaitForRequestsDestroyed(ReportExpectation::Delayed({"report0"}));
+}
+
+// Delayed reports should cleaned when the service is reset.
+TEST_F(CertificateReportingServiceTest, Delayed_Reset) {
+  // Let reports hang.
+  SetFailureMode(
+      certificate_reporting_test_utils::ReportSendingResult::REPORTS_DELAY);
+  // Send a report. The report is triggered but hangs, so no error or success
+  // callbacks should be called.
+  service()->Send("report0");
+
+  // Disable the service. This should reset the reporting service and
+  // clear all pending reports.
+  SetServiceEnabledAndWait(false);
+
+  // Resume delayed report. No report should be observed since the service
+  // should have reset and all pending reports should be cleared. If any report
+  // is observed, the next WaitForRequestsDestroyed() will fail.
+  ResumeDelayedRequest();
+
+  // Enable the service.
+  SetServiceEnabledAndWait(true);
+
+  // Send a report. The report is triggered but hangs, so no error or success
+  // callbacks should be called. The report id is again 0 since the pending
+  // report queue has been cleared above.
+  service()->Send("report1");
+
+  // Resume delayed report. The report should be observed.
+  ResumeDelayedRequest();
+  WaitForRequestsDestroyed(ReportExpectation::Delayed({"report0", "report1"}));
+}
diff --git a/chrome/browser/search/search_unittest.cc b/chrome/browser/search/search_unittest.cc
index 335905e..1761130 100644
--- a/chrome/browser/search/search_unittest.cc
+++ b/chrome/browser/search/search_unittest.cc
@@ -443,7 +443,6 @@
   std::map<std::string, bool> hosts;
   hosts["foo.com"] = false;
   url_filter->SetManualHosts(&hosts);
-  url_filter->SetEnabled(true);
 
   EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl),
             GetNewTabPageURL(profile()));
diff --git a/chrome/browser/search_engines/template_url_service_factory.cc b/chrome/browser/search_engines/template_url_service_factory.cc
index 464441b..e2d9366 100644
--- a/chrome/browser/search_engines/template_url_service_factory.cc
+++ b/chrome/browser/search_engines/template_url_service_factory.cc
@@ -23,8 +23,9 @@
 #include "components/search_engines/default_search_manager.h"
 #include "components/search_engines/search_engines_pref_names.h"
 #include "components/search_engines/template_url_service.h"
+#include "rlz/features/features.h"
 
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
 #include "components/rlz/rlz_tracker.h"
 #endif
 
@@ -43,7 +44,7 @@
 std::unique_ptr<KeyedService> TemplateURLServiceFactory::BuildInstanceFor(
     content::BrowserContext* context) {
   base::Closure dsp_change_callback;
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
   dsp_change_callback = base::Bind(
       base::IgnoreResult(&rlz::RLZTracker::RecordProductEvent), rlz_lib::CHROME,
       rlz::RLZTracker::ChromeOmnibox(), rlz_lib::SET_TO_GOOGLE);
diff --git a/chrome/browser/search_engines/ui_thread_search_terms_data.cc b/chrome/browser/search_engines/ui_thread_search_terms_data.cc
index 6ae87fa..9a31685 100644
--- a/chrome/browser/search_engines/ui_thread_search_terms_data.cc
+++ b/chrome/browser/search_engines/ui_thread_search_terms_data.cc
@@ -25,10 +25,11 @@
 #include "components/search/search.h"
 #include "components/version_info/version_info.h"
 #include "content/public/browser/browser_thread.h"
+#include "rlz/features/features.h"
 #include "ui/base/device_form_factor.h"
 #include "url/gurl.h"
 
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
 #include "components/rlz/rlz_tracker.h"
 #endif
 
@@ -74,7 +75,7 @@
   DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
       BrowserThread::CurrentlyOn(BrowserThread::UI));
   base::string16 rlz_string;
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
   // For organic brandcodes do not use rlz at all. Empty brandcode usually
   // means a chromium install. This is ok.
   std::string brand;
diff --git a/chrome/browser/supervised_user/supervised_user_resource_throttle.cc b/chrome/browser/supervised_user/supervised_user_resource_throttle.cc
index 53df77ad..a0695f6 100644
--- a/chrome/browser/supervised_user/supervised_user_resource_throttle.cc
+++ b/chrome/browser/supervised_user/supervised_user_resource_throttle.cc
@@ -117,7 +117,7 @@
     const SupervisedUserURLFilter* url_filter) {
   // Only treat main frame requests (ignoring subframes and subresources).
   bool is_main_frame = resource_type == content::RESOURCE_TYPE_MAIN_FRAME;
-  if (!is_main_frame || !url_filter->enabled())
+  if (!is_main_frame)
     return nullptr;
 
   // Can't use base::MakeUnique because the constructor is private.
diff --git a/chrome/browser/supervised_user/supervised_user_resource_throttle_browsertest.cc b/chrome/browser/supervised_user/supervised_user_resource_throttle_browsertest.cc
index 90955a67..c19e8d29 100644
--- a/chrome/browser/supervised_user/supervised_user_resource_throttle_browsertest.cc
+++ b/chrome/browser/supervised_user/supervised_user_resource_throttle_browsertest.cc
@@ -136,28 +136,3 @@
   ASSERT_TRUE(content::ExecuteScriptAndExtractBool(tab, "loaded2()", &loaded2));
   EXPECT_TRUE(loaded2);
 }
-
-class SupervisedUserResourceThrottleNotSupervisedTest
-    : public SupervisedUserResourceThrottleTest {
- protected:
-  SupervisedUserResourceThrottleNotSupervisedTest() {}
-  ~SupervisedUserResourceThrottleNotSupervisedTest() override {}
-
- private:
-  // Overridden to do nothing, so that the supervised user ID will be empty.
-  void SetUpCommandLine(base::CommandLine* command_line) override {}
-};
-
-IN_PROC_BROWSER_TEST_F(SupervisedUserResourceThrottleNotSupervisedTest,
-                       DontBlock) {
-  BlockHost(kExampleHost);
-
-  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
-
-  GURL blocked_url = embedded_test_server()->GetURL(
-      kExampleHost, "/supervised_user/simple.html");
-  ui_test_utils::NavigateToURL(browser(), blocked_url);
-  // Even though the URL is marked as blocked, the load should go through, since
-  // the user isn't supervised.
-  EXPECT_FALSE(tab->ShowingInterstitialPage());
-}
diff --git a/chrome/browser/supervised_user/supervised_user_service.cc b/chrome/browser/supervised_user/supervised_user_service.cc
index a470f3e..324f525d6 100644
--- a/chrome/browser/supervised_user/supervised_user_service.cc
+++ b/chrome/browser/supervised_user/supervised_user_service.cc
@@ -441,13 +441,6 @@
   return io_url_filter_.get();
 }
 
-void SupervisedUserService::URLFilterContext::SetEnabled(bool enabled) {
-  ui_url_filter_->SetEnabled(enabled);
-  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
-                          base::Bind(&SupervisedUserURLFilter::SetEnabled,
-                                     io_url_filter_, enabled));
-}
-
 void SupervisedUserService::URLFilterContext::SetDefaultFilteringBehavior(
     SupervisedUserURLFilter::FilteringBehavior behavior) {
   ui_url_filter_->SetDefaultFilteringBehavior(behavior);
@@ -679,8 +672,6 @@
     BrowserList::RemoveObserver(this);
 #endif
   }
-
-  url_filter_context_.SetEnabled(active_);
 }
 
 #if !defined(OS_ANDROID)
diff --git a/chrome/browser/supervised_user/supervised_user_service.h b/chrome/browser/supervised_user/supervised_user_service.h
index b461177..b896f63a5 100644
--- a/chrome/browser/supervised_user/supervised_user_service.h
+++ b/chrome/browser/supervised_user/supervised_user_service.h
@@ -250,7 +250,6 @@
     SupervisedUserURLFilter* ui_url_filter() const;
     SupervisedUserURLFilter* io_url_filter() const;
 
-    void SetEnabled(bool enabled);
     void SetDefaultFilteringBehavior(
         SupervisedUserURLFilter::FilteringBehavior behavior);
     void LoadWhitelists(
diff --git a/chrome/browser/supervised_user/supervised_user_url_filter.cc b/chrome/browser/supervised_user/supervised_user_url_filter.cc
index dfece48..5318b1b 100644
--- a/chrome/browser/supervised_user/supervised_user_url_filter.cc
+++ b/chrome/browser/supervised_user/supervised_user_url_filter.cc
@@ -231,8 +231,7 @@
 }  // namespace
 
 SupervisedUserURLFilter::SupervisedUserURLFilter()
-    : enabled_(false),
-      default_behavior_(ALLOW),
+    : default_behavior_(ALLOW),
       contents_(new Contents()),
       blacklist_(nullptr),
       amp_cache_path_regex_(kAmpCachePathPattern),
@@ -324,16 +323,6 @@
   return trimmed_host == trimmed_pattern;
 }
 
-void SupervisedUserURLFilter::SetEnabled(bool enabled) {
-  if (enabled_ == enabled)
-    return;
-
-  enabled_ = enabled;
-
-  for (Observer& observer : observers_)
-    observer.OnSiteListUpdated();
-}
-
 SupervisedUserURLFilter::FilteringBehavior
 SupervisedUserURLFilter::GetFilteringBehaviorForURL(const GURL& url) const {
   supervised_user_error_page::FilteringBehaviorReason reason;
@@ -354,11 +343,6 @@
     supervised_user_error_page::FilteringBehaviorReason* reason) const {
   DCHECK(CalledOnValidThread());
 
-  if (!enabled_) {
-    *reason = supervised_user_error_page::DEFAULT;
-    return ALLOW;
-  }
-
   GURL effective_url = GetEmbeddedURL(url);
   if (!effective_url.is_valid())
     effective_url = url;
@@ -661,10 +645,8 @@
 void SupervisedUserURLFilter::SetContents(std::unique_ptr<Contents> contents) {
   DCHECK(CalledOnValidThread());
   contents_ = std::move(contents);
-  if (enabled_) {
-    for (Observer& observer : observers_)
-      observer.OnSiteListUpdated();
-  }
+  for (Observer& observer : observers_)
+    observer.OnSiteListUpdated();
 }
 
 void SupervisedUserURLFilter::CheckCallback(
diff --git a/chrome/browser/supervised_user/supervised_user_url_filter.h b/chrome/browser/supervised_user/supervised_user_url_filter.h
index e11c50cc..0b34d37 100644
--- a/chrome/browser/supervised_user/supervised_user_url_filter.h
+++ b/chrome/browser/supervised_user/supervised_user_url_filter.h
@@ -61,11 +61,7 @@
 
   class Observer {
    public:
-    // Called whenever the filter changes.
-    // TODO(treib,bauerb): Rename to OnURLFilterUpdated.
     virtual void OnSiteListUpdated() = 0;
-    // Called whenever a check started via
-    // GetFilteringBehaviorForURLWithAsyncChecks completes.
     virtual void OnURLChecked(
         const GURL& url,
         FilteringBehavior behavior,
@@ -110,13 +106,6 @@
   static bool HostMatchesPattern(const std::string& canonical_host,
                                  const std::string& pattern);
 
-  // Returns whether the filter is enabled. If this is false, all URL checks
-  // will return ALLOW.
-  bool enabled() const { return enabled_; }
-
-  // Enables or disables the filter. Notifies observers if the state changed.
-  void SetEnabled(bool enabled);
-
   // Returns the filtering behavior for a given URL, based on the default
   // behavior and whether it is on a site list.
   FilteringBehavior GetFilteringBehaviorForURL(const GURL& url) const;
@@ -209,10 +198,6 @@
   // This is mutable to allow notification in const member functions.
   mutable base::ObserverList<Observer> observers_;
 
-  // Whether this filter is enabled. True for supervised user profiles, false
-  // otherwise.
-  bool enabled_;
-
   FilteringBehavior default_behavior_;
   std::unique_ptr<Contents> contents_;
 
diff --git a/chrome/browser/supervised_user/supervised_user_url_filter_unittest.cc b/chrome/browser/supervised_user/supervised_user_url_filter_unittest.cc
index bbac7bae..e306abc 100644
--- a/chrome/browser/supervised_user/supervised_user_url_filter_unittest.cc
+++ b/chrome/browser/supervised_user/supervised_user_url_filter_unittest.cc
@@ -22,7 +22,6 @@
  public:
   SupervisedUserURLFilterTest() : filter_(new SupervisedUserURLFilter) {
     filter_->SetDefaultFilteringBehavior(SupervisedUserURLFilter::BLOCK);
-    filter_->SetEnabled(true);
     filter_->AddObserver(this);
   }
 
@@ -69,11 +68,6 @@
   EXPECT_TRUE(IsURLWhitelisted("chrome://extensions/"));
   EXPECT_TRUE(IsURLWhitelisted("chrome-extension://foo/main.html"));
   EXPECT_TRUE(IsURLWhitelisted("file:///home/chronos/user/Downloads/img.jpg"));
-
-  // If the filter is disabled, everything should be allowed.
-  filter_->SetEnabled(false);
-  EXPECT_TRUE(IsURLWhitelisted("http://google.com"));
-  EXPECT_TRUE(IsURLWhitelisted("http://notgoogle.com/"));
 }
 
 TEST_F(SupervisedUserURLFilterTest, EffectiveURL) {
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 559b0fa..c594c46c 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -12,6 +12,7 @@
 import("//media/media_options.gni")
 import("//ppapi/features/features.gni")
 import("//printing/features/features.gni")
+import("//rlz/features/features.gni")
 import("//ui/base/ui_features.gni")
 
 config("ui_warnings") {
@@ -572,6 +573,7 @@
     "//net:net_with_v8",
     "//ppapi/features",
     "//printing/features",
+    "//rlz/features",
     "//services/service_manager/runner/common",
     "//skia",
     "//storage/browser",
@@ -1362,8 +1364,8 @@
       "ash/launcher/multi_profile_browser_status_monitor.h",
       "ash/launcher/settings_window_observer.cc",
       "ash/launcher/settings_window_observer.h",
-      "ash/media_delegate_chromeos.cc",
-      "ash/media_delegate_chromeos.h",
+      "ash/media_client.cc",
+      "ash/media_client.h",
       "ash/multi_user/multi_user_context_menu.h",
       "ash/multi_user/multi_user_context_menu_chromeos.cc",
       "ash/multi_user/multi_user_notification_blocker_chromeos.cc",
@@ -1892,8 +1894,14 @@
       # apart from aura::Window, which is also not supported).
       if (!is_mac) {
         sources += [
-          "views/ime_driver_mus.cc",
-          "views/ime_driver_mus.h",
+          "views/ime_driver/ime_driver_mus.cc",
+          "views/ime_driver/ime_driver_mus.h",
+          "views/ime_driver/input_method_bridge_chromeos.cc",
+          "views/ime_driver/input_method_bridge_chromeos.h",
+          "views/ime_driver/remote_text_input_client.cc",
+          "views/ime_driver/remote_text_input_client.h",
+          "views/ime_driver/simple_input_method.cc",
+          "views/ime_driver/simple_input_method.h",
           "views/tabs/window_finder_mus.cc",
           "views/tabs/window_finder_mus.h",
         ]
@@ -2061,8 +2069,6 @@
       "window_sizer/window_sizer_aura.cc",
     ]
     deps += [
-      # aura uses some of ash resources.
-      "//ash/resources",
       "//ui/aura",
       "//ui/keyboard",
       "//ui/keyboard:keyboard_with_content",
diff --git a/chrome/browser/ui/android/autofill/autofill_popup_view_android.cc b/chrome/browser/ui/android/autofill/autofill_popup_view_android.cc
index 3046b58..6795ac7 100644
--- a/chrome/browser/ui/android/autofill/autofill_popup_view_android.cc
+++ b/chrome/browser/ui/android/autofill/autofill_popup_view_android.cc
@@ -94,7 +94,7 @@
           controller_->layout_model().GetIconResourceID(suggestion.icon));
     }
 
-    bool deletable =
+    bool is_deletable =
         controller_->GetRemovalConfirmationText(i, nullptr, nullptr);
     bool is_label_multiline =
         suggestion.frontend_id ==
@@ -102,11 +102,16 @@
         suggestion.frontend_id == POPUP_ITEM_ID_CREDIT_CARD_SIGNIN_PROMO;
     Java_AutofillPopupBridge_addToAutofillSuggestionArray(
         env, data_array, i, value, label, android_icon_id,
-        suggestion.frontend_id, deletable, is_label_multiline);
+        controller_->layout_model().IsIconAtStart(suggestion.frontend_id),
+        suggestion.frontend_id, is_deletable, is_label_multiline,
+        suggestion.is_value_bold);
   }
 
-  Java_AutofillPopupBridge_show(env, java_object_, data_array,
-                                controller_->IsRTL());
+  Java_AutofillPopupBridge_show(
+      env, java_object_, data_array, controller_->IsRTL(),
+      controller_->layout_model().GetBackgroundColor(),
+      controller_->layout_model().GetDividerColor(),
+      controller_->layout_model().GetDropdownItemHeight());
 }
 
 void AutofillPopupViewAndroid::SuggestionSelected(
diff --git a/chrome/browser/ui/app_list/app_list_controller_delegate.cc b/chrome/browser/ui/app_list/app_list_controller_delegate.cc
index eef8d47a..fa717e49 100644
--- a/chrome/browser/ui/app_list/app_list_controller_delegate.cc
+++ b/chrome/browser/ui/app_list/app_list_controller_delegate.cc
@@ -22,13 +22,14 @@
 #include "extensions/common/manifest_handlers/options_page_info.h"
 #include "extensions/common/manifest_url_handlers.h"
 #include "net/base/url_util.h"
+#include "rlz/features/features.h"
 #include "ui/app_list/app_list_folder_item.h"
 #include "ui/app_list/app_list_item.h"
 #include "ui/app_list/app_list_model.h"
 #include "ui/app_list/app_list_switches.h"
 #include "ui/gfx/geometry/rect.h"
 
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
 #include "components/rlz/rlz_tracker.h"  // nogncheck
 #endif
 
@@ -203,7 +204,7 @@
 }
 
 void AppListControllerDelegate::OnSearchStarted() {
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
   rlz::RLZTracker::RecordAppListSearch();
 #endif
 }
diff --git a/chrome/browser/ui/ash/app_list/app_list_presenter_service.cc b/chrome/browser/ui/ash/app_list/app_list_presenter_service.cc
index 58fef58d..2770d89 100644
--- a/chrome/browser/ui/ash/app_list/app_list_presenter_service.cc
+++ b/chrome/browser/ui/ash/app_list/app_list_presenter_service.cc
@@ -5,9 +5,24 @@
 #include "chrome/browser/ui/ash/app_list/app_list_presenter_service.h"
 
 #include "chrome/browser/ui/ash/app_list/app_list_service_ash.h"
+#include "chrome/browser/ui/ash/ash_util.h"
+#include "content/public/common/service_manager_connection.h"
+#include "services/service_manager/public/cpp/connector.h"
 #include "ui/app_list/presenter/app_list_presenter.h"
 
-AppListPresenterService::AppListPresenterService() {}
+AppListPresenterService::AppListPresenterService() : binding_(this) {
+  content::ServiceManagerConnection* connection =
+      content::ServiceManagerConnection::GetForProcess();
+  if (connection && connection->GetConnector()) {
+    // Connect to the app list interface in the ash service.
+    app_list::mojom::AppListPtr app_list_ptr;
+    connection->GetConnector()->ConnectToInterface(
+        ash_util::GetAshServiceName(), &app_list_ptr);
+    // Register this object as the app list presenter.
+    app_list_ptr->SetAppListPresenter(binding_.CreateInterfacePtrAndBind());
+  }
+}
+
 AppListPresenterService::~AppListPresenterService() {}
 
 void AppListPresenterService::Show(int64_t display_id) {
diff --git a/chrome/browser/ui/ash/app_list/app_list_presenter_service.h b/chrome/browser/ui/ash/app_list/app_list_presenter_service.h
index 3e00e8b..969cc8e 100644
--- a/chrome/browser/ui/ash/app_list/app_list_presenter_service.h
+++ b/chrome/browser/ui/ash/app_list/app_list_presenter_service.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_UI_ASH_APP_LIST_APP_LIST_PRESENTER_SERVICE_H_
 
 #include "base/macros.h"
+#include "mojo/public/cpp/bindings/binding.h"
 #include "ui/app_list/presenter/app_list_presenter.mojom.h"
 
 namespace app_list {
@@ -26,6 +27,8 @@
  private:
   app_list::AppListPresenter* GetPresenter();
 
+  mojo::Binding<app_list::mojom::AppListPresenter> binding_;
+
   DISALLOW_COPY_AND_ASSIGN(AppListPresenterService);
 };
 
diff --git a/chrome/browser/ui/ash/app_list/app_list_service_ash.h b/chrome/browser/ui/ash/app_list/app_list_service_ash.h
index 02dcf00..b3f3763 100644
--- a/chrome/browser/ui/ash/app_list/app_list_service_ash.h
+++ b/chrome/browser/ui/ash/app_list/app_list_service_ash.h
@@ -9,6 +9,7 @@
 
 #include "base/macros.h"
 #include "chrome/browser/ui/app_list/app_list_service_impl.h"
+#include "chrome/browser/ui/ash/app_list/app_list_presenter_service.h"
 #include "ui/app_list/app_list_model.h"
 
 namespace app_list {
@@ -76,6 +77,8 @@
   std::unique_ptr<app_list::AppListPresenterImpl> app_list_presenter_;
   std::unique_ptr<AppListControllerDelegateAsh> controller_delegate_;
 
+  AppListPresenterService app_list_presenter_service_;
+
   DISALLOW_COPY_AND_ASSIGN(AppListServiceAsh);
 };
 
diff --git a/chrome/browser/ui/ash/chrome_new_window_client.cc b/chrome/browser/ui/ash/chrome_new_window_client.cc
index 92a8f8c9..6f2d4507 100644
--- a/chrome/browser/ui/ash/chrome_new_window_client.cc
+++ b/chrome/browser/ui/ash/chrome_new_window_client.cc
@@ -29,7 +29,6 @@
 #include "components/sessions/core/tab_restore_service_observer.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/service_manager_connection.h"
-#include "content/public/common/service_names.mojom.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/common/constants.h"
 #include "services/service_manager/public/cpp/connector.h"
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.cc b/chrome/browser/ui/ash/chrome_shell_delegate.cc
index 0440d50..2f1d12e 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.cc
@@ -49,7 +49,6 @@
 #include "chrome/browser/ui/ash/chrome_keyboard_ui.h"
 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.h"
 #include "chrome/browser/ui/ash/launcher/launcher_context_menu.h"
-#include "chrome/browser/ui/ash/media_delegate_chromeos.h"
 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
 #include "chrome/browser/ui/ash/palette_delegate_chromeos.h"
 #include "chrome/browser/ui/ash/session_state_delegate_chromeos.h"
@@ -533,10 +532,6 @@
   return new AccessibilityDelegateImpl;
 }
 
-ash::MediaDelegate* ChromeShellDelegate::CreateMediaDelegate() {
-  return new MediaDelegateChromeOS;
-}
-
 std::unique_ptr<ash::PaletteDelegate>
 ChromeShellDelegate::CreatePaletteDelegate() {
   return chromeos::PaletteDelegateChromeOS::Create();
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.h b/chrome/browser/ui/ash/chrome_shell_delegate.h
index 95d0052..f5c0e77 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.h
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.h
@@ -48,7 +48,6 @@
   std::unique_ptr<ash::WallpaperDelegate> CreateWallpaperDelegate() override;
   ash::SessionStateDelegate* CreateSessionStateDelegate() override;
   ash::AccessibilityDelegate* CreateAccessibilityDelegate() override;
-  ash::MediaDelegate* CreateMediaDelegate() override;
   std::unique_ptr<ash::PaletteDelegate> CreatePaletteDelegate() override;
   ui::MenuModel* CreateContextMenu(ash::WmShelf* wm_shelf,
                                    const ash::ShelfItem* item) override;
diff --git a/chrome/browser/ui/ash/media_client.cc b/chrome/browser/ui/ash/media_client.cc
new file mode 100644
index 0000000..1f16ac27
--- /dev/null
+++ b/chrome/browser/ui/ash/media_client.cc
@@ -0,0 +1,202 @@
+// 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.
+
+#include "chrome/browser/ui/ash/media_client.h"
+
+#include "ash/common/session/session_state_delegate.h"
+#include "ash/common/wm_shell.h"
+#include "ash/content/shell_content_state.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "chrome/browser/chromeos/extensions/media_player_api.h"
+#include "chrome/browser/chromeos/extensions/media_player_event_router.h"
+#include "chrome/browser/media/webrtc/media_stream_capture_indicator.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/ui/ash/ash_util.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/service_manager_connection.h"
+#include "extensions/browser/app_window/app_window.h"
+#include "extensions/browser/app_window/app_window_registry.h"
+#include "extensions/browser/process_manager.h"
+#include "services/service_manager/public/cpp/connector.h"
+
+using ash::mojom::MediaCaptureState;
+
+namespace {
+
+MediaCaptureState& operator|=(MediaCaptureState& lhs, MediaCaptureState rhs) {
+  lhs = static_cast<MediaCaptureState>(static_cast<int>(lhs) |
+                                       static_cast<int>(rhs));
+  return lhs;
+}
+
+void GetMediaCaptureState(const MediaStreamCaptureIndicator* indicator,
+                          content::WebContents* web_contents,
+                          MediaCaptureState* media_state_out) {
+  bool video = indicator->IsCapturingVideo(web_contents);
+  bool audio = indicator->IsCapturingAudio(web_contents);
+
+  if (video)
+    *media_state_out |= MediaCaptureState::VIDEO;
+  if (audio)
+    *media_state_out |= MediaCaptureState::AUDIO;
+}
+
+void GetBrowserMediaCaptureState(const MediaStreamCaptureIndicator* indicator,
+                                 const content::BrowserContext* context,
+                                 MediaCaptureState* media_state_out) {
+  const BrowserList* desktop_list = BrowserList::GetInstance();
+
+  for (BrowserList::BrowserVector::const_iterator iter = desktop_list->begin();
+       iter != desktop_list->end(); ++iter) {
+    TabStripModel* tab_strip_model = (*iter)->tab_strip_model();
+    for (int i = 0; i < tab_strip_model->count(); ++i) {
+      content::WebContents* web_contents = tab_strip_model->GetWebContentsAt(i);
+      if (web_contents->GetBrowserContext() != context)
+        continue;
+      GetMediaCaptureState(indicator, web_contents, media_state_out);
+      if (*media_state_out == MediaCaptureState::AUDIO_VIDEO)
+        return;
+    }
+  }
+}
+
+void GetAppMediaCaptureState(const MediaStreamCaptureIndicator* indicator,
+                             content::BrowserContext* context,
+                             MediaCaptureState* media_state_out) {
+  const extensions::AppWindowRegistry::AppWindowList& apps =
+      extensions::AppWindowRegistry::Get(context)->app_windows();
+  for (extensions::AppWindowRegistry::AppWindowList::const_iterator iter =
+           apps.begin();
+       iter != apps.end(); ++iter) {
+    GetMediaCaptureState(indicator, (*iter)->web_contents(), media_state_out);
+    if (*media_state_out == MediaCaptureState::AUDIO_VIDEO)
+      return;
+  }
+}
+
+void GetExtensionMediaCaptureState(const MediaStreamCaptureIndicator* indicator,
+                                   content::BrowserContext* context,
+                                   MediaCaptureState* media_state_out) {
+  for (content::RenderFrameHost* host :
+       extensions::ProcessManager::Get(context)->GetAllFrames()) {
+    content::WebContents* web_contents =
+        content::WebContents::FromRenderFrameHost(host);
+    // RFH may not have web contents.
+    if (!web_contents)
+      continue;
+    GetMediaCaptureState(indicator, web_contents, media_state_out);
+    if (*media_state_out == MediaCaptureState::AUDIO_VIDEO)
+      return;
+  }
+}
+
+MediaCaptureState GetMediaCaptureStateOfAllWebContents(
+    content::BrowserContext* context) {
+  if (!context)
+    return MediaCaptureState::NONE;
+
+  scoped_refptr<MediaStreamCaptureIndicator> indicator =
+      MediaCaptureDevicesDispatcher::GetInstance()
+          ->GetMediaStreamCaptureIndicator();
+
+  MediaCaptureState media_state = MediaCaptureState::NONE;
+  // Browser windows
+  GetBrowserMediaCaptureState(indicator.get(), context, &media_state);
+  if (media_state == MediaCaptureState::AUDIO_VIDEO)
+    return MediaCaptureState::AUDIO_VIDEO;
+
+  // App windows
+  GetAppMediaCaptureState(indicator.get(), context, &media_state);
+  if (media_state == MediaCaptureState::AUDIO_VIDEO)
+    return MediaCaptureState::AUDIO_VIDEO;
+
+  // Extensions
+  GetExtensionMediaCaptureState(indicator.get(), context, &media_state);
+
+  return media_state;
+}
+
+}  // namespace
+
+MediaClient::MediaClient() : binding_(this), weak_ptr_factory_(this) {
+  MediaCaptureDevicesDispatcher::GetInstance()->AddObserver(this);
+
+  service_manager::Connector* connector =
+      content::ServiceManagerConnection::GetForProcess()->GetConnector();
+  connector->ConnectToInterface(ash_util::GetAshServiceName(),
+                                &media_controller_);
+
+  // Register this object as the client interface implementation.
+  ash::mojom::MediaClientAssociatedPtrInfo ptr_info;
+  binding_.Bind(&ptr_info, media_controller_.associated_group());
+  media_controller_->SetClient(std::move(ptr_info));
+}
+
+MediaClient::~MediaClient() {
+  MediaCaptureDevicesDispatcher::GetInstance()->RemoveObserver(this);
+}
+
+void MediaClient::HandleMediaNextTrack() {
+  extensions::MediaPlayerAPI::Get(ProfileManager::GetActiveUserProfile())
+      ->media_player_event_router()
+      ->NotifyNextTrack();
+}
+
+void MediaClient::HandleMediaPlayPause() {
+  extensions::MediaPlayerAPI::Get(ProfileManager::GetActiveUserProfile())
+      ->media_player_event_router()
+      ->NotifyTogglePlayState();
+}
+
+void MediaClient::HandleMediaPrevTrack() {
+  extensions::MediaPlayerAPI::Get(ProfileManager::GetActiveUserProfile())
+      ->media_player_event_router()
+      ->NotifyPrevTrack();
+}
+
+void MediaClient::RequestCaptureState() {
+  // TODO(erg): Ash doesn't have stable user indexes. Given the asynchronous
+  // nature of sending messages over mojo pipes, this could theoretically cause
+  // bad data, as one side thinks the vector is [user1, user2] while the other
+  // thinks [user2, user1]. However, since parts of this system are already
+  // asynchronous (see OnRequestUpdate's PostTask()), we're not worrying about
+  // this right now.
+  ash::SessionStateDelegate* session_state_delegate =
+      ash::WmShell::Get()->GetSessionStateDelegate();
+  std::vector<MediaCaptureState> state;
+  for (ash::UserIndex i = 0;
+       i < session_state_delegate->NumberOfLoggedInUsers(); ++i) {
+    state.push_back(GetMediaCaptureStateByIndex(i));
+  }
+
+  media_controller_->NotifyCaptureState(std::move(state));
+}
+
+void MediaClient::OnRequestUpdate(int render_process_id,
+                                  int render_frame_id,
+                                  content::MediaStreamType stream_type,
+                                  const content::MediaRequestState state) {
+  DCHECK(base::MessageLoopForUI::IsCurrent());
+  // The PostTask is necessary because the state of MediaStreamCaptureIndicator
+  // gets updated after this.
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::Bind(&MediaClient::RequestCaptureState,
+                            weak_ptr_factory_.GetWeakPtr()));
+}
+
+MediaCaptureState MediaClient::GetMediaCaptureStateByIndex(int user_index) {
+  content::BrowserContext* context =
+      ash::ShellContentState::GetInstance()->GetBrowserContextByIndex(
+          user_index);
+  return GetMediaCaptureStateOfAllWebContents(context);
+}
diff --git a/chrome/browser/ui/ash/media_client.h b/chrome/browser/ui/ash/media_client.h
new file mode 100644
index 0000000..cfcc72db
--- /dev/null
+++ b/chrome/browser/ui/ash/media_client.h
@@ -0,0 +1,47 @@
+// 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 CHROME_BROWSER_UI_ASH_MEDIA_CLIENT_H_
+#define CHROME_BROWSER_UI_ASH_MEDIA_CLIENT_H_
+
+#include "ash/public/interfaces/media.mojom.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
+
+class MediaClient : public ash::mojom::MediaClient,
+                    MediaCaptureDevicesDispatcher::Observer {
+ public:
+  MediaClient();
+  ~MediaClient() override;
+
+  // ash::MediaClient:
+  void HandleMediaNextTrack() override;
+  void HandleMediaPlayPause() override;
+  void HandleMediaPrevTrack() override;
+  void RequestCaptureState() override;
+
+  // MediaCaptureDevicesDispatcher::Observer:
+  void OnRequestUpdate(int render_process_id,
+                       int render_frame_id,
+                       content::MediaStreamType stream_type,
+                       const content::MediaRequestState state) override;
+
+ private:
+  // Returns the media capture state for the current user at
+  // |user_index|. (Note that this isn't stable, see implementation comment on
+  // RequestCaptureState()).
+  ash::mojom::MediaCaptureState GetMediaCaptureStateByIndex(int user_index);
+
+  ash::mojom::MediaControllerPtr media_controller_;
+
+  mojo::AssociatedBinding<ash::mojom::MediaClient> binding_;
+
+  base::WeakPtrFactory<MediaClient> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(MediaClient);
+};
+
+#endif  // CHROME_BROWSER_UI_ASH_MEDIA_CLIENT_H_
diff --git a/chrome/browser/ui/ash/media_delegate_chromeos.cc b/chrome/browser/ui/ash/media_delegate_chromeos.cc
deleted file mode 100644
index eb98064c..0000000
--- a/chrome/browser/ui/ash/media_delegate_chromeos.cc
+++ /dev/null
@@ -1,169 +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.
-
-#include "chrome/browser/ui/ash/media_delegate_chromeos.h"
-
-#include "ash/common/system/tray/system_tray_notifier.h"
-#include "ash/common/wm_shell.h"
-#include "ash/content/shell_content_state.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "chrome/browser/chromeos/extensions/media_player_api.h"
-#include "chrome/browser/chromeos/extensions/media_player_event_router.h"
-#include "chrome/browser/media/webrtc/media_stream_capture_indicator.h"
-#include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_list.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/web_contents.h"
-#include "extensions/browser/app_window/app_window.h"
-#include "extensions/browser/app_window/app_window_registry.h"
-#include "extensions/browser/process_manager.h"
-
-namespace {
-
-void GetMediaCaptureState(
-    const MediaStreamCaptureIndicator* indicator,
-    content::WebContents* web_contents,
-    int* media_state_out) {
-  if (indicator->IsCapturingVideo(web_contents))
-    *media_state_out |= ash::MEDIA_CAPTURE_VIDEO;
-  if (indicator->IsCapturingAudio(web_contents))
-    *media_state_out |= ash::MEDIA_CAPTURE_AUDIO;
-}
-
-void GetBrowserMediaCaptureState(
-    const MediaStreamCaptureIndicator* indicator,
-    const content::BrowserContext* context,
-    int* media_state_out) {
-  const BrowserList* desktop_list = BrowserList::GetInstance();
-
-  for (BrowserList::BrowserVector::const_iterator iter = desktop_list->begin();
-       iter != desktop_list->end();
-       ++iter) {
-    TabStripModel* tab_strip_model = (*iter)->tab_strip_model();
-    for (int i = 0; i < tab_strip_model->count(); ++i) {
-      content::WebContents* web_contents = tab_strip_model->GetWebContentsAt(i);
-      if (web_contents->GetBrowserContext() != context)
-        continue;
-      GetMediaCaptureState(indicator, web_contents, media_state_out);
-      if (*media_state_out == ash::MEDIA_CAPTURE_AUDIO_VIDEO)
-        return;
-    }
-  }
-}
-
-void GetAppMediaCaptureState(
-    const MediaStreamCaptureIndicator* indicator,
-    content::BrowserContext* context,
-    int* media_state_out) {
-  const extensions::AppWindowRegistry::AppWindowList& apps =
-      extensions::AppWindowRegistry::Get(context)->app_windows();
-  for (extensions::AppWindowRegistry::AppWindowList::const_iterator iter =
-           apps.begin();
-       iter != apps.end();
-       ++iter) {
-    GetMediaCaptureState(indicator, (*iter)->web_contents(), media_state_out);
-    if (*media_state_out == ash::MEDIA_CAPTURE_AUDIO_VIDEO)
-      return;
-  }
-}
-
-void GetExtensionMediaCaptureState(
-    const MediaStreamCaptureIndicator* indicator,
-    content::BrowserContext* context,
-    int* media_state_out) {
-  for (content::RenderFrameHost* host :
-           extensions::ProcessManager::Get(context)->GetAllFrames()) {
-    content::WebContents* web_contents =
-        content::WebContents::FromRenderFrameHost(host);
-    // RFH may not have web contents.
-    if (!web_contents)
-      continue;
-    GetMediaCaptureState(indicator, web_contents, media_state_out);
-    if (*media_state_out == ash::MEDIA_CAPTURE_AUDIO_VIDEO)
-      return;
-  }
-}
-
-ash::MediaCaptureState GetMediaCaptureStateOfAllWebContents(
-    content::BrowserContext* context) {
-  if (!context)
-    return ash::MEDIA_CAPTURE_NONE;
-
-  scoped_refptr<MediaStreamCaptureIndicator> indicator =
-      MediaCaptureDevicesDispatcher::GetInstance()
-          ->GetMediaStreamCaptureIndicator();
-
-  int media_state = ash::MEDIA_CAPTURE_NONE;
-  // Browser windows
-  GetBrowserMediaCaptureState(indicator.get(), context, &media_state);
-  if (media_state == ash::MEDIA_CAPTURE_AUDIO_VIDEO)
-    return ash::MEDIA_CAPTURE_AUDIO_VIDEO;
-
-  // App windows
-  GetAppMediaCaptureState(indicator.get(), context, &media_state);
-  if (media_state == ash::MEDIA_CAPTURE_AUDIO_VIDEO)
-    return ash::MEDIA_CAPTURE_AUDIO_VIDEO;
-
-  // Extensions
-  GetExtensionMediaCaptureState(indicator.get(), context, &media_state);
-
-  return static_cast<ash::MediaCaptureState>(media_state);
-}
-
-}  // namespace
-
-MediaDelegateChromeOS::MediaDelegateChromeOS() : weak_ptr_factory_(this) {
-  MediaCaptureDevicesDispatcher::GetInstance()->AddObserver(this);
-}
-
-MediaDelegateChromeOS::~MediaDelegateChromeOS() {
-  MediaCaptureDevicesDispatcher::GetInstance()->RemoveObserver(this);
-}
-
-void MediaDelegateChromeOS::HandleMediaNextTrack() {
-  extensions::MediaPlayerAPI::Get(ProfileManager::GetActiveUserProfile())
-      ->media_player_event_router()
-      ->NotifyNextTrack();
-}
-
-void MediaDelegateChromeOS::HandleMediaPlayPause() {
-  extensions::MediaPlayerAPI::Get(ProfileManager::GetActiveUserProfile())
-      ->media_player_event_router()
-      ->NotifyTogglePlayState();
-}
-
-void MediaDelegateChromeOS::HandleMediaPrevTrack() {
-  extensions::MediaPlayerAPI::Get(ProfileManager::GetActiveUserProfile())
-      ->media_player_event_router()
-      ->NotifyPrevTrack();
-}
-
-ash::MediaCaptureState MediaDelegateChromeOS::GetMediaCaptureState(
-    ash::UserIndex index) {
-  content::BrowserContext* context =
-      ash::ShellContentState::GetInstance()->GetBrowserContextByIndex(index);
-  return GetMediaCaptureStateOfAllWebContents(context);
-}
-
-void MediaDelegateChromeOS::OnRequestUpdate(
-    int render_process_id,
-    int render_frame_id,
-    content::MediaStreamType stream_type,
-    const content::MediaRequestState state) {
-  DCHECK(base::MessageLoopForUI::IsCurrent());
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::Bind(&MediaDelegateChromeOS::NotifyMediaCaptureChange,
-                            weak_ptr_factory_.GetWeakPtr()));
-}
-
-void MediaDelegateChromeOS::NotifyMediaCaptureChange() {
-  ash::WmShell::Get()->system_tray_notifier()->NotifyMediaCaptureChanged();
-}
diff --git a/chrome/browser/ui/ash/media_delegate_chromeos.h b/chrome/browser/ui/ash/media_delegate_chromeos.h
deleted file mode 100644
index 32b04a1..0000000
--- a/chrome/browser/ui/ash/media_delegate_chromeos.h
+++ /dev/null
@@ -1,39 +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 CHROME_BROWSER_UI_ASH_MEDIA_DELEGATE_CHROMEOS_H_
-#define CHROME_BROWSER_UI_ASH_MEDIA_DELEGATE_CHROMEOS_H_
-
-#include "ash/common/media_delegate.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
-
-class MediaDelegateChromeOS : public ash::MediaDelegate,
-                              MediaCaptureDevicesDispatcher::Observer {
- public:
-  MediaDelegateChromeOS();
-  ~MediaDelegateChromeOS() override;
-
-  // ash::MediaDelegate:
-  void HandleMediaNextTrack() override;
-  void HandleMediaPlayPause() override;
-  void HandleMediaPrevTrack() override;
-  ash::MediaCaptureState GetMediaCaptureState(ash::UserIndex index) override;
-
-  // MediaCaptureDevicesDispatcher::Observer:
-  void OnRequestUpdate(int render_process_id,
-                       int render_frame_id,
-                       content::MediaStreamType stream_type,
-                       const content::MediaRequestState state) override;
-
- private:
-  void NotifyMediaCaptureChange();
-
-  base::WeakPtrFactory<MediaDelegateChromeOS> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(MediaDelegateChromeOS);
-};
-
-#endif  // CHROME_BROWSER_UI_ASH_MEDIA_DELEGATE_CHROMEOS_H_
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc
index 48e2e5c..099b47f3 100644
--- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc
+++ b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc
@@ -5,9 +5,9 @@
 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h"
 
 #include "ash/aura/wm_window_aura.h"
+#include "ash/common/media_controller.h"
 #include "ash/common/multi_profile_uma.h"
 #include "ash/common/session/session_state_delegate.h"
-#include "ash/common/system/tray/system_tray_notifier.h"
 #include "ash/common/wm/maximize_mode/maximize_mode_controller.h"
 #include "ash/common/wm/window_state.h"
 #include "ash/common/wm_shell.h"
@@ -445,7 +445,7 @@
       this, account_id, GetAdjustedAnimationTimeInMS(kUserFadeTimeMS)));
   // Call notifier here instead of observing ActiveUserChanged because
   // this must happen after MultiUserWindowManagerChromeOS is notified.
-  ash::WmShell::Get()->system_tray_notifier()->NotifyMediaCaptureChanged();
+  ash::WmShell::Get()->media_controller()->RequestCaptureState();
 }
 
 void MultiUserWindowManagerChromeOS::OnWindowDestroyed(aura::Window* window) {
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
index bcdcaf6f..169aac1 100644
--- a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
+++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
@@ -70,7 +70,7 @@
                                                    container_view,
                                                    web_contents)),
       view_(NULL),
-      layout_model_(this),
+      layout_model_(this, delegate->IsCreditCardPopup()),
       delegate_(delegate),
       weak_ptr_factory_(this) {
   ClearState();
diff --git a/chrome/browser/ui/autofill/autofill_popup_layout_model.cc b/chrome/browser/ui/autofill/autofill_popup_layout_model.cc
index 5364cb6..c93e702 100644
--- a/chrome/browser/ui/autofill/autofill_popup_layout_model.cc
+++ b/chrome/browser/ui/autofill/autofill_popup_layout_model.cc
@@ -10,10 +10,12 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ui/autofill/autofill_popup_view.h"
 #include "chrome/browser/ui/autofill/popup_constants.h"
+#include "components/autofill/core/browser/autofill_experiments.h"
 #include "components/autofill/core/browser/popup_item_ids.h"
 #include "components/autofill/core/browser/suggestion.h"
 #include "components/autofill/core/common/autofill_util.h"
 #include "components/grit/components_scaled_resources.h"
+#include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/color_utils.h"
@@ -70,8 +72,8 @@
 }  // namespace
 
 AutofillPopupLayoutModel::AutofillPopupLayoutModel(
-    AutofillPopupViewDelegate* delegate)
-    : delegate_(delegate) {
+    AutofillPopupViewDelegate* delegate, bool is_credit_card_popup)
+    : delegate_(delegate), is_credit_card_popup_(is_credit_card_popup) {
 #if !defined(OS_ANDROID)
   smaller_font_list_ =
       normal_font_list_.DeriveWithSizeDelta(kSmallerFontSizeDelta);
@@ -282,4 +284,28 @@
   return gfx::ToEnclosingRect(delegate_->element_bounds());
 }
 
+bool AutofillPopupLayoutModel::IsPopupLayoutExperimentEnabled() const {
+  return is_credit_card_popup_ &&
+      IsAutofillCreditCardPopupLayoutExperimentEnabled();
+}
+
+SkColor AutofillPopupLayoutModel::GetBackgroundColor() const {
+  return is_credit_card_popup_ ?
+      GetCreditCardPopupBackgroundColor() : SK_ColorTRANSPARENT;
+}
+
+SkColor AutofillPopupLayoutModel::GetDividerColor() const {
+  return is_credit_card_popup_ ?
+      GetCreditCardPopupDividerColor() : SK_ColorTRANSPARENT;
+}
+
+unsigned int AutofillPopupLayoutModel::GetDropdownItemHeight() const {
+  return GetPopupDropdownItemHeight();
+}
+
+bool AutofillPopupLayoutModel::IsIconAtStart(int frontend_id) const {
+  return frontend_id == POPUP_ITEM_ID_HTTP_NOT_SECURE_WARNING_MESSAGE ||
+      (is_credit_card_popup_ && IsIconInCreditCardPopupAtStart());
+}
+
 }  // namespace autofill
diff --git a/chrome/browser/ui/autofill/autofill_popup_layout_model.h b/chrome/browser/ui/autofill/autofill_popup_layout_model.h
index b3a2c73..6e31077 100644
--- a/chrome/browser/ui/autofill/autofill_popup_layout_model.h
+++ b/chrome/browser/ui/autofill/autofill_popup_layout_model.h
@@ -25,7 +25,9 @@
 // TODO(mathp): investigate moving ownership of this class to the view.
 class AutofillPopupLayoutModel {
  public:
-  explicit AutofillPopupLayoutModel(AutofillPopupViewDelegate* delegate);
+  AutofillPopupLayoutModel(AutofillPopupViewDelegate* delegate,
+                           bool is_credit_card_popup);
+
   ~AutofillPopupLayoutModel();
 
   // The minimum amount of padding between the Autofill name and subtext,
@@ -92,6 +94,27 @@
   // resource isn't recognized.
   int GetIconResourceID(const base::string16& resource_name) const;
 
+  // Returns whether |GetBackgroundColor, GetDividerColor| returns a custom
+  // color configured in an experiment to tweak autofill popup layout.
+  bool IsPopupLayoutExperimentEnabled() const;
+
+  // Returns the background color for the autofill popup, or
+  // |SK_ColorTRANSPARENT| if not in an experiment to tweak autofill popup
+  // layout.
+  SkColor GetBackgroundColor() const;
+
+  // Returns the divider color for the autofill popup, or
+  // |SK_ColorTRANSPARENT| if not in an experiment to tweak autofill popup
+  // layout.
+  SkColor GetDividerColor() const;
+
+  // Returns the dropdown item height, or 0 if the dropdown item height isn't
+  // configured in an experiment to tweak autofill popup layout.
+  unsigned int GetDropdownItemHeight() const;
+
+  // Returns true if suggestion icon must be displayed before suggestion text.
+  bool IsIconAtStart(int frontend_id) const;
+
  private:
   // Returns the enclosing rectangle for the element_bounds.
   const gfx::Rect RoundedElementBounds() const;
@@ -116,6 +139,8 @@
 
   AutofillPopupViewDelegate* delegate_;  // Weak reference.
 
+  const bool is_credit_card_popup_;
+
   DISALLOW_COPY_AND_ASSIGN(AutofillPopupLayoutModel);
 };
 
diff --git a/chrome/browser/ui/autofill/autofill_popup_layout_model_unittest.cc b/chrome/browser/ui/autofill/autofill_popup_layout_model_unittest.cc
index 47b408a7..920a88a 100644
--- a/chrome/browser/ui/autofill/autofill_popup_layout_model_unittest.cc
+++ b/chrome/browser/ui/autofill/autofill_popup_layout_model_unittest.cc
@@ -74,7 +74,8 @@
     ChromeRenderViewHostTestHarness::SetUp();
 
     delegate_.reset(new TestAutofillPopupViewDelegate(web_contents()));
-    layout_model_.reset(new AutofillPopupLayoutModel(delegate_.get()));
+    layout_model_.reset(new AutofillPopupLayoutModel(
+        delegate_.get(), false /* is_credit_card_field */));
   }
 
   AutofillPopupLayoutModel* layout_model() { return layout_model_.get(); }
diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc
index 077e483..285a3828 100644
--- a/chrome/browser/ui/browser_commands.cc
+++ b/chrome/browser/ui/browser_commands.cc
@@ -87,6 +87,7 @@
 #include "extensions/features/features.h"
 #include "net/base/escape.h"
 #include "printing/features/features.h"
+#include "rlz/features/features.h"
 #include "ui/events/keycodes/keyboard_codes.h"
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
@@ -110,7 +111,7 @@
 #endif  // BUILDFLAG(ENABLE_PRINT_PREVIEW)
 #endif  // BUILDFLAG(ENABLE_PRINTING)
 
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
 #include "components/rlz/rlz_tracker.h"  // nogncheck
 #endif
 
@@ -473,7 +474,7 @@
   content::RecordAction(UserMetricsAction("Home"));
 
   std::string extra_headers;
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
   // If the home page is a Google home page, add the RLZ header to the request.
   PrefService* pref_service = browser->profile()->GetPrefs();
   if (pref_service) {
@@ -483,7 +484,7 @@
           rlz::RLZTracker::ChromeHomePage());
     }
   }
-#endif  // defined(ENABLE_RLZ)
+#endif  // BUILDFLAG(ENABLE_RLZ)
 
   GURL url = browser->profile()->GetHomePage();
 
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h
index e390147..5f4fe0b 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h
@@ -294,10 +294,10 @@
   base::scoped_nsobject<BookmarkContextMenuCocoaController>
       contextMenuController_;
 
-  // Weak pointer to the pulsed button for the currently pulsing node. We need
-  // to store this as it may not be possible to determine the pulsing button if
-  // the pulsing node is deleted. Nil if there is no pulsing node.
-  BookmarkButton* pulsingButton_;
+  // The pulsed button for the currently pulsing node. We need to store this as
+  // it may not be possible to determine the pulsing button if the pulsing node
+  // is deleted. Nil if there is no pulsing node.
+  base::scoped_nsobject<BookmarkButton> pulsingButton_;
 
   // Specifically watch the currently pulsing node. This lets us stop pulsing
   // when anything happens to the node. Null if there is no pulsing node.
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm
index 51c7bce..d3b2c4f1 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm
@@ -361,7 +361,8 @@
 - (void)startPulsingBookmarkNode:(const BookmarkNode*)node {
   [self stopPulsingBookmarkNode];
 
-  pulsingButton_ = [self bookmarkButtonToPulseForNode:node];
+  pulsingButton_.reset([self bookmarkButtonToPulseForNode:node],
+                       base::scoped_policy::RETAIN);
   if (!pulsingButton_)
     return;
 
@@ -379,7 +380,7 @@
     return;
 
   [pulsingButton_ setPulseIsStuckOn:NO];
-  pulsingButton_ = nil;
+  pulsingButton_.reset();
   pulsingBookmarkObserver_.reset();
 }
 
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller_unittest.mm
index c0056eb..a182b0f 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller_unittest.mm
@@ -1568,6 +1568,46 @@
   EXPECT_TRUE([view isHidden]);
 }
 
+// Simulate coarse browser window width change and ensure that the bookmark
+// buttons that should be visible are visible.
+TEST_F(BookmarkBarControllerTest, RedistributeButtonsOnBarAsNeeded) {
+  // Hide the apps shortcut.
+  profile()->GetPrefs()->SetBoolean(
+      bookmarks::prefs::kShowAppsShortcutInBookmarkBar, false);
+  ASSERT_TRUE([bar_ appsPageShortcutButtonIsHidden]);
+
+  // Add three buttons to the bookmark bar.
+  BookmarkModel* model = BookmarkModelFactory::GetForBrowserContext(profile());
+  const BookmarkNode* root = model->bookmark_bar_node();
+  // Make long labels to test coarse resizes. After 16 digits, text eliding
+  // starts.
+  const std::string model_string(
+      "0000000000000000 1111111111111111 2222222222222222 ");
+  bookmarks::test::AddNodesFromModelString(model, root, model_string);
+  NSRect frame = [[bar_ view] frame];
+  frame.size.width = 400;  // Typical minimum browser size.
+  [[bar_ view] setFrame:frame];
+  EXPECT_EQ(2, [bar_ displayedButtonCount]);
+
+  {
+    base::mac::ScopedNSAutoreleasePool pool;
+    frame.size.width = 800;
+    [[bar_ view] setFrame:frame];
+    EXPECT_EQ(3, [bar_ displayedButtonCount]);
+
+    const BookmarkNode* last = model->bookmark_bar_node()->GetChild(2);
+    EXPECT_TRUE(last);
+    [bar_ startPulsingBookmarkNode:last];
+
+    frame.size.width = 400;
+    [[bar_ view] setFrame:frame];
+    EXPECT_EQ(2, [bar_ displayedButtonCount]);
+  }
+
+  // Regression test for http://crbug.com/616051.
+  [bar_ stopPulsingBookmarkNode];
+}
+
 // Simiulate browser window width change and ensure that the bookmark buttons
 // that should be visible are visible.
 // Appears to fail on Mac 10.11 bot on the waterfall; http://crbug.com/612640.
diff --git a/chrome/browser/ui/cocoa/profiles/avatar_base_controller.h b/chrome/browser/ui/cocoa/profiles/avatar_base_controller.h
index 05e33de..30bb569 100644
--- a/chrome/browser/ui/cocoa/profiles/avatar_base_controller.h
+++ b/chrome/browser/ui/cocoa/profiles/avatar_base_controller.h
@@ -35,7 +35,6 @@
   // as AvatarButtonErrorController.
   std::unique_ptr<ProfileUpdateObserver> profileObserver_;
 
- @private
   // The menu controller, if the menu is open.
   BaseBubbleController* menuController_;
 }
@@ -59,8 +58,6 @@
 
 @interface AvatarBaseController (ExposedForTesting)
 - (BaseBubbleController*)menuController;
-
-- (BOOL)isCtrlPressed;
 @end
 
 class ProfileUpdateObserver : public ProfileAttributesStorage::Observer,
diff --git a/chrome/browser/ui/cocoa/profiles/avatar_base_controller.mm b/chrome/browser/ui/cocoa/profiles/avatar_base_controller.mm
index fde4c663..a3e0d5a1 100644
--- a/chrome/browser/ui/cocoa/profiles/avatar_base_controller.mm
+++ b/chrome/browser/ui/cocoa/profiles/avatar_base_controller.mm
@@ -171,13 +171,6 @@
   profiles::TutorialMode tutorialMode;
   profiles::BubbleViewModeFromAvatarBubbleMode(
       mode, &viewMode, &tutorialMode);
-  // Don't start creating the view if it would be an empty fast user switcher.
-  // It has to happen here to prevent the view system from creating an empty
-  // container.
-  if (viewMode == profiles::BUBBLE_VIEW_MODE_FAST_PROFILE_CHOOSER &&
-      !profiles::HasProfileSwitchTargets(browser_->profile())) {
-    return;
-  }
 
   menuController_ =
       [[ProfileChooserController alloc] initWithBrowser:browser_
@@ -197,29 +190,9 @@
   ProfileMetrics::LogProfileOpenMethod(ProfileMetrics::ICON_AVATAR_BUBBLE);
 }
 
-- (BOOL)isCtrlPressed {
-  return [NSEvent modifierFlags] & NSControlKeyMask ? YES : NO;
-}
-
 - (IBAction)buttonClicked:(id)sender {
-  BrowserWindow::AvatarBubbleMode mode =
-      BrowserWindow::AVATAR_BUBBLE_MODE_DEFAULT;
-  if ([self isCtrlPressed])
-    mode = BrowserWindow::AVATAR_BUBBLE_MODE_FAST_USER_SWITCH;
-
   [self showAvatarBubbleAnchoredAt:button_
-                          withMode:mode
-                   withServiceType:signin::GAIA_SERVICE_TYPE_NONE
-                   fromAccessPoint:signin_metrics::AccessPoint::
-                                       ACCESS_POINT_AVATAR_BUBBLE_SIGN_IN];
-}
-
-- (IBAction)buttonRightClicked:(id)sender {
-  BrowserWindow::AvatarBubbleMode mode =
-      BrowserWindow::AVATAR_BUBBLE_MODE_FAST_USER_SWITCH;
-
-  [self showAvatarBubbleAnchoredAt:button_
-                          withMode:mode
+                          withMode:BrowserWindow::AVATAR_BUBBLE_MODE_DEFAULT
                    withServiceType:signin::GAIA_SERVICE_TYPE_NONE
                    fromAccessPoint:signin_metrics::AccessPoint::
                                        ACCESS_POINT_AVATAR_BUBBLE_SIGN_IN];
diff --git a/chrome/browser/ui/cocoa/profiles/avatar_button_controller.mm b/chrome/browser/ui/cocoa/profiles/avatar_button_controller.mm
index 13e7fab..7bc7e0d 100644
--- a/chrome/browser/ui/cocoa/profiles/avatar_button_controller.mm
+++ b/chrome/browser/ui/cocoa/profiles/avatar_button_controller.mm
@@ -185,7 +185,7 @@
       [avatarButton setAutoresizingMask:NSViewMinXMargin | NSViewMinYMargin];
     [avatarButton setTarget:self];
     [avatarButton setAction:@selector(buttonClicked:)];
-    [avatarButton setRightAction:@selector(buttonRightClicked:)];
+    [avatarButton setRightAction:@selector(buttonClicked:)];
 
     // Check if the account already has an authentication or sync error and
     // initialize the avatar button UI.
@@ -298,12 +298,13 @@
                           withMode:(BrowserWindow::AvatarBubbleMode)mode
                    withServiceType:(signin::GAIAServiceType)serviceType
                    fromAccessPoint:(signin_metrics::AccessPoint)accessPoint {
-  AvatarButton* button = base::mac::ObjCCastStrict<AvatarButton>(button_);
-  [button setIsActive:YES];
   [super showAvatarBubbleAnchoredAt:anchor
                            withMode:mode
                     withServiceType:serviceType
                     fromAccessPoint:accessPoint];
+
+  AvatarButton* button = base::mac::ObjCCastStrict<AvatarButton>(button_);
+  [button setIsActive:[[menuController_ window] isVisible]];
 }
 
 - (void)bubbleWillClose:(NSNotification*)notif {
diff --git a/chrome/browser/ui/cocoa/profiles/avatar_button_controller_unittest.mm b/chrome/browser/ui/cocoa/profiles/avatar_button_controller_unittest.mm
index 015cfbd5..8e7d6d3 100644
--- a/chrome/browser/ui/cocoa/profiles/avatar_button_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/profiles/avatar_button_controller_unittest.mm
@@ -29,31 +29,6 @@
 - (void)setErrorStatus:(BOOL)hasError;
 @end
 
-// Subclassing AvatarButtonController to be able to control the state of
-// keyboard modifierFlags.
-@interface AvatarButtonControllerForTesting : AvatarButtonController {
- @private
-  bool isCtrlPressed_;
-}
-@end
-
-@interface AvatarButtonControllerForTesting (ExposedForTesting)
-- (void)setIsCtrlPressed:(BOOL)isPressed;
-- (BOOL)isCtrlPressed;
-@end
-
-@implementation AvatarButtonControllerForTesting
-- (void)setIsCtrlPressed:(BOOL)isPressed {
-  isCtrlPressed_ = isPressed;
-}
-
-- (BOOL)isCtrlPressed {
- // Always report that Cmd is not pressed since that's the case we're testing
- // and otherwise running the test while holding the Cmd key makes it fail.
- return isCtrlPressed_;
-}
-@end
-
 class AvatarButtonControllerTest : public CocoaProfileTest {
  public:
   void SetUp() override {
@@ -63,8 +38,7 @@
     ASSERT_TRUE(browser());
 
     controller_.reset(
-        [[AvatarButtonControllerForTesting alloc] initWithBrowser:browser()]);
-    [controller_ setIsCtrlPressed:false];
+        [[AvatarButtonController alloc] initWithBrowser:browser()]);
   }
 
   void TearDown() override {
@@ -76,10 +50,10 @@
 
   NSView* view() { return [controller_ view]; }
 
-  AvatarButtonControllerForTesting* controller() { return controller_.get(); }
+  AvatarButtonController* controller() { return controller_.get(); }
 
  private:
-  base::scoped_nsobject<AvatarButtonControllerForTesting> controller_;
+  base::scoped_nsobject<AvatarButtonController> controller_;
 };
 
 TEST_F(AvatarButtonControllerTest, GenericButtonShown) {
@@ -130,32 +104,3 @@
   [menu close];
   EXPECT_FALSE([controller() menuController]);
 }
-
-TEST_F(AvatarButtonControllerTest, DontOpenFastSwitcherWithoutTarget) {
-  EXPECT_FALSE([controller() menuController]);
-
-  [controller() setIsCtrlPressed:YES];
-  [button() performClick:button()];
-
-  // If there's only one profile and the fast user switcher is requested,
-  // nothing should happen.
-  EXPECT_FALSE([controller() menuController]);
-}
-
-TEST_F(AvatarButtonControllerTest, OpenFastUserSwitcherWithTarget) {
-  testing_profile_manager()->CreateTestingProfile("batman");
-  EXPECT_FALSE([controller() menuController]);
-
-  [controller() setIsCtrlPressed:YES];
-  [button() performClick:button()];
-
-  BaseBubbleController* menu = [controller() menuController];
-  EXPECT_TRUE(menu);
-  EXPECT_TRUE([menu isKindOfClass:[ProfileChooserController class]]);
-
-  // Do not animate out because that is hard to test around.
-  static_cast<InfoBubbleWindow*>(menu.window).allowedAnimations =
-      info_bubble::kAnimateNone;
-  [menu close];
-  EXPECT_FALSE([controller() menuController]);
-}
diff --git a/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.h b/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.h
index 7f125c7..0413e5f 100644
--- a/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.h
+++ b/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.h
@@ -36,15 +36,13 @@
   // The list of identities offered to the user.
   base::ScopedCFTypeRef<CFMutableArrayRef> identities_;
   // The corresponding list of certificates.
-  std::vector<scoped_refptr<net::X509Certificate> > certificates_;
+  std::vector<scoped_refptr<net::X509Certificate>> certificates_;
   // A C++ object to bridge SSLClientAuthObserver notifications to us.
   std::unique_ptr<SSLClientAuthObserverCocoaBridge> observer_;
   base::scoped_nsobject<SFChooseIdentityPanel> panel_;
   std::unique_ptr<ConstrainedWindowMac> constrainedWindow_;
   base::scoped_nsobject<NSWindow> overlayWindow_;
   BOOL closePending_;
-  // A copy of the sheet's frame used to restore on show.
-  NSRect oldSheetFrame_;
   // A copy of the sheet's |autoresizesSubviews| flag to restore on show.
   BOOL oldResizesSubviews_;
   // True if the user dismissed the dialog directly, either via the OK (continue
diff --git a/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.mm b/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.mm
index 2400ec2..aa06b2d 100644
--- a/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.mm
+++ b/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.mm
@@ -282,25 +282,17 @@
 - (void)hideSheet {
   NSWindow* sheetWindow = [overlayWindow_ attachedSheet];
   [sheetWindow setAlphaValue:0.0];
+  [sheetWindow setIgnoresMouseEvents:YES];
 
   oldResizesSubviews_ = [[sheetWindow contentView] autoresizesSubviews];
   [[sheetWindow contentView] setAutoresizesSubviews:NO];
-
-  oldSheetFrame_ = [sheetWindow frame];
-  NSRect overlayFrame = [overlayWindow_ frame];
-  oldSheetFrame_.origin.x -= NSMinX(overlayFrame);
-  oldSheetFrame_.origin.y -= NSMinY(overlayFrame);
-  [sheetWindow setFrame:ui::kWindowSizeDeterminedLater display:NO];
 }
 
 - (void)unhideSheet {
   NSWindow* sheetWindow = [overlayWindow_ attachedSheet];
-  NSRect overlayFrame = [overlayWindow_ frame];
-  oldSheetFrame_.origin.x += NSMinX(overlayFrame);
-  oldSheetFrame_.origin.y += NSMinY(overlayFrame);
-  [sheetWindow setFrame:oldSheetFrame_ display:NO];
   [[sheetWindow contentView] setAutoresizesSubviews:oldResizesSubviews_];
-  [[overlayWindow_ attachedSheet] setAlphaValue:1.0];
+  [sheetWindow setAlphaValue:1.0];
+  [sheetWindow setIgnoresMouseEvents:NO];
 }
 
 - (void)pulseSheet {
diff --git a/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa_browsertest.mm b/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa_browsertest.mm
index 09bb431a..bd18903 100644
--- a/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa_browsertest.mm
+++ b/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa_browsertest.mm
@@ -105,16 +105,17 @@
   content::RunAllPendingInMessageLoop();
 
   NSWindow* sheetWindow = [[selector overlayWindow] attachedSheet];
-  NSRect sheetFrame = [sheetWindow frame];
   EXPECT_EQ(1.0, [sheetWindow alphaValue]);
 
-  // Switch to another tab and verify that the sheet is hidden.
+  // Switch to another tab and verify that the sheet is hidden. Interaction with
+  // the tab underneath should not be blocked.
   AddBlankTabAndShow(browser());
   EXPECT_EQ(0.0, [sheetWindow alphaValue]);
-  EXPECT_NSEQ(ui::kWindowSizeDeterminedLater, [sheetWindow frame]);
+  EXPECT_TRUE([[selector overlayWindow] ignoresMouseEvents]);
 
-  // Switch back and verify that the sheet is shown.
+  // Switch back and verify that the sheet is shown. Interaction with the tab
+  // underneath should be blocked while the sheet is showing.
   chrome::SelectNumberedTab(browser(), 0);
   EXPECT_EQ(1.0, [sheetWindow alphaValue]);
-  EXPECT_NSEQ(sheetFrame, [sheetWindow frame]);
+  EXPECT_FALSE([[selector overlayWindow] ignoresMouseEvents]);
 }
diff --git a/chrome/browser/ui/cocoa/website_settings/website_settings_bubble_controller.h b/chrome/browser/ui/cocoa/website_settings/website_settings_bubble_controller.h
index 10bfdff..f59a72bf 100644
--- a/chrome/browser/ui/cocoa/website_settings/website_settings_bubble_controller.h
+++ b/chrome/browser/ui/cocoa/website_settings/website_settings_bubble_controller.h
@@ -8,7 +8,7 @@
 
 #include "base/mac/scoped_nsobject.h"
 #include "base/macros.h"
-#import "chrome/browser/ui/cocoa/base_bubble_controller.h"
+#import "chrome/browser/ui/cocoa/omnibox_decoration_bubble_controller.h"
 #include "chrome/browser/ui/website_settings/website_settings_ui.h"
 #include "content/public/browser/web_contents_observer.h"
 
@@ -31,7 +31,7 @@
 //
 // TODO(palmer): Normalize all WebsiteSettings*, SiteSettings*, PageInfo*, et c.
 // to OriginInfo*.
-@interface WebsiteSettingsBubbleController : BaseBubbleController {
+@interface WebsiteSettingsBubbleController : OmniboxDecorationBubbleController {
  @private
   content::WebContents* webContents_;
 
diff --git a/chrome/browser/ui/cocoa/website_settings/website_settings_bubble_controller.mm b/chrome/browser/ui/cocoa/website_settings/website_settings_bubble_controller.mm
index 23152e05..df64d4e3 100644
--- a/chrome/browser/ui/cocoa/website_settings/website_settings_bubble_controller.mm
+++ b/chrome/browser/ui/cocoa/website_settings/website_settings_bubble_controller.mm
@@ -235,6 +235,12 @@
   return self;
 }
 
+- (LocationBarDecoration*)decorationForBubble {
+  BrowserWindowController* controller = [[self parentWindow] windowController];
+  LocationBarViewMac* location_bar = [controller locationBarBridge];
+  return location_bar ? location_bar->GetPageInfoDecoration() : nullptr;
+}
+
 - (Profile*)profile {
   return Profile::FromBrowserContext(webContents_->GetBrowserContext());
 }
diff --git a/chrome/browser/ui/layout_constants.cc b/chrome/browser/ui/layout_constants.cc
index 9611f19..264409f 100644
--- a/chrome/browser/ui/layout_constants.cc
+++ b/chrome/browser/ui/layout_constants.cc
@@ -9,91 +9,47 @@
 #include "ui/base/material_design/material_design_controller.h"
 
 int GetLayoutConstant(LayoutConstant constant) {
-  const int kFindBarVerticalOffset[] = {6, 6};
-  const int kLocationBarBorderThickness[] = {1, 1};
-  const int kLocationBarBubbleFontVerticalPadding[] = {2, 4};
-  const int kLocationBarBubbleVerticalPadding[] = {3, 3};
-  const int kLocationBarBubbleAnchorVerticalInset[] = {6, 8};
-  const int kLocationBarHeight[] = {28, 32};
-  const int kLocationBarHorizontalPadding[] = {6, 6};
-  const int kLocationBarVerticalPadding[] = {1, 1};
-  const int kOmniboxFontPixelSize[] = {14, 14};
-  const int kTabFaviconTitleSpacing[] = {6, 6};
-  const int kTabHeight[] = {29, 33};
-  const int kTabPinnedContentWidth[] = {23, 23};
-  const int kTabstripNewTabButtonOverlap[] = {5, 6};
-  const int kTabstripTabOverlap[] = {16, 16};
-  const int kToolbarStandardSpacing[] = {4, 8};
-  const int kToolbarElementPadding[] = {0, 8};
-  const int kToolbarLocationBarRightPadding[] = {4, 8};
-
-  const int mode = ui::MaterialDesignController::GetMode();
+  const bool hybrid = ui::MaterialDesignController::GetMode() ==
+                      ui::MaterialDesignController::MATERIAL_HYBRID;
   switch (constant) {
-    case AVATAR_ICON_PADDING:
-      return 4;
-    case FIND_BAR_TOOLBAR_OVERLAP:
-      return kFindBarVerticalOffset[mode];
-    case LOCATION_BAR_BORDER_THICKNESS:
-      return kLocationBarBorderThickness[mode];
     case LOCATION_BAR_BUBBLE_FONT_VERTICAL_PADDING:
-      return kLocationBarBubbleFontVerticalPadding[mode];
-    case LOCATION_BAR_BUBBLE_VERTICAL_PADDING:
-      return kLocationBarBubbleVerticalPadding[mode];
+      return hybrid ? 4 : 2;
     case LOCATION_BAR_BUBBLE_ANCHOR_VERTICAL_INSET:
       if (ui::MaterialDesignController::IsSecondaryUiMaterial())
         return 1;
-      return kLocationBarBubbleAnchorVerticalInset[mode];
+      return hybrid ? 8 : 6;
     case LOCATION_BAR_HEIGHT:
-      return kLocationBarHeight[mode];
-    case LOCATION_BAR_HORIZONTAL_PADDING:
-      return kLocationBarHorizontalPadding[mode];
-    case LOCATION_BAR_VERTICAL_PADDING:
-      return kLocationBarVerticalPadding[mode];
-    case OMNIBOX_FONT_PIXEL_SIZE:
-      return kOmniboxFontPixelSize[mode];
+      return hybrid ? 32 : 28;
     case TABSTRIP_NEW_TAB_BUTTON_OVERLAP:
-      return kTabstripNewTabButtonOverlap[mode];
-    case TABSTRIP_TAB_OVERLAP:
-      return kTabstripTabOverlap[mode];
-    case TAB_FAVICON_TITLE_SPACING:
-      return kTabFaviconTitleSpacing[mode];
+      return hybrid ? 6 : 5;
     case TAB_HEIGHT:
-      return kTabHeight[mode];
-    case TAB_PINNED_CONTENT_WIDTH:
-      return kTabPinnedContentWidth[mode];
-    case TOOLBAR_BUTTON_PADDING:
-      return 6;
+      return hybrid ? 33 : 29;
     case TOOLBAR_ELEMENT_PADDING:
-      return kToolbarElementPadding[mode];
-    case TOOLBAR_LOCATION_BAR_RIGHT_PADDING:
-      return kToolbarLocationBarRightPadding[mode];
+      return hybrid ? 8 : 0;
     case TOOLBAR_STANDARD_SPACING:
-      return kToolbarStandardSpacing[mode];
+      return hybrid ? 8 : 4;
   }
   NOTREACHED();
   return 0;
 }
 
 gfx::Insets GetLayoutInsets(LayoutInset inset) {
+  const bool hybrid = ui::MaterialDesignController::GetMode() ==
+                      ui::MaterialDesignController::MATERIAL_HYBRID;
   switch (inset) {
-    case TAB: {
-      const bool hybrid = ui::MaterialDesignController::GetMode() ==
-                          ui::MaterialDesignController::MATERIAL_HYBRID;
+    case TAB:
       return gfx::Insets(1, hybrid ? 18 : 16);
-    }
   }
   NOTREACHED();
   return gfx::Insets();
 }
 
 gfx::Size GetLayoutSize(LayoutSize size) {
-  const int kNewTabButtonWidth[] = {36, 39};
-  const int kNewTabButtonHeight[] = {18, 21};
-
-  const int mode = ui::MaterialDesignController::GetMode();
+  const bool hybrid = ui::MaterialDesignController::GetMode() ==
+                      ui::MaterialDesignController::MATERIAL_HYBRID;
   switch (size) {
     case NEW_TAB_BUTTON:
-      return gfx::Size(kNewTabButtonWidth[mode], kNewTabButtonHeight[mode]);
+      return hybrid ? gfx::Size(39, 21) : gfx::Size(36, 18);
   }
   NOTREACHED();
   return gfx::Size();
diff --git a/chrome/browser/ui/layout_constants.h b/chrome/browser/ui/layout_constants.h
index 9f380c3..b51bdcba 100644
--- a/chrome/browser/ui/layout_constants.h
+++ b/chrome/browser/ui/layout_constants.h
@@ -9,22 +9,10 @@
 #include "ui/gfx/geometry/size.h"
 
 enum LayoutConstant {
-  // The padding on the left, right, and bottom of the avatar icon.
-  AVATAR_ICON_PADDING,
-
-  // Vertical offset from top of content to the top of find bar.
-  FIND_BAR_TOOLBAR_OVERLAP,
-
-  // The thickness of the location bar's border.
-  LOCATION_BAR_BORDER_THICKNESS,
-
   // The vertical padding between the edge of a location bar bubble and its
   // contained text.
   LOCATION_BAR_BUBBLE_FONT_VERTICAL_PADDING,
 
-  // The additional vertical padding of a bubble.
-  LOCATION_BAR_BUBBLE_VERTICAL_PADDING,
-
   // The vertical inset to apply to the bounds of a location bar bubble's anchor
   // view, to bring the bubble closer to the anchor.  This compensates for the
   // space between the bottoms of most such views and the visible bottoms of the
@@ -34,43 +22,17 @@
   // The height to be occupied by the LocationBar.
   LOCATION_BAR_HEIGHT,
 
-  // Space between items in the location bar, as well as between items and the
-  // edges.
-  LOCATION_BAR_HORIZONTAL_PADDING,
-
-  // Space between the location bar edge and contents.
-  LOCATION_BAR_VERTICAL_PADDING,
-
-  // The font size to use in the location bar and omnibox dropdown, in pixels.
-  OMNIBOX_FONT_PIXEL_SIZE,
-
   // The amount of overlap between the last tab and the new tab button.
   TABSTRIP_NEW_TAB_BUTTON_OVERLAP,
 
-  // The amount of overlap between two adjacent tabs.
-  TABSTRIP_TAB_OVERLAP,
-
-  // The horizontal space between a tab's favicon and its title.
-  TAB_FAVICON_TITLE_SPACING,
-
   // The height of a tab, including outer strokes.  In non-100% scales this is
   // slightly larger than the apparent height of the tab, as the top stroke is
   // drawn as a 1-px line flush with the bottom of the tab's topmost DIP.
   TAB_HEIGHT,
 
-  // Width available for content inside a pinned tab.
-  TAB_PINNED_CONTENT_WIDTH,
-
-  // Padding inside toolbar button, between its border and image.
-  TOOLBAR_BUTTON_PADDING,
-
   // Additional horizontal padding between the elements in the toolbar.
   TOOLBAR_ELEMENT_PADDING,
 
-  // Padding between the right edge of the location bar and the left edge of the
-  // app menu icon when the browser actions container is not present.
-  TOOLBAR_LOCATION_BAR_RIGHT_PADDING,
-
   // The horizontal space between most items in the toolbar.
   TOOLBAR_STANDARD_SPACING,
 };
diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl.cc b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
index b088b96..214243e 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_impl.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
@@ -103,6 +103,7 @@
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_set.h"
 #include "net/base/network_change_notifier.h"
+#include "rlz/features/features.h"
 #include "ui/base/l10n/l10n_util.h"
 
 #if defined(OS_MACOSX)
@@ -117,7 +118,7 @@
 #include "chrome/browser/shell_integration_win.h"
 #endif
 
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
 #include "components/rlz/rlz_tracker.h"  // nogncheck
 #endif
 
@@ -471,12 +472,12 @@
                                    : WindowOpenDisposition::NEW_BACKGROUND_TAB;
     params.tabstrip_add_types = add_types;
 
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
     if (process_startup && google_util::IsGoogleHomePageUrl(tabs[i].url)) {
       params.extra_headers = rlz::RLZTracker::GetAccessPointHttpHeader(
           rlz::RLZTracker::ChromeHomePage());
     }
-#endif  // defined(ENABLE_RLZ)
+#endif  // BUILDFLAG(ENABLE_RLZ)
 
     chrome::Navigate(&params);
 
diff --git a/chrome/browser/ui/views/ash/OWNERS b/chrome/browser/ui/views/ash/OWNERS
index f19e7650..6c1a33b 100644
--- a/chrome/browser/ui/views/ash/OWNERS
+++ b/chrome/browser/ui/views/ash/OWNERS
@@ -1,2 +1,4 @@
 derat@chromium.org
 sky@chromium.org
+jamescook@chromium.org
+erg@chromium.org
diff --git a/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.cc b/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.cc
index e75bc96..5bb30c1 100644
--- a/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.cc
+++ b/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.cc
@@ -17,6 +17,7 @@
 #include "chrome/browser/ui/ash/cast_config_client_media_router.h"
 #include "chrome/browser/ui/ash/chrome_new_window_client.h"
 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller_mus.h"
+#include "chrome/browser/ui/ash/media_client.h"
 #include "chrome/browser/ui/views/ash/tab_scrubber.h"
 #include "chrome/browser/ui/views/frame/immersive_context_mus.h"
 #include "chrome/browser/ui/views/frame/immersive_handler_factory_mus.h"
@@ -78,6 +79,7 @@
 
   cast_config_client_media_router_ =
       base::MakeUnique<CastConfigClientMediaRouter>();
+  media_client_ = base::MakeUnique<MediaClient>();
 
   if (!ash::Shell::HasInstance())
     return;
@@ -96,6 +98,7 @@
   volume_controller_.reset();
   new_window_client_.reset();
   system_tray_client_.reset();
+  media_client_.reset();
   cast_config_client_media_router_.reset();
   session_controller_client_.reset();
 #endif
diff --git a/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.h b/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.h
index f3faec7..6d50ed29 100644
--- a/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.h
+++ b/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.h
@@ -15,6 +15,7 @@
 class ChromeNewWindowClient;
 class ImmersiveContextMus;
 class ImmersiveHandlerFactoryMus;
+class MediaClient;
 class SessionControllerClient;
 class SystemTrayClient;
 class VolumeController;
@@ -33,6 +34,7 @@
  private:
   std::unique_ptr<ChromeLauncherControllerMus> chrome_launcher_controller_mus_;
   std::unique_ptr<CastConfigClientMediaRouter> cast_config_client_media_router_;
+  std::unique_ptr<MediaClient> media_client_;
   std::unique_ptr<ImmersiveHandlerFactoryMus> immersive_handler_factory_;
   std::unique_ptr<ImmersiveContextMus> immersive_context_;
   std::unique_ptr<SessionControllerClient> session_controller_client_;
diff --git a/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc b/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc
index f158192..83f63ce 100644
--- a/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc
+++ b/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc
@@ -6,7 +6,7 @@
 
 #include "chrome/browser/ui/views/chrome_constrained_window_views_client.h"
 #include "chrome/browser/ui/views/chrome_views_delegate.h"
-#include "chrome/browser/ui/views/ime_driver_mus.h"
+#include "chrome/browser/ui/views/ime_driver/ime_driver_mus.h"
 #include "components/constrained_window/constrained_window_views.h"
 
 #if defined(USE_AURA)
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
index 9fbced7..c09ae08 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
@@ -17,6 +17,9 @@
 class BrowserNonClientFrameView : public views::NonClientFrameView,
                                   public ProfileAttributesStorage::Observer {
  public:
+  // The padding on the left, right, and bottom of the avatar icon.
+  static constexpr int kAvatarIconPadding = 4;
+
   BrowserNonClientFrameView(BrowserFrame* frame, BrowserView* browser_view);
   ~BrowserNonClientFrameView() override;
 
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
index b137776..6fb936b 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
@@ -408,10 +408,11 @@
 // BrowserNonClientFrameViewAsh, private:
 
 int BrowserNonClientFrameViewAsh::GetTabStripLeftInset() const {
-  const int pad = GetLayoutConstant(AVATAR_ICON_PADDING);
   const int avatar_right =
-      profile_indicator_icon() ? (pad + GetIncognitoAvatarIcon().width()) : 0;
-  return avatar_right + pad;
+      profile_indicator_icon()
+          ? (kAvatarIconPadding + GetIncognitoAvatarIcon().width())
+          : 0;
+  return avatar_right + kAvatarIconPadding;
 }
 
 int BrowserNonClientFrameViewAsh::GetTabStripRightInset() const {
@@ -448,9 +449,9 @@
 #endif
 
   const gfx::ImageSkia incognito_icon = GetIncognitoAvatarIcon();
-  const int pad = GetLayoutConstant(AVATAR_ICON_PADDING);
-  const int avatar_bottom =
-      GetTopInset(false) + browser_view()->GetTabStripHeight() - pad;
+  const int avatar_bottom = GetTopInset(false) +
+                            browser_view()->GetTabStripHeight() -
+                            kAvatarIconPadding;
   int avatar_y = avatar_bottom - incognito_icon.height();
 
   // Hide the incognito icon in immersive fullscreen when the tab light bar is
@@ -458,8 +459,8 @@
   // recognizable.
   const bool avatar_visible = !UseImmersiveLightbarHeaderStyle();
   const int avatar_height = avatar_visible ? (avatar_bottom - avatar_y) : 0;
-  profile_indicator_icon()->SetBounds(pad, avatar_y, incognito_icon.width(),
-                                      avatar_height);
+  profile_indicator_icon()->SetBounds(kAvatarIconPadding, avatar_y,
+                                      incognito_icon.width(), avatar_height);
   profile_indicator_icon()->SetVisible(avatar_visible);
 }
 
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.cc
index 58cf38f8..8c303f6 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.cc
@@ -371,11 +371,12 @@
 }
 
 int BrowserNonClientFrameViewMus::GetTabStripLeftInset() const {
-  const int pad = GetLayoutConstant(AVATAR_ICON_PADDING);
-  const int avatar_right = profile_indicator_icon()
-      ? (pad + GetIncognitoAvatarIcon().width())
-      : 0;
-  return avatar_right + pad + frame_values().normal_insets.left();
+  const int avatar_right =
+      profile_indicator_icon()
+          ? (kAvatarIconPadding + GetIncognitoAvatarIcon().width())
+          : 0;
+  return avatar_right + kAvatarIconPadding +
+         frame_values().normal_insets.left();
 }
 
 int BrowserNonClientFrameViewMus::GetTabStripRightInset() const {
@@ -424,9 +425,8 @@
   DCHECK(browser_view()->IsTabStripVisible());
 #endif
   gfx::ImageSkia incognito_icon = GetIncognitoAvatarIcon();
-  const int pad = GetLayoutConstant(AVATAR_ICON_PADDING);
-  int avatar_bottom =
-      GetTopInset(false) + browser_view()->GetTabStripHeight() - pad;
+  int avatar_bottom = GetTopInset(false) + browser_view()->GetTabStripHeight() -
+                      kAvatarIconPadding;
   int avatar_y = avatar_bottom - incognito_icon.height();
 
   // Hide the incognito icon in immersive fullscreen when the tab light bar is
@@ -435,7 +435,8 @@
   bool avatar_visible = !UseImmersiveLightbarHeaderStyle();
   int avatar_height = avatar_visible ? incognito_icon.height() : 0;
 
-  gfx::Rect avatar_bounds(pad, avatar_y, incognito_icon.width(), avatar_height);
+  gfx::Rect avatar_bounds(kAvatarIconPadding, avatar_y, incognito_icon.width(),
+                          avatar_height);
   profile_indicator_icon()->SetBoundsRect(avatar_bounds);
   profile_indicator_icon()->SetVisible(avatar_visible);
 }
diff --git a/chrome/browser/ui/views/frame/browser_view_layout.cc b/chrome/browser/ui/views/frame/browser_view_layout.cc
index 18c70c1..11214a86 100644
--- a/chrome/browser/ui/views/frame/browser_view_layout.cc
+++ b/chrome/browser/ui/views/frame/browser_view_layout.cc
@@ -12,7 +12,6 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/find_bar/find_bar.h"
 #include "chrome/browser/ui/find_bar/find_bar_controller.h"
-#include "chrome/browser/ui/layout_constants.h"
 #include "chrome/browser/ui/search/search_model.h"
 #include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h"
 #include "chrome/browser/ui/views/download/download_shelf_view.h"
@@ -222,10 +221,8 @@
     find_bar_y = top_container_bounds.bottom();
   } else {
     // Overlap the find bar atop |top_container_|.
-    // The find bar should look connected to the top container when material
-    // design is not enabled.
-    find_bar_y = top_container_bounds.bottom() -
-                 GetLayoutConstant(FIND_BAR_TOOLBAR_OVERLAP);
+    const int kTopOverlap = 6;
+    find_bar_y = top_container_bounds.bottom() - kTopOverlap;
   }
 
   // Grow the height of |bounding_box| by the height of any elements between
diff --git a/chrome/browser/ui/views/frame/browser_view_unittest.cc b/chrome/browser/ui/views/frame/browser_view_unittest.cc
index 470136e0..a12611c 100644
--- a/chrome/browser/ui/views/frame/browser_view_unittest.cc
+++ b/chrome/browser/ui/views/frame/browser_view_unittest.cc
@@ -7,7 +7,6 @@
 #include "base/macros.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/ui/browser_commands.h"
-#include "chrome/browser/ui/layout_constants.h"
 #include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h"
 #include "chrome/browser/ui/views/frame/browser_view_layout.h"
 #include "chrome/browser/ui/views/frame/test_with_browser_view.h"
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
index 0ceb12d4..d78a8b72 100644
--- a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
+++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
@@ -139,8 +139,7 @@
 
 gfx::Rect GlassBrowserFrameView::GetBoundsForTabStrip(
     views::View* tabstrip) const {
-  const int x =
-      incognito_bounds_.right() + GetLayoutConstant(AVATAR_ICON_PADDING);
+  const int x = incognito_bounds_.right() + kAvatarIconPadding;
   int end_x = width() - ClientBorderThickness(false);
   if (!CaptionButtonsOnLeadingEdge()) {
     end_x = std::min(MinimizeButtonX(), end_x) -
@@ -739,7 +738,6 @@
 }
 
 void GlassBrowserFrameView::LayoutIncognitoIcon() {
-  const int pad = GetLayoutConstant(AVATAR_ICON_PADDING);
   const gfx::Size size(GetIncognitoAvatarIcon().size());
   int x = ClientBorderThickness(false);
   // In RTL, the icon needs to start after the caption buttons.
@@ -749,11 +747,12 @@
                                      kProfileSwitcherButtonOffset)
                                   : 0);
   }
-  const int bottom =
-      GetTopInset(false) + browser_view()->GetTabStripHeight() - pad;
+  const int bottom = GetTopInset(false) + browser_view()->GetTabStripHeight() -
+                     kAvatarIconPadding;
   incognito_bounds_.SetRect(
-      x + (profile_indicator_icon() ? pad : 0), bottom - size.height(),
-      profile_indicator_icon() ? size.width() : 0, size.height());
+      x + (profile_indicator_icon() ? kAvatarIconPadding : 0),
+      bottom - size.height(), profile_indicator_icon() ? size.width() : 0,
+      size.height());
   if (profile_indicator_icon())
     profile_indicator_icon()->SetBoundsRect(incognito_bounds_);
 }
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc
index 36ed8cc..398fcf0 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc
@@ -107,7 +107,7 @@
 gfx::Rect OpaqueBrowserFrameViewLayout::GetBoundsForTabStrip(
     const gfx::Size& tabstrip_preferred_size,
     int available_width) const {
-  int x = leading_button_start_ + GetLayoutConstant(AVATAR_ICON_PADDING);
+  int x = leading_button_start_ + OpaqueBrowserFrameView::kAvatarIconPadding;
   available_width -= x + NewTabCaptionSpacing() + trailing_button_start_;
   return gfx::Rect(x, GetTabStripInsetsTop(false), std::max(0, available_width),
                    tabstrip_preferred_size.height());
@@ -369,7 +369,7 @@
   trailing_button_start_ = std::max(trailing_button_start_, min_button_width);
 
   if (incognito_icon_) {
-    const int pad = GetLayoutConstant(AVATAR_ICON_PADDING);
+    constexpr int pad = OpaqueBrowserFrameView::kAvatarIconPadding;
     const gfx::Size size(delegate_->GetIncognitoAvatarIcon().size());
     const int incognito_width = pad + size.width();
     int x;
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc
index 156121c..bc18be5 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc
@@ -236,7 +236,7 @@
           (maximized ? OBFVL::kCaptionSpacing
                      : -GetLayoutSize(NEW_TAB_BUTTON).width());
     }
-    int tabstrip_x = GetLayoutConstant(AVATAR_ICON_PADDING);
+    int tabstrip_x = OpaqueBrowserFrameView::kAvatarIconPadding;
     if (show_caption_buttons && caption_buttons_on_left) {
       int right_of_close =
           maximized ? kMaximizedExtraCloseWidth : OBFVL::kFrameBorderThickness;
diff --git a/chrome/browser/ui/views/ime_driver/ime_driver_mus.cc b/chrome/browser/ui/views/ime_driver/ime_driver_mus.cc
new file mode 100644
index 0000000..763cbd90
--- /dev/null
+++ b/chrome/browser/ui/views/ime_driver/ime_driver_mus.cc
@@ -0,0 +1,58 @@
+// 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/views/ime_driver/ime_driver_mus.h"
+
+#include "content/public/browser/browser_thread.h"
+#include "content/public/common/service_manager_connection.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "services/service_manager/public/cpp/connector.h"
+#include "services/ui/public/interfaces/constants.mojom.h"
+#include "services/ui/public/interfaces/ime/ime.mojom.h"
+#include "ui/base/ime/ime_bridge.h"
+
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.h"
+#else
+#include "chrome/browser/ui/views/ime_driver/simple_input_method.h"
+#endif  // defined(OS_CHROMEOS)
+
+IMEDriver::IMEDriver() {
+  ui::IMEBridge::Initialize();
+}
+
+IMEDriver::~IMEDriver() {}
+
+// static
+void IMEDriver::Register() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  ui::mojom::IMEDriverPtr ime_driver_ptr;
+  mojo::MakeStrongBinding(base::MakeUnique<IMEDriver>(),
+                          GetProxy(&ime_driver_ptr));
+  ui::mojom::IMERegistrarPtr ime_registrar;
+  content::ServiceManagerConnection::GetForProcess()
+      ->GetConnector()
+      ->ConnectToInterface(ui::mojom::kServiceName, &ime_registrar);
+  ime_registrar->RegisterDriver(std::move(ime_driver_ptr));
+}
+
+void IMEDriver::StartSession(
+    int32_t session_id,
+    ui::mojom::TextInputClientPtr client,
+    ui::mojom::InputMethodRequest input_method_request) {
+#if defined(OS_CHROMEOS)
+  input_method_bindings_[session_id] =
+      base::MakeUnique<mojo::Binding<ui::mojom::InputMethod>>(
+          new InputMethodBridge(std::move(client)),
+          std::move(input_method_request));
+#else
+  input_method_bindings_[session_id] =
+      base::MakeUnique<mojo::Binding<ui::mojom::InputMethod>>(
+          new SimpleInputMethod());
+#endif
+}
+
+void IMEDriver::CancelSession(int32_t session_id) {
+  input_method_bindings_.erase(session_id);
+}
diff --git a/chrome/browser/ui/views/ime_driver_mus.h b/chrome/browser/ui/views/ime_driver/ime_driver_mus.h
similarity index 82%
rename from chrome/browser/ui/views/ime_driver_mus.h
rename to chrome/browser/ui/views/ime_driver/ime_driver_mus.h
index bc70b37..e81d34d 100644
--- a/chrome/browser/ui/views/ime_driver_mus.h
+++ b/chrome/browser/ui/views/ime_driver/ime_driver_mus.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_VIEWS_IME_DRIVER_MUS_H_
-#define CHROME_BROWSER_UI_VIEWS_IME_DRIVER_MUS_H_
+#ifndef CHROME_BROWSER_UI_VIEWS_IME_DRIVER_IME_DRIVER_MUS_H_
+#define CHROME_BROWSER_UI_VIEWS_IME_DRIVER_IME_DRIVER_MUS_H_
 
 #include <stdint.h>
 
@@ -15,14 +15,13 @@
 
 class IMEDriver : public ui::mojom::IMEDriver {
  public:
+  IMEDriver();
   ~IMEDriver() override;
 
   // Instantiate the IME driver and register it to the UI service.
   static void Register();
 
  private:
-  IMEDriver();
-
   // ui::mojom::IMEDriver:
   void StartSession(
       int32_t session_id,
@@ -36,4 +35,4 @@
   DISALLOW_COPY_AND_ASSIGN(IMEDriver);
 };
 
-#endif  // CHROME_BROWSER_UI_VIEWS_IME_DRIVER_MUS_H_
+#endif  // CHROME_BROWSER_UI_VIEWS_IME_DRIVER_IME_DRIVER_MUS_H_
diff --git a/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.cc b/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.cc
new file mode 100644
index 0000000..76869b1c
--- /dev/null
+++ b/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.cc
@@ -0,0 +1,48 @@
+// 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/views/ime_driver/input_method_bridge_chromeos.h"
+
+#include "chrome/browser/ui/views/ime_driver/remote_text_input_client.h"
+
+InputMethodBridge::InputMethodBridge(ui::mojom::TextInputClientPtr client)
+    : client_(base::MakeUnique<RemoteTextInputClient>(std::move(client))),
+      input_method_chromeos_(
+          base::MakeUnique<ui::InputMethodChromeOS>(nullptr)) {
+  input_method_chromeos_->SetFocusedTextInputClient(client_.get());
+}
+
+InputMethodBridge::~InputMethodBridge() {}
+
+void InputMethodBridge::OnTextInputModeChanged(
+    ui::mojom::TextInputMode text_input_mode) {
+  // TODO(moshayedi): crbug.com/631527. Consider removing this, as
+  // ui::InputMethodChromeOS doesn't have this.
+}
+
+void InputMethodBridge::OnTextInputTypeChanged(
+    ui::mojom::TextInputType text_input_type) {
+  input_method_chromeos_->OnTextInputTypeChanged(client_.get());
+}
+
+void InputMethodBridge::OnCaretBoundsChanged(const gfx::Rect& caret_bounds) {
+  input_method_chromeos_->OnCaretBoundsChanged(client_.get());
+}
+
+void InputMethodBridge::ProcessKeyEvent(
+    std::unique_ptr<ui::Event> event,
+    const ProcessKeyEventCallback& callback) {
+  DCHECK(event->IsKeyEvent());
+  ui::KeyEvent* key_event = event->AsKeyEvent();
+  if (!key_event->is_char()) {
+    input_method_chromeos_->DispatchKeyEvent(
+        key_event, base::MakeUnique<base::Callback<void(bool)>>(callback));
+  } else {
+    callback.Run(false);
+  }
+}
+
+void InputMethodBridge::CancelComposition() {
+  input_method_chromeos_->CancelComposition(client_.get());
+}
diff --git a/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.h b/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.h
new file mode 100644
index 0000000..d757a75
--- /dev/null
+++ b/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.h
@@ -0,0 +1,35 @@
+// 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_VIEWS_IME_DRIVER_INPUT_METHOD_BRIDGE_CHROMEOS_H_
+#define CHROME_BROWSER_UI_VIEWS_IME_DRIVER_INPUT_METHOD_BRIDGE_CHROMEOS_H_
+
+#include "services/ui/public/interfaces/ime/ime.mojom.h"
+#include "ui/base/ime/input_method_chromeos.h"
+
+// This bridges between mojo InputMethod API and ui::InputMethodChromeOS. It
+// forwards the received events to an instance of ui::InputMethodChromeOS.
+class InputMethodBridge : public ui::mojom::InputMethod {
+ public:
+  explicit InputMethodBridge(ui::mojom::TextInputClientPtr client);
+  ~InputMethodBridge() override;
+
+  // ui::mojom::InputMethod:
+  void OnTextInputModeChanged(
+      ui::mojom::TextInputMode text_input_mode) override;
+  void OnTextInputTypeChanged(
+      ui::mojom::TextInputType text_input_type) override;
+  void OnCaretBoundsChanged(const gfx::Rect& caret_bounds) override;
+  void ProcessKeyEvent(std::unique_ptr<ui::Event> key_event,
+                       const ProcessKeyEventCallback& callback) override;
+  void CancelComposition() override;
+
+ private:
+  std::unique_ptr<ui::TextInputClient> client_;
+  std::unique_ptr<ui::InputMethodChromeOS> input_method_chromeos_;
+
+  DISALLOW_COPY_AND_ASSIGN(InputMethodBridge);
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_IME_DRIVER_INPUT_METHOD_BRIDGE_CHROMEOS_H_
diff --git a/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos_unittest.cc b/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos_unittest.cc
new file mode 100644
index 0000000..9d7cc668
--- /dev/null
+++ b/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos_unittest.cc
@@ -0,0 +1,200 @@
+// 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 <stdint.h>
+
+#include "base/bind.h"
+#include "base/macros.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/ime/ime_bridge.h"
+#include "ui/events/event.h"
+#include "ui/events/event_constants.h"
+#include "ui/events/event_utils.h"
+#include "ui/events/keycodes/dom/dom_code.h"
+#include "ui/events/keycodes/dom/dom_key.h"
+#include "ui/events/keycodes/keyboard_code_conversion.h"
+#include "ui/events/keycodes/keyboard_codes.h"
+
+enum class CompositionEventType {
+  SET,
+  CONFIRM,
+  CLEAR,
+  INSERT_TEXT,
+  INSERT_CHAR
+};
+
+struct CompositionEvent {
+  CompositionEventType type;
+  base::string16 text_data;
+  base::char16 char_data;
+};
+
+class TestTextInputClient : public ui::mojom::TextInputClient {
+ public:
+  explicit TestTextInputClient(ui::mojom::TextInputClientRequest request)
+      : binding_(this, std::move(request)) {}
+
+  CompositionEvent WaitUntilCompositionEvent() {
+    if (!receieved_event_.has_value()) {
+      run_loop_ = base::MakeUnique<base::RunLoop>();
+      run_loop_->Run();
+      run_loop_.reset();
+    }
+    CompositionEvent result = receieved_event_.value();
+    receieved_event_.reset();
+    return result;
+  }
+
+ private:
+  void SetCompositionText(const ui::CompositionText& composition) override {
+    CompositionEvent ev = {CompositionEventType::SET, composition.text, 0};
+    receieved_event_ = ev;
+    if (run_loop_)
+      run_loop_->Quit();
+  }
+  void ConfirmCompositionText() override {
+    CompositionEvent ev = {CompositionEventType::CONFIRM, base::string16(), 0};
+    receieved_event_ = ev;
+    if (run_loop_)
+      run_loop_->Quit();
+  }
+  void ClearCompositionText() override {
+    CompositionEvent ev = {CompositionEventType::CLEAR, base::string16(), 0};
+    receieved_event_ = ev;
+    if (run_loop_)
+      run_loop_->Quit();
+  }
+  void InsertText(const std::string& text) override {
+    CompositionEvent ev = {CompositionEventType::INSERT_TEXT,
+                           base::UTF8ToUTF16(text), 0};
+    receieved_event_ = ev;
+    if (run_loop_)
+      run_loop_->Quit();
+  }
+  void InsertChar(std::unique_ptr<ui::Event> event) override {
+    ASSERT_TRUE(event->IsKeyEvent());
+    CompositionEvent ev = {CompositionEventType::INSERT_CHAR, base::string16(),
+                           event->AsKeyEvent()->GetCharacter()};
+    receieved_event_ = ev;
+    if (run_loop_)
+      run_loop_->Quit();
+  }
+
+  mojo::Binding<ui::mojom::TextInputClient> binding_;
+  std::unique_ptr<base::RunLoop> run_loop_;
+  base::Optional<CompositionEvent> receieved_event_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestTextInputClient);
+};
+
+class InputMethodBridgeChromeOSTest : public testing::Test {
+ public:
+  InputMethodBridgeChromeOSTest()
+      : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {}
+  ~InputMethodBridgeChromeOSTest() override {}
+
+  void SetUp() override {
+    ui::IMEBridge::Initialize();
+
+    ui::mojom::TextInputClientPtr client_ptr;
+    client_ = base::MakeUnique<TestTextInputClient>(GetProxy(&client_ptr));
+    input_method_ = base::MakeUnique<InputMethodBridge>(std::move(client_ptr));
+  }
+
+  bool ProcessKeyEvent(std::unique_ptr<ui::Event> event) {
+    handled_.reset();
+
+    input_method_->ProcessKeyEvent(
+        std::move(event),
+        base::Bind(&InputMethodBridgeChromeOSTest::ProcessKeyEventCallback,
+                   base::Unretained(this)));
+
+    if (!handled_.has_value()) {
+      run_loop_ = base::MakeUnique<base::RunLoop>();
+      run_loop_->Run();
+      run_loop_.reset();
+    }
+
+    return handled_.value();
+  }
+
+  std::unique_ptr<ui::Event> UnicodeKeyPress(ui::KeyboardCode vkey,
+                                             ui::DomCode code,
+                                             int flags,
+                                             base::char16 character) const {
+    return base::MakeUnique<ui::KeyEvent>(ui::ET_KEY_PRESSED, vkey, code, flags,
+                                          ui::DomKey::FromCharacter(character),
+                                          ui::EventTimeForNow());
+  }
+
+ protected:
+  void ProcessKeyEventCallback(bool handled) {
+    handled_ = handled;
+    if (run_loop_)
+      run_loop_->Quit();
+  }
+
+  content::TestBrowserThreadBundle thread_bundle_;
+  std::unique_ptr<TestTextInputClient> client_;
+  std::unique_ptr<InputMethodBridge> input_method_;
+  std::unique_ptr<base::RunLoop> run_loop_;
+  base::Optional<bool> handled_;
+
+  DISALLOW_COPY_AND_ASSIGN(InputMethodBridgeChromeOSTest);
+};
+
+// Tests if hexadecimal composition provided by ui::CharacterComposer works
+// correctly. ui::CharacterComposer is tried if no input method extensions
+// have been registered yet.
+TEST_F(InputMethodBridgeChromeOSTest, HexadecimalComposition) {
+  struct {
+    ui::KeyboardCode vkey;
+    ui::DomCode code;
+    int flags;
+    base::char16 character;
+    std::string composition_text;
+  } kTestSequence[] = {
+      {ui::VKEY_U, ui::DomCode::US_U, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
+       'U', "u"},
+      {ui::VKEY_3, ui::DomCode::DIGIT3, 0, '3', "u3"},
+      {ui::VKEY_0, ui::DomCode::DIGIT0, 0, '0', "u30"},
+      {ui::VKEY_4, ui::DomCode::DIGIT4, 0, '4', "u304"},
+      {ui::VKEY_2, ui::DomCode::DIGIT2, 0, '2', "u3042"},
+  };
+
+  // Send the Ctrl-Shift-U,3,4,0,2 sequence.
+  for (size_t i = 0; i < arraysize(kTestSequence); i++) {
+    EXPECT_TRUE(ProcessKeyEvent(
+        UnicodeKeyPress(kTestSequence[i].vkey, kTestSequence[i].code,
+                        kTestSequence[i].flags, kTestSequence[i].character)));
+    CompositionEvent ev = client_->WaitUntilCompositionEvent();
+    EXPECT_EQ(CompositionEventType::SET, ev.type);
+    EXPECT_EQ(base::UTF8ToUTF16(kTestSequence[i].composition_text),
+              ev.text_data);
+  }
+
+  // Press the return key and verify that the composition text was converted
+  // to the desired text.
+  EXPECT_TRUE(ProcessKeyEvent(
+      UnicodeKeyPress(ui::VKEY_RETURN, ui::DomCode::ENTER, 0, '\r')));
+  CompositionEvent ev = client_->WaitUntilCompositionEvent();
+  EXPECT_EQ(CompositionEventType::INSERT_TEXT, ev.type);
+  EXPECT_EQ(base::string16(1, 0x3042), ev.text_data);
+}
+
+// Test that Ctrl-C, Ctrl-X, and Ctrl-V are not handled.
+TEST_F(InputMethodBridgeChromeOSTest, ClipboardAccelerators) {
+  EXPECT_FALSE(ProcessKeyEvent(UnicodeKeyPress(ui::VKEY_C, ui::DomCode::US_C,
+                                               ui::EF_CONTROL_DOWN, 'C')));
+  EXPECT_FALSE(ProcessKeyEvent(UnicodeKeyPress(ui::VKEY_X, ui::DomCode::US_X,
+                                               ui::EF_CONTROL_DOWN, 'X')));
+  EXPECT_FALSE(ProcessKeyEvent(UnicodeKeyPress(ui::VKEY_V, ui::DomCode::US_V,
+                                               ui::EF_CONTROL_DOWN, 'V')));
+}
diff --git a/chrome/browser/ui/views/ime_driver/remote_text_input_client.cc b/chrome/browser/ui/views/ime_driver/remote_text_input_client.cc
new file mode 100644
index 0000000..b7705ad0
--- /dev/null
+++ b/chrome/browser/ui/views/ime_driver/remote_text_input_client.cc
@@ -0,0 +1,163 @@
+// 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.
+
+// Reduce number of log messages by logging each NOTIMPLEMENTED() only once.
+// This has to be before any other includes, else default is picked up.
+// See base/logging.h for details on this.
+#define NOTIMPLEMENTED_POLICY 5
+
+#include "chrome/browser/ui/views/ime_driver/remote_text_input_client.h"
+
+#include "base/strings/utf_string_conversions.h"
+
+RemoteTextInputClient::RemoteTextInputClient(
+    ui::mojom::TextInputClientPtr remote_client)
+    : remote_client_(std::move(remote_client)) {}
+
+RemoteTextInputClient::~RemoteTextInputClient() {}
+
+void RemoteTextInputClient::SetCompositionText(
+    const ui::CompositionText& composition) {
+  remote_client_->SetCompositionText(composition);
+}
+
+void RemoteTextInputClient::ConfirmCompositionText() {
+  remote_client_->ConfirmCompositionText();
+}
+
+void RemoteTextInputClient::ClearCompositionText() {
+  remote_client_->ClearCompositionText();
+}
+
+void RemoteTextInputClient::InsertText(const base::string16& text) {
+  remote_client_->InsertText(base::UTF16ToUTF8(text));
+}
+
+void RemoteTextInputClient::InsertChar(const ui::KeyEvent& event) {
+  remote_client_->InsertChar(ui::Event::Clone(event));
+}
+
+ui::TextInputType RemoteTextInputClient::GetTextInputType() const {
+  // TODO(moshayedi): crbug.com/631527.
+  NOTIMPLEMENTED();
+  return ui::TEXT_INPUT_TYPE_TEXT;
+}
+
+ui::TextInputMode RemoteTextInputClient::GetTextInputMode() const {
+  // TODO(moshayedi): crbug.com/631527.
+  NOTIMPLEMENTED();
+  return ui::TEXT_INPUT_MODE_DEFAULT;
+}
+
+base::i18n::TextDirection RemoteTextInputClient::GetTextDirection() const {
+  // TODO(moshayedi): crbug.com/631527.
+  NOTIMPLEMENTED();
+  return base::i18n::UNKNOWN_DIRECTION;
+}
+
+int RemoteTextInputClient::GetTextInputFlags() const {
+  // TODO(moshayedi): crbug.com/631527.
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+bool RemoteTextInputClient::CanComposeInline() const {
+  // If we return false here, ui::InputMethodChromeOS will try to create a
+  // composition window. But here we are at IMEDriver, and composition
+  // window shouldn't be created by IMEDriver.
+  return true;
+}
+
+gfx::Rect RemoteTextInputClient::GetCaretBounds() const {
+  // TODO(moshayedi): crbug.com/631527.
+  NOTIMPLEMENTED();
+  return gfx::Rect();
+}
+
+bool RemoteTextInputClient::GetCompositionCharacterBounds(
+    uint32_t index,
+    gfx::Rect* rect) const {
+  // TODO(moshayedi): crbug.com/631527.
+  NOTIMPLEMENTED();
+  return false;
+}
+
+bool RemoteTextInputClient::HasCompositionText() const {
+  // TODO(moshayedi): crbug.com/631527.
+  NOTIMPLEMENTED();
+  return false;
+}
+
+bool RemoteTextInputClient::GetTextRange(gfx::Range* range) const {
+  // TODO(moshayedi): crbug.com/631527.
+  NOTIMPLEMENTED();
+  return false;
+}
+
+bool RemoteTextInputClient::GetCompositionTextRange(gfx::Range* range) const {
+  // TODO(moshayedi): crbug.com/631527.
+  NOTIMPLEMENTED();
+  return false;
+}
+
+bool RemoteTextInputClient::GetSelectionRange(gfx::Range* range) const {
+  // TODO(moshayedi): crbug.com/631527.
+  NOTIMPLEMENTED();
+  return false;
+}
+
+bool RemoteTextInputClient::SetSelectionRange(const gfx::Range& range) {
+  // TODO(moshayedi): crbug.com/631527.
+  NOTIMPLEMENTED();
+  return false;
+}
+
+bool RemoteTextInputClient::DeleteRange(const gfx::Range& range) {
+  // TODO(moshayedi): crbug.com/631527.
+  NOTIMPLEMENTED();
+  return false;
+}
+
+bool RemoteTextInputClient::GetTextFromRange(const gfx::Range& range,
+                                             base::string16* text) const {
+  // TODO(moshayedi): crbug.com/631527.
+  NOTIMPLEMENTED();
+  return false;
+}
+
+void RemoteTextInputClient::OnInputMethodChanged() {
+  // TODO(moshayedi): crbug.com/631527.
+  NOTIMPLEMENTED();
+}
+
+bool RemoteTextInputClient::ChangeTextDirectionAndLayoutAlignment(
+    base::i18n::TextDirection direction) {
+  // TODO(moshayedi): crbug.com/631527.
+  NOTIMPLEMENTED();
+  return false;
+}
+
+void RemoteTextInputClient::ExtendSelectionAndDelete(size_t before,
+                                                     size_t after) {
+  // TODO(moshayedi): crbug.com/631527.
+  NOTIMPLEMENTED();
+}
+
+void RemoteTextInputClient::EnsureCaretNotInRect(const gfx::Rect& rect) {
+  // TODO(moshayedi): crbug.com/631527.
+  NOTIMPLEMENTED();
+}
+
+bool RemoteTextInputClient::IsTextEditCommandEnabled(
+    ui::TextEditCommand command) const {
+  // TODO(moshayedi): crbug.com/631527.
+  NOTIMPLEMENTED();
+  return false;
+}
+
+void RemoteTextInputClient::SetTextEditCommandForNextKeyEvent(
+    ui::TextEditCommand command) {
+  // TODO(moshayedi): crbug.com/631527.
+  NOTIMPLEMENTED();
+}
diff --git a/chrome/browser/ui/views/ime_driver/remote_text_input_client.h b/chrome/browser/ui/views/ime_driver/remote_text_input_client.h
new file mode 100644
index 0000000..056be5f1
--- /dev/null
+++ b/chrome/browser/ui/views/ime_driver/remote_text_input_client.h
@@ -0,0 +1,55 @@
+// 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_VIEWS_IME_DRIVER_REMOTE_TEXT_INPUT_CLIENT_H_
+#define CHROME_BROWSER_UI_VIEWS_IME_DRIVER_REMOTE_TEXT_INPUT_CLIENT_H_
+
+#include "services/ui/public/interfaces/ime/ime.mojom.h"
+#include "ui/base/ime/text_input_client.h"
+
+// This implementation of ui::TextInputClient sends all updates via mojo IPC to
+// a remote client. This is intended to be passed to the overrides of
+// ui::InputMethod::SetFocusedTextInputClient().
+class RemoteTextInputClient : public ui::TextInputClient {
+ public:
+  explicit RemoteTextInputClient(ui::mojom::TextInputClientPtr remote_client);
+  ~RemoteTextInputClient() override;
+
+ private:
+  // ui::TextInputClient:
+  void SetCompositionText(const ui::CompositionText& composition) override;
+  void ConfirmCompositionText() override;
+  void ClearCompositionText() override;
+  void InsertText(const base::string16& text) override;
+  void InsertChar(const ui::KeyEvent& event) override;
+  ui::TextInputType GetTextInputType() const override;
+  ui::TextInputMode GetTextInputMode() const override;
+  base::i18n::TextDirection GetTextDirection() const override;
+  int GetTextInputFlags() const override;
+  bool CanComposeInline() const override;
+  gfx::Rect GetCaretBounds() const override;
+  bool GetCompositionCharacterBounds(uint32_t index,
+                                     gfx::Rect* rect) const override;
+  bool HasCompositionText() const override;
+  bool GetTextRange(gfx::Range* range) const override;
+  bool GetCompositionTextRange(gfx::Range* range) const override;
+  bool GetSelectionRange(gfx::Range* range) const override;
+  bool SetSelectionRange(const gfx::Range& range) override;
+  bool DeleteRange(const gfx::Range& range) override;
+  bool GetTextFromRange(const gfx::Range& range,
+                        base::string16* text) const override;
+  void OnInputMethodChanged() override;
+  bool ChangeTextDirectionAndLayoutAlignment(
+      base::i18n::TextDirection direction) override;
+  void ExtendSelectionAndDelete(size_t before, size_t after) override;
+  void EnsureCaretNotInRect(const gfx::Rect& rect) override;
+  bool IsTextEditCommandEnabled(ui::TextEditCommand command) const override;
+  void SetTextEditCommandForNextKeyEvent(ui::TextEditCommand command) override;
+
+  ui::mojom::TextInputClientPtr remote_client_;
+
+  DISALLOW_COPY_AND_ASSIGN(RemoteTextInputClient);
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_IME_DRIVER_REMOTE_TEXT_INPUT_CLIENT_H_
diff --git a/chrome/browser/ui/views/ime_driver/simple_input_method.cc b/chrome/browser/ui/views/ime_driver/simple_input_method.cc
new file mode 100644
index 0000000..e040d2c
--- /dev/null
+++ b/chrome/browser/ui/views/ime_driver/simple_input_method.cc
@@ -0,0 +1,25 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/ime_driver/simple_input_method.h"
+
+SimpleInputMethod::SimpleInputMethod() {}
+
+SimpleInputMethod::~SimpleInputMethod() {}
+
+void SimpleInputMethod::OnTextInputModeChanged(
+    ui::mojom::TextInputMode text_input_mode) {}
+
+void SimpleInputMethod::OnTextInputTypeChanged(
+    ui::mojom::TextInputType text_input_type) {}
+
+void SimpleInputMethod::OnCaretBoundsChanged(const gfx::Rect& caret_bounds) {}
+
+void SimpleInputMethod::ProcessKeyEvent(
+    std::unique_ptr<ui::Event> key_event,
+    const ProcessKeyEventCallback& callback) {
+  callback.Run(false);
+}
+
+void SimpleInputMethod::CancelComposition() {}
diff --git a/chrome/browser/ui/views/ime_driver/simple_input_method.h b/chrome/browser/ui/views/ime_driver/simple_input_method.h
new file mode 100644
index 0000000..c488cce
--- /dev/null
+++ b/chrome/browser/ui/views/ime_driver/simple_input_method.h
@@ -0,0 +1,33 @@
+// 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_VIEWS_IME_DRIVER_SIMPLE_INPUT_METHOD_H_
+#define CHROME_BROWSER_UI_VIEWS_IME_DRIVER_SIMPLE_INPUT_METHOD_H_
+
+#include "services/ui/public/interfaces/ime/ime.mojom.h"
+
+// This is to be used on platforms where a proper implementation of
+// ui::mojom::InputMethod is missing. It doesn't handle any events and calls
+// the callback with false, which will result in client code handling events
+// locally.
+class SimpleInputMethod : public ui::mojom::InputMethod {
+ public:
+  SimpleInputMethod();
+  ~SimpleInputMethod() override;
+
+  // ui::mojom::InputMethod:
+  void OnTextInputModeChanged(
+      ui::mojom::TextInputMode text_input_mode) override;
+  void OnTextInputTypeChanged(
+      ui::mojom::TextInputType text_input_type) override;
+  void OnCaretBoundsChanged(const gfx::Rect& caret_bounds) override;
+  void ProcessKeyEvent(std::unique_ptr<ui::Event> key_event,
+                       const ProcessKeyEventCallback& callback) override;
+  void CancelComposition() override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SimpleInputMethod);
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_IME_DRIVER_SIMPLE_INPUT_METHOD_H_
diff --git a/chrome/browser/ui/views/ime_driver_mus.cc b/chrome/browser/ui/views/ime_driver_mus.cc
deleted file mode 100644
index 2b618861..0000000
--- a/chrome/browser/ui/views/ime_driver_mus.cc
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/views/ime_driver_mus.h"
-
-#include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
-#include "services/service_manager/public/cpp/connector.h"
-#include "services/ui/public/interfaces/constants.mojom.h"
-#include "services/ui/public/interfaces/ime/ime.mojom.h"
-
-namespace {
-
-class InputMethod : public ui::mojom::InputMethod {
- public:
-  explicit InputMethod(ui::mojom::TextInputClientPtr client)
-      : client_(std::move(client)) {}
-  ~InputMethod() override {}
-
- private:
-  // ui::mojom::InputMethod:
-  void OnTextInputModeChanged(
-      ui::mojom::TextInputMode text_input_mode) override {}
-  void OnTextInputTypeChanged(
-      ui::mojom::TextInputType text_input_type) override {}
-  void OnCaretBoundsChanged(const gfx::Rect& caret_bounds) override {}
-  void ProcessKeyEvent(std::unique_ptr<ui::Event> key_event,
-                       const ProcessKeyEventCallback& callback) override {
-    DCHECK(key_event->IsKeyEvent());
-
-    if (key_event->AsKeyEvent()->is_char()) {
-      client_->InsertChar(std::move(key_event));
-      callback.Run(true);
-    } else {
-      callback.Run(false);
-    }
-  }
-  void CancelComposition() override {}
-
-  ui::mojom::TextInputClientPtr client_;
-
-  DISALLOW_COPY_AND_ASSIGN(InputMethod);
-};
-
-}  // namespace
-
-IMEDriver::~IMEDriver() {}
-
-// static
-void IMEDriver::Register() {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  ui::mojom::IMEDriverPtr ime_driver_ptr;
-  mojo::MakeStrongBinding(base::WrapUnique(new IMEDriver),
-                          GetProxy(&ime_driver_ptr));
-  ui::mojom::IMERegistrarPtr ime_registrar;
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->ConnectToInterface(ui::mojom::kServiceName, &ime_registrar);
-  ime_registrar->RegisterDriver(std::move(ime_driver_ptr));
-}
-
-void IMEDriver::StartSession(
-    int32_t session_id,
-    ui::mojom::TextInputClientPtr client,
-    ui::mojom::InputMethodRequest input_method_request) {
-  input_method_bindings_[session_id] =
-      base::MakeUnique<mojo::Binding<ui::mojom::InputMethod>>(
-          new InputMethod(std::move(client)), std::move(input_method_request));
-}
-
-IMEDriver::IMEDriver() {}
-
-void IMEDriver::CancelSession(int32_t session_id) {
-  input_method_bindings_.erase(session_id);
-}
diff --git a/chrome/browser/ui/views/location_bar/background_with_1_px_border.cc b/chrome/browser/ui/views/location_bar/background_with_1_px_border.cc
index d489a3b..82f5226 100644
--- a/chrome/browser/ui/views/location_bar/background_with_1_px_border.cc
+++ b/chrome/browser/ui/views/location_bar/background_with_1_px_border.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/ui/views/location_bar/background_with_1_px_border.h"
 
-#include "chrome/browser/ui/layout_constants.h"
 #include "third_party/skia/include/core/SkPaint.h"
 #include "third_party/skia/include/core/SkPath.h"
 #include "third_party/skia/include/pathops/SkPathOps.h"
@@ -27,14 +26,13 @@
   const float scale = canvas->UndoDeviceScaleFactor();
   border_rect_f.Scale(scale);
   // Draw the border as a 1px thick line aligned with the inside edge of the
-  // LOCATION_BAR_BORDER_THICKNESS region. This line needs to be snapped to the
+  // kLocationBarBorderThicknessDip region. This line needs to be snapped to the
   // pixel grid, so the result of the scale-up needs to be snapped to an integer
   // value. Using floor() instead of round() ensures that, for non-integral
   // scale factors, the border will still be drawn inside the BORDER_THICKNESS
   // region instead of being partially inside it.
-  border_rect_f.Inset(gfx::InsetsF(
-      std::floor(GetLayoutConstant(LOCATION_BAR_BORDER_THICKNESS) * scale) -
-      0.5f));
+  border_rect_f.Inset(
+      gfx::InsetsF(std::floor(kLocationBarBorderThicknessDip * scale) - 0.5f));
 
   SkPath path;
   const SkScalar scaled_corner_radius =
diff --git a/chrome/browser/ui/views/location_bar/background_with_1_px_border.h b/chrome/browser/ui/views/location_bar/background_with_1_px_border.h
index 6904579..1512527 100644
--- a/chrome/browser/ui/views/location_bar/background_with_1_px_border.h
+++ b/chrome/browser/ui/views/location_bar/background_with_1_px_border.h
@@ -25,6 +25,9 @@
   // Corner radius of the inside edge of the roundrect border stroke.
   static constexpr int kCornerRadius = 2;
 
+  // The thickness of the location bar's border in DIP.
+  static constexpr int kLocationBarBorderThicknessDip = 1;
+
   BackgroundWith1PxBorder(SkColor background, SkColor border);
 
   void Paint(gfx::Canvas* canvas, views::View* view) const override;
diff --git a/chrome/browser/ui/views/location_bar/content_setting_image_view.cc b/chrome/browser/ui/views/location_bar/content_setting_image_view.cc
index 3b5f6cb..c914e2cd 100644
--- a/chrome/browser/ui/views/location_bar/content_setting_image_view.cc
+++ b/chrome/browser/ui/views/location_bar/content_setting_image_view.cc
@@ -8,7 +8,6 @@
 #include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/ui/content_settings/content_setting_bubble_model.h"
 #include "chrome/browser/ui/content_settings/content_setting_image_model.h"
-#include "chrome/browser/ui/layout_constants.h"
 #include "chrome/browser/ui/views/content_setting_bubble_contents.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/grit/theme_resources.h"
@@ -163,9 +162,8 @@
 
 bool ContentSettingImageView::ShouldShowLabel() const {
   return (!IsShrinking() ||
-          (width() >
-           (image()->GetPreferredSize().width() +
-            2 * GetLayoutConstant(LOCATION_BAR_HORIZONTAL_PADDING)))) &&
+          (width() > (image()->GetPreferredSize().width() +
+                      2 * LocationBarView::kHorizontalPadding))) &&
          (slide_animator_.is_animating() || pause_animation_);
 }
 
diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc
index 65804a0..9d1ff7d 100644
--- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc
+++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/ui/views/location_bar/icon_label_bubble_view.h"
 
-#include "chrome/browser/ui/layout_constants.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/color_utils.h"
@@ -42,7 +42,7 @@
   // the bubble should be smaller, so use an empty border to shrink down the
   // content bounds so the background gets painted correctly.
   SetBorder(views::CreateEmptyBorder(
-      gfx::Insets(GetLayoutConstant(LOCATION_BAR_BUBBLE_VERTICAL_PADDING), 0)));
+      gfx::Insets(LocationBarView::kBubbleVerticalPadding, 0)));
 
   // Flip the canvas in RTL so the separator is drawn on the correct side.
   EnableCanvasFlippingForRTLUI(true);
@@ -94,7 +94,7 @@
 
 void IconLabelBubbleView::Layout() {
   // Compute the image bounds. Leading and trailing padding are the same.
-  int image_x = GetLayoutConstant(LOCATION_BAR_HORIZONTAL_PADDING);
+  int image_x = LocationBarView::kHorizontalPadding;
   int bubble_trailing_padding = image_x;
 
   // If ShouldShowLabel() is true, then either we show a label in the
@@ -192,7 +192,7 @@
     // enough to show the icon. We don't want to shrink all the way back to
     // zero, since this would mean the view would completely disappear and then
     // pop back to an icon after the animation finishes.
-    const int max_width = GetLayoutConstant(LOCATION_BAR_HORIZONTAL_PADDING) +
+    const int max_width = LocationBarView::kHorizontalPadding +
                           image_->GetPreferredSize().width() +
                           GetInternalSpacing() + label_width + post_label_width;
     const int current_width = WidthMultiplier() * max_width;
@@ -205,13 +205,12 @@
 int IconLabelBubbleView::GetInternalSpacing() const {
   return image_->GetPreferredSize().IsEmpty()
              ? 0
-             : GetLayoutConstant(LOCATION_BAR_HORIZONTAL_PADDING);
+             : LocationBarView::kHorizontalPadding;
 }
 
 int IconLabelBubbleView::GetPostSeparatorPadding() const {
-  // The location bar will add LOCATION_BAR_HORIZONTAL_PADDING after us.
-  return kSpaceBesideSeparator -
-         GetLayoutConstant(LOCATION_BAR_HORIZONTAL_PADDING);
+  // The location bar will add LocationBarView::kHorizontalPadding after us.
+  return kSpaceBesideSeparator - LocationBarView::kHorizontalPadding;
 }
 
 float IconLabelBubbleView::GetScaleFactor() const {
diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view_unittest.cc b/chrome/browser/ui/views/location_bar/icon_label_bubble_view_unittest.cc
index 74e0664..28f3efe 100644
--- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view_unittest.cc
+++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view_unittest.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/ui/views/location_bar/icon_label_bubble_view.h"
 
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/ui/layout_constants.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/test/views_test_base.h"
@@ -65,7 +65,7 @@
   bool ShouldShowLabel() const override {
     return !IsShrinking() ||
            (width() > (image()->GetPreferredSize().width() +
-                       2 * GetLayoutConstant(LOCATION_BAR_HORIZONTAL_PADDING)));
+                       2 * LocationBarView::kHorizontalPadding));
   }
 
   double WidthMultiplier() const override {
diff --git a/chrome/browser/ui/views/location_bar/keyword_hint_view.cc b/chrome/browser/ui/views/location_bar/keyword_hint_view.cc
index 0256f91..5f7c0bc 100644
--- a/chrome/browser/ui/views/location_bar/keyword_hint_view.cc
+++ b/chrome/browser/ui/views/location_bar/keyword_hint_view.cc
@@ -11,8 +11,8 @@
 #include "base/macros.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
-#include "chrome/browser/ui/layout_constants.h"
 #include "chrome/browser/ui/views/location_bar/background_with_1_px_border.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/search_engines/template_url_service.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -39,7 +39,7 @@
 TabKeyBubbleView::TabKeyBubbleView(const gfx::FontList& font_list)
     : views::Label(l10n_util::GetStringUTF16(IDS_APP_TAB_KEY), font_list) {
   SetBorder(views::CreateEmptyBorder(
-      gfx::Insets(GetLayoutConstant(LOCATION_BAR_BUBBLE_VERTICAL_PADDING), 0)));
+      gfx::Insets(LocationBarView::kBubbleVerticalPadding, 0)));
 }
 
 TabKeyBubbleView::~TabKeyBubbleView() {}
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index 76c548b..fcd840cb 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -220,10 +220,10 @@
   gfx::FontList font_list = ResourceBundle::GetSharedInstance().GetFontList(
       ResourceBundle::BaseFont);
   const int current_font_size = font_list.GetFontSize();
-  const int desired_font_size = GetLayoutConstant(OMNIBOX_FONT_PIXEL_SIZE);
-  if (current_font_size != desired_font_size) {
+  constexpr int kDesiredFontSize = 14;
+  if (current_font_size != kDesiredFontSize) {
     font_list =
-        font_list.DeriveWithSizeDelta(desired_font_size - current_font_size);
+        font_list.DeriveWithSizeDelta(kDesiredFontSize - current_font_size);
   }
   // Shrink large fonts to make them fit.
   // TODO(pkasting): Stretch the location bar instead in this case.
@@ -234,7 +234,7 @@
 
   // Determine the font for use inside the bubbles.
   const int bubble_padding =
-      GetLayoutConstant(LOCATION_BAR_BUBBLE_VERTICAL_PADDING) +
+      kBubbleVerticalPadding +
       GetLayoutConstant(LOCATION_BAR_BUBBLE_FONT_VERTICAL_PADDING);
   const int bubble_height = location_height - (bubble_padding * 2);
 
@@ -490,8 +490,6 @@
 
   min_size.set_height(min_size.height() * size_animation_.GetCurrentValue());
 
-  const int padding = GetLayoutConstant(LOCATION_BAR_HORIZONTAL_PADDING);
-
   // Compute width of omnibox-leading content.
   const int edge_thickness = GetHorizontalEdgeThickness();
   int leading_width = edge_thickness;
@@ -502,7 +500,8 @@
     leading_width +=
         location_icon_view_->GetMinimumSizeForLabelText(security_text).width();
   } else {
-    leading_width += padding + location_icon_view_->GetMinimumSize().width();
+    leading_width +=
+        kHorizontalPadding + location_icon_view_->GetMinimumSize().width();
   }
 
   // Compute width of omnibox-trailing content.
@@ -521,8 +520,8 @@
   }
 
   min_size.set_width(leading_width + omnibox_view_->GetMinimumSize().width() +
-                     2 * padding - omnibox_view_->GetInsets().width() +
-                     trailing_width);
+                     2 * kHorizontalPadding -
+                     omnibox_view_->GetInsets().width() + trailing_width);
   return min_size;
 }
 
@@ -534,8 +533,7 @@
   location_icon_view_->SetVisible(false);
   keyword_hint_view_->SetVisible(false);
 
-  const int item_padding = GetLayoutConstant(LOCATION_BAR_HORIZONTAL_PADDING);
-  const int edge_thickness = GetHorizontalEdgeThickness();
+  constexpr int item_padding = kHorizontalPadding;
 
   LocationBarLayout leading_decorations(
       LocationBarLayout::LEFT_EDGE, item_padding,
@@ -633,6 +631,8 @@
       keyword_hint_view_->SetKeyword(keyword);
   }
 
+  const int edge_thickness = GetHorizontalEdgeThickness();
+
   // Perform layout.
   int full_width = width() - (2 * edge_thickness);
 
@@ -728,18 +728,20 @@
 // LocationBarView, private:
 
 int LocationBarView::IncrementalMinimumWidth(views::View* view) const {
-  return view->visible() ?
-      (GetLayoutConstant(LOCATION_BAR_HORIZONTAL_PADDING) +
-          view->GetMinimumSize().width()) : 0;
+  return view->visible() ? (kHorizontalPadding + view->GetMinimumSize().width())
+                         : 0;
 }
 
 int LocationBarView::GetHorizontalEdgeThickness() const {
-  return is_popup_mode_ ? 0 : GetLayoutConstant(LOCATION_BAR_BORDER_THICKNESS);
+  return is_popup_mode_
+             ? 0
+             : BackgroundWith1PxBorder::kLocationBarBorderThicknessDip;
 }
 
 int LocationBarView::GetTotalVerticalPadding() const {
-  return GetLayoutConstant(LOCATION_BAR_BORDER_THICKNESS) +
-         GetLayoutConstant(LOCATION_BAR_VERTICAL_PADDING);
+  constexpr int kInteriorPadding = 1;
+  return BackgroundWith1PxBorder::kLocationBarBorderThicknessDip +
+         kInteriorPadding;
 }
 
 void LocationBarView::RefreshLocationIcon() {
@@ -1182,9 +1184,10 @@
   // border images are meant to rest atop the toolbar background and parts atop
   // the omnibox background, so we can't just blindly fill our entire bounds.
   gfx::Rect bounds(GetContentsBounds());
-  bounds.Inset(
-      GetHorizontalEdgeThickness(),
-      is_popup_mode_ ? 0 : GetLayoutConstant(LOCATION_BAR_BORDER_THICKNESS));
+  bounds.Inset(GetHorizontalEdgeThickness(),
+               is_popup_mode_
+                   ? 0
+                   : BackgroundWith1PxBorder::kLocationBarBorderThicknessDip);
   SkColor background_color(GetColor(BACKGROUND));
   canvas->FillRect(bounds, background_color);
   const SkColor border_color = GetBorderColor(profile()->IsOffTheRecord());
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.h b/chrome/browser/ui/views/location_bar/location_bar_view.h
index 6ef1642..82fb098 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.h
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.h
@@ -111,6 +111,13 @@
   // Width (and height) of icons in location bar.
   static constexpr int kIconWidth = 16;
 
+  // Space between items in the location bar, as well as between items and the
+  // edges.
+  static constexpr int kHorizontalPadding = 6;
+
+  // The additional vertical padding of a bubble.
+  static constexpr int kBubbleVerticalPadding = 3;
+
   // The location bar view's class name.
   static const char kViewClassName[];
 
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
index d6d3055..8d41cdd 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
@@ -11,7 +11,6 @@
 #include "build/build_config.h"
 #include "chrome/browser/search/search.h"
 #include "chrome/browser/themes/theme_properties.h"
-#include "chrome/browser/ui/layout_constants.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/browser/ui/views/omnibox/omnibox_result_view.h"
 #include "chrome/browser/ui/views/theme_copying_widget.h"
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
index 2a1fc53..fa8546b2 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
@@ -20,7 +20,6 @@
 #include "base/i18n/bidi_line_iterator.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
-#include "chrome/browser/ui/layout_constants.h"
 #include "chrome/browser/ui/views/location_bar/background_with_1_px_border.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h"
@@ -590,20 +589,21 @@
 }
 
 void OmniboxResultView::Layout() {
-  int horizontal_padding =
-      GetLayoutConstant(LOCATION_BAR_HORIZONTAL_PADDING);
+  constexpr int horizontal_padding = LocationBarView::kHorizontalPadding;
   // The horizontal bounds we're given are the outside bounds, so we can match
   // the omnibox border outline shape exactly in OnPaint().  We have to inset
   // here to keep the icons lined up.
-  const int start_x =
-      GetLayoutConstant(LOCATION_BAR_BORDER_THICKNESS) + horizontal_padding;
+  constexpr int start_x =
+      BackgroundWith1PxBorder::kLocationBarBorderThicknessDip +
+      horizontal_padding;
   const int end_x = width() - start_x;
 
   const gfx::ImageSkia icon = GetIcon();
   icon_bounds_.SetRect(start_x, (GetContentLineHeight() - icon.height()) / 2,
                        icon.width(), icon.height());
 
-  const int text_x = start_x + LocationBarView::kIconWidth + horizontal_padding;
+  constexpr int text_x =
+      start_x + LocationBarView::kIconWidth + horizontal_padding;
   int text_width = end_x - text_x;
 
   if (match_.associated_keyword.get()) {
diff --git a/chrome/browser/ui/views/profiles/new_avatar_button.cc b/chrome/browser/ui/views/profiles/new_avatar_button.cc
index 0b7b45a..160c44f 100644
--- a/chrome/browser/ui/views/profiles/new_avatar_button.cc
+++ b/chrome/browser/ui/views/profiles/new_avatar_button.cc
@@ -70,7 +70,8 @@
   // is larger than this, it will be shrunk to match it.
   // TODO(noms): Calculate this constant algorithmically from the button's size.
   const int kDisplayFontHeight = 16;
-  SetFontList(GetFontList().DeriveWithHeightUpperBound(kDisplayFontHeight));
+  SetFontList(
+      label()->font_list().DeriveWithHeightUpperBound(kDisplayFontHeight));
 
   ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
   if (button_style == AvatarButtonStyle::THEMED) {
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.cc b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
index 638f0497..f2a8cfd 100644
--- a/chrome/browser/ui/views/profiles/profile_chooser_view.cc
+++ b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
@@ -534,7 +534,7 @@
     AddChildView(profile_name_textfield_);
 
     button_ = new RightAlignedIconLabelButton(this, text);
-    button_->SetFontList(medium_font_list);
+    button_->SetFontListDeprecated(medium_font_list);
     // Show an "edit" pencil icon when hovering over. In the default state,
     // we need to create an empty placeholder of the correct size, so that
     // the text doesn't jump around when the hovered icon appears.
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc
index 1f39de8..10ea017 100644
--- a/chrome/browser/ui/views/tabs/tab.cc
+++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -728,8 +728,7 @@
 // static
 gfx::Size Tab::GetStandardSize() {
   const int kNetTabWidth = 193;
-  return gfx::Size(kNetTabWidth + GetLayoutConstant(TABSTRIP_TAB_OVERLAP),
-                   GetMinimumInactiveSize().height());
+  return gfx::Size(kNetTabWidth + kOverlap, GetMinimumInactiveSize().height());
 }
 
 // static
@@ -739,8 +738,8 @@
 
 // static
 int Tab::GetPinnedWidth() {
-  return GetMinimumInactiveSize().width() +
-         GetLayoutConstant(TAB_PINNED_CONTENT_WIDTH);
+  constexpr int kTabPinnedContentWidth = 23;
+  return GetMinimumInactiveSize().width() + kTabPinnedContentWidth;
 }
 
 // static
@@ -919,9 +918,9 @@
   // Size the title to fill the remaining width and use all available height.
   const bool show_title = ShouldRenderAsNormalTab();
   if (show_title) {
-    const int title_spacing = GetLayoutConstant(TAB_FAVICON_TITLE_SPACING);
-    int title_left = showing_icon_ ?
-        (favicon_bounds_.right() + title_spacing) : start;
+    constexpr int kTitleSpacing = 6;
+    int title_left =
+        showing_icon_ ? (favicon_bounds_.right() + kTitleSpacing) : start;
     int title_width = lb.right() - title_left;
     if (showing_alert_indicator_) {
       title_width =
diff --git a/chrome/browser/ui/views/tabs/tab.h b/chrome/browser/ui/views/tabs/tab.h
index 9aefb65..180b1d9 100644
--- a/chrome/browser/ui/views/tabs/tab.h
+++ b/chrome/browser/ui/views/tabs/tab.h
@@ -52,6 +52,9 @@
   // The Tab's class name.
   static const char kViewClassName[];
 
+  // The amount of overlap between two adjacent tabs.
+  static constexpr int kOverlap = 16;
+
   Tab(TabController* controller, gfx::AnimationContainer* container);
   ~Tab() override;
 
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc
index 0fb15a9..c5c58a3 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -253,7 +253,7 @@
   tab_size_info->min_active_width = Tab::GetMinimumActiveSize().width();
   tab_size_info->min_inactive_width = Tab::GetMinimumInactiveSize().width();
   tab_size_info->max_size = Tab::GetStandardSize();
-  tab_size_info->tab_overlap = GetLayoutConstant(TABSTRIP_TAB_OVERLAP);
+  tab_size_info->tab_overlap = Tab::kOverlap;
   tab_size_info->pinned_to_normal_offset = kPinnedToNonPinnedOffset;
   return *tab_size_info;
 }
@@ -872,7 +872,7 @@
     Tab* last_tab = tab_at(model_count - 1);
     Tab* tab_being_removed = tab_at(model_index);
     available_width_for_tabs_ = last_tab->x() + last_tab->width() -
-        tab_being_removed->width() + GetLayoutConstant(TABSTRIP_TAB_OVERLAP);
+                                tab_being_removed->width() + Tab::kOverlap;
     if (model_index == 0 && tab_being_removed->data().pinned &&
         !tab_at(1)->data().pinned) {
       available_width_for_tabs_ -= kPinnedToNonPinnedOffset;
@@ -1297,8 +1297,7 @@
     if (current_x < previous_x)
       return true;  // Can happen during dragging.
 
-    if (previous_bounds.right() - GetLayoutConstant(TABSTRIP_TAB_OVERLAP) !=
-        current_x) {
+    if (previous_bounds.right() - Tab::kOverlap != current_x) {
       *clip = border_callback.Run(tab_at(index - 1)->size());
       clip->offset(SkIntToScalar(previous_x - current_x), 0);
     }
@@ -1497,14 +1496,13 @@
       needed_tab_width += kPinnedToNonPinnedOffset + min_selected_width +
                           ((remaining_tab_count - 1) * min_unselected_width);
     }
-    const int tab_overlap = GetLayoutConstant(TABSTRIP_TAB_OVERLAP);
     if (tab_count() > 1)
-      needed_tab_width -= (tab_count() - 1) * tab_overlap;
+      needed_tab_width -= (tab_count() - 1) * Tab::kOverlap;
 
     // Don't let the tabstrip shrink smaller than is necessary to show one tab,
     // and don't force it to be larger than is necessary to show 20 tabs.
     const int largest_min_tab_width =
-        min_selected_width + 19 * (min_unselected_width - tab_overlap);
+        min_selected_width + 19 * (min_unselected_width - Tab::kOverlap);
     needed_tab_width = std::min(
         std::max(needed_tab_width, min_selected_width), largest_min_tab_width);
   }
@@ -1659,9 +1657,9 @@
                    ideal_bounds(model_index).height());
   } else {
     Tab* last_tab = tab_at(model_index - 1);
-    tab->SetBounds(
-        last_tab->bounds().right() - GetLayoutConstant(TABSTRIP_TAB_OVERLAP),
-        ideal_bounds(model_index).y(), 0, ideal_bounds(model_index).height());
+    tab->SetBounds(last_tab->bounds().right() - Tab::kOverlap,
+                   ideal_bounds(model_index).y(), 0,
+                   ideal_bounds(model_index).height());
   }
 
   AnimateToIdealBounds();
@@ -1909,7 +1907,7 @@
     gfx::Rect new_bounds = tab->bounds();
     new_bounds.set_origin(gfx::Point(x, 0));
     bounds->push_back(new_bounds);
-    x += tab->width() - GetLayoutConstant(TABSTRIP_TAB_OVERLAP);
+    x += tab->width() - Tab::kOverlap;
   }
 }
 
@@ -1922,7 +1920,7 @@
       width += kPinnedToNonPinnedOffset;
   }
   if (!tabs.empty())
-    width -= GetLayoutConstant(TABSTRIP_TAB_OVERLAP) * (tabs.size() - 1);
+    width -= Tab::kOverlap * (tabs.size() - 1);
   return width;
 }
 
@@ -2256,13 +2254,12 @@
                                   bool* is_beneath) {
   DCHECK_NE(drop_index, -1);
   int center_x;
-  const int tab_overlap = GetLayoutConstant(TABSTRIP_TAB_OVERLAP);
   if (drop_index < tab_count()) {
     Tab* tab = tab_at(drop_index);
-    center_x = tab->x() + ((drop_before ? tab_overlap : tab->width()) / 2);
+    center_x = tab->x() + ((drop_before ? Tab::kOverlap : tab->width()) / 2);
   } else {
     Tab* last_tab = tab_at(drop_index - 1);
-    center_x = last_tab->x() + last_tab->width() - (tab_overlap / 2);
+    center_x = last_tab->x() + last_tab->width() - (Tab::kOverlap / 2);
   }
 
   // Mirror the center point if necessary.
@@ -2450,8 +2447,7 @@
     tabs_.set_ideal_bounds(i, tab_bounds[i]);
   return (num_pinned_tabs < tab_count())
              ? tab_bounds[num_pinned_tabs].x()
-             : tab_bounds[num_pinned_tabs - 1].right() -
-                   GetLayoutConstant(TABSTRIP_TAB_OVERLAP);
+             : tab_bounds[num_pinned_tabs - 1].right() - Tab::kOverlap;
 }
 
 int TabStrip::GetTabAreaWidth() const {
@@ -2478,7 +2474,7 @@
   // The user initiated the close. We want to persist the bounds of all the
   // existing tabs, so we manually shift ideal_bounds then animate.
   Tab* tab_closing = tab_at(model_index);
-  int delta = tab_closing->width() - GetLayoutConstant(TABSTRIP_TAB_OVERLAP);
+  int delta = tab_closing->width() - Tab::kOverlap;
   // If the tab being closed is a pinned tab next to a non-pinned tab, be sure
   // to add the extra padding.
   DCHECK_LT(model_index, tab_count() - 1);
@@ -2531,8 +2527,7 @@
   int pinned_tab_count = GetPinnedTabCount();
   if (pinned_tab_count == 0)
     return 0;
-  const int overlap = GetLayoutConstant(TABSTRIP_TAB_OVERLAP);
-  return pinned_tab_count * (Tab::GetPinnedWidth() - overlap) +
+  return pinned_tab_count * (Tab::GetPinnedWidth() - Tab::kOverlap) +
          kPinnedToNonPinnedOffset;
 }
 
@@ -2601,11 +2596,7 @@
     gfx::Size tab_size(Tab::GetMinimumActiveSize());
     tab_size.set_width(Tab::GetTouchWidth());
     touch_layout_.reset(new StackedTabStripLayout(
-                            tab_size,
-                            GetLayoutConstant(TABSTRIP_TAB_OVERLAP),
-                            kStackedPadding,
-                            kMaxStackedCount,
-                            &tabs_));
+        tab_size, Tab::kOverlap, kStackedPadding, kMaxStackedCount, &tabs_));
     touch_layout_->SetWidth(GetTabAreaWidth());
     // This has to be after SetWidth() as SetWidth() is going to reset the
     // bounds of the pinned tabs (since StackedTabStripLayout doesn't yet know
@@ -2633,9 +2624,9 @@
   int normal_count = tab_count() - pinned_tab_count;
   if (normal_count <= 1 || normal_count == pinned_tab_count)
     return false;
-  const int overlap = GetLayoutConstant(TABSTRIP_TAB_OVERLAP);
-  return (Tab::GetTouchWidth() * normal_count - overlap * (normal_count - 1)) >
-      GetTabAreaWidth() - GetStartXForNormalTabs();
+  return (Tab::GetTouchWidth() * normal_count -
+          Tab::kOverlap * (normal_count - 1)) >
+         GetTabAreaWidth() - GetStartXForNormalTabs();
 }
 
 void TabStrip::SetResetToShrinkOnExit(bool value) {
diff --git a/chrome/browser/ui/views/toolbar/app_menu_button.cc b/chrome/browser/ui/views/toolbar/app_menu_button.cc
index 58937a5..b66144b7 100644
--- a/chrome/browser/ui/views/toolbar/app_menu_button.cc
+++ b/chrome/browser/ui/views/toolbar/app_menu_button.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/ui/toolbar/app_menu_model.h"
 #include "chrome/browser/ui/views/extensions/browser_action_drag_data.h"
 #include "chrome/browser/ui/views/toolbar/app_menu.h"
+#include "chrome/browser/ui/views/toolbar/toolbar_button.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
 #include "chrome/grit/theme_resources.h"
 #include "extensions/common/feature_switch.h"
@@ -108,10 +109,9 @@
 }
 
 gfx::Size AppMenuButton::GetPreferredSize() const {
-  gfx::Size size(image()->GetPreferredSize());
-  const int pad = GetLayoutConstant(TOOLBAR_BUTTON_PADDING);
-  size.Enlarge(pad * 2, pad * 2);
-  return size;
+  gfx::Rect rect(image()->GetPreferredSize());
+  rect.Inset(gfx::Insets(-ToolbarButton::kInteriorPadding));
+  return rect.size();
 }
 
 void AppMenuButton::UpdateIcon() {
diff --git a/chrome/browser/ui/views/toolbar/toolbar_button.cc b/chrome/browser/ui/views/toolbar/toolbar_button.cc
index 00e427c..57fb60de 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_button.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_button.cc
@@ -12,8 +12,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/themes/theme_service.h"
 #include "chrome/browser/themes/theme_service_factory.h"
-#include "chrome/browser/ui/layout_constants.h"
-#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/models/menu_model.h"
@@ -57,16 +55,10 @@
 }
 
 gfx::Size ToolbarButton::GetPreferredSize() const {
-  gfx::Size size(image()->GetPreferredSize());
-  gfx::Size label_size = label()->GetPreferredSize();
-  if (label_size.width() > 0) {
-    size.Enlarge(
-        label_size.width() + GetLayoutConstant(LOCATION_BAR_HORIZONTAL_PADDING),
-        0);
-  }
-  const int pad = GetLayoutConstant(TOOLBAR_BUTTON_PADDING);
-  size.Enlarge(2 * pad, 2 * pad);
-  return size;
+  DCHECK(label()->text().empty());
+  gfx::Rect rect(gfx::Size(image()->GetPreferredSize()));
+  rect.Inset(gfx::Insets(-kInteriorPadding));
+  return rect.size();
 }
 
 bool ToolbarButton::OnMousePressed(const ui::MouseEvent& event) {
@@ -150,7 +142,7 @@
       views::LabelButton::CreateDefaultBorder();
 
   if (ThemeServiceFactory::GetForProfile(profile_)->UsingSystemTheme())
-    border->set_insets(gfx::Insets(GetLayoutConstant(TOOLBAR_BUTTON_PADDING)));
+    border->set_insets(gfx::Insets(kInteriorPadding));
 
   return border;
 }
diff --git a/chrome/browser/ui/views/toolbar/toolbar_button.h b/chrome/browser/ui/views/toolbar/toolbar_button.h
index c3a3207c..04e0dfa 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_button.h
+++ b/chrome/browser/ui/views/toolbar/toolbar_button.h
@@ -33,6 +33,9 @@
 class ToolbarButton : public views::LabelButton,
                       public views::ContextMenuController {
  public:
+  // Padding inside the border (around the image).
+  static constexpr int kInteriorPadding = 6;
+
   // Takes ownership of the |model|, which can be null if no menu
   // is to be shown.
   ToolbarButton(Profile* profile,
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc
index beae60d..96191078 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -570,8 +570,7 @@
       home_->bounds().right() + GetLayoutConstant(TOOLBAR_STANDARD_SPACING);
 
   int app_menu_width = app_menu_button_->GetPreferredSize().width();
-  const int right_padding =
-      GetLayoutConstant(TOOLBAR_LOCATION_BAR_RIGHT_PADDING);
+  const int right_padding = GetLayoutConstant(TOOLBAR_STANDARD_SPACING);
 
   // Note that the browser actions container has its own internal left and right
   // padding to visually separate it from the location bar and app menu button.
@@ -710,8 +709,6 @@
     const int element_padding = GetLayoutConstant(TOOLBAR_ELEMENT_PADDING);
     const int browser_actions_width =
         (browser_actions_->*get_size)().width();
-    const int right_padding =
-        GetLayoutConstant(TOOLBAR_LOCATION_BAR_RIGHT_PADDING);
     const int content_width =
         2 * GetToolbarHorizontalPadding() + (back_->*get_size)().width() +
         element_padding + (forward_->*get_size)().width() + element_padding +
@@ -720,7 +717,9 @@
              ? element_padding + (home_->*get_size)().width()
              : 0) +
         GetLayoutConstant(TOOLBAR_STANDARD_SPACING) +
-        (browser_actions_width > 0 ? browser_actions_width : right_padding) +
+        (browser_actions_width > 0
+             ? browser_actions_width
+             : GetLayoutConstant(TOOLBAR_STANDARD_SPACING)) +
         (app_menu_button_->*get_size)().width();
     size.Enlarge(content_width, 0);
   }
diff --git a/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.cc
index 2128ca0d..f6f6061 100644
--- a/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.cc
@@ -23,6 +23,7 @@
 #include "components/login/localized_values_builder.h"
 #include "components/strings/grit/components_strings.h"
 #include "content/public/browser/web_contents.h"
+#include "rlz/features/features.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/views/widget/widget.h"
 #include "url/gurl.h"
@@ -131,7 +132,7 @@
   builder->Add("eulaTpmBusy", IDS_EULA_TPM_BUSY);
   builder->Add("eulaSystemInstallationSettingsOkButton", IDS_OK);
   builder->Add("termsOfServiceLoading", IDS_TERMS_OF_SERVICE_SCREEN_LOADING);
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
   builder->AddF("eulaRlzDesc",
                 IDS_EULA_RLZ_DESCRIPTION,
                 IDS_SHORT_PRODUCT_NAME,
@@ -161,7 +162,7 @@
 }
 
 void EulaScreenHandler::GetAdditionalParameters(base::DictionaryValue* dict) {
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
   dict->SetString("rlzEnabled", "enabled");
 #else
   dict->SetString("rlzEnabled", "disabled");
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
index 2b9092ec..c3067a60c 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -894,12 +894,22 @@
 }
 
 void SigninScreenHandler::Initialize() {
-  // If delegate_ is nullptr here (e.g. WebUIScreenLocker has been destroyed),
-  // don't do anything, just return.
-  if (!delegate_)
-    return;
+  // Preload PIN keyboard if any of the users can authenticate via PIN.
+  if (user_manager::UserManager::IsInitialized()) {
+    for (user_manager::User* user :
+         user_manager::UserManager::Get()->GetLoggedInUsers()) {
 
-  if (show_on_init_) {
+      chromeos::PinStorage* pin_storage =
+          chromeos::PinStorageFactory::GetForUser(user);
+      if (pin_storage && pin_storage->IsPinAuthenticationAvailable()) {
+        CallJS("cr.ui.Oobe.preloadPinKeyboard");
+        break;
+      }
+    }
+  }
+
+  // |delegate_| is null when we are preloading the lock screen.
+  if (delegate_ && show_on_init_) {
     show_on_init_ = false;
     ShowImpl();
   }
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 df9faab..fac5055 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
@@ -237,6 +237,9 @@
      IDS_SETTINGS_ABOUT_PAGE_UNSTABLE_WARNING_MESSAGE},
     {"aboutUnstableWarningTitle",
      IDS_SETTINGS_ABOUT_PAGE_UNSTABLE_WARNING_TITLE},
+    {"aboutChannelDialogBeta", IDS_SETTINGS_ABOUT_PAGE_DIALOG_CHANNEL_BETA},
+    {"aboutChannelDialogDev", IDS_SETTINGS_ABOUT_PAGE_DIALOG_CHANNEL_DEV},
+    {"aboutChannelDialogStable", IDS_SETTINGS_ABOUT_PAGE_DIALOG_CHANNEL_STABLE},
 #endif
   };
   AddLocalizedStringsBulk(html_source, localized_strings,
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 769c213e..e656b88 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -1018,8 +1018,14 @@
 const char kHelp[]                          = "help";
 const char kHelpShort[]                     = "h";
 
-// Specifies which password store to use
-// (detect, default, gnome-keyring, gnome-libsecret, kwallet).
+// Specifies which encryption storage backend to use. Possible values are
+// kwallet, kwallet5, gnome, gnome-keyring, gnome-libsecret, basic. Any other
+// value will lead to Chrome detecting the best backend automatically.
+// TODO(crbug.com/571003): Once PasswordStore no longer uses the Keyring or
+// KWallet for storing passwords, rename this flag to stop referencing
+// passwords. Do not rename it sooner, though; developers and testers might
+// rely on it keeping large amounts of testing passwords out of their Keyrings
+// or KWallets.
 const char kPasswordStore[]                 = "password-store";
 
 // The same as the --class argument in X applications.  Overrides the WM_CLASS
diff --git a/chrome/common/stack_sampling_configuration.cc b/chrome/common/stack_sampling_configuration.cc
index ca79f3f..c2b0786 100644
--- a/chrome/common/stack_sampling_configuration.cc
+++ b/chrome/common/stack_sampling_configuration.cc
@@ -128,7 +128,8 @@
   DCHECK(IsBrowserProcess());
 
   if (process_type == switches::kGpuProcess &&
-      (configuration_ == PROFILE_GPU_PROCESS ||
+      (configuration_ == PROFILE_CONTROL ||
+       configuration_ == PROFILE_GPU_PROCESS ||
        configuration_ == PROFILE_BROWSER_AND_GPU_PROCESS)) {
     command_line->AppendSwitch(switches::kStartStackProfiler);
   }
@@ -180,18 +181,18 @@
       return ChooseConfiguration({
         { PROFILE_BROWSER_PROCESS, 0},
         { PROFILE_GPU_PROCESS, 0},
-        { PROFILE_BROWSER_AND_GPU_PROCESS, 50},
-        { PROFILE_CONTROL, 50},
-        { PROFILE_DISABLED, 0}
+        { PROFILE_BROWSER_AND_GPU_PROCESS, 80},
+        { PROFILE_CONTROL, 10},
+        { PROFILE_DISABLED, 10}
       });
 
     case version_info::Channel::DEV:
       return ChooseConfiguration({
         { PROFILE_BROWSER_PROCESS, 0},
         { PROFILE_GPU_PROCESS, 0},
-        { PROFILE_BROWSER_AND_GPU_PROCESS, 50},
-        { PROFILE_CONTROL, 50},
-        { PROFILE_DISABLED, 0}
+        { PROFILE_BROWSER_AND_GPU_PROCESS, 80},
+        { PROFILE_CONTROL, 10},
+        { PROFILE_DISABLED, 10}
       });
 
     default:
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index e39ee89..8aa3629 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -16,6 +16,7 @@
 import("//media/media_options.gni")
 import("//ppapi/features/features.gni")
 import("//remoting/remoting_enable.gni")
+import("//rlz/features/features.gni")
 import("//services/service_manager/public/service_manifest.gni")
 import("//testing/test.gni")
 import("//ui/base/ui_features.gni")
@@ -1228,6 +1229,7 @@
     "//media:media_features",
     "//ppapi/features",
     "//printing/features",
+    "//rlz/features",
     "//third_party/WebKit/public:features",
   ]
 
@@ -4757,6 +4759,9 @@
       "../browser/ui/views/apps/app_info_dialog/app_info_permissions_panel_unittest.cc",
       "../browser/ui/views/website_settings/website_settings_popup_view_unittest.cc",
     ]
+    if (is_chromeos) {
+      sources += [ "../browser/ui/views/ime_driver/input_method_bridge_chromeos_unittest.cc" ]
+    }
     if (!is_chromeos && (!is_mac || mac_views_browser)) {
       sources += [
         "../browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc",
diff --git a/chrome/test/DEPS b/chrome/test/DEPS
index 254e0473..a975b8f 100644
--- a/chrome/test/DEPS
+++ b/chrome/test/DEPS
@@ -11,6 +11,7 @@
   "+extensions",
   "+mash/package",
   "+mojo",
+  "+rlz/features",
   "+services",
 
   # Tests under chrome/ shouldn't need to access the internals of content/ and
diff --git a/chrome/test/data/extensions/api_test/cast_channel/api/common.js b/chrome/test/data/extensions/api_test/cast_channel/api/common.js
index eabcc5cd..2eda086 100644
--- a/chrome/test/data/extensions/api_test/cast_channel/api/common.js
+++ b/chrome/test/data/extensions/api_test/cast_channel/api/common.js
@@ -8,7 +8,7 @@
   chrome.test.assertTrue(channel.channelId > 0);
   chrome.test.assertTrue(channel.connectInfo.ipAddress == '192.168.1.1');
   chrome.test.assertTrue(channel.connectInfo.port == 8009);
-  chrome.test.assertTrue(channel.connectInfo.auth == 'ssl');
+  chrome.test.assertTrue(channel.connectInfo.auth == 'ssl_verified');
   chrome.test.assertTrue(channel.readyState == 'open');
   chrome.test.assertTrue(channel.errorState == undefined);
 };
@@ -23,7 +23,7 @@
   chrome.test.assertTrue(channel.channelId > 0);
   chrome.test.assertTrue(channel.connectInfo.ipAddress == '192.168.1.1');
   chrome.test.assertTrue(channel.connectInfo.port == 8009);
-  chrome.test.assertTrue(channel.connectInfo.auth == 'ssl');
+  chrome.test.assertTrue(channel.connectInfo.auth == 'ssl_verified');
   chrome.test.assertTrue(channel.readyState == 'closed');
   chrome.test.assertTrue(channel.errorState == error);
 };
diff --git a/chrome/test/data/extensions/api_test/cast_channel/api/test_get_logs.js b/chrome/test/data/extensions/api_test/cast_channel/api/test_get_logs.js
index 99acf9f..315029b 100644
--- a/chrome/test/data/extensions/api_test/cast_channel/api/test_get_logs.js
+++ b/chrome/test/data/extensions/api_test/cast_channel/api/test_get_logs.js
@@ -29,5 +29,8 @@
   chrome.cast.channel.send(channel, message, onSend);
 };
 
-chrome.cast.channel.open({ipAddress: '192.168.1.1', port: 8009, auth: 'ssl'},
-                         onOpen);
+chrome.cast.channel.open({
+  ipAddress: '192.168.1.1',
+  port: 8009,
+  auth: 'ssl_verified'
+}, onOpen);
diff --git a/chrome/test/data/extensions/api_test/cast_channel/api/test_open_error.js b/chrome/test/data/extensions/api_test/cast_channel/api/test_open_error.js
index 3637ab3..2df11f6 100644
--- a/chrome/test/data/extensions/api_test/cast_channel/api/test_open_error.js
+++ b/chrome/test/data/extensions/api_test/cast_channel/api/test_open_error.js
@@ -33,5 +33,7 @@
 };
 
 chrome.cast.channel.onError.addListener(onError);
-chrome.cast.channel.open({ipAddress: '192.168.1.1', port: 8009, auth: 'ssl'},
-                         onOpen);
+chrome.cast.channel.open({
+  ipAddress: '192.168.1.1',
+  port: 8009,
+  auth: 'ssl_verified'}, onOpen);
diff --git a/chrome/test/data/extensions/api_test/cast_channel/api/test_open_receive_close.js b/chrome/test/data/extensions/api_test/cast_channel/api/test_open_receive_close.js
index 6fe6a79..36c255dc 100644
--- a/chrome/test/data/extensions/api_test/cast_channel/api/test_open_receive_close.js
+++ b/chrome/test/data/extensions/api_test/cast_channel/api/test_open_receive_close.js
@@ -30,5 +30,7 @@
   chrome.test.notifyPass();
 };
 
-chrome.cast.channel.open({ipAddress: '192.168.1.1', port: 8009, auth: 'ssl'},
-                         onOpen);
+chrome.cast.channel.open({
+  ipAddress: '192.168.1.1',
+  port: 8009,
+  auth: 'ssl_verified'}, onOpen);
diff --git a/chrome/test/data/extensions/api_test/cast_channel/api/test_open_send_close.js b/chrome/test/data/extensions/api_test/cast_channel/api/test_open_send_close.js
index 4afce56..6ec4ad5 100644
--- a/chrome/test/data/extensions/api_test/cast_channel/api/test_open_send_close.js
+++ b/chrome/test/data/extensions/api_test/cast_channel/api/test_open_send_close.js
@@ -23,6 +23,7 @@
   assertOpenChannel(channel);
   chrome.cast.channel.send(channel, message, onSend);
 };
-
-chrome.cast.channel.open({ipAddress: '192.168.1.1', port: 8009, auth: 'ssl'},
-                         onOpen);
+chrome.cast.channel.open({
+  ipAddress: '192.168.1.1',
+  port: 8009,
+  auth: 'ssl_verified'}, onOpen);
diff --git a/chrome/test/data/extensions/api_test/cast_channel/api/test_open_timeout.js b/chrome/test/data/extensions/api_test/cast_channel/api/test_open_timeout.js
index 348974e..f8949ffd 100644
--- a/chrome/test/data/extensions/api_test/cast_channel/api/test_open_timeout.js
+++ b/chrome/test/data/extensions/api_test/cast_channel/api/test_open_timeout.js
@@ -6,7 +6,7 @@
 chrome.cast.channel.open({
   ipAddress: '192.168.1.1',
   port: 8009,
-  auth: 'ssl',
+  auth: 'ssl_verified',
   livenessTimeout: 5000,
   pingInterval: 1000
 }, function(channel) {
diff --git a/chrome/test/data/extensions/api_test/platform_keys/basic.js b/chrome/test/data/extensions/api_test/platform_keys/basic.js
index 5e1eccba..ee4516d3 100644
--- a/chrome/test/data/extensions/api_test/platform_keys/basic.js
+++ b/chrome/test/data/extensions/api_test/platform_keys/basic.js
@@ -36,39 +36,38 @@
 
   // X.509 client certificate in DER encoding.
   // Algorithm in SPKI: rsaEncryption.
-  // openssl x509 -in net/data/ssl/certificates/client_1.pem -outform DER -out
-  //   client_1.der
+  // Generated by create_net_cert_data.sh .
   client_1: 'client_1.der',
 
   // X.509 client certificate in DER encoding.
   // Algorithm in SPKI: rsaEncryption.
-  // openssl x509 -in net/data/ssl/certificates/client_2.pem -outform DER -out
-  //   client_2.der
+  // Generated by create_net_cert_data.sh .
   client_2: 'client_2.der',
 
   // The public key of client_1 as Subject Public Key Info in DER encoding.
-  // openssl rsa -in net/data/ssl/certificates/client_1.key -inform PEM -out
-  //   pubkey.der -pubout -outform DER
+  // Generated by create_net_cert_data.sh .
   client_1_spki: 'client_1_spki.der',
 
   // The distinguished name of the CA that issued client_1 in DER encoding.
-  // openssl asn1parse -in client_1.der -inform DER -strparse 32 -out
-  //   client_1_issuer_dn.der
+  // Generated by create_net_cert_data.sh .
   client_1_issuer_dn: 'client_1_issuer_dn.der',
 
-  // echo -n "hello world" > data
+  // The string "hello world".
+  // Generated by create_net_cert_data.sh .
   raw_data: 'data',
 
-  // openssl rsautl -inkey net/data/ssl/certificates/client_1.key -sign -in
-  //   data -pkcs -out signature_nohash_pkcs
+  // A signature of raw_data using RSASSA-PKCS1-v1_5 with client_1, but treating
+  // raw_data as a raw digest and without adding the DigestInfo prefix.
+  // Generated by create_net_cert_data.sh .
   signature_nohash_pkcs: 'signature_nohash_pkcs',
 
-  // openssl dgst -sha1 -sign net/data/ssl/certificates/client_1.key
-  //   -out signature_sha1_pkcs data
+  // A signature of raw_data using RSASSA-PKCS1-v1_5 with client_1, using SHA-1
+  // as the hash function.
+  // Generated by create_net_cert_data.sh .
   signature_sha1_pkcs: 'signature_sha1_pkcs',
 };
 
-// Reads the binary file at |path| and passes it as a Uin8Array to |callback|.
+// Reads the binary file at |path| and passes it as a Uint8Array to |callback|.
 function readFile(path, callback) {
   var oReq = new XMLHttpRequest();
   oReq.responseType = "arraybuffer";
diff --git a/chrome/test/data/extensions/api_test/platform_keys/client_1.der b/chrome/test/data/extensions/api_test/platform_keys/client_1.der
index 248df92..a5d1da179a 100644
--- a/chrome/test/data/extensions/api_test/platform_keys/client_1.der
+++ b/chrome/test/data/extensions/api_test/platform_keys/client_1.der
Binary files differ
diff --git a/chrome/test/data/extensions/api_test/platform_keys/client_1_spki.der b/chrome/test/data/extensions/api_test/platform_keys/client_1_spki.der
index 7bd2e3f..55a79d4 100644
--- a/chrome/test/data/extensions/api_test/platform_keys/client_1_spki.der
+++ b/chrome/test/data/extensions/api_test/platform_keys/client_1_spki.der
Binary files differ
diff --git a/chrome/test/data/extensions/api_test/platform_keys/client_2.der b/chrome/test/data/extensions/api_test/platform_keys/client_2.der
index e2de8cb..8f49092 100644
--- a/chrome/test/data/extensions/api_test/platform_keys/client_2.der
+++ b/chrome/test/data/extensions/api_test/platform_keys/client_2.der
Binary files differ
diff --git a/chrome/test/data/extensions/api_test/platform_keys/create_net_cert_data.sh b/chrome/test/data/extensions/api_test/platform_keys/create_net_cert_data.sh
new file mode 100755
index 0000000..45e87b6
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/platform_keys/create_net_cert_data.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# 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.
+
+# Updates the files which depend on net/data/ssl/certificates.
+
+try() {
+  "$@" || {
+    e=$?
+    echo "*** ERROR $e ***  $@  " > /dev/stderr
+    exit $e
+  }
+}
+
+net_certs_dir=../../../../../../net/data/ssl/certificates
+
+try openssl x509 -in "${net_certs_dir}/client_1.pem" -outform DER -out \
+  client_1.der
+try openssl x509 -in "${net_certs_dir}/client_2.pem" -outform DER -out \
+  client_2.der
+try openssl rsa -in "${net_certs_dir}/client_1.key" -inform PEM -out \
+  client_1_spki.der -pubout -outform DER
+try openssl asn1parse -in client_1.der -inform DER -strparse 32 -out \
+  client_1_issuer_dn.der
+try echo -n "hello world" > data
+try openssl rsautl -inkey "${net_certs_dir}/client_1.key" -sign -in \
+   data -pkcs -out signature_nohash_pkcs
+try openssl dgst -sha1 -sign "${net_certs_dir}/client_1.key" -out \
+   signature_sha1_pkcs data
diff --git a/chrome/test/data/extensions/api_test/platform_keys/signature_nohash_pkcs b/chrome/test/data/extensions/api_test/platform_keys/signature_nohash_pkcs
index 36784aa..bf916de 100644
--- a/chrome/test/data/extensions/api_test/platform_keys/signature_nohash_pkcs
+++ b/chrome/test/data/extensions/api_test/platform_keys/signature_nohash_pkcs
Binary files differ
diff --git a/chrome/test/data/extensions/api_test/platform_keys/signature_sha1_pkcs b/chrome/test/data/extensions/api_test/platform_keys/signature_sha1_pkcs
index c4b768e..e8d5e25 100644
--- a/chrome/test/data/extensions/api_test/platform_keys/signature_sha1_pkcs
+++ b/chrome/test/data/extensions/api_test/platform_keys/signature_sha1_pkcs
Binary files differ
diff --git a/chrome/test/data/webui/bluetooth_internals_browsertest.js b/chrome/test/data/webui/bluetooth_internals_browsertest.js
index 8d15b7d..ae30e2da9 100644
--- a/chrome/test/data/webui/bluetooth_internals_browsertest.js
+++ b/chrome/test/data/webui/bluetooth_internals_browsertest.js
@@ -67,7 +67,8 @@
           ]);
 
           this.adapter = new TestAdapter();
-          this.adapterHandle_ = connection.bindStubDerivedImpl(this.adapter);
+          this.adapterBinding_ = new bindings.Binding(adapter.Adapter,
+                                                      this.adapter);
         };
 
         TestAdapterFactoryProxy.prototype = {
@@ -77,7 +78,7 @@
 
             // Create message pipe bound to TestAdapter.
             return Promise.resolve({
-              adapter: this.adapterHandle_,
+              adapter: this.adapterBinding_.createInterfacePtrAndBind(),
             });
           }
         };
diff --git a/chrome/test/ppapi/ppapi_browsertest.cc b/chrome/test/ppapi/ppapi_browsertest.cc
index a191672..e78ed0a 100644
--- a/chrome/test/ppapi/ppapi_browsertest.cc
+++ b/chrome/test/ppapi/ppapi_browsertest.cc
@@ -31,6 +31,7 @@
 #include "extensions/common/constants.h"
 #include "extensions/test/extension_test_message_listener.h"
 #include "ppapi/shared_impl/test_utils.h"
+#include "rlz/features/features.h"
 
 #if defined(OS_MACOSX)
 #include "base/mac/mac_util.h"
@@ -1233,7 +1234,7 @@
 
 IN_PROC_BROWSER_TEST_F(OutOfProcessPPAPITest, FlashDRM) {
   RunTest(
-#if (defined(OS_WIN) && defined(ENABLE_RLZ)) || defined(OS_CHROMEOS)
+#if (defined(OS_WIN) && BUILDFLAG(ENABLE_RLZ)) || defined(OS_CHROMEOS)
           // Only implemented on Windows and ChromeOS currently.
           LIST_TEST(FlashDRM_GetDeviceID)
 #endif
diff --git a/chrome/tools/build/win/create_installer_archive.py b/chrome/tools/build/win/create_installer_archive.py
index 8c0f814..4a4f0807 100755
--- a/chrome/tools/build/win/create_installer_archive.py
+++ b/chrome/tools/build/win/create_installer_archive.py
@@ -485,30 +485,8 @@
   if not os.path.exists(installer_dir):
     os.mkdir(installer_dir)
 
-  if setup_runtime_deps:
-    setup_component_dlls = ParseDLLsFromDeps(build_dir, setup_runtime_deps)
-  else:
-    # Explicitly list the component DLLs setup.exe depends on (this list may
-    # contain wildcards). These will be copied to |installer_dir| in the
-    # archive.
-    # TODO(jbauman): Remove when GYP is deprecated on Windows.
-    setup_component_dll_globs = [ 'api-ms-win-*.dll',
-                                  'base.dll',
-                                  'boringssl.dll',
-                                  'crcrypto.dll',
-                                  'icui18n.dll',
-                                  'icuuc.dll',
-                                  'msvc*.dll',
-                                  'ucrtbase*.dll',
-                                  'vcruntime*.dll', ]
-    setup_component_dlls = set()
-    for setup_component_dll_glob in setup_component_dll_globs:
-      setup_component_partial_dlls = glob.glob(
-          os.path.join(build_dir, setup_component_dll_glob))
-      if len(setup_component_partial_dlls) == 0:
-        raise Exception('Error: missing expected DLL for component build '
-                        'mini_installer: "%s"' % setup_component_dll_glob)
-      setup_component_dlls.update(setup_component_partial_dlls)
+  setup_component_dlls = ParseDLLsFromDeps(build_dir, setup_runtime_deps)
+
   for setup_component_dll in setup_component_dlls:
     g_archive_inputs.append(setup_component_dll)
     shutil.copy(setup_component_dll, installer_dir)
@@ -517,26 +495,13 @@
   # the version assembly to be able to refer to them below and make sure
   # chrome.exe can find them at runtime), except the ones that are already
   # staged (i.e. non-component DLLs).
-  if chrome_runtime_deps:
-    build_dlls = ParseDLLsFromDeps(build_dir, chrome_runtime_deps)
-  else:
-    # If no chrome_runtime_deps was specified, every DLL in build_dir is
-    # considered to be a component DLL.
-    # TODO(jbauman): Remove when GYP is deprecated on Windows.
-    build_dlls = glob.glob(os.path.join(build_dir, '*.dll'))
+  build_dlls = ParseDLLsFromDeps(build_dir, chrome_runtime_deps)
   staged_dll_basenames = [os.path.basename(staged_dll) for staged_dll in \
                           glob.glob(os.path.join(version_dir, '*.dll'))]
   component_dll_filenames = []
   for component_dll in [dll for dll in build_dlls if \
                         os.path.basename(dll) not in staged_dll_basenames]:
     component_dll_name = os.path.basename(component_dll)
-    # These remoting_*.dll's don't belong in the archive (it doesn't depend
-    # on them in gyp). Trying to copy them causes a build race when creating the
-    # installer archive in component mode. See: crbug.com/180996 and
-    # crbug.com/586967
-    if (component_dll_name.startswith('remoting_')):
-      continue
-
     component_dll_filenames.append(component_dll_name)
     g_archive_inputs.append(component_dll)
     shutil.copy(component_dll, version_dir)
@@ -646,9 +611,6 @@
   parser.add_option('--depfile',
       help='Generate a depfile with the given name listing the implicit inputs '
            'to the archive process that can be used with a build system.')
-
-  # TODO(jbauman): Make --chrome_runtime_deps and --setup_runtime_deps
-  # mandatory when GYP is deprecated on Windows.
   parser.add_option('--chrome_runtime_deps',
       help='A file listing runtime dependencies. This will be used to get a '
            'list of DLLs to archive in a component build.')
@@ -674,6 +636,12 @@
   if not options.input_file:
     parser.error('You must provide an input file')
 
+  is_component_build = options.component_build == '1'
+  if is_component_build and not options.chrome_runtime_deps:
+    parser.error("chrome_runtime_deps must be specified for a component build")
+  if is_component_build and not options.setup_runtime_deps:
+    parser.error("setup_runtime_deps must be specified for a component build")
+
   if not options.output_dir:
     options.output_dir = options.build_dir
 
diff --git a/chrome/utility/chrome_content_utility_client.cc b/chrome/utility/chrome_content_utility_client.cc
index f364d639..f95ceadf 100644
--- a/chrome/utility/chrome_content_utility_client.cc
+++ b/chrome/utility/chrome_content_utility_client.cc
@@ -204,7 +204,7 @@
   registry->AddInterface<net::interfaces::ProxyResolverFactory>(
       base::Bind(CreateProxyResolverFactory));
   registry->AddInterface(base::Bind(CreateResourceUsageReporter));
-  registry->AddInterface(base::Bind(ProfileImportHandler::Create));
+  registry->AddInterface(base::Bind(&ProfileImportHandler::Create));
 #endif
   registry->AddInterface(
       base::Bind(&safe_json::SafeJsonParserMojoImpl::Create));
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn
index c2ab7a3..edf45a1 100644
--- a/chromecast/BUILD.gn
+++ b/chromecast/BUILD.gn
@@ -85,7 +85,6 @@
       args = [
         "--no-sandbox",
         "--enable-local-file-accesses",
-        "--enable-cma-media-pipeline",
         "--ozone-platform=cast",
         "--test-launcher-jobs=1",
       ]
diff --git a/chromecast/base/metrics/BUILD.gn b/chromecast/base/metrics/BUILD.gn
index a9556a5..c547e8fa 100644
--- a/chromecast/base/metrics/BUILD.gn
+++ b/chromecast/base/metrics/BUILD.gn
@@ -22,6 +22,8 @@
   sources = [
     "cast_metrics_test_helper.cc",
     "cast_metrics_test_helper.h",
+    "mock_cast_metrics_helper.cc",
+    "mock_cast_metrics_helper.h",
   ]
 
   public_deps = [
@@ -30,5 +32,6 @@
 
   deps = [
     "//base",
+    "//testing/gmock",
   ]
 }
diff --git a/chromecast/base/metrics/mock_cast_metrics_helper.cc b/chromecast/base/metrics/mock_cast_metrics_helper.cc
new file mode 100644
index 0000000..2af76e04
--- /dev/null
+++ b/chromecast/base/metrics/mock_cast_metrics_helper.cc
@@ -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.
+
+#include "chromecast/base/metrics/mock_cast_metrics_helper.h"
+
+namespace chromecast {
+namespace metrics {
+
+MockCastMetricsHelper::MockCastMetricsHelper() = default;
+
+MockCastMetricsHelper::~MockCastMetricsHelper() = default;
+
+}  // namespace metrics
+}  // namespace chromecast
diff --git a/chromecast/base/metrics/mock_cast_metrics_helper.h b/chromecast/base/metrics/mock_cast_metrics_helper.h
new file mode 100644
index 0000000..7436620
--- /dev/null
+++ b/chromecast/base/metrics/mock_cast_metrics_helper.h
@@ -0,0 +1,49 @@
+// 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 CHROMECAST_BASE_METRICS_MOCK_CAST_METRICS_HELPER_H_
+#define CHROMECAST_BASE_METRICS_MOCK_CAST_METRICS_HELPER_H_
+
+#include "base/macros.h"
+#include "chromecast/base/metrics/cast_metrics_helper.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace chromecast {
+namespace metrics {
+
+class MockCastMetricsHelper : public CastMetricsHelper {
+ public:
+  MockCastMetricsHelper();
+  ~MockCastMetricsHelper() override;
+
+  MOCK_METHOD2(UpdateCurrentAppInfo,
+               void(const std::string& app_id, const std::string& session_id));
+  MOCK_METHOD1(UpdateSDKInfo, void(const std::string& sdk_version));
+  MOCK_METHOD0(LogMediaPlay, void());
+  MOCK_METHOD0(LogMediaPause, void());
+  MOCK_METHOD1(RecordSimpleAction, void(const std::string& action));
+  MOCK_METHOD2(RecordEventWithValue,
+               void(const std::string& action, int value));
+  MOCK_METHOD1(RecordApplicationEvent, void(const std::string& event));
+  MOCK_METHOD2(RecordApplicationEventWithValue,
+               void(const std::string& event, int value));
+  MOCK_METHOD0(LogTimeToFirstPaint, void());
+  MOCK_METHOD0(LogTimeToFirstAudio, void());
+  MOCK_METHOD2(LogTimeToBufferAv,
+               void(BufferingType buffering_type, base::TimeDelta time));
+  MOCK_CONST_METHOD2(GetMetricsNameWithAppName,
+                     std::string(const std::string& prefix,
+                                 const std::string& suffix));
+  MOCK_METHOD1(SetMetricsSink, void(MetricsSink* delegate));
+  MOCK_METHOD1(SetRecordActionCallback,
+               void(const RecordActionCallback& callback));
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockCastMetricsHelper);
+};
+
+}  // namespace metrics
+}  // namespace chromecast
+
+#endif  // CHROMECAST_BASE_METRICS_MOCK_CAST_METRICS_HELPER_H_
diff --git a/chromecast/browser/android/apk/AndroidManifest.xml.jinja2 b/chromecast/browser/android/apk/AndroidManifest.xml.jinja2
index 01e6497..b977a9dd 100644
--- a/chromecast/browser/android/apk/AndroidManifest.xml.jinja2
+++ b/chromecast/browser/android/apk/AndroidManifest.xml.jinja2
@@ -44,7 +44,7 @@
                  android:exported="false" />
         {% endfor %}
 
-        {% set num_privileged_services = 20 %}
+        {% set num_privileged_services = 3 %}
         <meta-data android:name="org.chromium.content.browser.NUM_PRIVILEGED_SERVICES"
                    android:value="{{ num_privileged_services }}"/>
         {% for i in range(num_privileged_services) %}
diff --git a/chromecast/renderer/cast_content_renderer_client.cc b/chromecast/renderer/cast_content_renderer_client.cc
index c3d1419..125c4bd 100644
--- a/chromecast/renderer/cast_content_renderer_client.cc
+++ b/chromecast/renderer/cast_content_renderer_client.cc
@@ -170,6 +170,7 @@
   static const int mojo_resource_ids[] = {
       IDR_MOJO_UNICODE_JS,
       IDR_MOJO_BUFFER_JS,
+      IDR_MOJO_INTERFACE_TYPES_JS,
       IDR_MOJO_CODEC_JS,
       IDR_MOJO_CONNECTOR_JS,
       IDR_MOJO_VALIDATOR_JS,
diff --git a/components/BUILD.gn b/components/BUILD.gn
index d57d240..bfe31f2 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -6,6 +6,7 @@
 import("//build/config/features.gni")
 import("//build/config/ui.gni")
 import("//printing/features/features.gni")
+import("//rlz/features/features.gni")
 import("//testing/test.gni")
 import("//tools/grit/repack.gni")
 
diff --git a/components/arc/BUILD.gn b/components/arc/BUILD.gn
index c09d970..155d286 100644
--- a/components/arc/BUILD.gn
+++ b/components/arc/BUILD.gn
@@ -64,8 +64,6 @@
     "power/arc_power_bridge.h",
     "storage_manager/arc_storage_manager.cc",
     "storage_manager/arc_storage_manager.h",
-    "user_data/arc_user_data_service.cc",
-    "user_data/arc_user_data_service.h",
   ]
 
   public_deps = [
diff --git a/components/arc/user_data/arc_user_data_service.cc b/components/arc/user_data/arc_user_data_service.cc
deleted file mode 100644
index b9b3082f..0000000
--- a/components/arc/user_data/arc_user_data_service.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/arc/user_data/arc_user_data_service.h"
-
-#include <utility>
-
-#include "base/command_line.h"
-#include "chromeos/chromeos_switches.h"
-#include "chromeos/cryptohome/cryptohome_parameters.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "components/prefs/pref_member.h"
-#include "components/signin/core/account_id/account_id.h"
-#include "components/user_manager/user_manager.h"
-
-namespace arc {
-
-ArcUserDataService::ArcUserDataService(
-    ArcBridgeService* bridge_service,
-    std::unique_ptr<BooleanPrefMember> arc_enabled_pref,
-    const AccountId& account_id)
-    : ArcService(bridge_service),
-      arc_enabled_pref_(std::move(arc_enabled_pref)),
-      primary_user_account_id_(account_id),
-      weak_ptr_factory_(this) {
-  arc_bridge_service()->AddObserver(this);
-  pref_change_registrar_.Init(arc_enabled_pref_->prefs());
-  pref_change_registrar_.Add(
-      arc_enabled_pref_->GetPrefName(),
-      base::Bind(&ArcUserDataService::OnOptInPreferenceChanged,
-                 weak_ptr_factory_.GetWeakPtr()));
-  WipeIfRequired();
-}
-
-ArcUserDataService::~ArcUserDataService() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  arc_bridge_service()->RemoveObserver(this);
-}
-
-void ArcUserDataService::OnBridgeStopped(ArcBridgeService::StopReason reason) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  const AccountId& account_id =
-      user_manager::UserManager::Get()->GetPrimaryUser()->GetAccountId();
-  if (account_id != primary_user_account_id_) {
-    LOG(ERROR) << "User preferences not loaded for "
-               << primary_user_account_id_.GetUserEmail()
-               << ", but current primary user is " << account_id.GetUserEmail();
-    primary_user_account_id_ = EmptyAccountId();
-    return;
-  }
-  WipeIfRequired();
-}
-
-void ArcUserDataService::RequireUserDataWiped(const ArcDataCallback& callback) {
-  VLOG(1) << "Require ARC user data to be wiped.";
-  arc_user_data_wipe_required_ = true;
-  callback_ = callback;
-}
-
-void ArcUserDataService::WipeIfRequired() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  if (!arc_bridge_service()->stopped()) {
-    LOG(ERROR) << "ARC instance not stopped, user data can't be wiped";
-    return;
-  }
-  if ((arc_enabled_pref_->GetValue() && !arc_user_data_wipe_required_) ||
-      base::CommandLine::ForCurrentProcess()->HasSwitch(
-          chromeos::switches::kDisableArcDataWipe)) {
-    return;
-  }
-  VLOG(1) << "Wipe ARC user data.";
-  arc_user_data_wipe_required_ = false;
-  const cryptohome::Identification cryptohome_id(primary_user_account_id_);
-  chromeos::SessionManagerClient* session_manager_client =
-      chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
-  session_manager_client->RemoveArcData(cryptohome_id, callback_);
-  callback_.Reset();
-}
-
-void ArcUserDataService::OnOptInPreferenceChanged() {
-  if (!arc_enabled_pref_->GetValue())
-    arc_user_data_wipe_required_ = true;
-}
-
-}  // namespace arc
diff --git a/components/arc/user_data/arc_user_data_service.h b/components/arc/user_data/arc_user_data_service.h
deleted file mode 100644
index 1ac89a2..0000000
--- a/components/arc/user_data/arc_user_data_service.h
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_ARC_USER_DATA_ARC_USER_DATA_SERVICE_H_
-#define COMPONENTS_ARC_USER_DATA_ARC_USER_DATA_SERVICE_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/threading/thread_checker.h"
-#include "chromeos/dbus/session_manager_client.h"
-#include "components/arc/arc_bridge_service.h"
-#include "components/arc/arc_service.h"
-#include "components/prefs/pref_change_registrar.h"
-#include "components/prefs/pref_member.h"
-#include "components/signin/core/account_id/account_id.h"
-
-namespace arc {
-
-class ArcBridgeService;
-
-// This class controls the lifecycle of ARC user data, removing it when
-// necessary.
-class ArcUserDataService : public ArcService,
-                           public ArcBridgeService::Observer {
- public:
-  explicit ArcUserDataService(
-      ArcBridgeService* arc_bridge_service,
-      std::unique_ptr<BooleanPrefMember> arc_enabled_pref,
-      const AccountId& account_id);
-  ~ArcUserDataService() override;
-
-  using ArcDataCallback = chromeos::SessionManagerClient::ArcCallback;
-
-  // ArcBridgeService::Observer:
-  // Called whenever the arc bridge is stopped to potentially wipe data if
-  // the user has not opted in or it is required.
-  void OnBridgeStopped(ArcBridgeService::StopReason reason) override;
-
-  // Requires to wipe ARC user data after the next ARC bridge shutdown and call
-  // |callback| with an operation result.
-  void RequireUserDataWiped(const ArcDataCallback& callback);
-
- private:
-  base::ThreadChecker thread_checker_;
-
-  // Checks if ARC is both stopped and disabled (not opt-in) or data wipe is
-  // required and triggers removal of user data.
-  void WipeIfRequired();
-
-  // Callback when the kArcEnabled preference changes. It watches for instances
-  // where the preference is disabled and remembers this so that it can wipe
-  // user data once the bridge has stopped.
-  void OnOptInPreferenceChanged();
-
-  const std::unique_ptr<BooleanPrefMember> arc_enabled_pref_;
-
-  // Account ID for the account for which we currently have opt-in information.
-  AccountId primary_user_account_id_;
-
-  // Registrar used to monitor ARC enabled state.
-  PrefChangeRegistrar pref_change_registrar_;
-
-  // Set to true when kArcEnabled goes from true to false or user data wipe is
-  // required and set to false again after user data has been wiped.
-  // This ensures data is wiped even if the user tries to enable ARC before the
-  // bridge has shut down.
-  bool arc_user_data_wipe_required_ = false;
-
-  // Callback object that is passed to RemoveArcData to be invoked with a
-  // result of ARC user data wipe.
-  // Set when ARC user data wipe is required by RequireUserDataWiped.
-  ArcDataCallback callback_;
-
-  base::WeakPtrFactory<ArcUserDataService> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(ArcUserDataService);
-};
-
-}  // namespace arc
-
-#endif  // COMPONENTS_ARC_USER_DATA_ARC_USER_DATA_SERVICE_H_
diff --git a/components/autofill/DEPS b/components/autofill/DEPS
index 7e8eeb9..6b6ca5cf 100644
--- a/components/autofill/DEPS
+++ b/components/autofill/DEPS
@@ -4,6 +4,7 @@
   "+grit",  # For generated headers
   "+jni",
   "+net",
+  "+third_party/skia",
   "+third_party/zlib/google",
   "+ui",
 
diff --git a/components/autofill/android/java/src/org/chromium/components/autofill/AutofillPopup.java b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillPopup.java
index 55c214f..3a5bd06 100644
--- a/components/autofill/android/java/src/org/chromium/components/autofill/AutofillPopup.java
+++ b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillPopup.java
@@ -6,6 +6,7 @@
 
 import android.annotation.SuppressLint;
 import android.content.Context;
+import android.graphics.Color;
 import android.view.View;
 import android.widget.AdapterView;
 import android.widget.PopupWindow;
@@ -28,7 +29,8 @@
 
     /**
      * The constant used to specify a separator in a list of Autofill suggestions.
-     * Has to be kept in sync with enum in WebAutofillClient.h
+     * Has to be kept in sync with {@code POPUP_ITEM_ID_SEPARATOR} enum in
+     * components/autofill/core/browser/popup_item_ids.h
      */
     private static final int ITEM_ID_SEPARATOR_ENTRY = -3;
 
@@ -57,9 +59,18 @@
     /**
      * Filters the Autofill suggestions to the ones that we support and shows the popup.
      * @param suggestions Autofill suggestion data.
+     * @param isRtl @code true if right-to-left text.
+     * @param backgroundColor popup background color, or {@code Color.TRANSPARENT} if unspecified.
+     * @param dividerColor color for divider between popup items, or {@code Color.TRANSPARENT} if
+     * unspecified.
+     * @param isBoldLabel true if suggestion label's type face is {@code Typeface.BOLD}, false if
+     * suggestion label's type face is {@code Typeface.NORMAL}.
+     * @param dropdownItemHeight height of each dropdown item in dimension independent pixel units,
+     * 0 if unspecified.
      */
     @SuppressLint("InlinedApi")
-    public void filterAndShow(AutofillSuggestion[] suggestions, boolean isRtl) {
+    public void filterAndShow(AutofillSuggestion[] suggestions, boolean isRtl,
+            int backgroundColor, int dividerColor, int dropdownItemHeight) {
         mSuggestions = new ArrayList<AutofillSuggestion>(Arrays.asList(suggestions));
         // Remove the AutofillSuggestions with IDs that are not supported by Android
         ArrayList<DropdownItem> cleanedData = new ArrayList<DropdownItem>();
@@ -73,7 +84,10 @@
             }
         }
 
-        setAdapter(new DropdownAdapter(mContext, cleanedData, separators));
+        setAdapter(new DropdownAdapter(mContext, cleanedData, separators,
+                backgroundColor == Color.TRANSPARENT ? null : backgroundColor,
+                dividerColor == Color.TRANSPARENT ? null : dividerColor,
+                dropdownItemHeight == 0 ? null : dropdownItemHeight));
         setRtl(isRtl);
         show();
         getListView().setOnItemLongClickListener(this);
diff --git a/components/autofill/android/java/src/org/chromium/components/autofill/AutofillSuggestion.java b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillSuggestion.java
index eaf23c363..666dcbf 100644
--- a/components/autofill/android/java/src/org/chromium/components/autofill/AutofillSuggestion.java
+++ b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillSuggestion.java
@@ -12,34 +12,42 @@
 public class AutofillSuggestion extends DropdownItemBase {
     /**
      * The constant used to specify a http warning message in a list of Autofill suggestions.
-     * Has to be kept in sync with enum in popup_item_ids.h
-     * TODO(crbug.com/666529): Generate java constants from C++ enum.
+     * Has to be kept in sync with {@code POPUP_ITEM_ID_SEPARATOR} enum in
+     * components/autofill/core/browser/popup_item_ids.h
      */
     private static final int ITEM_ID_HTTP_NOT_SECURE_WARNING_MESSAGE = -10;
 
     private final String mLabel;
     private final String mSublabel;
     private final int mIconId;
+    private final boolean mIsIconAtStart;
     private final int mSuggestionId;
-    private final boolean mDeletable;
+    private final boolean mIsDeletable;
     private final boolean mIsMultilineLabel;
+    private final boolean mIsBoldLabel;
 
     /**
      * Constructs a Autofill suggestion container.
      * @param label The main label of the Autofill suggestion.
      * @param sublabel The describing sublabel of the Autofill suggestion.
+     * @param iconId The resource ID for the icon associated with the suggestion, or
+     * {@code DropdownItem.NO_ICON} for no icon.
+     * @param isIconAtStart {@code true} if {@param iconId} is displayed before {@param label}.
      * @param suggestionId The type of suggestion.
-     * @param deletable Whether the item can be deleted by the user.
-     * @param multilineLabel Whether the label is displayed over multiple lines.
+     * @param isDeletable Whether the item can be deleted by the user.
+     * @param isMultilineLabel Whether the label is displayed over multiple lines.
+     * @param isBoldLabel Whether the label is displayed in {@code Typeface.BOLD}.
      */
-    public AutofillSuggestion(String label, String sublabel, int iconId, int suggestionId,
-            boolean deletable, boolean multilineLabel) {
+    public AutofillSuggestion(String label, String sublabel, int iconId, boolean isIconAtStart,
+            int suggestionId, boolean isDeletable, boolean isMultilineLabel, boolean isBoldLabel) {
         mLabel = label;
         mSublabel = sublabel;
         mIconId = iconId;
+        mIsIconAtStart = isIconAtStart;
         mSuggestionId = suggestionId;
-        mDeletable = deletable;
-        mIsMultilineLabel = multilineLabel;
+        mIsDeletable = isDeletable;
+        mIsMultilineLabel = isMultilineLabel;
+        mIsBoldLabel = isBoldLabel;
     }
 
     @Override
@@ -63,6 +71,11 @@
     }
 
     @Override
+    public boolean isBoldLabel() {
+        return mIsBoldLabel;
+    }
+
+    @Override
     public int getLabelFontColorResId() {
         if (mSuggestionId == ITEM_ID_HTTP_NOT_SECURE_WARNING_MESSAGE) {
             return R.color.http_bad_warning_message_text;
@@ -88,7 +101,7 @@
 
     @Override
     public boolean isIconAtStart() {
-        if (mSuggestionId == ITEM_ID_HTTP_NOT_SECURE_WARNING_MESSAGE) {
+        if (mIsIconAtStart) {
             return true;
         }
         return super.isIconAtStart();
@@ -99,7 +112,7 @@
     }
 
     public boolean isDeletable() {
-        return mDeletable;
+        return mIsDeletable;
     }
 
     public boolean isFillable() {
diff --git a/components/autofill/core/browser/autofill_experiments.cc b/components/autofill/core/browser/autofill_experiments.cc
index 6ecc864b..28fdc27b 100644
--- a/components/autofill/core/browser/autofill_experiments.cc
+++ b/components/autofill/core/browser/autofill_experiments.cc
@@ -7,9 +7,12 @@
 #include "base/command_line.h"
 #include "base/feature_list.h"
 #include "base/metrics/field_trial.h"
+#include "base/strings/string16.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "components/autofill/core/browser/suggestion.h"
 #include "components/autofill/core/common/autofill_pref_names.h"
 #include "components/autofill/core/common/autofill_switches.h"
 #include "components/prefs/pref_service.h"
@@ -17,6 +20,8 @@
 #include "components/sync/driver/sync_service.h"
 #include "components/variations/variations_associated_data.h"
 #include "google_apis/gaia/gaia_auth_util.h"
+#include "grit/components_strings.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace autofill {
 
@@ -28,7 +33,34 @@
                                             base::FEATURE_DISABLED_BY_DEFAULT};
 const base::Feature kAutofillScanCardholderName{
     "AutofillScanCardholderName", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kAutofillCreditCardPopupLayout{
+    "AutofillCreditCardPopupLayout", base::FEATURE_DISABLED_BY_DEFAULT};
 const char kCreditCardSigninPromoImpressionLimitParamKey[] = "impression_limit";
+const char kAutofillCreditCardPopupBackgroundColorKey[] = "background_color";
+const char kAutofillCreditCardPopupDividerColorKey[] = "dropdown_divider_color";
+const char kAutofillCreditCardPopupValueBoldKey[] = "is_value_bold";
+const char kAutofillCreditCardPopupIsValueAndLabelInSingleLineKey[] =
+    "is_value_and_label_in_single_line";
+const char kAutofillPopupDropdownItemHeightKey[] =
+    "dropdown_item_height";
+const char kAutofillCreditCardPopupIsIconAtStartKey[] =
+    "is_credit_card_icon_at_start";
+
+namespace {
+
+// Returns parameter value in |kAutofillCreditCardPopupLayout| feature, or 0 if
+// parameter is not specified.
+unsigned int GetCreditCardPopupParameterUintValue(
+    const std::string& param_name) {
+  unsigned int value;
+  const std::string param_value = variations::GetVariationParamValueByFeature(
+      kAutofillCreditCardPopupLayout, param_name);
+  if (!param_value.empty() && base::StringToUint(param_value, &value))
+    return value;
+  return 0;
+}
+
+}  // namespace
 
 bool IsAutofillEnabled(const PrefService* pref_service) {
   return pref_service->GetBoolean(prefs::kAutofillEnabled);
@@ -67,6 +99,60 @@
   return 0;
 }
 
+bool IsAutofillCreditCardPopupLayoutExperimentEnabled() {
+  return base::FeatureList::IsEnabled(kAutofillCreditCardPopupLayout);
+}
+
+// |GetCreditCardPopupParameterUintValue| returns 0 if experiment parameter is
+// not specified. 0 == |SK_ColorTRANSPARENT|.
+SkColor GetCreditCardPopupBackgroundColor() {
+  return GetCreditCardPopupParameterUintValue(
+      kAutofillCreditCardPopupBackgroundColorKey);
+}
+
+SkColor GetCreditCardPopupDividerColor() {
+  return GetCreditCardPopupParameterUintValue(
+      kAutofillCreditCardPopupDividerColorKey);
+}
+
+bool IsCreditCardPopupValueBold() {
+  const std::string param_value = variations::GetVariationParamValueByFeature(
+      kAutofillCreditCardPopupLayout, kAutofillCreditCardPopupValueBoldKey);
+  return param_value == "true";
+}
+
+unsigned int GetPopupDropdownItemHeight() {
+  return GetCreditCardPopupParameterUintValue(
+      kAutofillPopupDropdownItemHeightKey);
+}
+
+bool IsIconInCreditCardPopupAtStart() {
+  const std::string param_value = variations::GetVariationParamValueByFeature(
+      kAutofillCreditCardPopupLayout, kAutofillCreditCardPopupIsIconAtStartKey);
+  return param_value == "true";
+}
+
+// Modifies |suggestion| as follows if experiment to display value and label in
+// a single line is enabled.
+// Say, |value| is 'Visa ....1111' and |label| is '01/18' (expiration date).
+// Modifies |value| to 'Visa ....1111, exp 01/18' and clears |label|.
+void ModifyAutofillCreditCardSuggestion(Suggestion* suggestion) {
+  DCHECK(IsAutofillCreditCardPopupLayoutExperimentEnabled());
+  const std::string param_value = variations::GetVariationParamValueByFeature(
+      kAutofillCreditCardPopupLayout,
+      kAutofillCreditCardPopupIsValueAndLabelInSingleLineKey);
+  if (param_value == "true") {
+    const base::string16 format_string = l10n_util::GetStringUTF16(
+        IDS_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE_LABEL_AND_ABBR);
+    if (!format_string.empty()) {
+      suggestion->value.append(l10n_util::GetStringFUTF16(
+          IDS_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE_LABEL_AND_ABBR,
+          suggestion->label));
+    }
+    suggestion->label.clear();
+  }
+}
+
 bool OfferStoreUnmaskedCards() {
 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
   // The checkbox can be forced on with a flag, but by default we don't store
diff --git a/components/autofill/core/browser/autofill_experiments.h b/components/autofill/core/browser/autofill_experiments.h
index 9fe4fc0b..fc02866 100644
--- a/components/autofill/core/browser/autofill_experiments.h
+++ b/components/autofill/core/browser/autofill_experiments.h
@@ -7,6 +7,9 @@
 
 #include <string>
 
+#include "base/strings/string16.h"
+#include "third_party/skia/include/core/SkColor.h"
+
 class PrefService;
 
 namespace base {
@@ -19,11 +22,15 @@
 
 namespace autofill {
 
+struct Suggestion;
+
 extern const base::Feature kAutofillCreditCardAssist;
 extern const base::Feature kAutofillCreditCardSigninPromo;
 extern const base::Feature kAutofillProfileCleanup;
 extern const base::Feature kAutofillScanCardholderName;
+extern const base::Feature kAutofillCreditCardPopupLayout;
 extern const char kCreditCardSigninPromoImpressionLimitParamKey[];
+extern const char kAutofillCreditCardPopupSettingsSuggestionValueKey[];
 
 // Returns true if autofill should be enabled. See also
 // IsInAutofillSuggestionsDisabledExperiment below.
@@ -64,6 +71,37 @@
 // in the autofill dropdown when credit card fields are on an HTTP page.
 bool IsCreditCardAutofillHttpWarningEnabled();
 
+// Returns whether the new Autofill credit card popup layout experiment is
+// enabled.
+bool IsAutofillCreditCardPopupLayoutExperimentEnabled();
+
+// Returns the background color for credit card autofill popup, or
+// |SK_ColorTRANSPARENT| if the new credit card autofill popup layout experiment
+// is not enabled.
+SkColor GetCreditCardPopupBackgroundColor();
+
+// Returns the divider color for credit card autofill popup, or
+// |SK_ColorTRANSPARENT| if the new credit card autofill popup layout experiment
+// is not enabled.
+SkColor GetCreditCardPopupDividerColor();
+
+// Returns true if the credit card autofill popup suggestion value is displayed
+// in bold type face.
+bool IsCreditCardPopupValueBold();
+
+// Returns the dropdown item height for autofill popup, returning 0 if the
+// dropdown item height isn't configured in an experiment to tweak autofill
+// popup layout.
+unsigned int GetPopupDropdownItemHeight();
+
+// Returns true if the icon in the credit card autofill popup must be displayed
+// before the credit card value or any other suggestion text.
+bool IsIconInCreditCardPopupAtStart();
+
+// Modifies the suggestion value and label if the new credit card autofill popup
+// experiment is enabled to tweak the display of the value and label.
+void ModifyAutofillCreditCardSuggestion(struct Suggestion* suggestion);
+
 }  // namespace autofill
 
 #endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_EXPERIMENTS_H_
diff --git a/components/autofill/core/browser/autofill_external_delegate.cc b/components/autofill/core/browser/autofill_external_delegate.cc
index 9c8c7c13..bfab143d 100644
--- a/components/autofill/core/browser/autofill_external_delegate.cc
+++ b/components/autofill/core/browser/autofill_external_delegate.cc
@@ -19,6 +19,7 @@
 #include "build/build_config.h"
 #include "components/autofill/core/browser/autocomplete_history_manager.h"
 #include "components/autofill/core/browser/autofill_driver.h"
+#include "components/autofill/core/browser/autofill_experiments.h"
 #include "components/autofill/core/browser/autofill_manager.h"
 #include "components/autofill/core/browser/autofill_metrics.h"
 #include "components/autofill/core/browser/popup_item_ids.h"
@@ -48,6 +49,7 @@
       has_autofill_suggestions_(false),
       has_shown_popup_for_current_edit_(false),
       should_show_scan_credit_card_(false),
+      is_credit_card_popup_(false),
       should_show_cc_signin_promo_(false),
       has_shown_address_book_prompt(false),
       weak_ptr_factory_(this) {
@@ -69,6 +71,8 @@
   element_bounds_ = element_bounds;
   should_show_scan_credit_card_ =
       manager_->ShouldShowScanCreditCard(query_form_, query_field_);
+  is_credit_card_popup_ =
+      manager_->IsCreditCardPopup(query_form_, query_field_);
   should_show_cc_signin_promo_ =
       manager_->ShouldShowCreditCardSigninPromo(query_form_, query_field_);
 }
@@ -275,6 +279,10 @@
   driver_->RendererShouldClearPreviewedForm();
 }
 
+bool AutofillExternalDelegate::IsCreditCardPopup() {
+  return is_credit_card_popup_;
+}
+
 void AutofillExternalDelegate::Reset() {
   manager_->client()->HideAutofillPopup();
 }
@@ -325,8 +333,6 @@
   if (query_field_.is_autofilled) {
     base::string16 value =
         l10n_util::GetStringUTF16(IDS_AUTOFILL_CLEAR_FORM_MENU_ITEM);
-    // TODO(rouslan): Remove manual upper-casing when keyboard accessory becomes
-    // default on Android.
     if (IsKeyboardAccessoryEnabled())
       value = base::i18n::ToUpper(value);
 
@@ -334,12 +340,9 @@
     suggestions->back().frontend_id = POPUP_ITEM_ID_CLEAR_FORM;
   }
 
-  // Append the 'Chrome Autofill options' menu item;
-  // TODO(rouslan): Switch on the platform in the GRD file when keyboard
-  // accessory becomes default on Android.
-  suggestions->push_back(Suggestion(l10n_util::GetStringUTF16(
-      IsKeyboardAccessoryEnabled() ? IDS_AUTOFILL_OPTIONS_CONTENT_DESCRIPTION
-                                   : IDS_AUTOFILL_OPTIONS_POPUP)));
+  // Append the 'Chrome Autofill options' menu item, or the menu item specified
+  // in the popup layout experiment.
+  suggestions->push_back(Suggestion(GetSettingsSuggestionValue()));
   suggestions->back().frontend_id = POPUP_ITEM_ID_AUTOFILL_OPTIONS;
   if (IsKeyboardAccessoryEnabled())
     suggestions->back().icon = base::ASCIIToUTF16("settings");
@@ -382,4 +385,14 @@
   }
 }
 
+base::string16 AutofillExternalDelegate::GetSettingsSuggestionValue()
+    const {
+  if (IsKeyboardAccessoryEnabled()) {
+    return l10n_util::GetStringUTF16(IDS_AUTOFILL_OPTIONS_CONTENT_DESCRIPTION);
+  }
+  return l10n_util::GetStringUTF16(is_credit_card_popup_ ?
+                                   IDS_AUTOFILL_CREDIT_CARD_OPTIONS_POPUP :
+                                   IDS_AUTOFILL_OPTIONS_POPUP);
+}
+
 }  // namespace autofill
diff --git a/components/autofill/core/browser/autofill_external_delegate.h b/components/autofill/core/browser/autofill_external_delegate.h
index 4afbb92..6a9807a0 100644
--- a/components/autofill/core/browser/autofill_external_delegate.h
+++ b/components/autofill/core/browser/autofill_external_delegate.h
@@ -51,6 +51,9 @@
                                    base::string16* body) override;
   bool RemoveSuggestion(const base::string16& value, int identifier) override;
   void ClearPreviewedForm() override;
+  // Returns false for all popups prior to |onQuery|, true for credit card
+  // popups after call to |onQuery|.
+  bool IsCreditCardPopup() override;
 
   // Records and associates a query_id with web form data.  Called
   // when the renderer posts an Autofill query to the browser. |bounds|
@@ -115,6 +118,9 @@
   // version.
   void InsertDataListValues(std::vector<Suggestion>* suggestions);
 
+  // Returns the text (i.e. |Suggestion| value) for Chrome autofill options.
+  base::string16 GetSettingsSuggestionValue() const;
+
   AutofillManager* manager_;  // weak.
 
   // Provides driver-level context to the shared code of the component. Must
@@ -139,8 +145,8 @@
   // currently editing?  Used to keep track of state for metrics logging.
   bool has_shown_popup_for_current_edit_;
 
-  // FIXME
   bool should_show_scan_credit_card_;
+  bool is_credit_card_popup_;
 
   // Whether the credit card signin promo should be shown to the user.
   bool should_show_cc_signin_promo_;
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc
index fe2557c..6d12bb9 100644
--- a/components/autofill/core/browser/autofill_manager.cc
+++ b/components/autofill/core/browser/autofill_manager.cc
@@ -308,6 +308,12 @@
   return field.value.size() <= kShowScanCreditCardMaxValueLength;
 }
 
+bool AutofillManager::IsCreditCardPopup(const FormData& form,
+                                        const FormFieldData& field) {
+  AutofillField* autofill_field = GetAutofillField(form, field);
+  return autofill_field && autofill_field->Type().group() == CREDIT_CARD;
+}
+
 bool AutofillManager::ShouldShowCreditCardSigninPromo(
     const FormData& form,
     const FormFieldData& field) {
@@ -528,8 +534,6 @@
   if (!IsValidFormData(form) || !IsValidFormFieldData(field))
     return;
 
-  std::vector<Suggestion> suggestions;
-
   gfx::RectF transformed_box =
       driver_->TransformBoundingBoxToViewportCoordinates(bounding_box);
   external_delegate_->OnQuery(query_id, form, field, transformed_box);
@@ -554,6 +558,8 @@
     }
   }
 
+  std::vector<Suggestion> suggestions;
+
   if (is_autofill_possible &&
       driver_->RendererIsAvailable() &&
       got_autofillable_form) {
@@ -1790,6 +1796,7 @@
   for (size_t i = 0; i < suggestions.size(); i++) {
     suggestions[i].frontend_id =
         MakeFrontendID(suggestions[i].backend_id, std::string());
+    suggestions[i].is_value_bold = IsCreditCardPopupValueBold();
   }
   return suggestions;
 }
diff --git a/components/autofill/core/browser/autofill_manager.h b/components/autofill/core/browser/autofill_manager.h
index 16efc7f..ce8608f 100644
--- a/components/autofill/core/browser/autofill_manager.h
+++ b/components/autofill/core/browser/autofill_manager.h
@@ -96,6 +96,10 @@
   virtual bool ShouldShowScanCreditCard(const FormData& form,
                                         const FormFieldData& field);
 
+  // Whether the |field| belongs to CREDIT_CARD |FieldTypeGroup|.
+  virtual bool IsCreditCardPopup(const FormData& form,
+                                 const FormFieldData& field);
+
   // Whether we should show the signin promo, based on the triggered |field|
   // inside the |form|.
   virtual bool ShouldShowCreditCardSigninPromo(const FormData& form,
diff --git a/components/autofill/core/browser/autofill_popup_delegate.h b/components/autofill/core/browser/autofill_popup_delegate.h
index 99a6675..5a86424 100644
--- a/components/autofill/core/browser/autofill_popup_delegate.h
+++ b/components/autofill/core/browser/autofill_popup_delegate.h
@@ -43,6 +43,9 @@
 
   // Informs the delegate that the Autofill previewed form should be cleared.
   virtual void ClearPreviewedForm() = 0;
+
+  // Returns true if popup is for credit card.
+  virtual bool IsCreditCardPopup() = 0;
 };
 
 }  // namespace autofill
diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc
index 37418c7..b58bc6c 100644
--- a/components/autofill/core/browser/personal_data_manager.cc
+++ b/components/autofill/core/browser/personal_data_manager.cc
@@ -1626,6 +1626,8 @@
         suggestion->value = credit_card->TypeAndLastFourDigits();
         suggestion->label = credit_card->GetInfo(
             AutofillType(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR), app_locale_);
+        if (IsAutofillCreditCardPopupLayoutExperimentEnabled())
+          ModifyAutofillCreditCardSuggestion(suggestion);
       } else if (credit_card->number().empty()) {
         if (type.GetStorableType() != CREDIT_CARD_NAME_FULL) {
           suggestion->label = credit_card->GetInfo(
diff --git a/components/autofill/core/browser/suggestion.cc b/components/autofill/core/browser/suggestion.cc
index 22d4ac7..754ede93 100644
--- a/components/autofill/core/browser/suggestion.cc
+++ b/components/autofill/core/browser/suggestion.cc
@@ -10,7 +10,8 @@
 
 Suggestion::Suggestion()
     : frontend_id(0),
-      match(PREFIX_MATCH) {
+      match(PREFIX_MATCH),
+      is_value_bold(false) {
 }
 
 Suggestion::Suggestion(const Suggestion& other)
@@ -19,13 +20,15 @@
       value(other.value),
       label(other.label),
       icon(other.icon),
-      match(other.match) {
+      match(other.match),
+      is_value_bold(other.is_value_bold) {
 }
 
 Suggestion::Suggestion(const base::string16& v)
     : frontend_id(0),
       value(v),
-      match(PREFIX_MATCH) {
+      match(PREFIX_MATCH),
+      is_value_bold(false) {
 }
 
 Suggestion::Suggestion(const std::string& v,
@@ -36,7 +39,8 @@
       value(base::UTF8ToUTF16(v)),
       label(base::UTF8ToUTF16(l)),
       icon(base::UTF8ToUTF16(i)),
-      match(PREFIX_MATCH) {
+      match(PREFIX_MATCH),
+      is_value_bold(false) {
 }
 
 Suggestion::~Suggestion() {
diff --git a/components/autofill/core/browser/suggestion.h b/components/autofill/core/browser/suggestion.h
index 930ab23..63522de 100644
--- a/components/autofill/core/browser/suggestion.h
+++ b/components/autofill/core/browser/suggestion.h
@@ -47,6 +47,7 @@
   base::string16 label;
   base::string16 icon;
   MatchMode match;
+  bool is_value_bold;  // true if |value| should be displayed in bold type face.
 };
 
 }  // namespace autofill
diff --git a/components/autofill_strings.grdp b/components/autofill_strings.grdp
index e6bafa54..92713992 100644
--- a/components/autofill_strings.grdp
+++ b/components/autofill_strings.grdp
@@ -157,6 +157,17 @@
     </message>
   </if>
 
+  <if expr="_google_chrome">
+    <message name="IDS_AUTOFILL_CREDIT_CARD_OPTIONS_POPUP" desc="The label of the text displayed in the Autofill Credit Card popup to direct the user to the Autofill settings UI.">
+     Chrome Autofill settings...    
+    </message>
+  </if>
+  <if expr="not _google_chrome">
+    <message name="IDS_AUTOFILL_CREDIT_CARD_OPTIONS_POPUP" desc="The label of the text displayed in the Autofill Credit Card popup to direct the user to the Autofill settings UI.">    
+      Chromium Autofill settings...
+    </message>
+  </if>    
+
   <message name="IDS_AUTOFILL_OPTIONS_CONTENT_DESCRIPTION" desc="The text verbalised by a screen reader for the button that directs the user to the Autofill settings UI. This string is not displayed.">
     settings
   </message>
@@ -229,6 +240,10 @@
     Exp: <ph name="EXPIRATION_MONTH">$1<ex>06</ex></ph>/<ph name="EXPIRATION_YEAR">$2<ex>17</ex></ph>
   </message>
 
+  <message name="IDS_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE_LABEL_AND_ABBR" desc="text displayed in the Autofill Credit Card popup before the credit card expiration date and the abbreviated expiration date.">
+    , exp <ph name="EXPIRATION_DATE_ABBR">$1<ex>06/17</ex></ph>
+  </message>
+
   <!-- Autofill credit card unmask prompt -->
   <message name="IDS_AUTOFILL_CARD_UNMASK_PROMPT_ERROR_TRY_AGAIN_CVC" desc="Error message that encourages the user to try to re-enter their credit card CVC after a previous failed attempt." formatter_data="android_java">
     Check your CVC and try again
diff --git a/components/browsing_data/core/counters/autofill_counter.cc b/components/browsing_data/core/counters/autofill_counter.cc
index a852db4..b0e55d0f 100644
--- a/components/browsing_data/core/counters/autofill_counter.cc
+++ b/components/browsing_data/core/counters/autofill_counter.cc
@@ -81,7 +81,20 @@
     WebDataServiceBase::Handle handle,
     std::unique_ptr<WDTypedResult> result) {
   DCHECK(thread_checker_.CalledOnValidThread());
+
   if (!result) {
+    // CancelAllRequests will cancel all queries that are active; the query that
+    // just failed is complete and cannot be canceled so zero it out.
+    if (handle == suggestions_query_) {
+      suggestions_query_ = 0;
+    } else if (handle == credit_cards_query_) {
+      credit_cards_query_ = 0;
+    } else if (handle == addresses_query_) {
+      addresses_query_ = 0;
+    } else {
+      NOTREACHED();
+    }
+
     CancelAllRequests();
     return;
   }
diff --git a/components/cronet/android/api/src/org/chromium/net/ExperimentalCronetEngine.java b/components/cronet/android/api/src/org/chromium/net/ExperimentalCronetEngine.java
index 6fc67f4e..4535fe15 100644
--- a/components/cronet/android/api/src/org/chromium/net/ExperimentalCronetEngine.java
+++ b/components/cronet/android/api/src/org/chromium/net/ExperimentalCronetEngine.java
@@ -181,8 +181,12 @@
             return this;
         }
 
+        /**
+         * Returns delegate, only for testing.
+         * @hide
+         */
         @VisibleForTesting
-        ICronetEngineBuilder getBuilderDelegate() {
+        public ICronetEngineBuilder getBuilderDelegate() {
             return mBuilderDelegate;
         }
 
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestBase.java b/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestBase.java
index addc524f..c0b8d3c 100644
--- a/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestBase.java
+++ b/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestBase.java
@@ -152,7 +152,7 @@
         }
     }
 
-    void assertResponseEquals(UrlResponseInfo expected, UrlResponseInfo actual) {
+    public void assertResponseEquals(UrlResponseInfo expected, UrlResponseInfo actual) {
         assertEquals(expected.getAllHeaders(), actual.getAllHeaders());
         assertEquals(expected.getAllHeadersAsList(), actual.getAllHeadersAsList());
         assertEquals(expected.getHttpStatusCode(), actual.getHttpStatusCode());
@@ -168,7 +168,7 @@
         }
     }
 
-    static void assertContains(String expectedSubstring, String actualString) {
+    public static void assertContains(String expectedSubstring, String actualString) {
         assertNotNull(actualString);
         if (!actualString.contains(expectedSubstring)) {
             fail("String [" + actualString + "] doesn't contain substring [" + expectedSubstring
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/TestUrlRequestCallback.java b/components/cronet/android/test/javatests/src/org/chromium/net/TestUrlRequestCallback.java
index b088cfb..42f98a5 100644
--- a/components/cronet/android/test/javatests/src/org/chromium/net/TestUrlRequestCallback.java
+++ b/components/cronet/android/test/javatests/src/org/chromium/net/TestUrlRequestCallback.java
@@ -27,7 +27,7 @@
  * method to block thread until the request completes on another thread.
  * Allows to cancel, block request or throw an exception from an arbitrary step.
  */
-class TestUrlRequestCallback extends UrlRequest.Callback {
+public class TestUrlRequestCallback extends UrlRequest.Callback {
     public ArrayList<UrlResponseInfo> mRedirectResponseInfoList = new ArrayList<UrlResponseInfo>();
     public ArrayList<String> mRedirectUrlList = new ArrayList<String>();
     public UrlResponseInfo mResponseInfo;
diff --git a/components/cronet/android/test/src/org/chromium/net/QuicTestServer.java b/components/cronet/android/test/src/org/chromium/net/QuicTestServer.java
index 0e9c5878..4745e7f 100644
--- a/components/cronet/android/test/src/org/chromium/net/QuicTestServer.java
+++ b/components/cronet/android/test/src/org/chromium/net/QuicTestServer.java
@@ -7,6 +7,7 @@
 import android.content.Context;
 import android.os.ConditionVariable;
 
+import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
@@ -73,6 +74,7 @@
     }
 
     public static long createMockCertVerifier() {
+        TestFilesInstaller.installIfNeeded(ContextUtils.getApplicationContext());
         return MockCertVerifier.createMockCertVerifier(CERTS_USED, true);
     }
 
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc
index 40fbb78..f3374d5 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc
@@ -201,6 +201,13 @@
       percent_savings_via_data_reduction_proxy);
 }
 
+void RecordSavingsClearedNegativeClockMetric(int days_since_last_update) {
+  // Data savings are cleared if the system clock moved back by more than
+  // one day.
+  UMA_HISTOGRAM_BOOLEAN("DataReductionProxy.SavingsCleared.NegativeSystemClock",
+                        days_since_last_update < -1);
+}
+
 }  // namespace
 
 class DataReductionProxyCompressionStats::DailyContentLengthUpdate {
@@ -923,6 +930,8 @@
           "Net.DailyContentLength_ViaDataReductionProxy_UnknownMime");
     }
 
+    RecordSavingsClearedNegativeClockMetric(days_since_last_update);
+
     // The system may go backwards in time by up to a day for legitimate
     // reasons, such as with changes to the time zone. In such cases, we
     // keep adding to the current day which is why we check for
@@ -930,6 +939,11 @@
     // Note: we accept the fact that some reported data is shifted to
     // the adjacent day if users travel back and forth across time zones.
     if (days_since_last_update && (days_since_last_update != -1)) {
+      if (days_since_last_update < -1) {
+        pref_service_->SetInt64(
+            prefs::kDataReductionProxySavingsClearedNegativeSystemClock,
+            now.ToInternalValue());
+      }
       SetInt64(data_reduction_proxy::prefs::
                    kDailyHttpOriginalContentLengthApplication,
                0);
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats_unittest.cc
index 31a62cc..35ec52f 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats_unittest.cc
@@ -904,11 +904,14 @@
 }
 
 TEST_F(DataReductionProxyCompressionStatsTest, ForwardMultipleDays) {
+  base::HistogramTester histogram_tester;
   const int64_t kOriginalLength = 200;
   const int64_t kReceivedLength = 100;
   RecordContentLengthPrefs(
       kReceivedLength, kOriginalLength, true, VIA_DATA_REDUCTION_PROXY,
       FakeNow());
+  histogram_tester.ExpectUniqueSample(
+      "DataReductionProxy.SavingsCleared.NegativeSystemClock", false, 1);
 
   // Forward three days.
   SetFakeTimeDeltaInHours(3 * 24);
@@ -916,6 +919,8 @@
   RecordContentLengthPrefs(
       kReceivedLength, kOriginalLength, true, VIA_DATA_REDUCTION_PROXY,
       FakeNow());
+  histogram_tester.ExpectUniqueSample(
+      "DataReductionProxy.SavingsCleared.NegativeSystemClock", false, 2);
 
   int64_t original[] = {kOriginalLength, 0, 0, kOriginalLength};
   int64_t received[] = {kReceivedLength, 0, 0, kReceivedLength};
@@ -939,6 +944,8 @@
       original2, 8, received2, 8,
       original2, 8, received2, 8,
       original2, 8, received2, 8);
+  histogram_tester.ExpectUniqueSample(
+      "DataReductionProxy.SavingsCleared.NegativeSystemClock", false, 3);
 
   // Forward |kNumDaysInHistory| more days.
   AddFakeTimeDeltaInHours(kNumDaysInHistory * 24);
@@ -951,6 +958,8 @@
       original3, 1, received3, 1,
       original3, 1, received3, 1,
       original3, 1, received3, 1);
+  histogram_tester.ExpectUniqueSample(
+      "DataReductionProxy.SavingsCleared.NegativeSystemClock", false, 4);
 
   // Forward |kNumDaysInHistory| + 1 more days.
   AddFakeTimeDeltaInHours((kNumDaysInHistory + 1)* 24);
@@ -961,9 +970,12 @@
       original3, 1, received3, 1,
       original3, 1, received3, 1,
       original3, 1, received3, 1);
+  histogram_tester.ExpectUniqueSample(
+      "DataReductionProxy.SavingsCleared.NegativeSystemClock", false, 5);
 }
 
 TEST_F(DataReductionProxyCompressionStatsTest, BackwardAndForwardOneDay) {
+  base::HistogramTester histogram_tester;
   const int64_t kOriginalLength = 200;
   const int64_t kReceivedLength = 100;
   int64_t original[] = {kOriginalLength};
@@ -972,6 +984,8 @@
   RecordContentLengthPrefs(
       kReceivedLength, kOriginalLength, true, VIA_DATA_REDUCTION_PROXY,
       FakeNow());
+  histogram_tester.ExpectUniqueSample(
+      "DataReductionProxy.SavingsCleared.NegativeSystemClock", false, 1);
 
   // Backward one day.
   SetFakeTimeDeltaInHours(-24);
@@ -984,6 +998,8 @@
       original, 1, received, 1,
       original, 1, received, 1,
       original, 1, received, 1);
+  histogram_tester.ExpectUniqueSample(
+      "DataReductionProxy.SavingsCleared.NegativeSystemClock", false, 2);
 
   // Then, Forward one day
   AddFakeTimeDeltaInHours(24);
@@ -996,9 +1012,12 @@
       original2, 2, received2, 2,
       original2, 2, received2, 2,
       original2, 2, received2, 2);
+  histogram_tester.ExpectUniqueSample(
+      "DataReductionProxy.SavingsCleared.NegativeSystemClock", false, 3);
 }
 
 TEST_F(DataReductionProxyCompressionStatsTest, BackwardTwoDays) {
+  base::HistogramTester histogram_tester;
   const int64_t kOriginalLength = 200;
   const int64_t kReceivedLength = 100;
   int64_t original[] = {kOriginalLength};
@@ -1007,6 +1026,9 @@
   RecordContentLengthPrefs(
       kReceivedLength, kOriginalLength, true, VIA_DATA_REDUCTION_PROXY,
       FakeNow());
+  histogram_tester.ExpectUniqueSample(
+      "DataReductionProxy.SavingsCleared.NegativeSystemClock", false, 1);
+
   // Backward two days.
   SetFakeTimeDeltaInHours(-2 * 24);
   RecordContentLengthPrefs(
@@ -1016,6 +1038,30 @@
       original, 1, received, 1,
       original, 1, received, 1,
       original, 1, received, 1);
+  histogram_tester.ExpectTotalCount(
+      "DataReductionProxy.SavingsCleared.NegativeSystemClock", 2);
+  histogram_tester.ExpectBucketCount(
+      "DataReductionProxy.SavingsCleared.NegativeSystemClock", true, 1);
+  VerifyPrefInt64(prefs::kDataReductionProxySavingsClearedNegativeSystemClock,
+                  FakeNow().ToInternalValue());
+
+  // Backward two days.
+  SetFakeTimeDeltaInHours(-4 * 24);
+  RecordContentLengthPrefs(kReceivedLength, kOriginalLength, true,
+                           VIA_DATA_REDUCTION_PROXY, FakeNow());
+  histogram_tester.ExpectTotalCount(
+      "DataReductionProxy.SavingsCleared.NegativeSystemClock", 3);
+  histogram_tester.ExpectBucketCount(
+      "DataReductionProxy.SavingsCleared.NegativeSystemClock", true, 2);
+
+  // Forward 10 days.
+  AddFakeTimeDeltaInHours(10 * 24);
+  RecordContentLengthPrefs(kReceivedLength, kOriginalLength, true,
+                           VIA_DATA_REDUCTION_PROXY, FakeNow());
+  histogram_tester.ExpectTotalCount(
+      "DataReductionProxy.SavingsCleared.NegativeSystemClock", 4);
+  histogram_tester.ExpectBucketCount(
+      "DataReductionProxy.SavingsCleared.NegativeSystemClock", false, 2);
 }
 
 TEST_F(DataReductionProxyCompressionStatsTest, NormalizeHostname) {
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
index 4a2b45e2..5a96288 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
@@ -282,6 +282,62 @@
   DISALLOW_COPY_AND_ASSIGN(SecureProxyChecker);
 };
 
+// URLFetcherDelegate for fetching the warmup URL.
+class WarmupURLFetcher : public net::URLFetcherDelegate {
+ public:
+  explicit WarmupURLFetcher(const scoped_refptr<net::URLRequestContextGetter>&
+                                url_request_context_getter)
+      : url_request_context_getter_(url_request_context_getter) {
+    DCHECK(url_request_context_getter_);
+  }
+
+  ~WarmupURLFetcher() override {}
+
+  // Creates and starts a URLFetcher that fetches the warmup URL.
+  void FetchWarmupURL() {
+    UMA_HISTOGRAM_EXACT_LINEAR("DataReductionProxy.WarmupURL.FetchInitiated", 1,
+                               2);
+
+    fetcher_ = net::URLFetcher::Create(params::GetWarmupURL(),
+                                       net::URLFetcher::GET, this);
+    data_use_measurement::DataUseUserData::AttachToFetcher(
+        fetcher_.get(),
+        data_use_measurement::DataUseUserData::DATA_REDUCTION_PROXY);
+    fetcher_->SetLoadFlags(net::LOAD_BYPASS_CACHE);
+    fetcher_->SetRequestContext(url_request_context_getter_.get());
+    // |fetcher| should not retry on 5xx errors.
+    fetcher_->SetAutomaticallyRetryOn5xx(false);
+    fetcher_->SetAutomaticallyRetryOnNetworkChanges(0);
+    fetcher_->Start();
+  }
+
+  void SetWarmupURLFetcherCallbackForTesting(
+      base::Callback<void()> warmup_url_fetched_callback) {
+    fetch_completion_callback_ = warmup_url_fetched_callback;
+  }
+
+ private:
+  void OnURLFetchComplete(const net::URLFetcher* source) override {
+    DCHECK_EQ(source, fetcher_.get());
+    UMA_HISTOGRAM_BOOLEAN(
+        "DataReductionProxy.WarmupURL.FetchSuccessful",
+        source->GetStatus().status() == net::URLRequestStatus::SUCCESS);
+
+    if (fetch_completion_callback_)
+      fetch_completion_callback_.Run();
+  }
+
+  scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
+
+  // The URLFetcher being used for fetching the warmup URL.
+  std::unique_ptr<net::URLFetcher> fetcher_;
+
+  // Called upon the completion of fetching of the warmup URL. May be null.
+  base::Callback<void()> fetch_completion_callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(WarmupURLFetcher);
+};
+
 DataReductionProxyConfig::DataReductionProxyConfig(
     scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
     net::NetLog* net_log,
@@ -320,10 +376,16 @@
   net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
 }
 
-void DataReductionProxyConfig::InitializeOnIOThread(const scoped_refptr<
-    net::URLRequestContextGetter>& url_request_context_getter) {
+void DataReductionProxyConfig::InitializeOnIOThread(
+    const scoped_refptr<net::URLRequestContextGetter>&
+        basic_url_request_context_getter,
+    const scoped_refptr<net::URLRequestContextGetter>&
+        url_request_context_getter) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+
   secure_proxy_checker_.reset(
-      new SecureProxyChecker(url_request_context_getter));
+      new SecureProxyChecker(basic_url_request_context_getter));
+  warmup_url_fetcher_.reset(new WarmupURLFetcher(url_request_context_getter));
 
   if (!config_values_->allowed())
     return;
@@ -647,6 +709,7 @@
 
   if (enabled) {
     HandleCaptivePortal();
+    FetchWarmupURL();
 
     // Check if the proxy has been restricted explicitly by the carrier.
     // It is safe to use base::Unretained here, since it gets executed
@@ -732,6 +795,8 @@
 }
 
 void DataReductionProxyConfig::OnIPAddressChanged() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+
   if (enabled_by_user_) {
     DCHECK(config_values_->allowed());
     RecordNetworkChangeEvent(IP_CHANGED);
@@ -741,6 +806,7 @@
     network_quality_at_last_query_ = NETWORK_QUALITY_AT_LAST_QUERY_UNKNOWN;
 
     HandleCaptivePortal();
+    FetchWarmupURL();
     // It is safe to use base::Unretained here, since it gets executed
     // synchronously on the IO thread, and |this| outlives
     // |secure_proxy_checker_|.
@@ -791,6 +857,23 @@
                                                      fetcher_callback);
 }
 
+void DataReductionProxyConfig::FetchWarmupURL() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+
+  if (!enabled_by_user_ || !params::FetchWarmupURLEnabled())
+    return;
+
+  warmup_url_fetcher_->FetchWarmupURL();
+}
+
+void DataReductionProxyConfig::SetWarmupURLFetcherCallbackForTesting(
+    base::Callback<void()> warmup_url_fetched_callback) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+
+  warmup_url_fetcher_->SetWarmupURLFetcherCallbackForTesting(
+      warmup_url_fetched_callback);
+}
+
 void DataReductionProxyConfig::SetLoFiModeOff() {
   DCHECK(thread_checker_.CalledOnValidThread());
   lofi_off_ = true;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h
index 385bf60..3fe9f61 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h
@@ -51,6 +51,7 @@
 class DataReductionProxyConfigurator;
 class DataReductionProxyEventCreator;
 class SecureProxyChecker;
+class WarmupURLFetcher;
 struct DataReductionProxyTypeInfo;
 
 // Values of the UMA DataReductionProxy.ProbeURL histogram.
@@ -103,7 +104,13 @@
   ~DataReductionProxyConfig() override;
 
   // Performs initialization on the IO thread.
+  // |basic_url_request_context_getter| is the net::URLRequestContextGetter that
+  // disables the use of alternative protocols and proxies.
+  // |url_request_context_getter| is the default net::URLRequestContextGetter
+  // used for making URL requests.
   void InitializeOnIOThread(const scoped_refptr<net::URLRequestContextGetter>&
+                                basic_url_request_context_getter,
+                            const scoped_refptr<net::URLRequestContextGetter>&
                                 url_request_context_getter);
 
   // Sets the proxy configs, enabling or disabling the proxy according to
@@ -214,6 +221,10 @@
   // Updates the Data Reduction Proxy configurator with the current config.
   void UpdateConfigForTesting(bool enabled, bool restricted);
 
+  // Updates the callback that is called when the warmup URL has been fetched.
+  void SetWarmupURLFetcherCallbackForTesting(
+      base::Callback<void()> warmup_url_fetched_callback);
+
  private:
   friend class MockDataReductionProxyConfig;
   friend class TestDataReductionProxyConfig;
@@ -230,6 +241,7 @@
   FRIEND_TEST_ALL_PREFIXES(DataReductionProxyConfigTest, LoFiAccuracy);
   FRIEND_TEST_ALL_PREFIXES(DataReductionProxyConfigTest,
                            LoFiAccuracyNonZeroDelay);
+  FRIEND_TEST_ALL_PREFIXES(DataReductionProxyConfigTest, WarmupURL);
 
   // Values of the estimated network quality at the beginning of the most
   // recent query of the Network Quality Estimator.
@@ -308,8 +320,15 @@
   // for testing.
   virtual bool GetIsCaptivePortal() const;
 
+  // Fetches the warmup URL.
+  void FetchWarmupURL();
+
+  // URL fetcher used for performing the secure proxy check.
   std::unique_ptr<SecureProxyChecker> secure_proxy_checker_;
 
+  // URL fetcher used for fetching the warmup URL.
+  std::unique_ptr<WarmupURLFetcher> warmup_url_fetcher_;
+
   // Indicates if the secure Data Reduction Proxy can be used or not.
   bool secure_proxy_allowed_;
 
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h
index 05b59b3..4198e68 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h
@@ -118,6 +118,7 @@
   void SetIsCaptivePortal(bool is_captive_portal);
 
   using DataReductionProxyConfig::UpdateConfigForTesting;
+  using DataReductionProxyConfig::SetWarmupURLFetcherCallbackForTesting;
 
  private:
   bool GetIsCaptivePortal() const override;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
index 0535786..c2984bc 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
@@ -14,10 +14,13 @@
 #include <vector>
 
 #include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/metrics/field_trial.h"
+#include "base/run_loop.h"
 #include "base/strings/safe_sprintf.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
@@ -44,8 +47,10 @@
 #include "net/nqe/network_quality_estimator.h"
 #include "net/nqe/network_quality_estimator_test_util.h"
 #include "net/proxy/proxy_server.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "net/url_request/url_fetcher.h"
+#include "net/url_request/url_request.h"
 #include "net/url_request/url_request_test_util.h"
 
 using testing::_;
@@ -167,6 +172,17 @@
         1);
   }
 
+  void WarmupURLFetchedCallBack() const {
+    warmup_url_fetched_run_loop_->Quit();
+  }
+
+  void WarmUpURLFetchedRunLoop() {
+    warmup_url_fetched_run_loop_.reset(new base::RunLoop());
+    // |warmup_url_fetched_run_loop_| will run until WarmupURLFetchedCallBack()
+    // is called.
+    warmup_url_fetched_run_loop_->Run();
+  }
+
   void RunUntilIdle() {
     test_context_->RunUntilIdle();
   }
@@ -204,6 +220,7 @@
   std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_;
 
   base::MessageLoopForIO message_loop_;
+  std::unique_ptr<base::RunLoop> warmup_url_fetched_run_loop_;
   std::unique_ptr<DataReductionProxyTestContext> test_context_;
   std::unique_ptr<TestDataReductionProxyParams> expected_params_;
 };
@@ -304,6 +321,103 @@
       FAILED_PROXY_DISABLED, std::vector<net::ProxyServer>(1, kHttpProxy));
 }
 
+// Verifies that the warm up URL is fetched correctly.
+TEST_F(DataReductionProxyConfigTest, WarmupURL) {
+  const net::URLRequestStatus kSuccess(net::URLRequestStatus::SUCCESS, net::OK);
+  const net::ProxyServer kHttpsProxy = net::ProxyServer::FromURI(
+      "https://secure_origin.net:443", net::ProxyServer::SCHEME_HTTP);
+  const net::ProxyServer kHttpProxy = net::ProxyServer::FromURI(
+      "insecure_origin.net:80", net::ProxyServer::SCHEME_HTTP);
+
+  // Set up the embedded test server from where the warm up URL will be fetched.
+  net::EmbeddedTestServer embedded_test_server;
+  embedded_test_server.AddDefaultHandlers(
+      base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest")));
+  EXPECT_TRUE(embedded_test_server.Start());
+
+  GURL warmup_url = embedded_test_server.GetURL("/simple.html");
+
+  const struct {
+    bool data_reduction_proxy_enabled;
+    bool enabled_via_field_trial;
+  } tests[] = {
+      {
+          false, false,
+      },
+      {
+          false, true,
+      },
+      {
+          true, false,
+      },
+      {
+          true, true,
+      },
+  };
+  for (const auto& test : tests) {
+    base::HistogramTester histogram_tester;
+    SetProxiesForHttpOnCommandLine({kHttpsProxy, kHttpProxy});
+
+    ResetSettings(true, true, true, false);
+
+    variations::testing::ClearAllVariationParams();
+    std::map<std::string, std::string> variation_params;
+    variation_params["enable_warmup"] =
+        test.enabled_via_field_trial ? "true" : "false";
+    variation_params["warmup_url"] = warmup_url.spec();
+
+    ASSERT_TRUE(variations::AssociateVariationParams(
+        params::GetQuicFieldTrialName(), "Enabled", variation_params));
+
+    base::FieldTrialList field_trial_list(nullptr);
+    base::FieldTrialList::CreateFieldTrial(params::GetQuicFieldTrialName(),
+                                           "Enabled");
+
+    base::CommandLine::ForCurrentProcess()->InitFromArgv(0, NULL);
+    TestDataReductionProxyConfig config(
+        DataReductionProxyParams::kAllowed |
+            DataReductionProxyParams::kFallbackAllowed,
+        TestDataReductionProxyParams::HAS_EVERYTHING, task_runner(), nullptr,
+        configurator(), event_creator());
+
+    scoped_refptr<net::URLRequestContextGetter> request_context_getter_ =
+        new net::TestURLRequestContextGetter(task_runner());
+    config.InitializeOnIOThread(request_context_getter_.get(),
+                                request_context_getter_.get());
+    config.SetWarmupURLFetcherCallbackForTesting(
+        base::Bind(&DataReductionProxyConfigTest::WarmupURLFetchedCallBack,
+                   base::Unretained(this)));
+    config.SetProxyConfig(test.data_reduction_proxy_enabled, true);
+    bool warmup_url_enabled =
+        test.data_reduction_proxy_enabled && test.enabled_via_field_trial;
+
+    if (warmup_url_enabled) {
+      // Block until warm up URL is fetched successfully.
+      WarmUpURLFetchedRunLoop();
+      histogram_tester.ExpectUniqueSample(
+          "DataReductionProxy.WarmupURL.FetchInitiated", 1, 1);
+      histogram_tester.ExpectUniqueSample(
+          "DataReductionProxy.WarmupURL.FetchSuccessful", 1, 1);
+    }
+
+    config.OnIPAddressChanged();
+
+    if (warmup_url_enabled) {
+      // Block until warm up URL is fetched successfully.
+      WarmUpURLFetchedRunLoop();
+      histogram_tester.ExpectUniqueSample(
+          "DataReductionProxy.WarmupURL.FetchInitiated", 1, 2);
+      histogram_tester.ExpectUniqueSample(
+          "DataReductionProxy.WarmupURL.FetchSuccessful", 1, 2);
+    } else {
+      histogram_tester.ExpectTotalCount(
+          "DataReductionProxy.WarmupURL.FetchInitiated", 0);
+      histogram_tester.ExpectTotalCount(
+          "DataReductionProxy.WarmupURL.FetchSuccessful", 0);
+    }
+  }
+}
+
 TEST_F(DataReductionProxyConfigTest, AreProxiesBypassed) {
   const struct {
     // proxy flags
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc
index 4a1326e..91c05f7d 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc
@@ -196,7 +196,8 @@
 
 void DataReductionProxyIOData::InitializeOnIOThread() {
   DCHECK(io_task_runner_->BelongsToCurrentThread());
-  config_->InitializeOnIOThread(basic_url_request_context_getter_.get());
+  config_->InitializeOnIOThread(basic_url_request_context_getter_.get(),
+                                url_request_context_getter_);
   bypass_stats_->InitializeOnIOThread();
   proxy_delegate_->InitializeOnIOThread();
   if (config_client_.get())
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.cc
index c2b2b44..b3d912c 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.cc
@@ -21,6 +21,8 @@
                                 false);
 
   registry->RegisterInt64Pref(prefs::kDataReductionProxyLastEnabledTime, 0L);
+  registry->RegisterInt64Pref(
+      prefs::kDataReductionProxySavingsClearedNegativeSystemClock, 0);
 
   registry->RegisterBooleanPref(prefs::kDataUsageReportingEnabled, false);
 
@@ -108,7 +110,8 @@
   registry->RegisterStringPref(prefs::kDataReductionProxy, std::string());
   registry->RegisterInt64Pref(prefs::kDataReductionProxyLastEnabledTime, 0L);
   registry->RegisterInt64Pref(
-      prefs::kHttpReceivedContentLength, 0);
+      prefs::kDataReductionProxySavingsClearedNegativeSystemClock, 0);
+  registry->RegisterInt64Pref(prefs::kHttpReceivedContentLength, 0);
   registry->RegisterInt64Pref(
       prefs::kHttpOriginalContentLength, 0);
   registry->RegisterListPref(
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc
index ee018ff..4e6cb86 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc
@@ -277,6 +277,22 @@
           (clock_->Now() - base::Time::FromInternalValue(last_enabled_time))
               .InDays());
     }
+
+    int64_t last_savings_cleared_time = prefs->GetInt64(
+        prefs::kDataReductionProxySavingsClearedNegativeSystemClock);
+    if (last_savings_cleared_time != 0) {
+      int32_t days_since_savings_cleared =
+          (clock_->Now() -
+           base::Time::FromInternalValue(last_savings_cleared_time))
+              .InDays();
+
+      // Sample in the UMA histograms must be at least 1.
+      if (days_since_savings_cleared == 0)
+        days_since_savings_cleared = 1;
+      UMA_HISTOGRAM_CUSTOM_COUNTS(
+          "DataReductionProxy.DaysSinceSavingsCleared.NegativeSystemClock",
+          days_since_savings_cleared, 1, 365, 50);
+    }
   }
 
   if (spdy_proxy_auth_enabled_.GetValue() &&
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h
index 513a797..f522542 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h
@@ -270,6 +270,8 @@
                            TestDaysSinceEnabledWithTestClock);
   FRIEND_TEST_ALL_PREFIXES(DataReductionProxySettingsTest,
                            TestDaysSinceEnabledExistingUser);
+  FRIEND_TEST_ALL_PREFIXES(DataReductionProxySettingsTest,
+                           TestDaysSinceSavingsCleared);
 
   // Override of DataReductionProxyService::Observer.
   void OnServiceInitialized() override;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_unittest.cc
index 52566c0d..dd162d19 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_unittest.cc
@@ -731,6 +731,32 @@
                    prefs::kDataReductionProxyLastEnabledTime));
 }
 
+TEST_F(DataReductionProxySettingsTest, TestDaysSinceSavingsCleared) {
+  std::unique_ptr<base::SimpleTestClock> clock(new base::SimpleTestClock());
+  base::SimpleTestClock* clock_ptr = clock.get();
+  clock_ptr->Advance(base::TimeDelta::FromDays(1));
+  ResetSettings(std::move(clock), true, true, false, false);
+
+  InitPrefMembers();
+  base::HistogramTester histogram_tester;
+  test_context_->pref_service()->SetInt64(
+      prefs::kDataReductionProxySavingsClearedNegativeSystemClock,
+      clock_ptr->Now().ToInternalValue());
+
+  settings_->data_reduction_proxy_service_->SetIOData(
+      test_context_->io_data()->GetWeakPtr());
+  test_context_->RunUntilIdle();
+
+  clock_ptr->Advance(base::TimeDelta::FromDays(100));
+
+  // Simulate Chromium startup with data reduction proxy already enabled.
+  settings_->spdy_proxy_auth_enabled_.SetValue(true);
+  settings_->MaybeActivateDataReductionProxy(true /* at_startup */);
+  test_context_->RunUntilIdle();
+  histogram_tester.ExpectUniqueSample(
+      "DataReductionProxy.DaysSinceSavingsCleared.NegativeSystemClock", 100, 1);
+}
+
 TEST_F(DataReductionProxySettingsTest, TestGetDailyContentLengths) {
   ContentLengthList result =
       settings_->GetDailyContentLengths(prefs::kDailyHttpOriginalContentLength);
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc
index f4c28f4..84f14ec 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc
@@ -33,7 +33,7 @@
     "http://o-o.preferred.nttdocomodcp-hnd1.proxy-dev.googlezip.net:80";
 const char kDefaultFallbackOrigin[] = "compress.googlezip.net:80";
 const char kDefaultSecureProxyCheckUrl[] = "http://check.googlezip.net/connect";
-const char kDefaultWarmupUrl[] = "http://www.gstatic.com/generate_204";
+const char kDefaultWarmupUrl[] = "http://check.googlezip.net/generate_204";
 
 const char kAndroidOneIdentifier[] = "sprout";
 
@@ -138,6 +138,29 @@
              "TamperDetection_Enabled", base::CompareCase::SENSITIVE);
 }
 
+bool FetchWarmupURLEnabled() {
+  // Fetching of the warmup URL can be enabled only for Enabled* and Control*
+  // groups.
+  if (!base::StartsWith(FieldTrialList::FindFullName(kQuicFieldTrial), kEnabled,
+                        base::CompareCase::SENSITIVE) &&
+      !base::StartsWith(FieldTrialList::FindFullName(kQuicFieldTrial), kControl,
+                        base::CompareCase::SENSITIVE)) {
+    return false;
+  }
+
+  std::map<std::string, std::string> params;
+  variations::GetVariationParams(GetQuicFieldTrialName(), &params);
+  return GetStringValueForVariationParamWithDefaultValue(
+             params, "enable_warmup", "false") == "true";
+}
+
+GURL GetWarmupURL() {
+  std::map<std::string, std::string> params;
+  variations::GetVariationParams(GetQuicFieldTrialName(), &params);
+  return GURL(GetStringValueForVariationParamWithDefaultValue(
+      params, "warmup_url", kDefaultWarmupUrl));
+}
+
 bool IsLoFiOnViaFlags() {
   return IsLoFiAlwaysOnViaFlags() || IsLoFiCellularOnlyViaFlags() ||
          IsLoFiSlowConnectionsOnlyViaFlags();
@@ -427,8 +450,6 @@
     fallback_origin = GetDefaultFallbackOrigin();
   if (secure_proxy_check_url.empty())
     secure_proxy_check_url = GetDefaultSecureProxyCheckURL();
-  if (warmup_url.empty())
-    warmup_url = GetDefaultWarmupURL();
 
   origin_ = net::ProxyServer::FromURI(origin, net::ProxyServer::SCHEME_HTTP);
   fallback_origin_ =
@@ -439,7 +460,6 @@
     proxies_for_http_.push_back(fallback_origin_);
 
   secure_proxy_check_url_ = GURL(secure_proxy_check_url);
-  warmup_url_ = GURL(warmup_url);
 }
 
 const std::vector<net::ProxyServer>&
@@ -495,8 +515,5 @@
   return kDefaultSecureProxyCheckUrl;
 }
 
-std::string DataReductionProxyParams::GetDefaultWarmupURL() const {
-  return kDefaultWarmupUrl;
-}
 
 }  // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h
index 4aea4d5c..bfdf16e 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h
@@ -148,6 +148,12 @@
 // Returns the name of the server side experiment field trial.
 const char* GetServerExperimentsFieldTrialName();
 
+// Returns true if fetching of the warmup URL is enabled.
+bool FetchWarmupURLEnabled();
+
+// Returns the warmup URL.
+GURL GetWarmupURL();
+
 }  // namespace params
 
 // Contains information about a given proxy server. |proxies_for_http| contains
@@ -222,7 +228,6 @@
   virtual std::string GetDefaultOrigin() const;
   virtual std::string GetDefaultFallbackOrigin() const;
   virtual std::string GetDefaultSecureProxyCheckURL() const;
-  virtual std::string GetDefaultWarmupURL() const;
 
   std::vector<net::ProxyServer> proxies_for_http_;
 
@@ -231,7 +236,6 @@
   net::ProxyServer fallback_origin_;
 
   GURL secure_proxy_check_url_;
-  GURL warmup_url_;
 
   bool allowed_;
   bool fallback_allowed_;
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_params_unittest.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_params_unittest.cc
index 716e02a1..e849b0d 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_params_unittest.cc
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_params_unittest.cc
@@ -377,20 +377,31 @@
     bool expected_enabled;
     std::string zero_rtt_param;
     bool expected_zero_rtt;
+    bool enable_warmup_url;
+    bool expect_warmup_url_enabled;
+    std::string warmup_url;
   } tests[] = {
-      {"Enabled", true, "true", true},
-      {"Enabled_Control", true, "true", true},
-      {"Enabled_Control", true, "false", false},
-      {"Enabled_Control", true, std::string(), false},
-      {"Control", false, "true", false},
-      {"Disabled", false, "false", false},
-      {"enabled", false, "false", false},
+      {"Enabled", true, "true", true, true, true, std::string()},
+      {"Enabled", true, "true", true, false, false, std::string()},
+      {"Enabled_Control", true, "true", true, true, true, std::string()},
+      {"Enabled_Control", true, "false", false, true, true, std::string()},
+      {"Enabled_Control", true, std::string(), false, true, true,
+       std::string()},
+      {"Control", false, "true", false, true, true, std::string()},
+      {"Disabled", false, "false", false, true, false, std::string()},
+      {"enabled", false, "false", false, true, false, std::string()},
+      {"Enabled", true, "true", true, true, true, "example.com/test.html"},
   };
 
   for (const auto& test : tests) {
     variations::testing::ClearAllVariationParams();
     std::map<std::string, std::string> variation_params;
     variation_params["enable_zero_rtt"] = test.zero_rtt_param;
+    if (test.enable_warmup_url)
+      variation_params["enable_warmup"] = "true";
+
+    if (!test.warmup_url.empty())
+      variation_params["warmup_url"] = test.warmup_url;
     ASSERT_TRUE(variations::AssociateVariationParams(
         params::GetQuicFieldTrialName(), test.trial_group_name,
         variation_params));
@@ -401,6 +412,13 @@
 
     EXPECT_EQ(test.expected_enabled, params::IsIncludedInQuicFieldTrial());
     EXPECT_EQ(test.expected_zero_rtt, params::IsZeroRttQuicEnabled());
+    if (!test.warmup_url.empty()) {
+      EXPECT_EQ(GURL(test.warmup_url), params::GetWarmupURL());
+    } else {
+      EXPECT_EQ(GURL("http://check.googlezip.net/generate_204"),
+                params::GetWarmupURL());
+    }
+    EXPECT_EQ(test.expect_warmup_url_enabled, params::FetchWarmupURLEnabled());
   }
 }
 
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.cc
index cd72646..0ac6d04 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.cc
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.cc
@@ -191,6 +191,11 @@
 const char kDataReductionProxyLastEnabledTime[] =
     "data_reduction.last_enabled_time";
 
+// An integer pref that contains the time when the data reduction proxy savings
+// were last cleared because the system clock was moved back by more than 1 day.
+const char kDataReductionProxySavingsClearedNegativeSystemClock[] =
+    "data_reduction.savings_cleared_negative_system_clock";
+
 // An int64_t pref that contains the total size of all HTTP content received
 // from the network.
 const char kHttpReceivedContentLength[] = "http_received_content_length";
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h
index 65c93b2b..e67a082 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h
@@ -48,6 +48,7 @@
 extern const char kDataUsageReportingEnabled[];
 extern const char kDataReductionProxyWasEnabledBefore[];
 extern const char kDataReductionProxyLastEnabledTime[];
+extern const char kDataReductionProxySavingsClearedNegativeSystemClock[];
 extern const char kHttpOriginalContentLength[];
 extern const char kHttpReceivedContentLength[];
 extern const char kLoFiImplicitOptOutEpoch[];
diff --git a/components/data_use_measurement/core/data_use_measurement_unittest.cc b/components/data_use_measurement/core/data_use_measurement_unittest.cc
index 707577b..31a2784 100644
--- a/components/data_use_measurement/core/data_use_measurement_unittest.cc
+++ b/components/data_use_measurement/core/data_use_measurement_unittest.cc
@@ -41,9 +41,21 @@
   }
 };
 
+// The more usual initialization of kUserDataKey would be along the lines of
+//     const void* const UserRequestUserDataForTesting::kUserDataKey =
+//         &UserRequestUserDataForTesting::kUserDataKey;
+// but lld's identical constant folding then folds that with
+// DataUseUserData::kUserDataKey which is initialized like that as well, and
+// then UserRequestUserDataForTesting::IsUserRequest() starts classifying
+// service requests as user requests.  To work around this, make
+// UserRequestUserDataForTesting::kUserDataKey point to an arbitrary integer
+// instead.
+// TODO(thakis): If we changed lld to only ICF over code and not over data,
+// we could undo this again.
+const int kICFBuster = 12345634;
+
 // static
-const void* const UserRequestUserDataForTesting::kUserDataKey =
-    &UserRequestUserDataForTesting::kUserDataKey;
+const void* const UserRequestUserDataForTesting::kUserDataKey = &kICFBuster;
 
 class DataUseMeasurementTest : public testing::Test {
  public:
diff --git a/components/display_compositor/compositor_overlay_candidate_validator_android.cc b/components/display_compositor/compositor_overlay_candidate_validator_android.cc
index b5b1c130..a42d035 100644
--- a/components/display_compositor/compositor_overlay_candidate_validator_android.cc
+++ b/components/display_compositor/compositor_overlay_candidate_validator_android.cc
@@ -37,7 +37,7 @@
 
     // This quad either will be promoted, or would be if it were backed by a
     // SurfaceView.  Record that it should get a promotion hint.
-    candidates->promotable_resource_hints_.insert(candidate.resource_id);
+    candidates->AddPromotionHint(candidate);
 
     if (candidate.is_backed_by_surface_texture) {
       // This quad would be promoted if it were backed by a SurfaceView.  Since
diff --git a/components/omnibox/browser/omnibox_field_trial.cc b/components/omnibox/browser/omnibox_field_trial.cc
index cbcf6f6..371c7626 100644
--- a/components/omnibox/browser/omnibox_field_trial.cc
+++ b/components/omnibox/browser/omnibox_field_trial.cc
@@ -371,33 +371,21 @@
   }
 }
 
-bool OmniboxFieldTrial::HQPExperimentalScoringEnabled() {
-  return variations::GetVariationParamValue(
-      kBundledExperimentFieldTrialName,
-      kHQPExperimentalScoringEnabledParam) == "true";
-}
-
 std::string OmniboxFieldTrial::HQPExperimentalScoringBuckets() {
-  if (!HQPExperimentalScoringEnabled())
-    return "";
-
   return variations::GetVariationParamValue(
       kBundledExperimentFieldTrialName,
       kHQPExperimentalScoringBucketsParam);
 }
 
 float OmniboxFieldTrial::HQPExperimentalTopicalityThreshold() {
-  if (!HQPExperimentalScoringEnabled())
-    return -1;
-
-  std::string topicality_threhold_str =
-    variations::GetVariationParamValue(
-        kBundledExperimentFieldTrialName,
-        kHQPExperimentalScoringTopicalityThresholdParam);
+  std::string topicality_threshold_str = variations::GetVariationParamValue(
+      kBundledExperimentFieldTrialName,
+      kHQPExperimentalScoringTopicalityThresholdParam);
 
   double topicality_threshold;
-  if (!base::StringToDouble(topicality_threhold_str, &topicality_threshold))
-    return -1;
+  if (topicality_threshold_str.empty() ||
+      !base::StringToDouble(topicality_threshold_str, &topicality_threshold))
+    return 0.8f;
 
   return static_cast<float>(topicality_threshold);
 }
@@ -580,8 +568,6 @@
 const char OmniboxFieldTrial::kHUPNewScoringVisitedCountUseDecayFactorParam[] =
     "VisitedCountUseDecayFactor";
 
-const char OmniboxFieldTrial::kHQPExperimentalScoringEnabledParam[] =
-    "HQPExperimentalScoringEnabled";
 const char OmniboxFieldTrial::kHQPExperimentalScoringBucketsParam[] =
     "HQPExperimentalScoringBuckets";
 const char
diff --git a/components/omnibox/browser/omnibox_field_trial.h b/components/omnibox/browser/omnibox_field_trial.h
index c4c6afe7..ff72ad1f 100644
--- a/components/omnibox/browser/omnibox_field_trial.h
+++ b/components/omnibox/browser/omnibox_field_trial.h
@@ -270,22 +270,15 @@
   // For HQP scoring related experiments to control the topicality and scoring
   // ranges of relevancy scores.
 
-  // Returns true if HQP experimental scoring is enabled. Returns false if
-  // |kHQPExperimentalScoringEnabledParam| is not specified in the field trial.
-  static bool HQPExperimentalScoringEnabled();
-
-  // Returns the scoring buckets for HQP experiments. Returns empty string
-  // in case |kHQPExperimentalScoringBucketsParam| or
-  // |kHQPExperimentalScoringEnabledParam| is not specified in the
-  // field trial. Scoring buckets are stored in string form giving mapping from
-  // (topicality_score, frequency_score) to final relevance score.
-  // Please see GetRelevancyScore() under
-  // chrome/browser/history::ScoredHistoryMatch for details.
+  // Returns the scoring buckets for HQP experiments. Returns an empty string
+  // if scoring buckets are not specified in the field trial. Scoring buckets
+  // are stored in string form giving mapping from (topicality_score,
+  // frequency_score) to final relevance score. Please see GetRelevancyScore()
+  // under chrome/browser/history::ScoredHistoryMatch for details.
   static std::string HQPExperimentalScoringBuckets();
 
-  // Returns the topicality threshold for HQP experiments. Returns -1 if
-  // |kHQPExperimentalScoringTopicalityThresholdParam| or
-  // |kHQPExperimentalScoringEnabledParam| is not specified in the field trial.
+  // Returns the topicality threshold for HQP experiments. Returns a default
+  // value of 0.8 if no threshold is specified in the field trial.
   static float HQPExperimentalTopicalityThreshold();
 
   // ---------------------------------------------------------
@@ -411,7 +404,6 @@
   static const char kHUPNewScoringVisitedCountUseDecayFactorParam[];
 
   // Parameter names used by the HQP experimental scoring experiments.
-  static const char kHQPExperimentalScoringEnabledParam[];
   static const char kHQPExperimentalScoringBucketsParam[];
   static const char kHQPExperimentalScoringTopicalityThresholdParam[];
 
diff --git a/components/omnibox/browser/scored_history_match.cc b/components/omnibox/browser/scored_history_match.cc
index bdde8e5..8e88bfa 100644
--- a/components/omnibox/browser/scored_history_match.cc
+++ b/components/omnibox/browser/scored_history_match.cc
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "base/logging.h"
+#include "base/macros.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
@@ -113,17 +114,9 @@
 bool ScoredHistoryMatch::allow_tld_matches_;
 bool ScoredHistoryMatch::allow_scheme_matches_;
 size_t ScoredHistoryMatch::num_title_words_to_allow_;
-bool ScoredHistoryMatch::hqp_experimental_scoring_enabled_;
-
-// Default topicality threshold.  See GetTopicalityScore() for details.
-float ScoredHistoryMatch::topicality_threshold_ = 0.8f;
-
-// Default HQP relevance buckets. See GetFinalRelevancyScore() for more details
-// on these numbers.
-char ScoredHistoryMatch::hqp_relevance_buckets_str_[] =
-    "0.0:400,1.5:600,5.0:900,10.5:1203,15.0:1300,20.0:1399";
-std::vector<ScoredHistoryMatch::ScoreMaxRelevance>*
-    ScoredHistoryMatch::hqp_relevance_buckets_ = nullptr;
+float ScoredHistoryMatch::topicality_threshold_;
+ScoredHistoryMatch::ScoreMaxRelevances*
+    ScoredHistoryMatch::relevance_buckets_override_ = nullptr;
 
 ScoredHistoryMatch::ScoredHistoryMatch()
     : ScoredHistoryMatch(history::URLRow(),
@@ -261,8 +254,8 @@
   const float topicality_score = GetTopicalityScore(
       terms_vector.size(), url, terms_to_word_starts_offsets, word_starts);
   const float frequency_score = GetFrequency(now, is_url_bookmarked, visits);
-  raw_score = base::saturated_cast<int>(GetFinalRelevancyScore(
-      topicality_score, frequency_score, *hqp_relevance_buckets_));
+  raw_score = base::saturated_cast<int>(
+      GetFinalRelevancyScore(topicality_score, frequency_score));
 
   if (also_do_hup_like_scoring_ && likely_can_inline) {
     // HistoryURL-provider-like scoring gives any match that is
@@ -415,10 +408,11 @@
   allow_tld_matches_ = OmniboxFieldTrial::HQPAllowMatchInTLDValue();
   allow_scheme_matches_ = OmniboxFieldTrial::HQPAllowMatchInSchemeValue();
   num_title_words_to_allow_ = OmniboxFieldTrial::HQPNumTitleWordsToAllow();
+  topicality_threshold_ =
+      OmniboxFieldTrial::HQPExperimentalTopicalityThreshold();
 
   InitRawTermScoreToTopicalityScoreArray();
   InitDaysAgoToRecencyScoreArray();
-  InitHQPExperimentalParams();
 }
 
 float ScoredHistoryMatch::GetTopicalityScore(
@@ -617,12 +611,17 @@
 }
 
 // static
-float ScoredHistoryMatch::GetFinalRelevancyScore(
-    float topicality_score,
-    float frequency_score,
-    const std::vector<ScoreMaxRelevance>& hqp_relevance_buckets) {
-  DCHECK(hqp_relevance_buckets.size() > 0);
-  DCHECK_EQ(hqp_relevance_buckets[0].first, 0.0);
+float ScoredHistoryMatch::GetFinalRelevancyScore(float topicality_score,
+                                                 float frequency_score) {
+  // |relevance_buckets| gives a mapping from intemerdiate score to the final
+  // relevance score.
+  CR_DEFINE_STATIC_LOCAL(ScoreMaxRelevances, default_relevance_buckets,
+                         (GetHQPBuckets()));
+  ScoreMaxRelevances* relevance_buckets = relevance_buckets_override_
+                                              ? relevance_buckets_override_
+                                              : &default_relevance_buckets;
+  DCHECK(!relevance_buckets->empty());
+  DCHECK_EQ(0.0, (*relevance_buckets)[0].first);
 
   if (topicality_score == 0)
     return 0;
@@ -642,7 +641,7 @@
   //
   // The below code maps intermediate_score to the range [0, 1399].
   // For example:
-  // HQP default scoring buckets: "0.0:400,1.5:600,12.0:1300,20.0:1399"
+  // The default scoring buckets: "0.0:400,1.5:600,12.0:1300,20.0:1399"
   // We will linearly interpolate the scores between:
   //      0 to 1.5    --> 400 to 600
   //    1.5 to 12.0   --> 600 to 1300
@@ -655,76 +654,52 @@
 
   // Find the threshold where intermediate score is greater than bucket.
   size_t i = 1;
-  for (; i < hqp_relevance_buckets.size(); ++i) {
-    const ScoreMaxRelevance& hqp_bucket = hqp_relevance_buckets[i];
-    if (intermediate_score >= hqp_bucket.first) {
+  for (; i < relevance_buckets->size(); ++i) {
+    const ScoreMaxRelevance& bucket = (*relevance_buckets)[i];
+    if (intermediate_score >= bucket.first) {
       continue;
     }
-    const ScoreMaxRelevance& previous_bucket = hqp_relevance_buckets[i - 1];
-    const float slope = ((hqp_bucket.second - previous_bucket.second) /
-                         (hqp_bucket.first - previous_bucket.first));
+    const ScoreMaxRelevance& previous_bucket = (*relevance_buckets)[i - 1];
+    const float slope = ((bucket.second - previous_bucket.second) /
+                         (bucket.first - previous_bucket.first));
     return (previous_bucket.second +
             (slope * (intermediate_score - previous_bucket.first)));
   }
   // It will reach this stage when the score is > highest bucket score.
   // Return the highest bucket score.
-  return hqp_relevance_buckets[i - 1].second;
+  return (*relevance_buckets)[i - 1].second;
 }
 
 // static
-void ScoredHistoryMatch::InitHQPExperimentalParams() {
-  // These are default HQP relevance scoring buckets.
-  // See GetFinalRelevancyScore() for details.
-  std::string hqp_relevance_buckets_str = std::string(
-      hqp_relevance_buckets_str_);
-
-  // Fetch the experiment params if they are any.
-  hqp_experimental_scoring_enabled_ =
-      OmniboxFieldTrial::HQPExperimentalScoringEnabled();
-
-  if (hqp_experimental_scoring_enabled_) {
-    // Add the topicality threshold from experiment params.
-    float hqp_experimental_topicality_threhold =
-        OmniboxFieldTrial::HQPExperimentalTopicalityThreshold();
-    topicality_threshold_ = hqp_experimental_topicality_threhold;
-
-    // Add the HQP experimental scoring buckets.
-    std::string hqp_experimental_scoring_buckets =
-        OmniboxFieldTrial::HQPExperimentalScoringBuckets();
-    if (!hqp_experimental_scoring_buckets.empty())
-      hqp_relevance_buckets_str = hqp_experimental_scoring_buckets;
-  }
-
-  // Parse the hqp_relevance_buckets_str string once and store them in vector
-  // which is easy to access.
-  hqp_relevance_buckets_ =
-      new std::vector<ScoredHistoryMatch::ScoreMaxRelevance>();
-
-  bool is_valid_bucket_str = GetHQPBucketsFromString(hqp_relevance_buckets_str,
-                                                     hqp_relevance_buckets_);
-  DCHECK(is_valid_bucket_str);
+std::vector<ScoredHistoryMatch::ScoreMaxRelevance>
+ScoredHistoryMatch::GetHQPBuckets() {
+  // Start with the default buckets and override them if appropriate.
+  std::string relevance_buckets_str =
+      "0.0:400,1.5:600,5.0:900,10.5:1203,15.0:1300,20.0:1399";
+  std::string experimental_scoring_buckets =
+      OmniboxFieldTrial::HQPExperimentalScoringBuckets();
+  if (!experimental_scoring_buckets.empty())
+    relevance_buckets_str = experimental_scoring_buckets;
+  return GetHQPBucketsFromString(relevance_buckets_str);
 }
 
 // static
-bool ScoredHistoryMatch::GetHQPBucketsFromString(
-    const std::string& buckets_str,
-    std::vector<ScoreMaxRelevance>* hqp_buckets) {
-  DCHECK(hqp_buckets != NULL);
+ScoredHistoryMatch::ScoreMaxRelevances
+ScoredHistoryMatch::GetHQPBucketsFromString(const std::string& buckets_str) {
   DCHECK(!buckets_str.empty());
-
   base::StringPairs kv_pairs;
-  if (base::SplitStringIntoKeyValuePairs(buckets_str, ':', ',', &kv_pairs)) {
-    for (base::StringPairs::const_iterator it = kv_pairs.begin();
-         it != kv_pairs.end(); ++it) {
-      ScoreMaxRelevance bucket;
-      bool is_valid_intermediate_score =
-          base::StringToDouble(it->first, &bucket.first);
-      DCHECK(is_valid_intermediate_score);
-      bool is_valid_hqp_score = base::StringToInt(it->second, &bucket.second);
-      DCHECK(is_valid_hqp_score);
-      hqp_buckets->push_back(bucket);
-    }
-    return true;
+  if (!base::SplitStringIntoKeyValuePairs(buckets_str, ':', ',', &kv_pairs))
+    return ScoreMaxRelevances();
+  ScoreMaxRelevances hqp_buckets;
+  for (base::StringPairs::const_iterator it = kv_pairs.begin();
+       it != kv_pairs.end(); ++it) {
+    ScoreMaxRelevance bucket;
+    bool is_valid_intermediate_score =
+        base::StringToDouble(it->first, &bucket.first);
+    DCHECK(is_valid_intermediate_score);
+    bool is_valid_hqp_score = base::StringToInt(it->second, &bucket.second);
+    DCHECK(is_valid_hqp_score);
+    hqp_buckets.push_back(bucket);
   }
-  return false;
+  return hqp_buckets;
 }
diff --git a/components/omnibox/browser/scored_history_match.h b/components/omnibox/browser/scored_history_match.h
index dacd31ce..a58c62a 100644
--- a/components/omnibox/browser/scored_history_match.h
+++ b/components/omnibox/browser/scored_history_match.h
@@ -24,9 +24,14 @@
 struct ScoredHistoryMatch : public history::HistoryMatch {
   // ScoreMaxRelevance maps from an intermediate-score to the maximum
   // final-relevance score given to a URL for this intermediate score.
-  // This is used to store the score ranges of HQP relevance buckets.
+  // This is used to store the score ranges of relevance buckets.
   // Please see GetFinalRelevancyScore() for details.
-  typedef std::pair<double, int> ScoreMaxRelevance;
+  using ScoreMaxRelevance = std::pair<double, int>;
+
+  // A sorted vector of ScoreMaxRelevance entries, used by taking a score and
+  // interpolating between consecutive buckets.  See GetFinalRelevancyScore()
+  // for details.
+  using ScoreMaxRelevances = std::vector<ScoreMaxRelevance>;
 
   // Required for STL, we don't use this directly.
   ScoredHistoryMatch();
@@ -128,29 +133,22 @@
                      const bool bookmarked,
                      const VisitInfoVector& visits) const;
 
-  // Combines the two component scores into a final score that's
-  // an appropriate value to use as a relevancy score. Scoring buckets are
-  // specified through |hqp_relevance_buckets|. Please see the function
-  // implementation for more details.
-  static float GetFinalRelevancyScore(
-      float topicality_score,
-      float frequency_score,
-      const std::vector<ScoreMaxRelevance>& hqp_relevance_buckets);
+  // Combines the two component scores into a final score that's an appropriate
+  // value to use as a relevancy score.
+  static float GetFinalRelevancyScore(float topicality_score,
+                                      float frequency_score);
 
-  // Initializes the HQP experimental params: |hqp_relevance_buckets_|
-  // to default buckets. If hqp experimental scoring is enabled, it
-  // fetches the |hqp_experimental_scoring_enabled_|, |topicality_threshold_|
-  // and |hqp_relevance_buckets_| from omnibox field trials.
-  static void InitHQPExperimentalParams();
+  // Helper function that returns the string containing the scoring buckets
+  // (either the default ones or ones specified in an experiment).
+  static ScoreMaxRelevances GetHQPBuckets();
 
-  // Helper function to parse the string containing the scoring buckets.
-  // For example,
-  // String: "0.0:400,1.5:600,12.0:1300,20.0:1399"
-  // Buckets: vector[(0.0, 400),(1.5,600),(12.0,1300),(20.0,1399)]
-  // Returns false, in case if it fail to parse the string.
-  static bool GetHQPBucketsFromString(
-      const std::string& buckets_str,
-      std::vector<ScoreMaxRelevance>* hqp_buckets);
+  // Helper function to parse the string containing the scoring buckets and
+  // return the results.  For example, with |buckets_str| as
+  // "0.0:400,1.5:600,12.0:1300,20.0:1399", it returns [(0.0, 400), (1.5, 600),
+  // (12.0, 1300), (20.0, 1399)]. It returns an empty vector in the case of a
+  // malformed |buckets_str|.
+  static ScoreMaxRelevances GetHQPBucketsFromString(
+      const std::string& buckets_str);
 
   // If true, assign raw scores to be max(whatever it normally would be, a
   // score that's similar to the score HistoryURL provider would assign).
@@ -184,22 +182,15 @@
   // Words beyond this number are ignored.
   static size_t num_title_words_to_allow_;
 
-  // True, if hqp experimental scoring is enabled.
-  static bool hqp_experimental_scoring_enabled_;
-
   // |topicality_threshold_| is used to control the topicality scoring.
-  // If |topicality_threshold_| > 0, then URLs with topicality-score < threshold
-  // are given topicality score of 0. By default it is initalized to -1.
+  // If |topicality_threshold_| > 0, then URLs with topicality-score less than
+  // the threshold are given topicality score of 0.
   static float topicality_threshold_;
 
-  // |hqp_relevance_buckets_str_| is used to control the hqp score ranges.
-  // It is the string representation of |hqp_relevance_buckets_|.
-  static char hqp_relevance_buckets_str_[];
-
-  // |hqp_relevance_buckets_| gives mapping from (topicality*frequency)
-  // to the final relevance scoring. Please see GetFinalRelevancyScore()
-  // for more details and scoring method.
-  static std::vector<ScoreMaxRelevance>* hqp_relevance_buckets_;
+  // Used for testing.  A possibly null pointer to a vector.  If set,
+  // overrides the static local variable |relevance_buckets| declared in
+  // GetFinalRelevancyScore().
+  static ScoreMaxRelevances* relevance_buckets_override_;
 };
 typedef std::vector<ScoredHistoryMatch> ScoredHistoryMatches;
 
diff --git a/components/omnibox/browser/scored_history_match_unittest.cc b/components/omnibox/browser/scored_history_match_unittest.cc
index 1f416e4..06400b2 100644
--- a/components/omnibox/browser/scored_history_match_unittest.cc
+++ b/components/omnibox/browser/scored_history_match_unittest.cc
@@ -647,54 +647,51 @@
 
 // Test the function GetFinalRelevancyScore().
 TEST_F(ScoredHistoryMatchTest, GetFinalRelevancyScore) {
-  // hqp_relevance_buckets = "0.0:100,1.0:200,4.0:500,8.0:900,10.0:1000";
-  std::vector<ScoredHistoryMatch::ScoreMaxRelevance> hqp_buckets;
-  hqp_buckets.push_back(std::make_pair(0.0, 100));
-  hqp_buckets.push_back(std::make_pair(1.0, 200));
-  hqp_buckets.push_back(std::make_pair(4.0, 500));
-  hqp_buckets.push_back(std::make_pair(8.0, 900));
-  hqp_buckets.push_back(std::make_pair(10.0, 1000));
+  // relevance_buckets = "0.0:100,1.0:200,4.0:500,8.0:900,10.0:1000";
+  ScoredHistoryMatch::ScoreMaxRelevances relevance_buckets = {
+      {0.0, 100}, {1.0, 200}, {4.0, 500}, {8.0, 900}, {10.0, 1000}};
+  base::AutoReset<ScoredHistoryMatch::ScoreMaxRelevances*> tmp(
+      &ScoredHistoryMatch::relevance_buckets_override_, &relevance_buckets);
+
   // Check when topicality score is zero.
   float topicality_score = 0.0;
   float frequency_score = 10.0;
   // intermediate_score = 0.0 * 10.0 = 0.0.
-  EXPECT_EQ(0, ScoredHistoryMatch::GetFinalRelevancyScore(
-                   topicality_score, frequency_score, hqp_buckets));
+  EXPECT_EQ(0, ScoredHistoryMatch::GetFinalRelevancyScore(topicality_score,
+                                                          frequency_score));
 
   // Check when intermediate score falls at the border range.
   topicality_score = 0.4f;
   frequency_score = 10.0f;
   // intermediate_score = 0.5 * 10.0 = 4.0.
-  EXPECT_EQ(500, ScoredHistoryMatch::GetFinalRelevancyScore(
-                     topicality_score, frequency_score, hqp_buckets));
+  EXPECT_EQ(500, ScoredHistoryMatch::GetFinalRelevancyScore(topicality_score,
+                                                            frequency_score));
 
   // Checking the score that falls into one of the buckets.
   topicality_score = 0.5f;
   frequency_score = 10.0f;
   // intermediate_score = 0.5 * 10.0 = 5.0.
   EXPECT_EQ(600,  // 500 + (((900 - 500)/(8 -4)) * 1) = 600.
-            ScoredHistoryMatch::GetFinalRelevancyScore(
-                topicality_score, frequency_score, hqp_buckets));
+            ScoredHistoryMatch::GetFinalRelevancyScore(topicality_score,
+                                                       frequency_score));
 
   // Never give the score greater than maximum specified.
   topicality_score = 0.5f;
   frequency_score = 22.0f;
   // intermediate_score = 0.5 * 22.0 = 11.0
-  EXPECT_EQ(1000, ScoredHistoryMatch::GetFinalRelevancyScore(
-                      topicality_score, frequency_score, hqp_buckets));
+  EXPECT_EQ(1000, ScoredHistoryMatch::GetFinalRelevancyScore(topicality_score,
+                                                             frequency_score));
 }
 
 // Test the function GetHQPBucketsFromString().
 TEST_F(ScoredHistoryMatchTest, GetHQPBucketsFromString) {
   std::string buckets_str = "0.0:400,1.5:600,12.0:1300,20.0:1399";
-  std::vector<ScoredHistoryMatch::ScoreMaxRelevance> hqp_buckets;
-
-  EXPECT_TRUE(
-      ScoredHistoryMatch::GetHQPBucketsFromString(buckets_str, &hqp_buckets));
+  std::vector<ScoredHistoryMatch::ScoreMaxRelevance> hqp_buckets =
+      ScoredHistoryMatch::GetHQPBucketsFromString(buckets_str);
   EXPECT_THAT(hqp_buckets, ElementsAre(Pair(0.0, 400), Pair(1.5, 600),
                                        Pair(12.0, 1300), Pair(20.0, 1399)));
-  // invalid string.
+  // Test using an invalid string.
   buckets_str = "0.0,400,1.5,600";
-  EXPECT_FALSE(
-      ScoredHistoryMatch::GetHQPBucketsFromString(buckets_str, &hqp_buckets));
+  hqp_buckets = ScoredHistoryMatch::GetHQPBucketsFromString(buckets_str);
+  EXPECT_TRUE(hqp_buckets.empty());
 }
diff --git a/components/password_manager/core/browser/password_autofill_manager.cc b/components/password_manager/core/browser/password_autofill_manager.cc
index 1c0b1bf..56f3efc 100644
--- a/components/password_manager/core/browser/password_autofill_manager.cc
+++ b/components/password_manager/core/browser/password_autofill_manager.cc
@@ -310,6 +310,10 @@
   password_manager_driver_->ClearPreviewedForm();
 }
 
+bool PasswordAutofillManager::IsCreditCardPopup() {
+  return false;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // PasswordAutofillManager, private:
 
diff --git a/components/password_manager/core/browser/password_autofill_manager.h b/components/password_manager/core/browser/password_autofill_manager.h
index c1075c32..ce34770 100644
--- a/components/password_manager/core/browser/password_autofill_manager.h
+++ b/components/password_manager/core/browser/password_autofill_manager.h
@@ -42,6 +42,7 @@
                                    base::string16* body) override;
   bool RemoveSuggestion(const base::string16& value, int identifier) override;
   void ClearPreviewedForm() override;
+  bool IsCreditCardPopup() override;
 
   // Invoked when a password mapping is added.
   void OnAddPasswordFormMapping(
diff --git a/components/precache/content/BUILD.gn b/components/precache/content/BUILD.gn
index 54eed60..bca9748e5 100644
--- a/components/precache/content/BUILD.gn
+++ b/components/precache/content/BUILD.gn
@@ -39,6 +39,7 @@
     "//components/history/core/browser",
     "//components/precache/core",
     "//components/precache/core:proto",
+    "//components/variations:test_support",
     "//content/public/browser",
     "//content/test:test_support",
     "//net:test_support",
diff --git a/components/precache/content/DEPS b/components/precache/content/DEPS
index 6206a88..5a18477 100644
--- a/components/precache/content/DEPS
+++ b/components/precache/content/DEPS
@@ -5,12 +5,14 @@
   "+components/variations",
   "+content/public/browser",
   "+net/base",
+  "+net/disk_cache",
+  "+net/http",
+  "+net/url_request",
 ]
 
 specific_include_rules = {
   '.*_[a-z]*test\.cc': [
     "+content/public/test",
-    "+net/http",
-    "+net/url_request",
+    "+net/test",
   ],
 }
diff --git a/components/precache/content/precache_manager.cc b/components/precache/content/precache_manager.cc
index a884ff7..204ab49 100644
--- a/components/precache/content/precache_manager.cc
+++ b/components/precache/content/precache_manager.cc
@@ -11,7 +11,10 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/logging.h"
+#include "base/memory/ref_counted.h"
 #include "base/metrics/field_trial.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/time/time.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h"
@@ -27,12 +30,19 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/storage_partition.h"
 #include "net/base/network_change_notifier.h"
+#include "net/http/http_cache.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_context_getter.h"
 
 using content::BrowserThread;
 
-namespace {
+namespace precache {
 
 const char kPrecacheFieldTrialName[] = "Precache";
+const char kMinCacheSizeParam[] = "min_cache_size";
+
+namespace {
+
 const char kPrecacheFieldTrialEnabledGroup[] = "Enabled";
 const char kPrecacheFieldTrialControlGroup[] = "Control";
 const char kConfigURLParam[] = "config_url";
@@ -42,8 +52,6 @@
 
 }  // namespace
 
-namespace precache {
-
 size_t NumTopHosts() {
   return kNumTopHosts;
 }
@@ -123,6 +131,94 @@
   return AllowedType::DISALLOWED;
 }
 
+void PrecacheManager::OnCacheBackendReceived(int net_error_code) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  if (net_error_code != net::OK) {
+    // Assume there is no cache.
+    cache_backend_ = nullptr;
+    OnCacheSizeReceived(0);
+    return;
+  }
+  DCHECK(cache_backend_);
+  int result = cache_backend_->CalculateSizeOfAllEntries(base::Bind(
+      &PrecacheManager::OnCacheSizeReceived, base::Unretained(this)));
+  if (result == net::ERR_IO_PENDING) {
+    // Wait for the callback.
+  } else if (result >= 0) {
+    // The result is the expected bytes already.
+    OnCacheSizeReceived(result);
+  } else {
+    // Error occurred. Couldn't get the size. Assume there is no cache.
+    OnCacheSizeReceived(0);
+  }
+  cache_backend_ = nullptr;
+}
+
+void PrecacheManager::OnCacheSizeReceived(int cache_size_bytes) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      base::Bind(&PrecacheManager::OnCacheSizeReceivedInUIThread,
+                 base::Unretained(this), cache_size_bytes));
+}
+
+void PrecacheManager::OnCacheSizeReceivedInUIThread(int cache_size_bytes) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+  UMA_HISTOGRAM_MEMORY_KB("Precache.CacheSize.AllEntries",
+                          cache_size_bytes / 1024);
+
+  if (cache_size_bytes < min_cache_size_bytes_) {
+    OnDone();  // Do not continue.
+  } else {
+    BrowserThread::PostTaskAndReplyWithResult(
+        BrowserThread::DB, FROM_HERE,
+        base::Bind(&PrecacheDatabase::GetUnfinishedWork,
+                   base::Unretained(precache_database_.get())),
+        base::Bind(&PrecacheManager::OnGetUnfinishedWorkDone, AsWeakPtr()));
+  }
+}
+
+void PrecacheManager::PrecacheIfCacheIsBigEnough(
+    scoped_refptr<net::URLRequestContextGetter> url_request_context_getter) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  CHECK(url_request_context_getter);
+
+  // Continue with OnGetUnfinishedWorkDone only if the size of the cache is
+  // at least min_cache_size_bytes_.
+  // Class disk_cache::Backend does not expose its maximum size. However, caches
+  // are usually full, so we can use the size of all the entries stored in the
+  // cache (via CalculateSizeOfAllEntries) as a proxy of its maximum size.
+  net::URLRequestContext* context =
+      url_request_context_getter->GetURLRequestContext();
+  if (!context) {
+    OnCacheSizeReceived(0);
+    return;
+  }
+  net::HttpTransactionFactory* factory = context->http_transaction_factory();
+  if (!factory) {
+    OnCacheSizeReceived(0);
+    return;
+  }
+  net::HttpCache* cache = factory->GetCache();
+  if (!cache) {
+    // There is no known cache. Assume that there is no cache.
+    // TODO(jamartin): I'm not sure this can be an actual posibility. Consider
+    // making this a CHECK(cache).
+    OnCacheSizeReceived(0);
+    return;
+  }
+  const int net_error_code = cache->GetBackend(
+      &cache_backend_, base::Bind(&PrecacheManager::OnCacheBackendReceived,
+                                  base::Unretained(this)));
+  if (net_error_code != net::ERR_IO_PENDING) {
+    // No need to wait for the callback. The callback hasn't been called with
+    // the appropriate code, so we call it directly.
+    OnCacheBackendReceived(net_error_code);
+  }
+}
+
 void PrecacheManager::StartPrecaching(
     const PrecacheCompletionCallback& precache_completion_callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -140,12 +236,30 @@
       base::Bind(&PrecacheDatabase::SetLastPrecacheTimestamp,
                  base::Unretained(precache_database_.get()),
                  base::Time::Now()));
-  BrowserThread::PostTaskAndReplyWithResult(
-      BrowserThread::DB,
-      FROM_HERE,
-      base::Bind(&PrecacheDatabase::GetUnfinishedWork,
-                 base::Unretained(precache_database_.get())),
-      base::Bind(&PrecacheManager::OnGetUnfinishedWorkDone, AsWeakPtr()));
+
+  // Ignore boolean return value. In all documented failure cases, it sets the
+  // int to a reasonable value.
+  base::StringToInt(variations::GetVariationParamValue(kPrecacheFieldTrialName,
+                                                       kMinCacheSizeParam),
+                    &min_cache_size_bytes_);
+  if (min_cache_size_bytes_ <= 0) {
+    // Skip looking up the cache size, because it doesn't matter.
+    OnCacheSizeReceivedInUIThread(0);
+    return;
+  }
+
+  scoped_refptr<net::URLRequestContextGetter> url_request_context_getter(
+      content::BrowserContext::GetDefaultStoragePartition(browser_context_)
+          ->GetURLRequestContext());
+  if (!url_request_context_getter) {
+    OnCacheSizeReceivedInUIThread(0);
+    return;
+  }
+
+  BrowserThread::PostTask(
+      BrowserThread::IO, FROM_HERE,
+      base::Bind(&PrecacheManager::PrecacheIfCacheIsBigEnough, AsWeakPtr(),
+                 std::move(url_request_context_getter)));
 }
 
 void PrecacheManager::OnGetUnfinishedWorkDone(
diff --git a/components/precache/content/precache_manager.h b/components/precache/content/precache_manager.h
index 507aeba2..ec093b0 100644
--- a/components/precache/content/precache_manager.h
+++ b/components/precache/content/precache_manager.h
@@ -17,10 +17,13 @@
 #include "base/callback.h"
 #include "base/compiler_specific.h"
 #include "base/macros.h"
+#include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "components/history/core/browser/history_types.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/precache/core/precache_fetcher.h"
+#include "net/disk_cache/disk_cache.h"
+#include "net/http/http_cache.h"
 #include "url/gurl.h"
 
 namespace base {
@@ -55,6 +58,8 @@
 class PrecacheUnfinishedWork;
 
 // Visible for test.
+extern const char kPrecacheFieldTrialName[];
+extern const char kMinCacheSizeParam[];
 size_t NumTopHosts();
 
 // Class that manages all precaching-related activities. Owned by the
@@ -162,6 +167,14 @@
   // gets the list of TopHosts for metrics purposes, but otherwise does nothing.
   void OnHostsReceivedThenDone(const history::TopHostsList& host_counts);
 
+  // Chain of callbacks for StartPrecaching that make sure that we only precache
+  // if there is a cache big enough.
+  void PrecacheIfCacheIsBigEnough(
+      scoped_refptr<net::URLRequestContextGetter> url_request_context_getter);
+  void OnCacheBackendReceived(int net_error_code);
+  void OnCacheSizeReceived(int cache_size_bytes);
+  void OnCacheSizeReceivedInUIThread(int cache_size_bytes);
+
   // Returns true if precaching is allowed for the browser context.
   AllowedType PrecachingAllowed() const;
 
@@ -214,6 +227,15 @@
   // Flag indicating whether or not precaching is currently in progress.
   bool is_precaching_;
 
+  // Pointer to the backend of the cache. Required to get the size of the cache.
+  // It is not owned and it is reset on demand via callbacks.
+  // It should only be accessed from the IO thread.
+  disk_cache::Backend* cache_backend_;
+
+  // The minimum cache size allowed for precaching. Initialized by
+  // StartPrecaching and read by OnCacheSizeReceivedInUIThread.
+  int min_cache_size_bytes_;
+
   // Work that hasn't yet finished.
   std::unique_ptr<PrecacheUnfinishedWork> unfinished_work_;
 
diff --git a/components/precache/content/precache_manager_unittest.cc b/components/precache/content/precache_manager_unittest.cc
index c8d0d0c..a93a2ca 100644
--- a/components/precache/content/precache_manager_unittest.cc
+++ b/components/precache/content/precache_manager_unittest.cc
@@ -28,12 +28,17 @@
 #include "components/precache/core/precache_database.h"
 #include "components/precache/core/precache_switches.h"
 #include "components/precache/core/proto/unfinished_work.pb.h"
+#include "components/variations/variations_params_manager.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/storage_partition.h"
 #include "content/public/test/test_browser_context.h"
 #include "content/public/test/test_browser_thread_bundle.h"
+#include "net/base/test_completion_callback.h"
+#include "net/disk_cache/simple/simple_backend_impl.h"
 #include "net/http/http_response_headers.h"
 #include "net/http/http_response_info.h"
 #include "net/http/http_status_code.h"
+#include "net/test/gtest_util.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "net/url_request/url_request_status.h"
 #include "net/url_request/url_request_test_util.h"
@@ -223,6 +228,7 @@
   testing::NiceMock<MockHistoryService> history_service_;
   base::HistogramTester histograms_;
   net::HttpResponseInfo info_;
+  variations::testing::VariationParamsManager variation_params_;
 };
 
 TEST_F(PrecacheManagerTest, StartAndFinishPrecaching) {
@@ -253,6 +259,75 @@
   EXPECT_EQ(expected_requested_urls, url_callback_.requested_urls());
 }
 
+TEST_F(PrecacheManagerTest, StartPrecachingWithGoodSizedCache) {
+  variation_params_.SetVariationParams(kPrecacheFieldTrialName,
+                                       {{kMinCacheSizeParam, "1"}});
+
+  // Let's store something in the cache so we pass the min_cache_size threshold.
+  disk_cache::Backend* cache_backend;
+  {
+    // Get the CacheBackend.
+    net::TestCompletionCallback cb;
+    net::HttpCache* cache =
+        content::BrowserContext::GetDefaultStoragePartition(&browser_context_)
+            ->GetURLRequestContext()
+            ->GetURLRequestContext()
+            ->http_transaction_factory()
+            ->GetCache();
+    CHECK_NE(nullptr, cache);
+    int rv = cache->GetBackend(&cache_backend, cb.callback());
+    CHECK_EQ(net::OK, cb.GetResult(rv));
+    CHECK_NE(nullptr, cache_backend);
+    CHECK_EQ(cache_backend, cache->GetCurrentBackend());
+  }
+  disk_cache::Entry* entry = nullptr;
+  {
+    // Create a cache Entry.
+    net::TestCompletionCallback cb;
+    int rv = cache_backend->CreateEntry("key", &entry, cb.callback());
+    CHECK_EQ(net::OK, cb.GetResult(rv));
+    CHECK_NE(nullptr, entry);
+  }
+  {
+    // Store some data in the cache Entry.
+    const std::string data(1, 'a');
+    scoped_refptr<net::StringIOBuffer> buffer(new net::StringIOBuffer(data));
+    net::TestCompletionCallback cb;
+    int rv = entry->WriteData(0, 0, buffer.get(), buffer->size(), cb.callback(),
+                              false);
+    entry->Close();
+    CHECK_EQ(buffer->size(), cb.GetResult(rv));
+  }
+  {
+    // Make sure everything went according to plan.
+    net::TestCompletionCallback cb;
+    int rv = cache_backend->CalculateSizeOfAllEntries(cb.callback());
+    CHECK_LE(1, cb.GetResult(rv));
+  }
+  EXPECT_FALSE(precache_manager_->IsPrecaching());
+
+  precache_manager_->StartPrecaching(precache_callback_.GetCallback());
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_TRUE(precache_manager_->IsPrecaching());
+  // Now it should be waiting for the top hosts.
+}
+
+TEST_F(PrecacheManagerTest, StartPrecachingStopsOnSmallCaches) {
+  // We don't have any entry in the cache, so the reported cache_size = 0 and
+  // thus it will fall below the threshold of 1.
+  variation_params_.SetVariationParams(kPrecacheFieldTrialName,
+                                       {{kMinCacheSizeParam, "1"}});
+  EXPECT_FALSE(precache_manager_->IsPrecaching());
+
+  precache_manager_->StartPrecaching(precache_callback_.GetCallback());
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_FALSE(precache_manager_->IsPrecaching());
+  EXPECT_TRUE(precache_callback_.was_on_done_called());
+  EXPECT_TRUE(url_callback_.requested_urls().empty());
+}
+
 TEST_F(PrecacheManagerTest, StartAndFinishPrecachingWithUnfinishedHosts) {
   std::unique_ptr<PrecacheUnfinishedWork> unfinished_work(
       new PrecacheUnfinishedWork());
@@ -355,7 +430,9 @@
 
   EXPECT_TRUE(precache_manager_->IsPrecaching());
   // Run a task to get unfinished work, and to get hosts.
-  for (int i = 0; i < 2; ++i) {
+  // We need to call run_loop.Run as many times as needed to go through the
+  // chain of callbacks :-(.
+  for (int i = 0; i < 4; ++i) {
     base::RunLoop run_loop;
     base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
                                                   run_loop.QuitClosure());
@@ -418,7 +495,8 @@
   base::RunLoop().RunUntilIdle();
   EXPECT_THAT(
       histograms_.GetTotalCountsForPrefix("Precache."),
-      UnorderedElementsAre(Pair("Precache.DownloadedPrecacheMotivated", 1),
+      UnorderedElementsAre(Pair("Precache.CacheSize.AllEntries", 1),
+                           Pair("Precache.DownloadedPrecacheMotivated", 1),
                            Pair("Precache.Fetch.PercentCompleted", 1),
                            Pair("Precache.Fetch.ResponseBytes.Network", 1),
                            Pair("Precache.Fetch.ResponseBytes.Total", 1),
@@ -498,6 +576,7 @@
   RecordStatsForPrecacheFetch(
       GURL("http://yesterday-fetch.com"), std::string(), base::TimeDelta(),
       kCurrentTime - base::TimeDelta::FromDays(1), info_, 1000);
+  expected_histogram_count_map["Precache.CacheSize.AllEntries"]++;
   expected_histogram_count_map["Precache.DownloadedPrecacheMotivated"] += 3;
   expected_histogram_count_map["Precache.Fetch.PercentCompleted"]++;
   expected_histogram_count_map["Precache.Fetch.ResponseBytes.Network"]++;
@@ -527,6 +606,7 @@
   // The precache fetcher runs until done, which records these histograms,
   // and then cancels precaching, which records these histograms again.
   // In practice
+  expected_histogram_count_map["Precache.CacheSize.AllEntries"]++;
   expected_histogram_count_map["Precache.Fetch.PercentCompleted"]++;
   expected_histogram_count_map["Precache.Fetch.ResponseBytes.Network"]++;
   expected_histogram_count_map["Precache.Fetch.ResponseBytes.Total"]++;
diff --git a/components/proximity_auth/screenlock_bridge.cc b/components/proximity_auth/screenlock_bridge.cc
index d3996b1..0663dda 100644
--- a/components/proximity_auth/screenlock_bridge.cc
+++ b/components/proximity_auth/screenlock_bridge.cc
@@ -117,13 +117,13 @@
 }
 
 void ScreenlockBridge::SetLockHandler(LockHandler* lock_handler) {
-  DCHECK(lock_handler_ == nullptr || lock_handler == nullptr);
-
   // Don't notify observers if there is no change -- i.e. if the screen was
   // already unlocked, and is remaining unlocked.
   if (lock_handler == lock_handler_)
     return;
 
+  DCHECK(lock_handler_ == nullptr || lock_handler == nullptr);
+
   // TODO(isherman): If |lock_handler| is null, then |lock_handler_| might have
   // been freed. Cache the screen type rather than querying it below.
   LockHandler::ScreenType screen_type;
diff --git a/components/safe_browsing/OWNERS b/components/safe_browsing/OWNERS
index b7fd72e..41a80e21 100644
--- a/components/safe_browsing/OWNERS
+++ b/components/safe_browsing/OWNERS
@@ -1,3 +1,4 @@
+jialiul@chromium.org
 mattm@chromium.org
 nparker@chromium.org
 shess@chromium.org
diff --git a/components/sync/device_info/device_info_sync_bridge.cc b/components/sync/device_info/device_info_sync_bridge.cc
index c762c90..e1387abe 100644
--- a/components/sync/device_info/device_info_sync_bridge.cc
+++ b/components/sync/device_info/device_info_sync_bridge.cc
@@ -118,6 +118,13 @@
     EntityDataMap entity_data_map) {
   DCHECK(has_provider_initialized_);
   DCHECK(change_processor()->IsTrackingMetadata());
+  const DeviceInfo* local_info =
+      local_device_info_provider_->GetLocalDeviceInfo();
+  // If our dependency was yanked out from beneath us, we cannot correctly
+  // handle this request, and all our data will be deleted soon.
+  if (local_info == nullptr) {
+    return SyncError();
+  }
 
   // Local data should typically be near empty, with the only possible value
   // corresponding to this device. This is because on signout all device info
@@ -130,8 +137,6 @@
   }
 
   bool has_changes = false;
-  const DeviceInfo* local_info =
-      local_device_info_provider_->GetLocalDeviceInfo();
   std::string local_guid = local_info->guid();
   std::unique_ptr<WriteBatch> batch = store_->CreateWriteBatch();
   for (const auto& kv : entity_data_map) {
@@ -166,6 +171,13 @@
     std::unique_ptr<MetadataChangeList> metadata_change_list,
     EntityChangeList entity_changes) {
   DCHECK(has_provider_initialized_);
+  const DeviceInfo* local_info =
+      local_device_info_provider_->GetLocalDeviceInfo();
+  // If our dependency was yanked out from beneath us, we cannot correctly
+  // handle this request, and all our data will be deleted soon.
+  if (local_info == nullptr) {
+    return SyncError();
+  }
 
   std::unique_ptr<WriteBatch> batch = store_->CreateWriteBatch();
   bool has_changes = false;
@@ -173,7 +185,7 @@
     const std::string guid = change.storage_key();
     // Each device is the authoritative source for itself, ignore any remote
     // changes that have our local cache guid.
-    if (guid == local_device_info_provider_->GetLocalDeviceInfo()->guid()) {
+    if (guid == local_info->guid()) {
       continue;
     }
 
@@ -315,6 +327,8 @@
   // should only need to give the processor metadata upon initialization. If
   // sync is disabled and enabled, our provider will try to retrigger this
   // event, but we do not want to send any more metadata to the processor.
+  // TODO(skym, crbug.com/672600): Handle re-initialization and start the pulse
+  // timer.
   subscription_.reset();
 
   has_provider_initialized_ = true;
@@ -387,6 +401,15 @@
 
   const DeviceInfo* current_info =
       local_device_info_provider_->GetLocalDeviceInfo();
+  // Must ensure |pulse_timer_| is started even if sync is in the process of
+  // being disabled. TODO(skym, crbug.com/672600): Remove this timer Start(), as
+  // it should be started when the provider re-initializes instead.
+  if (current_info == nullptr) {
+    pulse_timer_.Start(FROM_HERE, DeviceInfoUtil::kPulseInterval,
+                       base::Bind(&DeviceInfoSyncBridge::SendLocalData,
+                                  base::Unretained(this)));
+    return;
+  }
   auto iter = all_data_.find(current_info->guid());
 
   // Convert to DeviceInfo for Equals function.
diff --git a/components/sync/device_info/device_info_sync_bridge_unittest.cc b/components/sync/device_info/device_info_sync_bridge_unittest.cc
index ace2211..3ed624e 100644
--- a/components/sync/device_info/device_info_sync_bridge_unittest.cc
+++ b/components/sync/device_info/device_info_sync_bridge_unittest.cc
@@ -26,6 +26,7 @@
 
 namespace syncer {
 
+using base::OneShotTimer;
 using base::Time;
 using base::TimeDelta;
 using sync_pb::DeviceInfoSpecifics;
@@ -287,6 +288,8 @@
     return processor_;
   }
 
+  const OneShotTimer& pulse_timer() { return bridge()->pulse_timer_; }
+
   // Should only be called after the bridge has been initialized. Will first
   // recover the bridge's store, so another can be initialized later, and then
   // deletes the bridge.
@@ -398,6 +401,16 @@
   EXPECT_TRUE(processor()->metadata());
 }
 
+// Simulate shutting down sync during the ModelTypeStore callbacks. The pulse
+// timer should still be initialized, even though reconcile never occurs.
+TEST_F(DeviceInfoSyncBridgeTest, ClearProviderDuringInit) {
+  InitializeBridge();
+  local_device()->Clear();
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(0u, bridge()->GetAllDeviceInfo().size());
+  EXPECT_TRUE(pulse_timer().IsRunning());
+}
+
 TEST_F(DeviceInfoSyncBridgeTest, GetClientTagNormal) {
   InitializeBridge();
   const std::string guid = "abc";
@@ -587,6 +600,25 @@
   EXPECT_EQ(1, change_count());
 }
 
+TEST_F(DeviceInfoSyncBridgeTest, ClearProviderAndApply) {
+  // This will initialize the provider a first time.
+  InitializeAndPump();
+  EXPECT_EQ(1u, bridge()->GetAllDeviceInfo().size());
+
+  const DeviceInfoSpecifics specifics = CreateSpecifics(1, Time::Now());
+
+  local_device()->Clear();
+  SyncError error = bridge()->ApplySyncChanges(
+      bridge()->CreateMetadataChangeList(), EntityAddList({specifics}));
+  EXPECT_FALSE(error.IsSet());
+  EXPECT_EQ(1u, bridge()->GetAllDeviceInfo().size());
+
+  local_device()->Initialize(CreateModel(kDefaultLocalSuffix));
+  error = bridge()->ApplySyncChanges(bridge()->CreateMetadataChangeList(),
+                                     EntityAddList({specifics}));
+  EXPECT_EQ(2u, bridge()->GetAllDeviceInfo().size());
+}
+
 TEST_F(DeviceInfoSyncBridgeTest, MergeEmpty) {
   InitializeAndPump();
   EXPECT_EQ(1, change_count());
@@ -680,6 +712,24 @@
   EXPECT_EQ(0u, bridge()->GetAllDeviceInfo().size());
 }
 
+TEST_F(DeviceInfoSyncBridgeTest, ClearProviderAndMerge) {
+  // This will initialize the provider a first time.
+  InitializeAndPump();
+  EXPECT_EQ(1u, bridge()->GetAllDeviceInfo().size());
+
+  const DeviceInfoSpecifics specifics = CreateSpecifics(1, Time::Now());
+
+  local_device()->Clear();
+  SyncError error = bridge()->MergeSyncData(
+      bridge()->CreateMetadataChangeList(), InlineEntityDataMap({specifics}));
+  EXPECT_FALSE(error.IsSet());
+  EXPECT_EQ(1u, bridge()->GetAllDeviceInfo().size());
+  local_device()->Initialize(CreateModel(kDefaultLocalSuffix));
+  error = bridge()->MergeSyncData(bridge()->CreateMetadataChangeList(),
+                                  InlineEntityDataMap({specifics}));
+  EXPECT_EQ(2u, bridge()->GetAllDeviceInfo().size());
+}
+
 TEST_F(DeviceInfoSyncBridgeTest, CountActiveDevices) {
   InitializeAndPump();
   EXPECT_EQ(1, bridge()->CountActiveDevices());
diff --git a/components/test/android/browsertests_apk/AndroidManifest.xml.jinja2 b/components/test/android/browsertests_apk/AndroidManifest.xml.jinja2
index 29baf6f..42b9282 100644
--- a/components/test/android/browsertests_apk/AndroidManifest.xml.jinja2
+++ b/components/test/android/browsertests_apk/AndroidManifest.xml.jinja2
@@ -48,7 +48,7 @@
                  android:exported="false" />
         {% endfor %}
 
-        {% set num_privileged_services = 20 %}
+        {% set num_privileged_services = 3 %}
         <meta-data android:name="org.chromium.content.browser.NUM_PRIVILEGED_SERVICES"
                    android:value="{{ num_privileged_services }}"/>
         {% for i in range(num_privileged_services) %}
diff --git a/components/ui_devtools/devtools_server.h b/components/ui_devtools/devtools_server.h
index 4060184..7dfc02c 100644
--- a/components/ui_devtools/devtools_server.h
+++ b/components/ui_devtools/devtools_server.h
@@ -13,7 +13,6 @@
 #include "components/ui_devtools/Forward.h"
 #include "components/ui_devtools/Protocol.h"
 #include "components/ui_devtools/devtools_client.h"
-#include "components/ui_devtools/devtools_export.h"
 #include "components/ui_devtools/string_util.h"
 #include "net/server/http_server.h"
 
@@ -26,12 +25,12 @@
 
   // Returns an empty unique_ptr if ui devtools flag isn't enabled or if a
   // server instance has already been created.
-  static UI_DEVTOOLS_EXPORT std::unique_ptr<UiDevToolsServer> Create(
+  static std::unique_ptr<UiDevToolsServer> Create(
       scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner);
 
   // Returns a list of attached UiDevToolsClient name + URL
   using NameUrlPair = std::pair<std::string, std::string>;
-  static UI_DEVTOOLS_EXPORT std::vector<NameUrlPair> GetClientNamesAndUrls();
+  static std::vector<NameUrlPair> GetClientNamesAndUrls();
 
   void AttachClient(std::unique_ptr<UiDevToolsClient> client);
   void SendOverWebSocket(int connection_id, const String& message);
diff --git a/content/app/content_main_runner.cc b/content/app/content_main_runner.cc
index 929756b..604acb0 100644
--- a/content/app/content_main_runner.cc
+++ b/content/app/content_main_runner.cc
@@ -453,6 +453,10 @@
   int Initialize(const ContentMainParams& params) override {
     ui_task_ = params.ui_task;
 
+#if defined(USE_AURA)
+    env_mode_ = params.env_mode;
+#endif
+
     base::EnableTerminationOnOutOfMemory();
 #if defined(OS_WIN)
     base::win::RegisterInvalidParamHandler();
@@ -782,6 +786,9 @@
 #elif defined(OS_MACOSX)
     main_params.autorelease_pool = autorelease_pool_.get();
 #endif
+#if defined(USE_AURA)
+    main_params.env_mode = env_mode_;
+#endif
 
     return RunNamedProcessTypeMain(process_type, main_params, delegate_);
   }
@@ -840,6 +847,10 @@
 
   base::Closure* ui_task_;
 
+#if defined(USE_AURA)
+  aura::Env::Mode env_mode_ = aura::Env::Mode::LOCAL;
+#endif
+
   DISALLOW_COPY_AND_ASSIGN(ContentMainRunnerImpl);
 };
 
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 5516a44..95e2cfba 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -162,13 +162,25 @@
     # //content/browser/devtools:gen_devtools_protocol_handler.
     "$root_gen_dir/content/browser/devtools/protocol/devtools_protocol_dispatcher.cc",
     "$root_gen_dir/content/browser/devtools/protocol/devtools_protocol_dispatcher.h",
+    "$target_gen_dir/devtools/protocol/dom.cc",
+    "$target_gen_dir/devtools/protocol/dom.h",
+    "$target_gen_dir/devtools/protocol/emulation.cc",
+    "$target_gen_dir/devtools/protocol/emulation.h",
     "$target_gen_dir/devtools/protocol/forward.h",
+    "$target_gen_dir/devtools/protocol/inspector.cc",
+    "$target_gen_dir/devtools/protocol/inspector.h",
     "$target_gen_dir/devtools/protocol/io.cc",
     "$target_gen_dir/devtools/protocol/io.h",
     "$target_gen_dir/devtools/protocol/memory.cc",
     "$target_gen_dir/devtools/protocol/memory.h",
+    "$target_gen_dir/devtools/protocol/network.cc",
+    "$target_gen_dir/devtools/protocol/network.h",
+    "$target_gen_dir/devtools/protocol/page.cc",
+    "$target_gen_dir/devtools/protocol/page.h",
     "$target_gen_dir/devtools/protocol/protocol.cc",
     "$target_gen_dir/devtools/protocol/protocol.h",
+    "$target_gen_dir/devtools/protocol/schema.cc",
+    "$target_gen_dir/devtools/protocol/schema.h",
     "$target_gen_dir/devtools/protocol/system_info.cc",
     "$target_gen_dir/devtools/protocol/system_info.h",
     "$target_gen_dir/devtools/protocol/tethering.cc",
@@ -656,6 +668,8 @@
     "gpu/gpu_process_host.h",
     "gpu/gpu_process_host_ui_shim.cc",
     "gpu/gpu_process_host_ui_shim.h",
+    "gpu/shader_cache_factory.cc",
+    "gpu/shader_cache_factory.h",
     "gpu/shader_disk_cache.cc",
     "gpu/shader_disk_cache.h",
     "histogram_controller.cc",
diff --git a/content/browser/bluetooth/bluetooth_device_chooser_controller.cc b/content/browser/bluetooth/bluetooth_device_chooser_controller.cc
index 5d444c8..6a0e22a8 100644
--- a/content/browser/bluetooth/bluetooth_device_chooser_controller.cc
+++ b/content/browser/bluetooth/bluetooth_device_chooser_controller.cc
@@ -30,19 +30,45 @@
 
 namespace {
 
-// Anything worse than or equal to this will show 0 bars.
-const int kMinRSSI = -100;
-// Anything better than or equal to this will show the maximum bars.
-const int kMaxRSSI = -55;
-// Number of RSSI levels used in the signal strength image.
-const int kNumSignalStrengthLevels = 5;
-
-const content::UMARSSISignalStrengthLevel kRSSISignalStrengthEnumTable[] = {
-    content::UMARSSISignalStrengthLevel::LEVEL_0,
-    content::UMARSSISignalStrengthLevel::LEVEL_1,
-    content::UMARSSISignalStrengthLevel::LEVEL_2,
-    content::UMARSSISignalStrengthLevel::LEVEL_3,
-    content::UMARSSISignalStrengthLevel::LEVEL_4};
+// Signal Strength Display Notes:
+//
+// RSSI values are displayed by the chooser to empower a user to differentiate
+// between multiple devices with the same name, comparing devices with different
+// names is a secondary goal. It is important that a user is able to move closer
+// and farther away from a device and have it transition between two different
+// signal strength levels, thus we want to spread RSSI values out evenly accross
+// displayed levels.
+//
+// RSSI values from UMA in RecordRSSISignalStrength are charted here:
+// https://goo.gl/photos/pCoAkF7mPyza9B1k7 (2016-12-08)
+// with a copy-paste of table data at every 5dBm:
+//  dBm   CDF* Histogram Bucket Quantity (hand drawn estimate)
+// -100 00.0%  -
+//  -95 00.4%  --
+//  -90 01.9%  ---
+//  -85 05.1%  ---
+//  -80 09.2%  ----
+//  -75 14.9%  -----
+//  -70 22.0%  ------
+//  -65 32.4%  --------
+//  -60 47.9%  ---------
+//  -55 60.4%  --------
+//  -50 72.8%  ---------
+//  -45 85.5%  -------
+//  -40 94.5%  -----
+//  -35 97.4%  ---
+//  -30 99.0%  --
+//  -25 99.7%  -
+//
+// CDF: Cumulative Distribution Function:
+// https://en.wikipedia.org/wiki/Cumulative_distribution_function
+//
+// Conversion to signal strengths is done by selecting 4 threshold points
+// equally spaced through the CDF.
+const int k20thPercentileRSSI = -71;
+const int k40thPercentileRSSI = -63;
+const int k60thPercentileRSSI = -55;
+const int k80thPercentileRSSI = -47;
 
 }  // namespace
 
@@ -436,24 +462,22 @@
     int8_t rssi) {
   RecordRSSISignalStrength(rssi);
 
-  if (rssi <= kMinRSSI) {
-    RecordRSSISignalStrengthLevel(
-        UMARSSISignalStrengthLevel::LESS_THAN_OR_EQUAL_TO_MIN_RSSI);
+  if (rssi < k20thPercentileRSSI) {
+    RecordRSSISignalStrengthLevel(content::UMARSSISignalStrengthLevel::LEVEL_0);
     return 0;
+  } else if (rssi < k40thPercentileRSSI) {
+    RecordRSSISignalStrengthLevel(content::UMARSSISignalStrengthLevel::LEVEL_1);
+    return 1;
+  } else if (rssi < k60thPercentileRSSI) {
+    RecordRSSISignalStrengthLevel(content::UMARSSISignalStrengthLevel::LEVEL_2);
+    return 2;
+  } else if (rssi < k80thPercentileRSSI) {
+    RecordRSSISignalStrengthLevel(content::UMARSSISignalStrengthLevel::LEVEL_3);
+    return 3;
+  } else {
+    RecordRSSISignalStrengthLevel(content::UMARSSISignalStrengthLevel::LEVEL_4);
+    return 4;
   }
-
-  if (rssi >= kMaxRSSI) {
-    RecordRSSISignalStrengthLevel(
-        UMARSSISignalStrengthLevel::GREATER_THAN_OR_EQUAL_TO_MAX_RSSI);
-    return kNumSignalStrengthLevels - 1;
-  }
-
-  double input_range = kMaxRSSI - kMinRSSI;
-  double output_range = kNumSignalStrengthLevels - 1;
-  int level = static_cast<int>((rssi - kMinRSSI) * output_range / input_range);
-  DCHECK(kNumSignalStrengthLevels == arraysize(kRSSISignalStrengthEnumTable));
-  RecordRSSISignalStrengthLevel(kRSSISignalStrengthEnumTable[level]);
-  return level;
 }
 
 void BluetoothDeviceChooserController::SetTestScanDurationForTesting() {
diff --git a/content/browser/bluetooth/bluetooth_device_chooser_controller_unittest.cc b/content/browser/bluetooth/bluetooth_device_chooser_controller_unittest.cc
index 59f06ef..42e689d8 100644
--- a/content/browser/bluetooth/bluetooth_device_chooser_controller_unittest.cc
+++ b/content/browser/bluetooth/bluetooth_device_chooser_controller_unittest.cc
@@ -13,23 +13,25 @@
   EXPECT_EQ(
       0, BluetoothDeviceChooserController::CalculateSignalStrengthLevel(-128));
   EXPECT_EQ(
-      0, BluetoothDeviceChooserController::CalculateSignalStrengthLevel(-100));
+      0, BluetoothDeviceChooserController::CalculateSignalStrengthLevel(-72));
+
   EXPECT_EQ(
-      0, BluetoothDeviceChooserController::CalculateSignalStrengthLevel(-89));
+      1, BluetoothDeviceChooserController::CalculateSignalStrengthLevel(-71));
   EXPECT_EQ(
-      1, BluetoothDeviceChooserController::CalculateSignalStrengthLevel(-88));
+      1, BluetoothDeviceChooserController::CalculateSignalStrengthLevel(-64));
+
   EXPECT_EQ(
-      1, BluetoothDeviceChooserController::CalculateSignalStrengthLevel(-78));
+      2, BluetoothDeviceChooserController::CalculateSignalStrengthLevel(-63));
   EXPECT_EQ(
-      2, BluetoothDeviceChooserController::CalculateSignalStrengthLevel(-77));
+      2, BluetoothDeviceChooserController::CalculateSignalStrengthLevel(-56));
+
   EXPECT_EQ(
-      2, BluetoothDeviceChooserController::CalculateSignalStrengthLevel(-67));
+      3, BluetoothDeviceChooserController::CalculateSignalStrengthLevel(-55));
   EXPECT_EQ(
-      3, BluetoothDeviceChooserController::CalculateSignalStrengthLevel(-66));
+      3, BluetoothDeviceChooserController::CalculateSignalStrengthLevel(-48));
+
   EXPECT_EQ(
-      3, BluetoothDeviceChooserController::CalculateSignalStrengthLevel(-56));
-  EXPECT_EQ(
-      4, BluetoothDeviceChooserController::CalculateSignalStrengthLevel(-55));
+      4, BluetoothDeviceChooserController::CalculateSignalStrengthLevel(-47));
   EXPECT_EQ(
       4, BluetoothDeviceChooserController::CalculateSignalStrengthLevel(127));
 }
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index e76edcb..bea6dcc8 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -60,7 +60,7 @@
 #include "content/browser/gpu/gpu_data_manager_impl.h"
 #include "content/browser/gpu/gpu_process_host.h"
 #include "content/browser/gpu/gpu_process_host_ui_shim.h"
-#include "content/browser/gpu/shader_disk_cache.h"
+#include "content/browser/gpu/shader_cache_factory.h"
 #include "content/browser/histogram_synchronizer.h"
 #include "content/browser/loader/resource_dispatcher_host_impl.h"
 #include "content/browser/loader_delegate_impl.h"
@@ -1342,7 +1342,7 @@
   // Initialize the GPU shader cache. This needs to be initialized before
   // BrowserGpuChannelHostFactory below, since that depends on an initialized
   // ShaderCacheFactory.
-  ShaderCacheFactory::InitInstance(
+  InitShaderCacheFactorySingleton(
       BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
       BrowserThread::GetTaskRunnerForThread(BrowserThread::CACHE));
 
@@ -1577,7 +1577,7 @@
 
   // Env creates the compositor. Aura widgets need the compositor to be created
   // before they can be initialized by the browser.
-  env_ = aura::Env::CreateInstance();
+  env_ = aura::Env::CreateInstance(parameters_.env_mode);
 #endif  // defined(USE_AURA)
 
   if (parts_)
diff --git a/content/browser/compositor/OWNERS b/content/browser/compositor/OWNERS
index 1e10cf3..2817671 100644
--- a/content/browser/compositor/OWNERS
+++ b/content/browser/compositor/OWNERS
@@ -2,6 +2,6 @@
 jbauman@chromium.org
 ccameron@chromium.org
 
-per-file *Mus*=fsamuel@chromium.org
-per-file *Mus*=sadrul@chromium.org
-per-file *Mus*=rjkroege@chromium.org
+per-file *mus*=fsamuel@chromium.org
+per-file *mus*=sadrul@chromium.org
+per-file *mus*=rjkroege@chromium.org
diff --git a/content/browser/compositor/mus_browser_compositor_output_surface.cc b/content/browser/compositor/mus_browser_compositor_output_surface.cc
index ce3b426a..a274eb9b 100644
--- a/content/browser/compositor/mus_browser_compositor_output_surface.cc
+++ b/content/browser/compositor/mus_browser_compositor_output_surface.cc
@@ -32,7 +32,8 @@
     : GpuBrowserCompositorOutputSurface(std::move(context),
                                         update_vsync_parameters_callback,
                                         std::move(overlay_candidate_validator)),
-      ui_window_(window) {
+      ui_window_(window),
+      window_(nullptr) {
   ui_compositor_frame_sink_ = ui_window_->RequestCompositorFrameSink(
       ui::mojom::CompositorFrameSinkType::DEFAULT, context,
       gpu_memory_buffer_manager);
@@ -49,6 +50,7 @@
     : GpuBrowserCompositorOutputSurface(std::move(context),
                                         update_vsync_parameters_callback,
                                         std::move(overlay_candidate_validator)),
+      ui_window_(nullptr),
       window_(window) {
   aura::WindowPortMus* window_port = aura::WindowPortMus::Get(window_);
   DCHECK(window_port);
diff --git a/content/browser/devtools/BUILD.gn b/content/browser/devtools/BUILD.gn
index 5493f21..a3a2ec6 100644
--- a/content/browser/devtools/BUILD.gn
+++ b/content/browser/devtools/BUILD.gn
@@ -55,13 +55,25 @@
 
   # These are relative to $target_gen_dir.
   outputs = [
+    "protocol/dom.cc",
+    "protocol/dom.h",
+    "protocol/emulation.cc",
+    "protocol/emulation.h",
     "protocol/forward.h",
+    "protocol/inspector.cc",
+    "protocol/inspector.h",
     "protocol/io.cc",
     "protocol/io.h",
     "protocol/memory.cc",
     "protocol/memory.h",
+    "protocol/network.cc",
+    "protocol/network.h",
+    "protocol/page.cc",
+    "protocol/page.h",
     "protocol/protocol.cc",
     "protocol/protocol.h",
+    "protocol/schema.cc",
+    "protocol/schema.h",
     "protocol/system_info.cc",
     "protocol/system_info.h",
     "protocol/tethering.cc",
diff --git a/content/browser/devtools/browser_devtools_agent_host.cc b/content/browser/devtools/browser_devtools_agent_host.cc
index 1ab06af..a715bb5 100644
--- a/content/browser/devtools/browser_devtools_agent_host.cc
+++ b/content/browser/devtools/browser_devtools_agent_host.cc
@@ -58,10 +58,15 @@
 }
 
 void BrowserDevToolsAgentHost::Detach() {
+  io_handler_->Disable();
   io_handler_.reset();
+  memory_handler_->Disable();
   memory_handler_.reset();
+  system_info_handler_->Disable();
   system_info_handler_.reset();
+  tethering_handler_->Disable();
   tethering_handler_.reset();
+  tracing_handler_->Disable();
   tracing_handler_.reset();
 }
 
diff --git a/content/browser/devtools/devtools_session.cc b/content/browser/devtools/devtools_session.cc
index 7f115e55..60ccb85 100644
--- a/content/browser/devtools/devtools_session.cc
+++ b/content/browser/devtools/devtools_session.cc
@@ -4,8 +4,12 @@
 
 #include "content/browser/devtools/devtools_session.h"
 
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
 #include "content/browser/devtools/devtools_agent_host_impl.h"
+#include "content/browser/devtools/devtools_manager.h"
 #include "content/browser/devtools/protocol/protocol.h"
+#include "content/public/browser/devtools_manager_delegate.h"
 
 namespace content {
 
@@ -23,6 +27,30 @@
   dispatcher_.reset();
 }
 
+protocol::Response::Status DevToolsSession::Dispatch(
+    const std::string& message,
+    int* call_id,
+    std::string* method) {
+  std::unique_ptr<base::Value> value = base::JSONReader::Read(message);
+
+  DevToolsManagerDelegate* delegate =
+      DevToolsManager::GetInstance()->delegate();
+  if (value && value->IsType(base::Value::Type::DICTIONARY) && delegate) {
+    std::unique_ptr<base::DictionaryValue> response(delegate->HandleCommand(
+        agent_host_,
+        static_cast<base::DictionaryValue*>(value.get())));
+    if (response) {
+      std::string json;
+      base::JSONWriter::Write(*response.get(), &json);
+      agent_host_->SendMessageToClient(session_id_, json);
+      return protocol::Response::kSuccess;
+    }
+  }
+
+  return dispatcher_->dispatch(protocol::toProtocolValue(value.get(), 1000),
+                               call_id, method);
+}
+
 void DevToolsSession::sendProtocolResponse(
     int call_id,
     std::unique_ptr<protocol::Serializable> message) {
diff --git a/content/browser/devtools/devtools_session.h b/content/browser/devtools/devtools_session.h
index 90e4e97..c02fc56 100644
--- a/content/browser/devtools/devtools_session.h
+++ b/content/browser/devtools/devtools_session.h
@@ -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 "content/browser/devtools/protocol/forward.h"
+#include "content/browser/devtools/protocol/protocol.h"
 
 namespace content {
 
@@ -14,6 +14,10 @@
   ~DevToolsSession() override;
 
   void ResetDispatcher();
+  protocol::Response::Status Dispatch(
+      const std::string& message,
+      int* call_id,
+      std::string* method);
 
   int session_id() { return session_id_; }
   protocol::UberDispatcher* dispatcher() { return dispatcher_.get(); }
diff --git a/content/browser/devtools/page_navigation_throttle.cc b/content/browser/devtools/page_navigation_throttle.cc
index 3b1e9e5f..5f9e58e 100644
--- a/content/browser/devtools/page_navigation_throttle.cc
+++ b/content/browser/devtools/page_navigation_throttle.cc
@@ -11,10 +11,9 @@
 #include "content/public/browser/web_contents.h"
 
 namespace content {
-namespace devtools {
 
 PageNavigationThrottle::PageNavigationThrottle(
-    base::WeakPtr<page::PageHandler> page_handler,
+    base::WeakPtr<protocol::PageHandler> page_handler,
     int navigation_id,
     content::NavigationHandle* navigation_handle)
     : content::NavigationThrottle(navigation_handle),
@@ -75,5 +74,4 @@
   // the line above.
 }
 
-}  // namespace devtools
 }  // namespace content
diff --git a/content/browser/devtools/page_navigation_throttle.h b/content/browser/devtools/page_navigation_throttle.h
index 86091a4e..3cdc11f 100644
--- a/content/browser/devtools/page_navigation_throttle.h
+++ b/content/browser/devtools/page_navigation_throttle.h
@@ -10,16 +10,15 @@
 #include "content/public/browser/navigation_throttle.h"
 
 namespace content {
-namespace devtools {
-namespace page {
+namespace protocol {
 class PageHandler;
-}  // namespace page
+}  // namespace protocol
 
 // Used to allow the DevTools client to optionally cancel navigations via the
 // Page.setControlNavigations and Page.processNavigation commands.
 class PageNavigationThrottle : public content::NavigationThrottle {
  public:
-  PageNavigationThrottle(base::WeakPtr<page::PageHandler> page_handler,
+  PageNavigationThrottle(base::WeakPtr<protocol::PageHandler> page_handler,
                          int navigation_id,
                          content::NavigationHandle* navigation_handle);
   ~PageNavigationThrottle() override;
@@ -47,7 +46,7 @@
   const int navigation_id_;
 
   // The PageHandler that this navigation throttle is associated with.
-  base::WeakPtr<page::PageHandler> page_handler_;
+  base::WeakPtr<protocol::PageHandler> page_handler_;
 
   // Whether or not a navigation was deferred. If deferred we expect a
   // subsequent call to AlwaysProceed, Resume or CancelDeferredNavigation.
@@ -56,7 +55,6 @@
   DISALLOW_COPY_AND_ASSIGN(PageNavigationThrottle);
 };
 
-}  // namespace devtools
 }  // namespace content
 
 #endif  // CONTENT_BROWSER_DEVTOOLS_PAGE_NAVIGATION_THROTTLE_H_
diff --git a/content/browser/devtools/protocol/color_picker.cc b/content/browser/devtools/protocol/color_picker.cc
index 40e119b..6aff7c61 100644
--- a/content/browser/devtools/protocol/color_picker.cc
+++ b/content/browser/devtools/protocol/color_picker.cc
@@ -18,8 +18,7 @@
 #include "ui/gfx/geometry/size_conversions.h"
 
 namespace content {
-namespace devtools {
-namespace page {
+namespace protocol {
 
 ColorPicker::ColorPicker(ColorPickedCallback callback)
     : callback_(callback),
@@ -259,6 +258,5 @@
   host_->SetCursor(cursor);
 }
 
-}  // namespace page
-}  // namespace devtools
+}  // namespace protocol
 }  // namespace content
diff --git a/content/browser/devtools/protocol/color_picker.h b/content/browser/devtools/protocol/color_picker.h
index 297500f4..6b7afdd 100644
--- a/content/browser/devtools/protocol/color_picker.h
+++ b/content/browser/devtools/protocol/color_picker.h
@@ -18,8 +18,7 @@
 
 class RenderWidgetHostImpl;
 
-namespace devtools {
-namespace page {
+namespace protocol {
 
 class ColorPicker {
  public:
@@ -51,8 +50,7 @@
   DISALLOW_COPY_AND_ASSIGN(ColorPicker);
 };
 
-}  // namespace page
-}  // namespace devtools
+}  // namespace protocol
 }  // namespace content
 
 #endif  // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_COLOR_PICKER_H_
diff --git a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
index 75a1d71..c6e228f 100644
--- a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
+++ b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -186,16 +186,13 @@
     agent_host_->DispatchProtocolMessage(this, json_command);
     // Some messages are dispatched synchronously.
     // Only run loop if we are not finished yet.
-    if (in_dispatch_ && wait)
-      WaitForResponse();
+    if (in_dispatch_ && wait) {
+      waiting_for_command_result_id_ = last_sent_id_;
+      base::RunLoop().Run();
+    }
     in_dispatch_ = false;
   }
 
-  void WaitForResponse() {
-    waiting_for_command_result_id_ = last_sent_id_;
-    base::RunLoop().Run();
-  }
-
   bool HasValue(const std::string& path) {
     base::Value* value = 0;
     return result_->Get(path, &value);
@@ -412,26 +409,14 @@
                     int modifier,
                     int windowsKeyCode,
                     int nativeKeyCode,
-                    const std::string& key,
-                    bool wait) {
+                    const std::string& key) {
     std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
     params->SetString("type", type);
     params->SetInteger("modifiers", modifier);
     params->SetInteger("windowsVirtualKeyCode", windowsKeyCode);
     params->SetInteger("nativeVirtualKeyCode", nativeKeyCode);
     params->SetString("key", key);
-    SendCommand("Input.dispatchKeyEvent", std::move(params), wait);
-  }
-};
-
-class SyntheticMouseEventTest : public DevToolsProtocolTest {
- protected:
-  void SendMouseEvent(const std::string& type, int x, int y, bool wait) {
-    std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
-    params->SetString("type", type);
-    params->SetInteger("x", x);
-    params->SetInteger("y", y);
-    SendCommand("Input.dispatchMouseEvent", std::move(params), wait);
+    SendCommand("Input.dispatchKeyEvent", std::move(params));
   }
 };
 
@@ -450,8 +435,8 @@
   DOMMessageQueue dom_message_queue;
 
   // Send enter (keycode 13).
-  SendKeyEvent("rawKeyDown", 0, 13, 13, "Enter", true);
-  SendKeyEvent("keyUp", 0, 13, 13, "Enter", true);
+  SendKeyEvent("rawKeyDown", 0, 13, 13, "Enter");
+  SendKeyEvent("keyUp", 0, 13, 13, "Enter");
 
   std::string key;
   ASSERT_TRUE(dom_message_queue.WaitForMessage(&key));
@@ -460,8 +445,8 @@
   EXPECT_EQ("\"Enter\"", key);
 
   // Send escape (keycode 27).
-  SendKeyEvent("rawKeyDown", 0, 27, 27, "Escape", true);
-  SendKeyEvent("keyUp", 0, 27, 27, "Escape", true);
+  SendKeyEvent("rawKeyDown", 0, 27, 27, "Escape");
+  SendKeyEvent("keyUp", 0, 27, 27, "Escape");
 
   ASSERT_TRUE(dom_message_queue.WaitForMessage(&key));
   EXPECT_EQ("\"Escape\"", key);
@@ -469,59 +454,6 @@
   EXPECT_EQ("\"Escape\"", key);
 }
 
-IN_PROC_BROWSER_TEST_F(SyntheticKeyEventTest, KeyboardEventAck) {
-  NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
-  Attach();
-  ASSERT_TRUE(content::ExecuteScript(
-      shell()->web_contents()->GetRenderViewHost(),
-      "document.body.addEventListener('keydown', () => console.log('x'));"));
-
-  scoped_refptr<InputMsgWatcher> filter = new InputMsgWatcher(
-      RenderWidgetHostImpl::From(
-          shell()->web_contents()->GetRenderViewHost()->GetWidget()),
-      blink::WebInputEvent::MouseMove);
-
-  SendCommand("Runtime.enable", nullptr);
-  SendKeyEvent("rawKeyDown", 0, 13, 13, "Enter", false);
-
-  // We expect that the console log message event arrives *before* the input
-  // event ack, and the subsequent command response for Input.dispatchKeyEvent.
-  WaitForNotification("Runtime.consoleAPICalled");
-  EXPECT_THAT(console_messages_, ElementsAre("x"));
-  EXPECT_FALSE(filter->HasReceivedAck());
-  EXPECT_EQ(1u, result_ids_.size());
-
-  WaitForResponse();
-  EXPECT_EQ(2u, result_ids_.size());
-}
-
-IN_PROC_BROWSER_TEST_F(SyntheticMouseEventTest, MouseEventAck) {
-  NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
-  Attach();
-  ASSERT_TRUE(content::ExecuteScript(
-      shell()->web_contents()->GetRenderViewHost(),
-      "document.body.addEventListener('mousemove', () => console.log('x'));"));
-
-  scoped_refptr<InputMsgWatcher> filter = new InputMsgWatcher(
-      RenderWidgetHostImpl::From(
-          shell()->web_contents()->GetRenderViewHost()->GetWidget()),
-      blink::WebInputEvent::MouseMove);
-
-  SendCommand("Runtime.enable", nullptr);
-  SendMouseEvent("mouseMoved", 15, 15, false);
-
-  // We expect that the console log message event arrives *before* the input
-  // event ack, and the subsequent command response for
-  // Input.dispatchMouseEvent.
-  WaitForNotification("Runtime.consoleAPICalled");
-  EXPECT_THAT(console_messages_, ElementsAre("x"));
-  EXPECT_FALSE(filter->HasReceivedAck());
-  EXPECT_EQ(1u, result_ids_.size());
-
-  WaitForResponse();
-  EXPECT_EQ(2u, result_ids_.size());
-}
-
 namespace {
 bool DecodePNG(std::string base64_data, SkBitmap* bitmap) {
   std::string png_data;
diff --git a/content/browser/devtools/protocol/devtools_protocol_handler_generator.py b/content/browser/devtools/protocol/devtools_protocol_handler_generator.py
index 45fc22d..7423215 100755
--- a/content/browser/devtools/protocol/devtools_protocol_handler_generator.py
+++ b/content/browser/devtools/protocol/devtools_protocol_handler_generator.py
@@ -643,28 +643,10 @@
 includes = []
 fields_init = []
 
-browser_domains_list = ["Inspector", "Page", "Emulation", "Security",
-    "Target", "ServiceWorker", "Input", "Storage", "Schema"]
-browser_commands_list = [
-    "DOM.setFileInputFiles",
-    "Network.enable",
-    "Network.disable",
-    "Network.clearBrowserCache",
-    "Network.clearBrowserCookies",
-    "Network.getCookies",
-    "Network.deleteCookie",
-    "Network.setCookie",
-    "Network.canEmulateNetworkConditions",
-    "Network.emulateNetworkConditions"]
+browser_domains_list = ["Security",
+    "Target", "ServiceWorker", "Input", "Storage"]
+browser_commands_list = []
 async_commands_list = [
-    "Page.getResourceContent",
-    "Page.searchInResource",
-    "Page.captureScreenshot",
-    "Network.getCookies",
-    "Network.deleteCookie",
-    "Network.setCookie",
-    "Input.dispatchKeyEvent",
-    "Input.dispatchMouseEvent",
     "Input.synthesizePinchGesture",
     "Input.synthesizeScrollGesture",
     "Input.synthesizeTapGesture"]
diff --git a/content/browser/devtools/protocol/dom_handler.cc b/content/browser/devtools/protocol/dom_handler.cc
index 8396255..036ca49 100644
--- a/content/browser/devtools/protocol/dom_handler.cc
+++ b/content/browser/devtools/protocol/dom_handler.cc
@@ -10,10 +10,7 @@
 #include "content/browser/frame_host/render_frame_host_impl.h"
 
 namespace content {
-namespace devtools {
-namespace dom {
-
-typedef DevToolsProtocolClient::Response Response;
+namespace protocol {
 
 DOMHandler::DOMHandler() : host_(nullptr) {
 }
@@ -21,28 +18,36 @@
 DOMHandler::~DOMHandler() {
 }
 
+void DOMHandler::Wire(UberDispatcher* dispatcher) {
+  DOM::Dispatcher::wire(dispatcher, this);
+}
+
 void DOMHandler::SetRenderFrameHost(RenderFrameHostImpl* host) {
   host_ = host;
 }
 
-Response DOMHandler::SetFileInputFiles(NodeId node_id,
-                                       const std::vector<std::string>& files) {
+Response DOMHandler::Disable() {
+  return Response::OK();
+}
+
+Response DOMHandler::SetFileInputFiles(
+    DOM::NodeId node_id,
+    std::unique_ptr<protocol::Array<std::string>> files) {
   if (host_) {
-    for (const auto& file : files) {
+    for (size_t i = 0; i < files->length(); i++) {
 #if defined(OS_WIN)
       ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
           host_->GetProcess()->GetID(),
-          base::FilePath(base::UTF8ToUTF16(file)));
+          base::FilePath(base::UTF8ToUTF16(files->get(i))));
 #else
       ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
           host_->GetProcess()->GetID(),
-          base::FilePath(file));
+          base::FilePath(files->get(i)));
 #endif  // OS_WIN
     }
   }
   return Response::FallThrough();
 }
 
-}  // namespace dom
-}  // namespace devtools
+}  // namespace protocol
 }  // namespace content
diff --git a/content/browser/devtools/protocol/dom_handler.h b/content/browser/devtools/protocol/dom_handler.h
index 56f80e2..808af9c 100644
--- a/content/browser/devtools/protocol/dom_handler.h
+++ b/content/browser/devtools/protocol/dom_handler.h
@@ -6,34 +6,33 @@
 #define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DOM_HANDLER_H_
 
 #include "base/macros.h"
-#include "content/browser/devtools/protocol/devtools_protocol_dispatcher.h"
+#include "content/browser/devtools/protocol/dom.h"
 
 namespace content {
 
 class RenderFrameHostImpl;
 
-namespace devtools {
-namespace dom {
+namespace protocol {
 
-class DOMHandler {
+class DOMHandler : public DOM::Backend {
  public:
-  typedef DevToolsProtocolClient::Response Response;
-
   DOMHandler();
-  virtual ~DOMHandler();
+  ~DOMHandler() override;
 
+  void Wire(UberDispatcher*);
   void SetRenderFrameHost(RenderFrameHostImpl* host);
+  Response Disable() override;
 
-  Response SetFileInputFiles(NodeId node_id,
-                             const std::vector<std::string>& files);
+  Response SetFileInputFiles(
+      DOM::NodeId node_id,
+      std::unique_ptr<protocol::Array<std::string>> files) override;
 
  private:
   RenderFrameHostImpl* host_;
   DISALLOW_COPY_AND_ASSIGN(DOMHandler);
 };
 
-}  // namespace dom
-}  // namespace devtools
+}  // namespace protocol
 }  // namespace content
 
 #endif  // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DOM_HANDLER_H_
diff --git a/content/browser/devtools/protocol/emulation_handler.cc b/content/browser/devtools/protocol/emulation_handler.cc
index a2f4cbd..7718aad 100644
--- a/content/browser/devtools/protocol/emulation_handler.cc
+++ b/content/browser/devtools/protocol/emulation_handler.cc
@@ -17,10 +17,8 @@
 #include "device/geolocation/geoposition.h"
 
 namespace content {
-namespace devtools {
-namespace emulation {
+namespace protocol {
 
-using Response = DevToolsProtocolClient::Response;
 using GeolocationServiceContext = device::GeolocationServiceContext;
 using Geoposition = device::Geoposition;
 
@@ -28,13 +26,13 @@
 
 blink::WebScreenOrientationType WebScreenOrientationTypeFromString(
     const std::string& type) {
-  if (type == screen_orientation::kTypePortraitPrimary)
+  if (type == Emulation::ScreenOrientation::TypeEnum::PortraitPrimary)
     return blink::WebScreenOrientationPortraitPrimary;
-  if (type == screen_orientation::kTypePortraitSecondary)
+  if (type == Emulation::ScreenOrientation::TypeEnum::PortraitSecondary)
     return blink::WebScreenOrientationPortraitSecondary;
-  if (type == screen_orientation::kTypeLandscapePrimary)
+  if (type == Emulation::ScreenOrientation::TypeEnum::LandscapePrimary)
     return blink::WebScreenOrientationLandscapePrimary;
-  if (type == screen_orientation::kTypeLandscapeSecondary)
+  if (type == Emulation::ScreenOrientation::TypeEnum::LandscapeSecondary)
     return blink::WebScreenOrientationLandscapeSecondary;
   return blink::WebScreenOrientationUndefined;
 }
@@ -44,11 +42,11 @@
   ui::GestureProviderConfigType result =
       ui::GestureProviderConfigType::CURRENT_PLATFORM;
   if (protocol_value ==
-      set_touch_emulation_enabled::kConfigurationMobile) {
+      Emulation::SetTouchEmulationEnabled::ConfigurationEnum::Mobile) {
     result = ui::GestureProviderConfigType::GENERIC_MOBILE;
   }
   if (protocol_value ==
-      set_touch_emulation_enabled::kConfigurationDesktop) {
+      Emulation::SetTouchEmulationEnabled::ConfigurationEnum::Desktop) {
     result = ui::GestureProviderConfigType::GENERIC_DESKTOP;
   }
   return result;
@@ -74,29 +72,33 @@
   UpdateDeviceEmulationState();
 }
 
-void EmulationHandler::Detached() {
+void EmulationHandler::Wire(UberDispatcher* dispatcher) {
+  Emulation::Dispatcher::wire(dispatcher, this);
+}
+
+Response EmulationHandler::Disable() {
   touch_emulation_enabled_ = false;
   device_emulation_enabled_ = false;
   UpdateTouchEventEmulationState();
   UpdateDeviceEmulationState();
+  return Response::OK();
 }
 
 Response EmulationHandler::SetGeolocationOverride(
-    double* latitude, double* longitude, double* accuracy) {
+    Maybe<double> latitude, Maybe<double> longitude, Maybe<double> accuracy) {
   if (!GetWebContents())
-    return Response::InternalError("Could not connect to view");
+    return Response::InternalError();
 
   GeolocationServiceContext* geolocation_context =
       GetWebContents()->GetGeolocationServiceContext();
   std::unique_ptr<Geoposition> geoposition(new Geoposition());
-  if (latitude && longitude && accuracy) {
-    geoposition->latitude = *latitude;
-    geoposition->longitude = *longitude;
-    geoposition->accuracy = *accuracy;
+  if (latitude.isJust() && longitude.isJust() && accuracy.isJust()) {
+    geoposition->latitude = latitude.fromJust();
+    geoposition->longitude = longitude.fromJust();
+    geoposition->accuracy = accuracy.fromJust();
     geoposition->timestamp = base::Time::Now();
-    if (!geoposition->Validate()) {
-      return Response::InternalError("Invalid geolocation");
-    }
+    if (!geoposition->Validate())
+      return Response::Error("Invalid geolocation");
   } else {
     geoposition->error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
   }
@@ -106,7 +108,7 @@
 
 Response EmulationHandler::ClearGeolocationOverride() {
   if (!GetWebContents())
-    return Response::InternalError("Could not connect to view");
+    return Response::InternalError();
 
   GeolocationServiceContext* geolocation_context =
       GetWebContents()->GetGeolocationServiceContext();
@@ -115,10 +117,9 @@
 }
 
 Response EmulationHandler::SetTouchEmulationEnabled(
-    bool enabled, const std::string* configuration) {
+    bool enabled, Maybe<std::string> configuration) {
   touch_emulation_enabled_ = enabled;
-  touch_emulation_configuration_ =
-      configuration ? *configuration : std::string();
+  touch_emulation_configuration_ = configuration.fromMaybe("");
   UpdateTouchEventEmulationState();
   return Response::FallThrough();
 }
@@ -142,32 +143,32 @@
     double device_scale_factor,
     bool mobile,
     bool fit_window,
-    const double* optional_scale,
-    const double* optional_offset_x,
-    const double* optional_offset_y,
-    const int* screen_width,
-    const int* screen_height,
-    const int* position_x,
-    const int* position_y,
-    const std::unique_ptr<base::DictionaryValue>& screen_orientation) {
+    Maybe<double> scale,
+    Maybe<double> offset_x,
+    Maybe<double> offset_y,
+    Maybe<int> screen_width,
+    Maybe<int> screen_height,
+    Maybe<int> position_x,
+    Maybe<int> position_y,
+    Maybe<Emulation::ScreenOrientation> screen_orientation) {
   const static int max_size = 10000000;
   const static double max_scale = 10;
   const static int max_orientation_angle = 360;
 
   if (!host_)
-    return Response::InternalError("Could not connect to view");
+    return Response::InternalError();
 
-  if (screen_width && screen_height &&
-      (*screen_width < 0 || *screen_height < 0 ||
-           *screen_width > max_size || *screen_height > max_size)) {
+  if (screen_width.fromMaybe(0) < 0 || screen_height.fromMaybe(0) < 0 ||
+      screen_width.fromMaybe(0) > max_size ||
+      screen_height.fromMaybe(0) > max_size) {
     return Response::InvalidParams(
         "Screen width and height values must be positive, not greater than " +
         base::IntToString(max_size));
   }
 
-  if (screen_width && screen_height && position_x && position_y &&
-      (*position_x < 0 || *position_y < 0 ||
-           *position_x > *screen_width || *position_y > *screen_height)) {
+  if (position_x.fromMaybe(0) < 0 || position_y.fromMaybe(0) < 0 ||
+      position_x.fromMaybe(0) > screen_width.fromMaybe(0) ||
+      position_y.fromMaybe(0) > screen_height.fromMaybe(0)) {
     return Response::InvalidParams("View position should be on the screen");
   }
 
@@ -180,7 +181,7 @@
   if (device_scale_factor < 0)
     return Response::InvalidParams("deviceScaleFactor must be non-negative");
 
-  if (optional_scale && (*optional_scale <= 0 || *optional_scale > max_scale)) {
+  if (scale.fromMaybe(1) <= 0 || scale.fromMaybe(1) > max_scale) {
     return Response::InvalidParams(
         "scale must be positive, not greater than " +
         base::DoubleToString(max_scale));
@@ -189,20 +190,13 @@
   blink::WebScreenOrientationType orientationType =
       blink::WebScreenOrientationUndefined;
   int orientationAngle = 0;
-  if (screen_orientation) {
-    std::string orientationTypeString;
-    if (!screen_orientation->GetString("type", &orientationTypeString)) {
-      return Response::InvalidParams(
-          "Screen orientation type must be a string");
-    }
-    orientationType = WebScreenOrientationTypeFromString(orientationTypeString);
+  if (screen_orientation.isJust()) {
+    Emulation::ScreenOrientation* orientation = screen_orientation.fromJust();
+    orientationType = WebScreenOrientationTypeFromString(
+        orientation->GetType());
     if (orientationType == blink::WebScreenOrientationUndefined)
       return Response::InvalidParams("Invalid screen orientation type value");
-
-    if (!screen_orientation->GetInteger("angle", &orientationAngle)) {
-      return Response::InvalidParams(
-          "Screen orientation angle must be a number");
-    }
+    orientationAngle = orientation->GetAngle();
     if (orientationAngle < 0 || orientationAngle >= max_orientation_angle) {
       return Response::InvalidParams(
           "Screen orientation angle must be non-negative, less than " +
@@ -213,14 +207,14 @@
   blink::WebDeviceEmulationParams params;
   params.screenPosition = mobile ? blink::WebDeviceEmulationParams::Mobile :
       blink::WebDeviceEmulationParams::Desktop;
-  if (screen_width && screen_height)
-    params.screenSize = blink::WebSize(*screen_width, *screen_height);
-  if (position_x && position_y)
-    params.viewPosition = blink::WebPoint(*position_x, *position_y);
+  params.screenSize = blink::WebSize(screen_width.fromMaybe(0),
+                                     screen_height.fromMaybe(0));
+  params.viewPosition = blink::WebPoint(position_x.fromMaybe(0),
+                                        position_y.fromMaybe(0));
   params.deviceScaleFactor = device_scale_factor;
   params.viewSize = blink::WebSize(width, height);
   params.fitToView = fit_window;
-  params.scale = optional_scale ? *optional_scale : 1;
+  params.scale = scale.fromMaybe(1);
   params.screenOrientationType = orientationType;
   params.screenOrientationAngle = orientationAngle;
 
@@ -250,46 +244,12 @@
   RenderWidgetHostImpl* widget_host =
       host_ ? host_->GetRenderWidgetHost() : nullptr;
   if (!widget_host)
-    return Response::ServerError("Target does not support setVisibleSize");
+    return Response::Error("Target does not support setVisibleSize");
 
   widget_host->GetView()->SetSize(gfx::Size(width, height));
   return Response::OK();
 }
 
-Response EmulationHandler::ForceViewport(double x, double y, double scale) {
-  return Response::FallThrough();
-}
-
-Response EmulationHandler::ResetViewport() {
-  return Response::FallThrough();
-}
-
-Response EmulationHandler::ResetPageScaleFactor() {
-  return Response::FallThrough();
-}
-
-Response EmulationHandler::SetPageScaleFactor(double page_scale_factor) {
-  return Response::FallThrough();
-}
-
-Response EmulationHandler::SetScriptExecutionDisabled(bool disabled) {
-  return Response::FallThrough();
-}
-
-Response EmulationHandler::SetEmulatedMedia(const std::string& media) {
-  return Response::FallThrough();
-}
-
-Response EmulationHandler::SetCPUThrottlingRate(double rate) {
-  return Response::FallThrough();
-}
-
-Response EmulationHandler::SetVirtualTimePolicy(
-    const std::string& policy,
-    const int* budget) {
-  return Response::FallThrough();
-}
-
 WebContentsImpl* EmulationHandler::GetWebContents() {
   return host_ ?
       static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(host_)) :
@@ -323,6 +283,5 @@
   }
 }
 
-}  // namespace emulation
-}  // namespace devtools
+}  // namespace protocol
 }  // namespace content
diff --git a/content/browser/devtools/protocol/emulation_handler.h b/content/browser/devtools/protocol/emulation_handler.h
index 8a98ce65..b5ff169 100644
--- a/content/browser/devtools/protocol/emulation_handler.h
+++ b/content/browser/devtools/protocol/emulation_handler.h
@@ -6,7 +6,7 @@
 #define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_EMULATION_HANDLER_H_
 
 #include "base/macros.h"
-#include "content/browser/devtools/protocol/devtools_protocol_dispatcher.h"
+#include "content/browser/devtools/protocol/emulation.h"
 #include "third_party/WebKit/public/web/WebDeviceEmulationParams.h"
 
 namespace content {
@@ -14,58 +14,43 @@
 class RenderFrameHostImpl;
 class WebContentsImpl;
 
-namespace devtools {
+namespace protocol {
 
-namespace page { class PageHandler; }
-
-namespace emulation {
-
-class EmulationHandler {
+class EmulationHandler : public Emulation::Backend {
  public:
-  using Response = DevToolsProtocolClient::Response;
-
   EmulationHandler();
-  ~EmulationHandler();
+  ~EmulationHandler() override;
 
   void SetRenderFrameHost(RenderFrameHostImpl* host);
-  void SetClient(std::unique_ptr<Client> client) { }
-  void Detached();
+  void Wire(UberDispatcher*);
+  Response Disable() override;
 
-  Response SetGeolocationOverride(double* latitude,
-                                  double* longitude,
-                                  double* accuracy);
-  Response ClearGeolocationOverride();
+  Response SetGeolocationOverride(Maybe<double> latitude,
+                                  Maybe<double> longitude,
+                                  Maybe<double> accuracy) override;
+  Response ClearGeolocationOverride() override;
 
   Response SetTouchEmulationEnabled(bool enabled,
-                                    const std::string* configuration);
+                                    Maybe<std::string> configuration) override;
 
-  Response CanEmulate(bool* result);
+  Response CanEmulate(bool* result) override;
   Response SetDeviceMetricsOverride(
       int width,
       int height,
       double device_scale_factor,
       bool mobile,
       bool fit_window,
-      const double* optional_scale,
-      const double* optional_offset_x,
-      const double* optional_offset_y,
-      const int* screen_widget,
-      const int* screen_height,
-      const int* position_x,
-      const int* position_y,
-      const std::unique_ptr<base::DictionaryValue>& screen_orientation);
-  Response ClearDeviceMetricsOverride();
+      Maybe<double> scale,
+      Maybe<double> offset_x,
+      Maybe<double> offset_y,
+      Maybe<int> screen_widget,
+      Maybe<int> screen_height,
+      Maybe<int> position_x,
+      Maybe<int> position_y,
+      Maybe<Emulation::ScreenOrientation> screen_orientation) override;
+  Response ClearDeviceMetricsOverride() override;
 
-  Response SetVisibleSize(int width, int height);
-
-  Response ForceViewport(double x, double y, double scale);
-  Response ResetViewport();
-  Response ResetPageScaleFactor();
-  Response SetPageScaleFactor(double page_scale_factor);
-  Response SetScriptExecutionDisabled(bool disabled);
-  Response SetEmulatedMedia(const std::string& media);
-  Response SetCPUThrottlingRate(double rate);
-  Response SetVirtualTimePolicy(const std::string& policy, const int* budget);
+  Response SetVisibleSize(int width, int height) override;
 
  private:
   WebContentsImpl* GetWebContents();
@@ -83,8 +68,7 @@
   DISALLOW_COPY_AND_ASSIGN(EmulationHandler);
 };
 
-}  // namespace emulation
-}  // namespace devtools
+}  // namespace protocol
 }  // namespace content
 
 #endif  // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_EMULATION_HANDLER_H_
diff --git a/content/browser/devtools/protocol/input_handler.cc b/content/browser/devtools/protocol/input_handler.cc
index 1c0526f..b963044 100644
--- a/content/browser/devtools/protocol/input_handler.cc
+++ b/content/browser/devtools/protocol/input_handler.cc
@@ -130,7 +130,6 @@
 
 InputHandler::InputHandler()
     : host_(NULL),
-      input_queued_(false),
       page_scale_factor_(1.0),
       weak_factory_(this) {
 }
@@ -138,30 +137,8 @@
 InputHandler::~InputHandler() {
 }
 
-void InputHandler::OnInputEvent(const blink::WebInputEvent& event) {
-  input_queued_ = true;
-}
-
-void InputHandler::OnInputEventAck(const blink::WebInputEvent& event) {
-  if (blink::WebInputEvent::isKeyboardEventType(event.type) &&
-      !pending_key_command_ids_.empty()) {
-    SendDispatchKeyEventResponse(pending_key_command_ids_.front());
-    pending_key_command_ids_.pop_front();
-  } else if (blink::WebInputEvent::isMouseEventType(event.type) &&
-             !pending_mouse_command_ids_.empty()) {
-    SendDispatchMouseEventResponse(pending_mouse_command_ids_.front());
-    pending_mouse_command_ids_.pop_front();
-  }
-}
-
 void InputHandler::SetRenderWidgetHost(RenderWidgetHostImpl* host) {
-  ClearPendingKeyCommands();
-  ClearPendingMouseCommands();
-  if (host_)
-    host_->RemoveInputEventObserver(this);
   host_ = host;
-  if (host)
-    host->AddInputEventObserver(this);
 }
 
 void InputHandler::SetClient(std::unique_ptr<Client> client) {
@@ -174,15 +151,7 @@
   scrollable_viewport_size_ = frame_metadata.scrollable_viewport_size;
 }
 
-void InputHandler::Detached() {
-  ClearPendingKeyCommands();
-  ClearPendingMouseCommands();
-  if (host_)
-    host_->RemoveInputEventObserver(this);
-}
-
 Response InputHandler::DispatchKeyEvent(
-    DevToolsCommandId command_id,
     const std::string& type,
     const int* modifiers,
     const double* timestamp,
@@ -244,17 +213,11 @@
     return Response::ServerError("Could not connect to view");
 
   host_->Focus();
-  input_queued_ = false;
   host_->ForwardKeyboardEvent(event);
-  if (input_queued_)
-    pending_key_command_ids_.push_back(command_id);
-  else
-    SendDispatchKeyEventResponse(command_id);
   return Response::OK();
 }
 
 Response InputHandler::DispatchMouseEvent(
-    DevToolsCommandId command_id,
     const std::string& type,
     int x,
     int y,
@@ -286,12 +249,7 @@
     return Response::ServerError("Could not connect to view");
 
   host_->Focus();
-  input_queued_ = false;
   host_->ForwardMouseEvent(event);
-  if (input_queued_)
-    pending_mouse_command_ids_.push_back(command_id);
-  else
-    SendDispatchMouseEventResponse(command_id);
   return Response::OK();
 }
 
@@ -521,17 +479,6 @@
   return Response::FallThrough();
 }
 
-void InputHandler::SendDispatchKeyEventResponse(DevToolsCommandId command_id) {
-  client_->SendDispatchKeyEventResponse(
-      command_id, DispatchKeyEventResponse::Create());
-}
-
-void InputHandler::SendDispatchMouseEventResponse(
-    DevToolsCommandId command_id) {
-  client_->SendDispatchMouseEventResponse(
-      command_id, DispatchMouseEventResponse::Create());
-}
-
 void InputHandler::SendSynthesizePinchGestureResponse(
     DevToolsCommandId command_id,
     SyntheticGesture::Result result) {
@@ -574,18 +521,6 @@
   }
 }
 
-void InputHandler::ClearPendingKeyCommands() {
-  for (const DevToolsCommandId& command_id : pending_key_command_ids_)
-    SendDispatchKeyEventResponse(command_id);
-  pending_key_command_ids_.clear();
-}
-
-void InputHandler::ClearPendingMouseCommands() {
-  for (const DevToolsCommandId& command_id : pending_mouse_command_ids_)
-    SendDispatchMouseEventResponse(command_id);
-  pending_mouse_command_ids_.clear();
-}
-
 }  // namespace input
 }  // namespace devtools
 }  // namespace content
diff --git a/content/browser/devtools/protocol/input_handler.h b/content/browser/devtools/protocol/input_handler.h
index e98c527..691cad2 100644
--- a/content/browser/devtools/protocol/input_handler.h
+++ b/content/browser/devtools/protocol/input_handler.h
@@ -10,7 +10,6 @@
 #include "content/browser/devtools/protocol/devtools_protocol_dispatcher.h"
 #include "content/browser/renderer_host/input/synthetic_gesture.h"
 #include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
-#include "content/public/browser/render_widget_host.h"
 #include "ui/gfx/geometry/size_f.h"
 
 namespace cc {
@@ -24,20 +23,18 @@
 namespace devtools {
 namespace input {
 
-class InputHandler : public RenderWidgetHost::InputEventObserver {
+class InputHandler {
  public:
   typedef DevToolsProtocolClient::Response Response;
 
   InputHandler();
-  ~InputHandler() override;
+  virtual ~InputHandler();
 
   void SetRenderWidgetHost(RenderWidgetHostImpl* host);
   void SetClient(std::unique_ptr<Client> client);
   void OnSwapCompositorFrame(const cc::CompositorFrameMetadata& frame_metadata);
-  void Detached();
 
-  Response DispatchKeyEvent(DevToolsCommandId command_id,
-                            const std::string& type,
+  Response DispatchKeyEvent(const std::string& type,
                             const int* modifiers,
                             const double* timestamp,
                             const std::string* text,
@@ -51,8 +48,7 @@
                             const bool* is_keypad,
                             const bool* is_system_key);
 
-  Response DispatchMouseEvent(DevToolsCommandId command_id,
-                              const std::string& type,
+  Response DispatchMouseEvent(const std::string& type,
                               int x,
                               int y,
                               const int* modifiers,
@@ -105,13 +101,6 @@
       const double* timestamp);
 
  private:
-  // InputEventObserver
-  void OnInputEvent(const blink::WebInputEvent& event) override;
-  void OnInputEventAck(const blink::WebInputEvent& event) override;
-
-  void SendDispatchKeyEventResponse(DevToolsCommandId command_id);
-  void SendDispatchMouseEventResponse(DevToolsCommandId command_id);
-
   void SendSynthesizePinchGestureResponse(DevToolsCommandId command_id,
                                           SyntheticGesture::Result result);
 
@@ -136,16 +125,8 @@
                         DevToolsCommandId command_id,
                         SyntheticGesture::Result result);
 
-  void ClearPendingKeyCommands();
-  void ClearPendingMouseCommands();
-
   RenderWidgetHostImpl* host_;
   std::unique_ptr<Client> client_;
-  // DevToolsCommandIds for calls to Input.dispatchKey/MouseEvent that have been
-  // sent to the renderer, but that we haven't yet received an ack for.
-  bool input_queued_;
-  std::deque<DevToolsCommandId> pending_key_command_ids_;
-  std::deque<DevToolsCommandId> pending_mouse_command_ids_;
   float page_scale_factor_;
   gfx::SizeF scrollable_viewport_size_;
   base::WeakPtrFactory<InputHandler> weak_factory_;
diff --git a/content/browser/devtools/protocol/inspector_handler.cc b/content/browser/devtools/protocol/inspector_handler.cc
index 8777c6a..b3333153 100644
--- a/content/browser/devtools/protocol/inspector_handler.cc
+++ b/content/browser/devtools/protocol/inspector_handler.cc
@@ -7,10 +7,7 @@
 #include "content/browser/frame_host/render_frame_host_impl.h"
 
 namespace content {
-namespace devtools {
-namespace inspector {
-
-using Response = DevToolsProtocolClient::Response;
+namespace protocol {
 
 InspectorHandler::InspectorHandler()
     : host_(nullptr) {
@@ -19,8 +16,9 @@
 InspectorHandler::~InspectorHandler() {
 }
 
-void InspectorHandler::SetClient(std::unique_ptr<Client> client) {
-  client_.swap(client);
+void InspectorHandler::Wire(UberDispatcher* dispatcher) {
+  frontend_.reset(new Inspector::Frontend(dispatcher->channel()));
+  Inspector::Dispatcher::wire(dispatcher, this);
 }
 
 void InspectorHandler::SetRenderFrameHost(RenderFrameHostImpl* host) {
@@ -28,16 +26,16 @@
 }
 
 void InspectorHandler::TargetCrashed() {
-  client_->TargetCrashed(TargetCrashedParams::Create());
+  frontend_->TargetCrashed();
 }
 
 void InspectorHandler::TargetDetached(const std::string& reason) {
-  client_->Detached(DetachedParams::Create()->set_reason(reason));
+  frontend_->Detached(reason);
 }
 
 Response InspectorHandler::Enable() {
   if (host_ && !host_->IsRenderFrameLive())
-    client_->TargetCrashed(TargetCrashedParams::Create());
+    frontend_->TargetCrashed();
   return Response::OK();
 }
 
@@ -45,6 +43,5 @@
   return Response::OK();
 }
 
-}  // namespace inspector
-}  // namespace devtools
+}  // namespace protocol
 }  // namespace content
diff --git a/content/browser/devtools/protocol/inspector_handler.h b/content/browser/devtools/protocol/inspector_handler.h
index cee8949..6bd0c375 100644
--- a/content/browser/devtools/protocol/inspector_handler.h
+++ b/content/browser/devtools/protocol/inspector_handler.h
@@ -6,40 +6,36 @@
 #define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_INSPECTOR_HANDLER_H_
 
 #include "base/macros.h"
-#include "content/browser/devtools/protocol/devtools_protocol_dispatcher.h"
+#include "content/browser/devtools/protocol/inspector.h"
 
 namespace content {
 
 class RenderFrameHostImpl;
 
-namespace devtools {
-namespace inspector {
+namespace protocol {
 
-class InspectorHandler {
+class InspectorHandler : public Inspector::Backend {
  public:
-  using Response = DevToolsProtocolClient::Response;
-
   InspectorHandler();
-  virtual ~InspectorHandler();
+  ~InspectorHandler() override;
 
-  void SetClient(std::unique_ptr<Client> client);
+  void Wire(UberDispatcher*);
   void SetRenderFrameHost(RenderFrameHostImpl* host);
 
   void TargetCrashed();
   void TargetDetached(const std::string& reason);
 
-  Response Enable();
-  Response Disable();
+  Response Enable() override;
+  Response Disable() override;
 
  private:
-  std::unique_ptr<Client> client_;
+  std::unique_ptr<Inspector::Frontend> frontend_;
   RenderFrameHostImpl* host_;
 
   DISALLOW_COPY_AND_ASSIGN(InspectorHandler);
 };
 
-}  // namespace inspector
-}  // namespace devtools
+}  // namespace protocol
 }  // namespace content
 
 #endif  // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_INSPECTOR_HANDLER_H_
diff --git a/content/browser/devtools/protocol/network_handler.cc b/content/browser/devtools/protocol/network_handler.cc
index 1f33abf2..a75a86d 100644
--- a/content/browser/devtools/protocol/network_handler.cc
+++ b/content/browser/devtools/protocol/network_handler.cc
@@ -25,15 +25,13 @@
 #include "net/url_request/url_request_context_getter.h"
 
 namespace content {
-namespace devtools {
-namespace network {
-
-using Response = DevToolsProtocolClient::Response;
-using CookieListCallback = net::CookieStore::GetCookieListCallback;
-using SetCookieCallback = net::CookieStore::SetCookiesCallback;
-
+namespace protocol {
 namespace {
 
+using GetCookiesCallback = protocol::Network::Backend::GetCookiesCallback;
+using SetCookieCallback = protocol::Network::Backend::SetCookieCallback;
+using DeleteCookieCallback = protocol::Network::Backend::DeleteCookieCallback;
+
 net::URLRequestContext* GetRequestContextOnIO(
     ResourceContext* resource_context,
     net::URLRequestContextGetter* context_getter,
@@ -47,8 +45,8 @@
   return context;
 }
 
-void GotCookiesForURLOnIO(
-    const CookieListCallback& callback,
+void GotCookiesOnIO(
+    const net::CookieStore::GetCookieListCallback& callback,
     const net::CookieList& cookie_list) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   BrowserThread::PostTask(
@@ -61,56 +59,32 @@
     ResourceContext* resource_context,
     net::URLRequestContextGetter* context_getter,
     const GURL& url,
-    const CookieListCallback& callback) {
+    const net::CookieStore::GetCookieListCallback& callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   net::URLRequestContext* request_context =
       GetRequestContextOnIO(resource_context, context_getter, url);
   request_context->cookie_store()->GetAllCookiesForURLAsync(
-      url, base::Bind(&GotCookiesForURLOnIO, callback));
+      url, base::Bind(&GotCookiesOnIO, callback));
 }
 
-void GetCookiesForURLOnUI(
+void GetAllCookiesOnIO(
     ResourceContext* resource_context,
     net::URLRequestContextGetter* context_getter,
-    const GURL& url,
-    const CookieListCallback& callback) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  BrowserThread::PostTask(
-      BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(&GetCookiesForURLOnIO,
-                 base::Unretained(resource_context),
-                 base::Unretained(context_getter),
-                 url,
-                 callback));
-}
-
-void GetCookiesOnIO(ResourceContext* resource_context,
-                    net::URLRequestContextGetter* context_getter,
-                    const CookieListCallback& callback) {
+    const net::CookieStore::GetCookieListCallback& callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   net::URLRequestContext* request_context =
       context_getter->GetURLRequestContext();
   request_context->cookie_store()->GetAllCookiesAsync(
-      base::Bind(&GotCookiesForURLOnIO, callback));
+      base::Bind(&GotCookiesOnIO, callback));
 }
 
-void GetCookiesOnUI(ResourceContext* resource_context,
-                    net::URLRequestContextGetter* context_getter,
-                    const CookieListCallback& callback) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      base::Bind(&GetCookiesOnIO, base::Unretained(resource_context),
-                 base::Unretained(context_getter), callback));
-}
-
-void DeletedCookieOnIO(const base::Closure& callback) {
+void DeletedCookieOnIO(std::unique_ptr<DeleteCookieCallback> callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   BrowserThread::PostTask(
       BrowserThread::UI,
       FROM_HERE,
-      callback);
+      base::Bind(&DeleteCookieCallback::sendSuccess,
+                 base::Passed(std::move(callback))));
 }
 
 void DeleteCookieOnIO(
@@ -118,38 +92,23 @@
     net::URLRequestContextGetter* context_getter,
     const GURL& url,
     const std::string& cookie_name,
-    const base::Closure& callback) {
+    std::unique_ptr<DeleteCookieCallback> callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   net::URLRequestContext* request_context =
       GetRequestContextOnIO(resource_context, context_getter, url);
   request_context->cookie_store()->DeleteCookieAsync(
-      url, cookie_name, base::Bind(&DeletedCookieOnIO, callback));
+      url, cookie_name, base::Bind(&DeletedCookieOnIO,
+                                   base::Passed(std::move(callback))));
 }
 
-void DeleteCookieOnUI(
-    ResourceContext* resource_context,
-    net::URLRequestContextGetter* context_getter,
-    const GURL& url,
-    const std::string& cookie_name,
-    const base::Closure& callback) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  BrowserThread::PostTask(
-      BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(&DeleteCookieOnIO,
-                 base::Unretained(resource_context),
-                 base::Unretained(context_getter),
-                 url,
-                 cookie_name,
-                 callback));
-}
-
-void CookieSetOnIO(const SetCookieCallback& callback, bool success) {
+void CookieSetOnIO(std::unique_ptr<SetCookieCallback> callback, bool success) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   BrowserThread::PostTask(
       BrowserThread::UI,
       FROM_HERE,
-      base::Bind(callback, success));
+      base::Bind(&SetCookieCallback::sendSuccess,
+                 base::Passed(std::move(callback)),
+                 success));
 }
 
 void SetCookieOnIO(
@@ -164,7 +123,7 @@
     bool http_only,
     net::CookieSameSite same_site,
     base::Time expires,
-    const SetCookieCallback& callback) {
+    std::unique_ptr<SetCookieCallback> callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   net::URLRequestContext* request_context =
       GetRequestContextOnIO(resource_context, context_getter, url);
@@ -183,51 +142,29 @@
       same_site,
       are_experimental_cookie_features_enabled,
       net::COOKIE_PRIORITY_DEFAULT,
-      base::Bind(&CookieSetOnIO, callback));
-}
-
-void SetCookieOnUI(
-    ResourceContext* resource_context,
-    net::URLRequestContextGetter* context_getter,
-    const GURL& url,
-    const std::string& name,
-    const std::string& value,
-    const std::string& domain,
-    const std::string& path,
-    bool secure,
-    bool http_only,
-    net::CookieSameSite same_site,
-    base::Time expires,
-    const SetCookieCallback& callback) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  BrowserThread::PostTask(
-      BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(&SetCookieOnIO,
-                 base::Unretained(resource_context),
-                 base::Unretained(context_getter),
-                 url, name, value, domain, path, secure, http_only,
-                 same_site, expires, callback));
+      base::Bind(&CookieSetOnIO, base::Passed(std::move(callback))));
 }
 
 class GetCookiesCommand {
  public:
-  GetCookiesCommand(RenderFrameHostImpl* frame_host,
-                    bool global,
-                    const CookieListCallback& callback)
-      : callback_(callback), request_count_(0) {
-    CookieListCallback got_cookies_callback = base::Bind(
+  GetCookiesCommand(
+      RenderFrameHostImpl* frame_host,
+      bool global,
+      std::unique_ptr<GetCookiesCallback> callback)
+      : callback_(std::move(callback)),
+        request_count_(0) {
+    net::CookieStore::GetCookieListCallback got_cookies_callback = base::Bind(
         &GetCookiesCommand::GotCookiesForURL, base::Unretained(this));
 
     if (global) {
       request_count_ = 1;
-      GetCookiesOnUI(frame_host->GetSiteInstance()
-                         ->GetBrowserContext()
-                         ->GetResourceContext(),
-                     frame_host->GetProcess()
-                         ->GetStoragePartition()
-                         ->GetURLRequestContext(),
-                     got_cookies_callback);
+      BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
+          &GetAllCookiesOnIO,
+          base::Unretained(frame_host->GetSiteInstance()->GetBrowserContext()->
+                           GetResourceContext()),
+          base::Unretained(frame_host->GetProcess()->GetStoragePartition()->
+                           GetURLRequestContext()),
+          got_cookies_callback));
       return;
     }
 
@@ -241,13 +178,14 @@
       if (node->current_frame_host()->IsCrossProcessSubframe())
         continue;
       ++request_count_;
-      GetCookiesForURLOnUI(
-          frame_host->GetSiteInstance()->GetBrowserContext()->
-              GetResourceContext(),
-          frame_host->GetProcess()->GetStoragePartition()->
-              GetURLRequestContext(),
+      BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
+          &GetCookiesForURLOnIO,
+          base::Unretained(frame_host->GetSiteInstance()->GetBrowserContext()->
+                           GetResourceContext()),
+          base::Unretained(frame_host->GetProcess()->GetStoragePartition()->
+                           GetURLRequestContext()),
           node->current_url(),
-          got_cookies_callback);
+          got_cookies_callback));
 
       for (size_t i = 0; i < node->child_count(); ++i)
         queue.push(node->child_at(i));
@@ -268,41 +206,68 @@
     }
     --request_count_;
     if (!request_count_) {
-      net::CookieList list;
-      list.reserve(cookies_.size());
-      for (const auto& pair : cookies_)
-        list.push_back(pair.second);
-      callback_.Run(list);
+      SendResponse();
       delete this;
     }
   }
 
-  CookieListCallback callback_;
+  void SendResponse() {
+    std::unique_ptr<protocol::Array<Network::Cookie>> cookies =
+        protocol::Array<Network::Cookie>::create();
+    for (const auto& pair : cookies_) {
+      const net::CanonicalCookie& cookie = pair.second;
+      std::unique_ptr<Network::Cookie> devtools_cookie =
+           Network::Cookie::Create()
+           .SetName(cookie.Name())
+           .SetValue(cookie.Value())
+           .SetDomain(cookie.Domain())
+           .SetPath(cookie.Path())
+           .SetExpires(cookie.ExpiryDate().ToDoubleT() * 1000)
+           .SetSize(cookie.Name().length() + cookie.Value().length())
+           .SetHttpOnly(cookie.IsHttpOnly())
+           .SetSecure(cookie.IsSecure())
+           .SetSession(!cookie.IsPersistent())
+           .Build();
+
+      switch (cookie.SameSite()) {
+        case net::CookieSameSite::STRICT_MODE:
+          devtools_cookie->SetSameSite(Network::CookieSameSiteEnum::Strict);
+          break;
+        case net::CookieSameSite::LAX_MODE:
+          devtools_cookie->SetSameSite(Network::CookieSameSiteEnum::Lax);
+          break;
+        case net::CookieSameSite::NO_RESTRICTION:
+          break;
+      }
+      cookies->addItem(std::move(devtools_cookie));
+    }
+    callback_->sendSuccess(std::move(cookies));
+  }
+
+  std::unique_ptr<GetCookiesCallback> callback_;
   int request_count_;
   base::hash_map<std::string, net::CanonicalCookie> cookies_;
 };
 
 }  // namespace
 
-typedef DevToolsProtocolClient::Response Response;
-
 NetworkHandler::NetworkHandler()
-    : host_(nullptr), enabled_(false), weak_factory_(this) {
+    : host_(nullptr), enabled_(false) {
 }
 
 NetworkHandler::~NetworkHandler() {
 }
 
+void NetworkHandler::Wire(UberDispatcher* dispatcher) {
+  Network::Dispatcher::wire(dispatcher, this);
+}
+
 void NetworkHandler::SetRenderFrameHost(RenderFrameHostImpl* host) {
   host_ = host;
 }
 
-void NetworkHandler::SetClient(std::unique_ptr<Client> client) {
-  client_.swap(client);
-}
-
-Response NetworkHandler::Enable(const int* max_total_size,
-                                const int* max_resource_size) {
+Response NetworkHandler::Enable(Maybe<int> max_total_size,
+                                Maybe<int> max_resource_size) {
   enabled_ = true;
   return Response::FallThrough();
 }
@@ -324,130 +289,80 @@
   return Response::OK();
 }
 
-Response NetworkHandler::GetCookies(DevToolsCommandId command_id,
-                                    const bool* global) {
+void NetworkHandler::GetCookies(
+    Maybe<bool> global,
+    std::unique_ptr<GetCookiesCallback> callback) {
   if (!host_)
-    return Response::InternalError("Could not connect to view");
-  new GetCookiesCommand(host_, global ? *global : false,
-                        base::Bind(&NetworkHandler::SendGetCookiesResponse,
-                                   weak_factory_.GetWeakPtr(), command_id));
-  return Response::OK();
+    callback->sendFailure(Response::InternalError());
+  else
+    new GetCookiesCommand(host_, global.fromMaybe(false), std::move(callback));
 }
 
-Response NetworkHandler::SetCookie(DevToolsCommandId command_id,
+void NetworkHandler::SetCookie(
     const std::string& url,
     const std::string& name,
     const std::string& value,
-    const std::string* domain,
-    const std::string* path,
-    bool* secure,
-    bool* http_only,
-    const std::string* same_site,
-    double* expires) {
-  if (!host_)
-    return Response::InternalError("Could not connect to view");
+    Maybe<std::string> domain,
+    Maybe<std::string> path,
+    Maybe<bool> secure,
+    Maybe<bool> http_only,
+    Maybe<std::string> same_site,
+    Maybe<double> expires,
+    std::unique_ptr<SetCookieCallback> callback) {
+  if (!host_) {
+    callback->sendFailure(Response::InternalError());
+    return;
+  }
 
   net::CookieSameSite same_site_enum = net::CookieSameSite::DEFAULT_MODE;
-  if (same_site && *same_site == kCookieSameSiteLax)
-    same_site_enum = net::CookieSameSite::LAX_MODE;
-  else if (same_site && *same_site == kCookieSameSiteStrict)
-    same_site_enum = net::CookieSameSite::STRICT_MODE;
+  if (same_site.isJust()) {
+    if (same_site.fromJust() == Network::CookieSameSiteEnum::Lax)
+      same_site_enum = net::CookieSameSite::LAX_MODE;
+    else if (same_site.fromJust() == Network::CookieSameSiteEnum::Strict)
+      same_site_enum = net::CookieSameSite::STRICT_MODE;
+  }
 
   base::Time expiration_date;
-  if (expires)
-    expiration_date = (*expires == 0)
+  if (expires.isJust()) {
+    expiration_date = expires.fromJust() == 0
             ? base::Time::UnixEpoch()
-            : base::Time::FromDoubleT(*expires);
-
-  SetCookieOnUI(
-      host_->GetSiteInstance()->GetBrowserContext()->GetResourceContext(),
-      host_->GetProcess()->GetStoragePartition()->GetURLRequestContext(),
-      GURL(url), name, value,
-      domain ? *domain : std::string(), path ? *path : std::string(),
-      secure ? *secure : false, http_only ? *http_only : false,
-      same_site_enum, expiration_date,
-      base::Bind(&NetworkHandler::SendSetCookieResponse,
-                 weak_factory_.GetWeakPtr(),
-                 command_id));
-  return Response::OK();
-}
-
-void NetworkHandler::SendSetCookieResponse(DevToolsCommandId command_id,
-    bool success) {
-  client_->SendSetCookieResponse(command_id,
-      SetCookieResponse::Create()->set_success(success));
-}
-
-void NetworkHandler::SendGetCookiesResponse(
-    DevToolsCommandId command_id,
-    const net::CookieList& cookie_list) {
-  std::vector<scoped_refptr<Cookie>> cookies;
-  for (size_t i = 0; i < cookie_list.size(); ++i) {
-    const net::CanonicalCookie& cookie = cookie_list[i];
-    scoped_refptr<Cookie> devtools_cookie = Cookie::Create()
-         ->set_name(cookie.Name())
-         ->set_value(cookie.Value())
-         ->set_domain(cookie.Domain())
-         ->set_path(cookie.Path())
-         ->set_expires(cookie.ExpiryDate().ToDoubleT() * 1000)
-         ->set_size(cookie.Name().length() + cookie.Value().length())
-         ->set_http_only(cookie.IsHttpOnly())
-         ->set_secure(cookie.IsSecure())
-         ->set_session(!cookie.IsPersistent());
-
-    switch (cookie.SameSite()) {
-      case net::CookieSameSite::STRICT_MODE:
-        devtools_cookie->set_same_site(kCookieSameSiteStrict);
-        break;
-      case net::CookieSameSite::LAX_MODE:
-        devtools_cookie->set_same_site(kCookieSameSiteLax);
-        break;
-      case net::CookieSameSite::NO_RESTRICTION:
-        break;
-    }
-    cookies.push_back(devtools_cookie);
+            : base::Time::FromDoubleT(expires.fromJust());
   }
-  client_->SendGetCookiesResponse(command_id,
-      GetCookiesResponse::Create()->set_cookies(cookies));
+
+  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
+      &SetCookieOnIO,
+      base::Unretained(host_->GetSiteInstance()->GetBrowserContext()->
+                       GetResourceContext()),
+      base::Unretained(host_->GetProcess()->GetStoragePartition()->
+                       GetURLRequestContext()),
+      GURL(url), name, value, domain.fromMaybe(""), path.fromMaybe(""),
+      secure.fromMaybe(false), http_only.fromMaybe(false), same_site_enum,
+      expiration_date, base::Passed(std::move(callback))));
 }
 
-Response NetworkHandler::DeleteCookie(
-    DevToolsCommandId command_id,
+void NetworkHandler::DeleteCookie(
     const std::string& cookie_name,
-    const std::string& url) {
-  if (!host_)
-    return Response::InternalError("Could not connect to view");
-  DeleteCookieOnUI(
-      host_->GetSiteInstance()->GetBrowserContext()->GetResourceContext(),
-      host_->GetProcess()->GetStoragePartition()->GetURLRequestContext(),
+    const std::string& url,
+    std::unique_ptr<DeleteCookieCallback> callback) {
+  if (!host_) {
+    callback->sendFailure(Response::InternalError());
+    return;
+  }
+  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
+      &DeleteCookieOnIO,
+      base::Unretained(host_->GetSiteInstance()->GetBrowserContext()->
+                       GetResourceContext()),
+      base::Unretained(host_->GetProcess()->GetStoragePartition()->
+                       GetURLRequestContext()),
       GURL(url),
       cookie_name,
-      base::Bind(&NetworkHandler::SendDeleteCookieResponse,
-                 weak_factory_.GetWeakPtr(),
-                 command_id));
-  return Response::OK();
+      base::Passed(std::move(callback))));
 }
 
-void NetworkHandler::SendDeleteCookieResponse(DevToolsCommandId command_id) {
-  client_->SendDeleteCookieResponse(command_id,
-      DeleteCookieResponse::Create());
-}
-
-
 Response NetworkHandler::CanEmulateNetworkConditions(bool* result) {
   *result = false;
   return Response::OK();
 }
 
-Response NetworkHandler::EmulateNetworkConditions(
-    bool offline,
-    double latency,
-    double download_throughput,
-    double upload_throughput,
-    const std::string* connection_type) {
-  return Response::FallThrough();
-}
-
-}  // namespace network
-}  // namespace devtools
+}  // namespace protocol
 }  // namespace content
diff --git a/content/browser/devtools/protocol/network_handler.h b/content/browser/devtools/protocol/network_handler.h
index 454d871..62a83434 100644
--- a/content/browser/devtools/protocol/network_handler.h
+++ b/content/browser/devtools/protocol/network_handler.h
@@ -6,74 +6,59 @@
 #define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_NETWORK_HANDLER_H_
 
 #include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "content/browser/devtools/protocol/devtools_protocol_dispatcher.h"
+#include "content/browser/devtools/protocol/network.h"
 #include "net/cookies/canonical_cookie.h"
 
 namespace content {
 
 class RenderFrameHostImpl;
 
-namespace devtools {
-namespace network {
+namespace protocol {
 
-class NetworkHandler {
+class NetworkHandler : public Network::Backend {
  public:
-  typedef DevToolsProtocolClient::Response Response;
   NetworkHandler();
-  virtual ~NetworkHandler();
+  ~NetworkHandler() override;
 
   void SetRenderFrameHost(RenderFrameHostImpl* host);
-  void SetClient(std::unique_ptr<Client> client);
+  void Wire(UberDispatcher*);
 
-  Response Enable(const int* max_total_size,
-                  const int* max_resource_size);
-  Response Disable();
+  Response Enable(Maybe<int> max_total_size,
+                  Maybe<int> max_resource_size) override;
+  Response Disable() override;
 
-  Response ClearBrowserCache();
-  Response ClearBrowserCookies();
-  Response GetCookies(DevToolsCommandId command_id, const bool* global);
-  Response DeleteCookie(DevToolsCommandId command_id,
-                        const std::string& cookie_name,
-                        const std::string& url);
+  Response ClearBrowserCache() override;
+  Response ClearBrowserCookies() override;
 
-  Response SetCookie(DevToolsCommandId command_id,
+  void GetCookies(Maybe<bool> global,
+                  std::unique_ptr<GetCookiesCallback> callback) override;
+  void DeleteCookie(const std::string& cookie_name,
+                    const std::string& url,
+                    std::unique_ptr<DeleteCookieCallback> callback) override;
+  void SetCookie(
       const std::string& url,
       const std::string& name,
       const std::string& value,
-      const std::string* domain,
-      const std::string* path,
-      bool* secure,
-      bool* http_only,
-      const std::string* same_site,
-      double* expires);
+      Maybe<std::string> domain,
+      Maybe<std::string> path,
+      Maybe<bool> secure,
+      Maybe<bool> http_only,
+      Maybe<std::string> same_site,
+      Maybe<double> expires,
+      std::unique_ptr<SetCookieCallback> callback) override;
 
-  Response CanEmulateNetworkConditions(bool* result);
-  Response EmulateNetworkConditions(bool offline,
-                                    double latency,
-                                    double download_throughput,
-                                    double upload_throughput,
-                                    const std::string* connection_type);
+  Response CanEmulateNetworkConditions(bool* result) override;
 
   bool enabled() const { return enabled_; }
 
  private:
-  void SendGetCookiesResponse(
-      DevToolsCommandId command_id,
-      const net::CookieList& cookie_list);
-  void SendDeleteCookieResponse(DevToolsCommandId command_id);
-  void SendSetCookieResponse(DevToolsCommandId command_id, bool success);
-
   RenderFrameHostImpl* host_;
-  std::unique_ptr<Client> client_;
   bool enabled_;
-  base::WeakPtrFactory<NetworkHandler> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(NetworkHandler);
 };
 
-}  // namespace network
-}  // namespace devtools
+}  // namespace protocol
 }  // namespace content
 
 #endif  // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_NETWORK_HANDLER_H_
diff --git a/content/browser/devtools/protocol/page_handler.cc b/content/browser/devtools/protocol/page_handler.cc
index 4ab47a3..f1361e76 100644
--- a/content/browser/devtools/protocol/page_handler.cc
+++ b/content/browser/devtools/protocol/page_handler.cc
@@ -40,8 +40,7 @@
 #include "url/gurl.h"
 
 namespace content {
-namespace devtools {
-namespace page {
+namespace protocol {
 
 namespace {
 
@@ -90,8 +89,6 @@
 
 }  // namespace
 
-typedef DevToolsProtocolClient::Response Response;
-
 PageHandler::PageHandler()
     : enabled_(false),
       screencast_enabled_(false),
@@ -139,12 +136,9 @@
   }
 }
 
-void PageHandler::SetClient(std::unique_ptr<Client> client) {
-  client_.swap(client);
-}
-
-void PageHandler::Detached() {
-  Disable();
+void PageHandler::Wire(UberDispatcher* dispatcher) {
+  frontend_.reset(new Page::Frontend(dispatcher->channel()));
+  Page::Dispatcher::wire(dispatcher, this);
 }
 
 void PageHandler::OnSwapCompositorFrame(
@@ -187,19 +181,19 @@
 void PageHandler::DidAttachInterstitialPage() {
   if (!enabled_)
     return;
-  client_->InterstitialShown(InterstitialShownParams::Create());
+  frontend_->InterstitialShown();
 }
 
 void PageHandler::DidDetachInterstitialPage() {
   if (!enabled_)
     return;
-  client_->InterstitialHidden(InterstitialHiddenParams::Create());
+  frontend_->InterstitialHidden();
 }
 
 Response PageHandler::Enable() {
   enabled_ = true;
   if (GetWebContents() && GetWebContents()->ShowingInterstitialPage())
-    client_->InterstitialShown(InterstitialShownParams::Create());
+    frontend_->InterstitialShown();
   return Response::FallThrough();
 }
 
@@ -211,17 +205,16 @@
   return Response::FallThrough();
 }
 
-Response PageHandler::Reload(const bool* bypassCache,
-                             const std::string* script_to_evaluate_on_load,
-                             const std::string* script_preprocessor) {
+Response PageHandler::Reload(Maybe<bool> bypassCache,
+                             Maybe<std::string> script_to_evaluate_on_load) {
   WebContentsImpl* web_contents = GetWebContents();
   if (!web_contents)
-    return Response::InternalError("Could not connect to view");
+    return Response::InternalError();
 
   if (web_contents->IsCrashed() ||
       (web_contents->GetController().GetVisibleEntry() &&
        web_contents->GetController().GetVisibleEntry()->IsViewSourceMode())) {
-    if (bypassCache && *bypassCache)
+    if (bypassCache.fromMaybe(false))
       web_contents->GetController().ReloadBypassingCache(false);
     else
       web_contents->GetController().Reload(false);
@@ -233,34 +226,36 @@
 }
 
 Response PageHandler::Navigate(const std::string& url,
-                               FrameId* frame_id) {
+                               Page::FrameId* frame_id) {
   GURL gurl(url);
   if (!gurl.is_valid())
-    return Response::InternalError("Cannot navigate to invalid URL");
+    return Response::Error("Cannot navigate to invalid URL");
 
   WebContentsImpl* web_contents = GetWebContents();
   if (!web_contents)
-    return Response::InternalError("Could not connect to view");
+    return Response::InternalError();
 
   web_contents->GetController()
       .LoadURL(gurl, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
   return Response::FallThrough();
 }
 
-Response PageHandler::GetNavigationHistory(int* current_index,
-                                           NavigationEntries* entries) {
+Response PageHandler::GetNavigationHistory(
+    int* current_index,
+    std::unique_ptr<NavigationEntries>* entries) {
   WebContentsImpl* web_contents = GetWebContents();
   if (!web_contents)
-    return Response::InternalError("Could not connect to view");
+    return Response::InternalError();
 
   NavigationController& controller = web_contents->GetController();
   *current_index = controller.GetCurrentEntryIndex();
+  *entries = NavigationEntries::create();
   for (int i = 0; i != controller.GetEntryCount(); ++i) {
-    entries->push_back(NavigationEntry::Create()
-        ->set_id(controller.GetEntryAtIndex(i)->GetUniqueID())
-        ->set_url(controller.GetEntryAtIndex(i)->GetURL().spec())
-        ->set_title(
-            base::UTF16ToUTF8(controller.GetEntryAtIndex(i)->GetTitle())));
+    (*entries)->addItem(Page::NavigationEntry::Create()
+        .SetId(controller.GetEntryAtIndex(i)->GetUniqueID())
+        .SetUrl(controller.GetEntryAtIndex(i)->GetURL().spec())
+        .SetTitle(base::UTF16ToUTF8(controller.GetEntryAtIndex(i)->GetTitle()))
+        .Build());
   }
   return Response::OK();
 }
@@ -268,7 +263,7 @@
 Response PageHandler::NavigateToHistoryEntry(int entry_id) {
   WebContentsImpl* web_contents = GetWebContents();
   if (!web_contents)
-    return Response::InternalError("Could not connect to view");
+    return Response::InternalError();
 
   NavigationController& controller = web_contents->GetController();
   for (int i = 0; i != controller.GetEntryCount(); ++i) {
@@ -281,38 +276,39 @@
   return Response::InvalidParams("No entry with passed id");
 }
 
-Response PageHandler::CaptureScreenshot(DevToolsCommandId command_id) {
-  if (!host_ || !host_->GetRenderWidgetHost())
-    return Response::InternalError("Could not connect to view");
+void PageHandler::CaptureScreenshot(
+    std::unique_ptr<CaptureScreenshotCallback> callback) {
+  if (!host_ || !host_->GetRenderWidgetHost()) {
+    callback->sendFailure(Response::InternalError());
+    return;
+  }
 
   host_->GetRenderWidgetHost()->GetSnapshotFromBrowser(
       base::Bind(&PageHandler::ScreenshotCaptured,
-          weak_factory_.GetWeakPtr(), command_id));
-  return Response::OK();
+          weak_factory_.GetWeakPtr(), base::Passed(std::move(callback))));
 }
 
-Response PageHandler::StartScreencast(const std::string* format,
-                                      const int* quality,
-                                      const int* max_width,
-                                      const int* max_height,
-                                      const int* every_nth_frame) {
+Response PageHandler::StartScreencast(Maybe<std::string> format,
+                                      Maybe<int> quality,
+                                      Maybe<int> max_width,
+                                      Maybe<int> max_height,
+                                      Maybe<int> every_nth_frame) {
   RenderWidgetHostImpl* widget_host =
       host_ ? host_->GetRenderWidgetHost() : nullptr;
   if (!widget_host)
-    return Response::InternalError("Could not connect to view");
+    return Response::InternalError();
 
   screencast_enabled_ = true;
-  screencast_format_ = format ? *format : kPng;
-  screencast_quality_ = quality ? *quality : kDefaultScreenshotQuality;
+  screencast_format_ = format.fromMaybe(kPng);
+  screencast_quality_ = quality.fromMaybe(kDefaultScreenshotQuality);
   if (screencast_quality_ < 0 || screencast_quality_ > 100)
     screencast_quality_ = kDefaultScreenshotQuality;
-  screencast_max_width_ = max_width ? *max_width : -1;
-  screencast_max_height_ = max_height ? *max_height : -1;
+  screencast_max_width_ = max_width.fromMaybe(-1);
+  screencast_max_height_ = max_height.fromMaybe(-1);
   ++session_id_;
   frame_counter_ = 0;
   frames_in_flight_ = 0;
-  capture_every_nth_frame_ =
-      every_nth_frame && *every_nth_frame ? *every_nth_frame : 1;
+  capture_every_nth_frame_ = every_nth_frame.fromMaybe(1);
 
   bool visible = !widget_host->is_hidden();
   NotifyScreencastVisibility(visible);
@@ -339,33 +335,29 @@
 }
 
 Response PageHandler::HandleJavaScriptDialog(bool accept,
-                                             const std::string* prompt_text) {
+                                             Maybe<std::string> prompt_text) {
   base::string16 prompt_override;
-  if (prompt_text)
-    prompt_override = base::UTF8ToUTF16(*prompt_text);
+  if (prompt_text.isJust())
+    prompt_override = base::UTF8ToUTF16(prompt_text.fromJust());
 
   WebContentsImpl* web_contents = GetWebContents();
   if (!web_contents)
-    return Response::InternalError("Could not connect to view");
+    return Response::InternalError();
 
   JavaScriptDialogManager* manager =
       web_contents->GetDelegate()->GetJavaScriptDialogManager(web_contents);
   if (manager && manager->HandleJavaScriptDialog(
-          web_contents, accept, prompt_text ? &prompt_override : nullptr)) {
+          web_contents, accept,
+          prompt_text.isJust() ? &prompt_override : nullptr)) {
     return Response::OK();
   }
 
-  return Response::InternalError("Could not handle JavaScript dialog");
-}
-
-Response PageHandler::QueryUsageAndQuota(DevToolsCommandId command_id,
-                                         const std::string& security_origin) {
-  return Response::OK();
+  return Response::Error("Could not handle JavaScript dialog");
 }
 
 Response PageHandler::SetColorPickerEnabled(bool enabled) {
   if (!host_)
-    return Response::InternalError("Could not connect to view");
+    return Response::InternalError();
 
   color_picker_->SetEnabled(enabled);
   return Response::OK();
@@ -374,7 +366,7 @@
 Response PageHandler::RequestAppBanner() {
   WebContentsImpl* web_contents = GetWebContents();
   if (!web_contents)
-    return Response::InternalError("Could not connect to view");
+    return Response::InternalError();
   web_contents->GetDelegate()->RequestAppBannerFromDevTools(web_contents);
   return Response::OK();
 }
@@ -396,13 +388,13 @@
   if (it == navigation_throttles_.end())
     return Response::InvalidParams("Unknown navigation id");
 
-  if (response == kNavigationResponseProceed) {
+  if (response == Page::NavigationResponseEnum::Proceed) {
     it->second->Resume();
     return Response::OK();
-  } else if (response == kNavigationResponseCancel) {
+  } else if (response == Page::NavigationResponseEnum::Cancel) {
     it->second->CancelDeferredNavigation(content::NavigationThrottle::CANCEL);
     return Response::OK();
-  } else if (response == kNavigationResponseCancelAndIgnore) {
+  } else if (response == Page::NavigationResponseEnum::CancelAndIgnore) {
     it->second->CancelDeferredNavigation(
         content::NavigationThrottle::CANCEL_AND_IGNORE);
     return Response::OK();
@@ -411,62 +403,6 @@
   return Response::InvalidParams("Unrecognized response");
 }
 
-Response PageHandler::AddScriptToEvaluateOnLoad(const std::string& source,
-                                                std::string* identifier) {
-  return Response::FallThrough();
-}
-
-Response PageHandler::RemoveScriptToEvaluateOnLoad(
-    const std::string& identifier) {
-  return Response::FallThrough();
-}
-
-Response PageHandler::SetAutoAttachToCreatedPages(bool auto_attach) {
-  return Response::FallThrough();
-}
-
-Response PageHandler::GetResourceTree(scoped_refptr<FrameResourceTree>* tree) {
-  return Response::FallThrough();
-}
-
-Response PageHandler::GetResourceContent(DevToolsCommandId command_id,
-                                         const std::string& frame_id,
-                                         const std::string& url) {
-  return Response::FallThrough();
-}
-
-Response PageHandler::SearchInResource(DevToolsCommandId command_id,
-                                       const std::string& frame_id,
-                                       const std::string& url,
-                                       const std::string& query,
-                                       bool* case_sensitive,
-                                       bool* is_regex) {
-  return Response::FallThrough();
-}
-
-Response PageHandler::SetDocumentContent(const std::string& frame_id,
-                                         const std::string& html) {
-  return Response::FallThrough();
-}
-
-Response PageHandler::ConfigureOverlay(const bool* is_suspended,
-                                       const std::string* message) {
-  return Response::FallThrough();
-}
-
-Response PageHandler::GetAppManifest(
-    std::string* url,
-    std::vector<scoped_refptr<AppManifestError>>* errors,
-    std::string* data) {
-  return Response::FallThrough();
-}
-
-Response PageHandler::GetLayoutMetrics(
-    scoped_refptr<LayoutViewport>* layout_viewport,
-    scoped_refptr<VisualViewport>* visual_viewport) {
-  return Response::FallThrough();
-}
-
 std::unique_ptr<PageNavigationThrottle>
 PageHandler::CreateThrottleForNavigation(NavigationHandle* navigation_handle) {
   if (!navigation_throttle_enabled_)
@@ -486,12 +422,11 @@
 
 void PageHandler::NavigationRequested(const PageNavigationThrottle* throttle) {
   NavigationHandle* navigation_handle = throttle->navigation_handle();
-  client_->NavigationRequested(
-      NavigationRequestedParams::Create()
-          ->set_is_in_main_frame(navigation_handle->IsInMainFrame())
-          ->set_is_redirect(navigation_handle->WasServerRedirect())
-          ->set_navigation_id(throttle->navigation_id())
-          ->set_url(navigation_handle->GetURL().spec()));
+  frontend_->NavigationRequested(
+      navigation_handle->IsInMainFrame(),
+      navigation_handle->WasServerRedirect(),
+      throttle->navigation_id(),
+      navigation_handle->GetURL().spec());
 }
 
 WebContentsImpl* PageHandler::GetWebContents() {
@@ -503,8 +438,7 @@
 void PageHandler::NotifyScreencastVisibility(bool visible) {
   if (visible)
     capture_retry_count_ = kCaptureRetryLimit;
-  client_->ScreencastVisibilityChanged(
-      ScreencastVisibilityChangedParams::Create()->set_visible(visible));
+  frontend_->ScreencastVisibilityChanged(visible);
 }
 
 void PageHandler::InnerSwapCompositorFrame() {
@@ -602,28 +536,26 @@
   gfx::SizeF screen_size_dip =
       gfx::ScaleSize(gfx::SizeF(view->GetPhysicalBackingSize()),
                      1 / metadata.device_scale_factor);
-  scoped_refptr<ScreencastFrameMetadata> param_metadata =
-      ScreencastFrameMetadata::Create()
-          ->set_page_scale_factor(metadata.page_scale_factor)
-          ->set_offset_top(metadata.top_controls_height *
-                           metadata.top_controls_shown_ratio)
-          ->set_device_width(screen_size_dip.width())
-          ->set_device_height(screen_size_dip.height())
-          ->set_scroll_offset_x(metadata.root_scroll_offset.x())
-          ->set_scroll_offset_y(metadata.root_scroll_offset.y())
-          ->set_timestamp(timestamp.ToDoubleT());
-  client_->ScreencastFrame(ScreencastFrameParams::Create()
-      ->set_data(data)
-      ->set_metadata(param_metadata)
-      ->set_session_id(session_id_));
+  std::unique_ptr<Page::ScreencastFrameMetadata> param_metadata =
+      Page::ScreencastFrameMetadata::Create()
+          .SetPageScaleFactor(metadata.page_scale_factor)
+          .SetOffsetTop(metadata.top_controls_height *
+                        metadata.top_controls_shown_ratio)
+          .SetDeviceWidth(screen_size_dip.width())
+          .SetDeviceHeight(screen_size_dip.height())
+          .SetScrollOffsetX(metadata.root_scroll_offset.x())
+          .SetScrollOffsetY(metadata.root_scroll_offset.y())
+          .SetTimestamp(timestamp.ToDoubleT())
+          .Build();
+  frontend_->ScreencastFrame(data, std::move(param_metadata), session_id_);
 }
 
-void PageHandler::ScreenshotCaptured(DevToolsCommandId command_id,
-                                     const unsigned char* png_data,
-                                     size_t png_size) {
+void PageHandler::ScreenshotCaptured(
+    std::unique_ptr<CaptureScreenshotCallback> callback,
+    const unsigned char* png_data,
+    size_t png_size) {
   if (!png_data || !png_size) {
-    client_->SendError(command_id,
-                       Response::InternalError("Unable to capture screenshot"));
+    callback->sendFailure(Response::Error("Unable to capture screenshot"));
     return;
   }
 
@@ -631,25 +563,21 @@
   base::Base64Encode(
       base::StringPiece(reinterpret_cast<const char*>(png_data), png_size),
       &base_64_data);
-
-  client_->SendCaptureScreenshotResponse(command_id,
-      CaptureScreenshotResponse::Create()->set_data(base_64_data));
+  callback->sendSuccess(base_64_data);
 }
 
 void PageHandler::OnColorPicked(int r, int g, int b, int a) {
-  scoped_refptr<dom::RGBA> color =
-      dom::RGBA::Create()->set_r(r)->set_g(g)->set_b(b)->set_a(a);
-  client_->ColorPicked(ColorPickedParams::Create()->set_color(color));
+  frontend_->ColorPicked(
+      DOM::RGBA::Create().SetR(r).SetG(g).SetB(b).SetA(a).Build());
 }
 
 Response PageHandler::StopLoading() {
   WebContentsImpl* web_contents = GetWebContents();
   if (!web_contents)
-    return Response::InternalError("Could not connect to view");
+    return Response::InternalError();
   web_contents->Stop();
   return Response::OK();
 }
 
-}  // namespace page
-}  // namespace devtools
+}  // namespace protocol
 }  // namespace content
diff --git a/content/browser/devtools/protocol/page_handler.h b/content/browser/devtools/protocol/page_handler.h
index ce125e6..32f80267 100644
--- a/content/browser/devtools/protocol/page_handler.h
+++ b/content/browser/devtools/protocol/page_handler.h
@@ -12,7 +12,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
 #include "cc/output/compositor_frame_metadata.h"
-#include "content/browser/devtools/protocol/devtools_protocol_dispatcher.h"
+#include "content/browser/devtools/protocol/page.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/readback_types.h"
@@ -22,26 +22,22 @@
 namespace content {
 
 class NavigationHandle;
+class PageNavigationThrottle;
 class RenderFrameHostImpl;
 class WebContentsImpl;
 
-namespace devtools {
-class PageNavigationThrottle;
-
-namespace page {
+namespace protocol {
 
 class ColorPicker;
 
-class PageHandler : public NotificationObserver {
+class PageHandler : public Page::Backend,
+                    public NotificationObserver {
  public:
-  typedef DevToolsProtocolClient::Response Response;
-
   PageHandler();
   ~PageHandler() override;
 
+  void Wire(UberDispatcher*);
   void SetRenderFrameHost(RenderFrameHostImpl* host);
-  void SetClient(std::unique_ptr<Client> client);
-  void Detached();
   void OnSwapCompositorFrame(cc::CompositorFrameMetadata frame_metadata);
   void OnSynchronousSwapCompositorFrame(
       cc::CompositorFrameMetadata frame_metadata);
@@ -49,69 +45,39 @@
   void DidDetachInterstitialPage();
   bool screencast_enabled() const { return enabled_ && screencast_enabled_; }
 
-  Response Enable();
-  Response Disable();
+  Response Enable() override;
+  Response Disable() override;
 
-  Response Reload(const bool* bypassCache,
-                  const std::string* script_to_evaluate_on_load,
-                  const std::string* script_preprocessor = NULL);
+  Response Reload(Maybe<bool> bypassCache,
+                  Maybe<std::string> script_to_evaluate_on_load) override;
+  Response Navigate(const std::string& url, Page::FrameId* frame_id) override;
+  Response StopLoading() override;
 
-  Response Navigate(const std::string& url, FrameId* frame_id);
+  using NavigationEntries = protocol::Array<Page::NavigationEntry>;
+  Response GetNavigationHistory(
+      int* current_index,
+      std::unique_ptr<NavigationEntries>* entries) override;
+  Response NavigateToHistoryEntry(int entry_id) override;
 
-  Response StopLoading();
+  void CaptureScreenshot(
+      std::unique_ptr<CaptureScreenshotCallback> callback) override;
+  Response StartScreencast(Maybe<std::string> format,
+                           Maybe<int> quality,
+                           Maybe<int> max_width,
+                           Maybe<int> max_height,
+                           Maybe<int> every_nth_frame) override;
+  Response StopScreencast() override;
+  Response ScreencastFrameAck(int session_id) override;
 
-  using NavigationEntries = std::vector<scoped_refptr<NavigationEntry>>;
-  Response GetNavigationHistory(int* current_index,
-                                NavigationEntries* entries);
+  Response HandleJavaScriptDialog(bool accept,
+                                  Maybe<std::string> prompt_text) override;
 
-  Response NavigateToHistoryEntry(int entry_id);
+  Response SetColorPickerEnabled(bool enabled) override;
+  Response RequestAppBanner() override;
 
-  Response CaptureScreenshot(DevToolsCommandId command_id);
-
-  Response StartScreencast(const std::string* format,
-                           const int* quality,
-                           const int* max_width,
-                           const int* max_height,
-                           const int* every_nth_frame);
-  Response StopScreencast();
-  Response ScreencastFrameAck(int session_id);
-
-  Response HandleJavaScriptDialog(bool accept, const std::string* prompt_text);
-
-  Response QueryUsageAndQuota(DevToolsCommandId command_id,
-                              const std::string& security_origin);
-
-  Response SetColorPickerEnabled(bool enabled);
-  Response RequestAppBanner();
-
-  Response SetControlNavigations(bool enabled);
-  Response ProcessNavigation(const std::string& response, int navigation_id);
-
-  Response AddScriptToEvaluateOnLoad(const std::string& source,
-                                     std::string* identifier);
-  Response RemoveScriptToEvaluateOnLoad(const std::string& identifier);
-  Response SetAutoAttachToCreatedPages(bool auto_attach);
-  Response GetResourceTree(scoped_refptr<FrameResourceTree>* tree);
-  Response GetResourceContent(DevToolsCommandId command_id,
-                              const std::string& frame_id,
-                              const std::string& url);
-  Response SearchInResource(DevToolsCommandId command_id,
-                            const std::string& frame_id,
-                            const std::string& url,
-                            const std::string& query,
-                            bool* case_sensitive,
-                            bool* is_regex);
-  Response SetDocumentContent(const std::string& frame_id,
-                              const std::string& html);
-  Response ConfigureOverlay(const bool* is_suspended,
-                            const std::string* message);
-  Response GetAppManifest(
-      std::string* url,
-      std::vector<scoped_refptr<AppManifestError>>* errors,
-      std::string* data);
-  Response GetLayoutMetrics(
-      scoped_refptr<LayoutViewport>* layout_viewport,
-      scoped_refptr<VisualViewport>* visual_viewport);
+  Response SetControlNavigations(bool enabled) override;
+  Response ProcessNavigation(const std::string& response,
+                             int navigation_id) override;
 
   std::unique_ptr<PageNavigationThrottle> CreateThrottleForNavigation(
       NavigationHandle* navigation_handle);
@@ -131,7 +97,7 @@
                               const std::string& data);
 
   void ScreenshotCaptured(
-      DevToolsCommandId command_id,
+      std::unique_ptr<CaptureScreenshotCallback> callback,
       const unsigned char* png_data,
       size_t png_size);
 
@@ -165,15 +131,14 @@
   std::map<int, PageNavigationThrottle*> navigation_throttles_;
 
   RenderFrameHostImpl* host_;
-  std::unique_ptr<Client> client_;
+  std::unique_ptr<Page::Frontend> frontend_;
   NotificationRegistrar registrar_;
   base::WeakPtrFactory<PageHandler> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(PageHandler);
 };
 
-}  // namespace page
-}  // namespace devtools
+}  // namespace protocol
 }  // namespace content
 
 #endif  // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_PAGE_HANDLER_H_
diff --git a/content/browser/devtools/protocol/schema_handler.cc b/content/browser/devtools/protocol/schema_handler.cc
index a7cbe1c..6583de6 100644
--- a/content/browser/devtools/protocol/schema_handler.cc
+++ b/content/browser/devtools/protocol/schema_handler.cc
@@ -5,10 +5,7 @@
 #include "content/browser/devtools/protocol/schema_handler.h"
 
 namespace content {
-namespace devtools {
-namespace schema {
-
-using Response = DevToolsProtocolClient::Response;
+namespace protocol {
 
 SchemaHandler::SchemaHandler() {
 }
@@ -16,8 +13,16 @@
 SchemaHandler::~SchemaHandler() {
 }
 
+void SchemaHandler::Wire(UberDispatcher* dispatcher) {
+  Schema::Dispatcher::wire(dispatcher, this);
+}
+
+Response SchemaHandler::Disable() {
+  return Response::OK();
+}
+
 Response SchemaHandler::GetDomains(
-    std::vector<scoped_refptr<Domain>>* domains) {
+    std::unique_ptr<protocol::Array<Schema::Domain>>* domains) {
   // TODO(kozyatisnkiy): get this from the target instead of hardcoding a list.
   static const char kVersion[] = "1.2";
   static const char* kDomains[] = {
@@ -28,14 +33,15 @@
     "Accessibility", "Storage", "Log", "Runtime", "Debugger",
     "Profiler", "HeapProfiler", "Schema", "Target"
   };
+  *domains = protocol::Array<Schema::Domain>::create();
   for (size_t i = 0; i < arraysize(kDomains); ++i) {
-    domains->push_back(Domain::Create()
-        ->set_name(kDomains[i])
-        ->set_version(kVersion));
+    (*domains)->addItem(Schema::Domain::Create()
+        .SetName(kDomains[i])
+        .SetVersion(kVersion)
+        .Build());
   }
   return Response::OK();
 }
 
-}  // namespace schema
-}  // namespace devtools
+}  // namespace protocol
 }  // namespace content
diff --git a/content/browser/devtools/protocol/schema_handler.h b/content/browser/devtools/protocol/schema_handler.h
index e79e86c7..33991ae4 100644
--- a/content/browser/devtools/protocol/schema_handler.h
+++ b/content/browser/devtools/protocol/schema_handler.h
@@ -6,26 +6,27 @@
 #define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_SCHEMA_HANDLER_H_
 
 #include "base/macros.h"
-#include "content/browser/devtools/protocol/devtools_protocol_dispatcher.h"
+#include "content/browser/devtools/protocol/schema.h"
 
 namespace content {
-namespace devtools {
-namespace schema {
+namespace protocol {
 
-class SchemaHandler {
+class SchemaHandler : public Schema::Backend {
  public:
-  using Response = DevToolsProtocolClient::Response;
-
   SchemaHandler();
-  ~SchemaHandler();
+  ~SchemaHandler() override;
 
-  Response GetDomains(std::vector<scoped_refptr<Domain>>* domains);
+  void Wire(UberDispatcher*);
+  Response Disable() override;
+
+  Response GetDomains(
+      std::unique_ptr<protocol::Array<Schema::Domain>>* domains) override;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(SchemaHandler);
 };
 
-}  // namespace schema
-}  // namespace devtools
+}  // namespace protocol
 }  // namespace content
 
 #endif  // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_SCHEMA_HANDLER_H_
diff --git a/content/browser/devtools/protocol_config.json b/content/browser/devtools/protocol_config.json
index ef70f5e0..57d7f22 100644
--- a/content/browser/devtools/protocol_config.json
+++ b/content/browser/devtools/protocol_config.json
@@ -10,6 +10,19 @@
         "export_header": "content/common/content_export.h",
         "options": [
             {
+                "domain": "DOM",
+                "include": ["setFileInputFiles"],
+                "include_events": [],
+                "include_types": ["NodeId", "RGBA"]
+            },
+            {
+                "domain": "Emulation",
+                "include": ["setGeolocationOverride", "clearGeolocationOverride", "setTouchEmulationEnabled", "canEmulate", "setDeviceMetricsOverride", "clearDeviceMetricsOverride", "setVisibleSize"]
+            },
+            {
+                "domain": "Inspector"
+            },
+            {
                 "domain": "IO",
                 "async": ["read"]
             },
@@ -18,6 +31,24 @@
                 "include": ["setPressureNotificationsSuppressed", "simulatePressureNotification"]
             },
             {
+                "domain": "Network",
+                "include": ["enable", "disable", "clearBrowserCache", "clearBrowserCookies", "getCookies", "deleteCookie", "setCookie", "canEmulateNetworkConditions"],
+                "include_types": ["CookieSameSite", "Cookie"],
+                "include_events": [],
+                "async": ["getCookies", "deleteCookie", "setCookie"]
+            },
+            {
+                "domain": "Page",
+                "include": ["enable", "disable", "reload", "navigate", "stopLoading", "getNavigationHistory", "navigateToHistoryEntry", "captureScreenshot",
+                    "startScreencast", "stopScreencast", "screencastFrameAck", "handleJavaScriptDialog", "setColorPickerEnabled", "requestAppBanner",
+                    "setControlNavigations", "processNavigation"],
+                "include_events": ["interstitialShown", "interstitialHidden", "navigationRequested", "screencastVisibilityChanged", "screencastFrame", "colorPicked"],
+                "async": ["captureScreenshot"]
+            },
+            {
+                "domain": "Schema"
+            },
+            {
                 "domain": "SystemInfo",
                 "async": ["getInfo"]
             },
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc
index 43253f6f9..b36ae17 100644
--- a/content/browser/devtools/render_frame_devtools_agent_host.cc
+++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -378,9 +378,8 @@
 bool RenderFrameDevToolsAgentHost::IsNetworkHandlerEnabled(
     FrameTreeNode* frame_tree_node) {
   RenderFrameDevToolsAgentHost* agent_host = FindAgentHost(frame_tree_node);
-  if (!agent_host)
-    return false;
-  return agent_host->network_handler_->enabled();
+  return agent_host && agent_host->network_handler_ &&
+         agent_host->network_handler_->enabled();
 }
 
 // static
@@ -395,18 +394,12 @@
 RenderFrameDevToolsAgentHost::RenderFrameDevToolsAgentHost(
     RenderFrameHostImpl* host)
     : DevToolsAgentHostImpl(base::GenerateGUID()),
-      dom_handler_(new devtools::dom::DOMHandler()),
       input_handler_(new devtools::input::InputHandler()),
-      inspector_handler_(new devtools::inspector::InspectorHandler()),
-      network_handler_(new devtools::network::NetworkHandler()),
-      page_handler_(nullptr),
-      schema_handler_(new devtools::schema::SchemaHandler()),
       security_handler_(nullptr),
       service_worker_handler_(
           new devtools::service_worker::ServiceWorkerHandler()),
       storage_handler_(new devtools::storage::StorageHandler()),
       target_handler_(new devtools::target::TargetHandler()),
-      emulation_handler_(nullptr),
       frame_trace_recorder_(nullptr),
       protocol_handler_(new DevToolsProtocolHandler(this)),
       handlers_frame_host_(nullptr),
@@ -414,23 +407,14 @@
       pending_handle_(nullptr),
       frame_tree_node_(host->frame_tree_node()) {
   DevToolsProtocolDispatcher* dispatcher = protocol_handler_->dispatcher();
-  dispatcher->SetDOMHandler(dom_handler_.get());
   dispatcher->SetInputHandler(input_handler_.get());
-  dispatcher->SetInspectorHandler(inspector_handler_.get());
-  dispatcher->SetNetworkHandler(network_handler_.get());
-  dispatcher->SetSchemaHandler(schema_handler_.get());
   dispatcher->SetServiceWorkerHandler(service_worker_handler_.get());
   dispatcher->SetStorageHandler(storage_handler_.get());
   dispatcher->SetTargetHandler(target_handler_.get());
 
   if (!host->GetParent()) {
     security_handler_.reset(new devtools::security::SecurityHandler());
-    page_handler_.reset(new devtools::page::PageHandler());
-    emulation_handler_.reset(
-        new devtools::emulation::EmulationHandler());
     dispatcher->SetSecurityHandler(security_handler_.get());
-    dispatcher->SetPageHandler(page_handler_.get());
-    dispatcher->SetEmulationHandler(emulation_handler_.get());
   }
 
   SetPending(host);
@@ -497,9 +481,36 @@
 void RenderFrameDevToolsAgentHost::Attach() {
   session()->dispatcher()->setFallThroughForNotFound(true);
 
+  if (!frame_tree_node_->parent()) {
+    emulation_handler_.reset(new protocol::EmulationHandler());
+    emulation_handler_->Wire(session()->dispatcher());
+    emulation_handler_->SetRenderFrameHost(handlers_frame_host_);
+  }
+
+  dom_handler_.reset(new protocol::DOMHandler());
+  dom_handler_->Wire(session()->dispatcher());
+  dom_handler_->SetRenderFrameHost(handlers_frame_host_);
+
+  inspector_handler_.reset(new protocol::InspectorHandler());
+  inspector_handler_->Wire(session()->dispatcher());
+  inspector_handler_->SetRenderFrameHost(handlers_frame_host_);
+
   io_handler_.reset(new protocol::IOHandler(GetIOContext()));
   io_handler_->Wire(session()->dispatcher());
 
+  network_handler_.reset(new protocol::NetworkHandler());
+  network_handler_->Wire(session()->dispatcher());
+  network_handler_->SetRenderFrameHost(handlers_frame_host_);
+
+  if (!frame_tree_node_->parent()) {
+    page_handler_.reset(new protocol::PageHandler());
+    page_handler_->Wire(session()->dispatcher());
+    page_handler_->SetRenderFrameHost(handlers_frame_host_);
+  }
+
+  schema_handler_.reset(new protocol::SchemaHandler());
+  schema_handler_->Wire(session()->dispatcher());
+
   tracing_handler_.reset(new protocol::TracingHandler(
       protocol::TracingHandler::Renderer,
       frame_tree_node_->frame_tree_node_id(),
@@ -514,8 +525,24 @@
 }
 
 void RenderFrameDevToolsAgentHost::Detach() {
+  dom_handler_->Disable();
+  dom_handler_.reset();
+  if (emulation_handler_) {
+    emulation_handler_->Disable();
+    emulation_handler_.reset();
+  }
+  inspector_handler_->Disable();
+  inspector_handler_.reset();
   io_handler_->Disable();
   io_handler_.reset();
+  network_handler_->Disable();
+  network_handler_.reset();
+  if (page_handler_) {
+    page_handler_->Disable();
+    page_handler_.reset();
+  }
+  schema_handler_->Disable();
+  schema_handler_.reset();
   tracing_handler_->Disable();
   tracing_handler_.reset();
 
@@ -580,11 +607,6 @@
 #if defined(OS_ANDROID)
   power_save_blocker_.reset();
 #endif
-  if (emulation_handler_)
-    emulation_handler_->Detached();
-  if (page_handler_)
-    page_handler_->Detached();
-  input_handler_->Detached();
   service_worker_handler_->Detached();
   target_handler_->Detached();
   frame_trace_recorder_.reset();
@@ -798,11 +820,13 @@
     case base::TERMINATION_STATUS_OOM_PROTECTED:
 #endif
     case base::TERMINATION_STATUS_LAUNCH_FAILED:
-      inspector_handler_->TargetCrashed();
+      if (inspector_handler_)
+        inspector_handler_->TargetCrashed();
       current_frame_crashed_ = true;
       break;
     default:
-      inspector_handler_->TargetDetached("Render process gone.");
+      if (inspector_handler_)
+        inspector_handler_->TargetDetached("Render process gone.");
       break;
   }
   DCHECK(CheckConsistency());
@@ -920,13 +944,16 @@
     handlers_frame_host_->GetRenderWidgetHost()->GetRoutingID();
 #endif
   handlers_frame_host_ = host;
-  dom_handler_->SetRenderFrameHost(host);
+  if (dom_handler_)
+    dom_handler_->SetRenderFrameHost(host);
   if (emulation_handler_)
     emulation_handler_->SetRenderFrameHost(host);
   input_handler_->SetRenderWidgetHost(
       host ? host->GetRenderWidgetHost() : nullptr);
-  inspector_handler_->SetRenderFrameHost(host);
-  network_handler_->SetRenderFrameHost(host);
+  if (inspector_handler_)
+    inspector_handler_->SetRenderFrameHost(host);
+  if (network_handler_)
+    network_handler_->SetRenderFrameHost(host);
   if (page_handler_)
     page_handler_->SetRenderFrameHost(host);
   service_worker_handler_->SetRenderFrameHost(host);
@@ -1072,9 +1099,10 @@
   ViewHostMsg_SwapCompositorFrame::Param param;
   if (!ViewHostMsg_SwapCompositorFrame::Read(&message, &param))
     return;
-  if (page_handler_)
+  if (page_handler_) {
     page_handler_->OnSwapCompositorFrame(
         std::move(std::get<1>(param).metadata));
+  }
   if (input_handler_)
     input_handler_->OnSwapCompositorFrame(std::get<1>(param).metadata);
   if (frame_trace_recorder_ && tracing_handler_->did_initiate_recording()) {
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.h b/content/browser/devtools/render_frame_devtools_agent_host.h
index 9cd9348..c9a989f3 100644
--- a/content/browser/devtools/render_frame_devtools_agent_host.h
+++ b/content/browser/devtools/render_frame_devtools_agent_host.h
@@ -40,13 +40,7 @@
 class RenderFrameHostImpl;
 
 namespace devtools {
-namespace dom { class DOMHandler; }
-namespace emulation { class EmulationHandler; }
 namespace input { class InputHandler; }
-namespace inspector { class InspectorHandler; }
-namespace network { class NetworkHandler; }
-namespace page { class PageHandler; }
-namespace schema { class SchemaHandler; }
 namespace security { class SecurityHandler; }
 namespace service_worker { class ServiceWorkerHandler; }
 namespace storage { class StorageHandler; }
@@ -54,7 +48,13 @@
 }
 
 namespace protocol {
+class DOMHandler;
+class EmulationHandler;
+class InspectorHandler;
 class IOHandler;
+class NetworkHandler;
+class PageHandler;
+class SchemaHandler;
 class TracingHandler;
 }  // namespace protocol
 
@@ -183,13 +183,13 @@
   // Stores per-host state between DisconnectWebContents and ConnectWebContents.
   std::unique_ptr<FrameHostHolder> disconnected_;
 
-  std::unique_ptr<devtools::dom::DOMHandler> dom_handler_;
+  std::unique_ptr<protocol::DOMHandler> dom_handler_;
   std::unique_ptr<devtools::input::InputHandler> input_handler_;
-  std::unique_ptr<devtools::inspector::InspectorHandler> inspector_handler_;
+  std::unique_ptr<protocol::InspectorHandler> inspector_handler_;
   std::unique_ptr<protocol::IOHandler> io_handler_;
-  std::unique_ptr<devtools::network::NetworkHandler> network_handler_;
-  std::unique_ptr<devtools::page::PageHandler> page_handler_;
-  std::unique_ptr<devtools::schema::SchemaHandler> schema_handler_;
+  std::unique_ptr<protocol::NetworkHandler> network_handler_;
+  std::unique_ptr<protocol::PageHandler> page_handler_;
+  std::unique_ptr<protocol::SchemaHandler> schema_handler_;
   std::unique_ptr<devtools::security::SecurityHandler> security_handler_;
   std::unique_ptr<devtools::service_worker::ServiceWorkerHandler>
       service_worker_handler_;
@@ -197,7 +197,7 @@
       storage_handler_;
   std::unique_ptr<devtools::target::TargetHandler> target_handler_;
   std::unique_ptr<protocol::TracingHandler> tracing_handler_;
-  std::unique_ptr<devtools::emulation::EmulationHandler> emulation_handler_;
+  std::unique_ptr<protocol::EmulationHandler> emulation_handler_;
   std::unique_ptr<DevToolsFrameTraceRecorder> frame_trace_recorder_;
 #if defined(OS_ANDROID)
   std::unique_ptr<device::PowerSaveBlocker> power_save_blocker_;
diff --git a/content/browser/devtools/service_worker_devtools_agent_host.cc b/content/browser/devtools/service_worker_devtools_agent_host.cc
index 0ac09f8..0745308 100644
--- a/content/browser/devtools/service_worker_devtools_agent_host.cc
+++ b/content/browser/devtools/service_worker_devtools_agent_host.cc
@@ -5,8 +5,6 @@
 #include "content/browser/devtools/service_worker_devtools_agent_host.h"
 
 #include "base/strings/stringprintf.h"
-#include "content/browser/devtools/devtools_protocol_handler.h"
-#include "content/browser/devtools/protocol/devtools_protocol_dispatcher.h"
 #include "content/browser/devtools/service_worker_devtools_manager.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/browser/service_worker/service_worker_version.h"
@@ -58,11 +56,8 @@
     bool is_installed_version)
     : WorkerDevToolsAgentHost(worker_id),
       service_worker_(new ServiceWorkerIdentifier(service_worker)),
-      network_handler_(new devtools::network::NetworkHandler()),
       version_installed_time_(is_installed_version ? base::Time::Now()
                                                    : base::Time()) {
-  DevToolsProtocolDispatcher* dispatcher = protocol_handler()->dispatcher();
-  dispatcher->SetNetworkHandler(network_handler_.get());
   NotifyCreated();
 }
 
diff --git a/content/browser/devtools/service_worker_devtools_agent_host.h b/content/browser/devtools/service_worker_devtools_agent_host.h
index 0e892985..7fac8489 100644
--- a/content/browser/devtools/service_worker_devtools_agent_host.h
+++ b/content/browser/devtools/service_worker_devtools_agent_host.h
@@ -11,7 +11,6 @@
 
 #include "base/macros.h"
 #include "base/time/time.h"
-#include "content/browser/devtools/protocol/network_handler.h"
 #include "content/browser/devtools/service_worker_devtools_manager.h"
 #include "content/browser/devtools/worker_devtools_agent_host.h"
 
@@ -61,7 +60,6 @@
  private:
   ~ServiceWorkerDevToolsAgentHost() override;
   std::unique_ptr<ServiceWorkerIdentifier> service_worker_;
-  std::unique_ptr<devtools::network::NetworkHandler> network_handler_;
   base::Time version_installed_time_;
   base::Time version_doomed_time_;
 
diff --git a/content/browser/devtools/worker_devtools_agent_host.cc b/content/browser/devtools/worker_devtools_agent_host.cc
index fb45e6d..5b91959 100644
--- a/content/browser/devtools/worker_devtools_agent_host.cc
+++ b/content/browser/devtools/worker_devtools_agent_host.cc
@@ -5,9 +5,10 @@
 #include "content/browser/devtools/worker_devtools_agent_host.h"
 
 #include "base/guid.h"
-#include "base/json/json_reader.h"
-#include "content/browser/devtools/devtools_protocol_handler.h"
 #include "content/browser/devtools/devtools_session.h"
+#include "content/browser/devtools/protocol/inspector_handler.h"
+#include "content/browser/devtools/protocol/network_handler.h"
+#include "content/browser/devtools/protocol/protocol.h"
 #include "content/browser/devtools/protocol/schema_handler.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_process_host.h"
@@ -28,12 +29,26 @@
     host->Send(new DevToolsAgentMsg_Attach(
         worker_id_.second, GetId(), session()->session_id()));
   }
+  session()->dispatcher()->setFallThroughForNotFound(true);
+  inspector_handler_.reset(new protocol::InspectorHandler());
+  inspector_handler_->Wire(session()->dispatcher());
+  network_handler_.reset(new protocol::NetworkHandler());
+  network_handler_->Wire(session()->dispatcher());
+  schema_handler_.reset(new protocol::SchemaHandler());
+  schema_handler_->Wire(session()->dispatcher());
+  session()->dispatcher()->setFallThroughForNotFound(true);
   OnAttachedStateChanged(true);
 }
 
 void WorkerDevToolsAgentHost::Detach() {
   if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first))
     host->Send(new DevToolsAgentMsg_Detach(worker_id_.second));
+  inspector_handler_->Disable();
+  inspector_handler_.reset();
+  network_handler_->Disable();
+  network_handler_.reset();
+  schema_handler_->Disable();
+  schema_handler_.reset();
   OnAttachedStateChanged(false);
   if (state_ == WORKER_INSPECTED) {
     state_ = WORKER_UNINSPECTED;
@@ -48,11 +63,10 @@
   if (state_ != WORKER_INSPECTED)
     return true;
 
-  std::unique_ptr<base::Value> value = base::JSONReader::Read(message);
-  int call_id;
+  int call_id = 0;
   std::string method;
-  if (protocol_handler_->HandleOptionalMessage(
-          session()->session_id(), std::move(value), &call_id, &method)) {
+  if (session()->Dispatch(message, &call_id, &method) !=
+      protocol::Response::kFallThrough) {
     return true;
   }
 
@@ -109,10 +123,7 @@
   DCHECK_NE(WORKER_TERMINATED, state_);
   if (state_ == WORKER_INSPECTED) {
     DCHECK(IsAttached());
-    // Client host is debugging this worker agent host.
-    devtools::inspector::Client inspector(this);
-    inspector.TargetCrashed(
-        devtools::inspector::TargetCrashedParams::Create());
+    inspector_handler_->TargetCrashed();
     DetachFromWorker();
   }
   state_ = WORKER_TERMINATED;
@@ -125,13 +136,10 @@
 
 WorkerDevToolsAgentHost::WorkerDevToolsAgentHost(WorkerId worker_id)
     : DevToolsAgentHostImpl(base::GenerateGUID()),
-      schema_handler_(new devtools::schema::SchemaHandler()),
-      protocol_handler_(new DevToolsProtocolHandler(this)),
       chunk_processor_(base::Bind(&WorkerDevToolsAgentHost::SendMessageToClient,
                                   base::Unretained(this))),
       state_(WORKER_UNINSPECTED),
       worker_id_(worker_id) {
-  protocol_handler_->dispatcher()->SetSchemaHandler(schema_handler_.get());
   WorkerCreated();
 }
 
diff --git a/content/browser/devtools/worker_devtools_agent_host.h b/content/browser/devtools/worker_devtools_agent_host.h
index e5d39f4..d0926ef 100644
--- a/content/browser/devtools/worker_devtools_agent_host.h
+++ b/content/browser/devtools/worker_devtools_agent_host.h
@@ -11,10 +11,13 @@
 
 namespace content {
 
-namespace devtools { namespace schema { class SchemaHandler; }}
+namespace protocol {
+class InspectorHandler;
+class NetworkHandler;
+class SchemaHandler;
+}
 
 class BrowserContext;
-class DevToolsProtocolHandler;
 
 class WorkerDevToolsAgentHost : public DevToolsAgentHostImpl,
                                 public IPC::Listener {
@@ -54,9 +57,6 @@
 
   virtual void OnAttachedStateChanged(bool attached);
   const WorkerId& worker_id() const { return worker_id_; }
-  DevToolsProtocolHandler* protocol_handler() {
-    return protocol_handler_.get();
-  }
 
  private:
   friend class SharedWorkerDevToolsManagerTest;
@@ -66,8 +66,9 @@
   void WorkerCreated();
   void OnDispatchOnInspectorFrontend(const DevToolsMessageChunk& message);
 
-  std::unique_ptr<devtools::schema::SchemaHandler> schema_handler_;
-  std::unique_ptr<DevToolsProtocolHandler> protocol_handler_;
+  std::unique_ptr<protocol::InspectorHandler> inspector_handler_;
+  std::unique_ptr<protocol::NetworkHandler> network_handler_;
+  std::unique_ptr<protocol::SchemaHandler> schema_handler_;
   DevToolsMessageChunkProcessor chunk_processor_;
   WorkerState state_;
   WorkerId worker_id_;
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 56e95b8..a574092 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
@@ -543,9 +543,14 @@
     const gfx::Point& point,
     RenderWidgetHostViewBase* target_view,
     gfx::Point* transformed_point) {
-  if (!frame_connector_ || !local_frame_id_.is_valid() || target_view == this)
+  if (!frame_connector_ || !local_frame_id_.is_valid())
     return false;
 
+  if (target_view == this) {
+    *transformed_point = point;
+    return true;
+  }
+
   return frame_connector_->TransformPointToCoordSpaceForView(
       point, target_view, cc::SurfaceId(frame_sink_id_, local_frame_id_),
       transformed_point);
diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.cc b/content/browser/gpu/browser_gpu_channel_host_factory.cc
index 601a4a6c..b9876e8 100644
--- a/content/browser/gpu/browser_gpu_channel_host_factory.cc
+++ b/content/browser/gpu/browser_gpu_channel_host_factory.cc
@@ -18,7 +18,7 @@
 #include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
 #include "content/browser/gpu/gpu_data_manager_impl.h"
 #include "content/browser/gpu/gpu_process_host.h"
-#include "content/browser/gpu/shader_disk_cache.h"
+#include "content/browser/gpu/shader_cache_factory.h"
 #include "content/common/child_process_host_impl.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/content_browser_client.h"
@@ -371,7 +371,7 @@
 void BrowserGpuChannelHostFactory::InitializeShaderDiskCacheOnIO(
     int gpu_client_id,
     const base::FilePath& cache_dir) {
-  ShaderCacheFactory::GetInstance()->SetCacheInfo(gpu_client_id, cache_dir);
+  GetShaderCacheFactorySingleton()->SetCacheInfo(gpu_client_id, cache_dir);
 }
 
 }  // namespace content
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index df3d612..6ff45f7f 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -31,7 +31,7 @@
 #include "content/browser/gpu/compositor_util.h"
 #include "content/browser/gpu/gpu_data_manager_impl.h"
 #include "content/browser/gpu/gpu_process_host_ui_shim.h"
-#include "content/browser/gpu/shader_disk_cache.h"
+#include "content/browser/gpu/shader_cache_factory.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
 #include "content/browser/service_manager/service_manager_context.h"
 #include "content/common/child_process_host_impl.h"
@@ -1172,7 +1172,7 @@
   TRACE_EVENT0("gpu", "GpuProcessHost::CreateChannelCache");
 
   scoped_refptr<ShaderDiskCache> cache =
-      ShaderCacheFactory::GetInstance()->Get(client_id);
+      GetShaderCacheFactorySingleton()->Get(client_id);
   if (!cache.get())
     return;
 
diff --git a/content/browser/gpu/shader_cache_factory.cc b/content/browser/gpu/shader_cache_factory.cc
new file mode 100644
index 0000000..b6f9f49
--- /dev/null
+++ b/content/browser/gpu/shader_cache_factory.cc
@@ -0,0 +1,40 @@
+// 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/gpu/shader_cache_factory.h"
+
+#include "base/single_thread_task_runner.h"
+#include "content/browser/gpu/shader_disk_cache.h"
+
+namespace content {
+
+namespace {
+
+ShaderCacheFactory* factory_instance = nullptr;
+
+void CreateFactoryInstance(
+    scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner) {
+  DCHECK(!factory_instance);
+  factory_instance = new ShaderCacheFactory(std::move(cache_task_runner));
+}
+
+}  // namespace
+
+void InitShaderCacheFactorySingleton(
+    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+    scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner) {
+  if (task_runner->BelongsToCurrentThread()) {
+    CreateFactoryInstance(std::move(cache_task_runner));
+  } else {
+    task_runner->PostTask(FROM_HERE, base::Bind(&CreateFactoryInstance,
+                                                std::move(cache_task_runner)));
+  }
+}
+
+ShaderCacheFactory* GetShaderCacheFactorySingleton() {
+  DCHECK(!factory_instance || factory_instance->CalledOnValidThread());
+  return factory_instance;
+}
+
+}  // namespace content
diff --git a/content/browser/gpu/shader_cache_factory.h b/content/browser/gpu/shader_cache_factory.h
new file mode 100644
index 0000000..57cb596
--- /dev/null
+++ b/content/browser/gpu/shader_cache_factory.h
@@ -0,0 +1,27 @@
+// 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 CONTENT_BROWSER_GPU_SHADER_CACHE_FACTORY_H_
+#define CONTENT_BROWSER_GPU_SHADER_CACHE_FACTORY_H_
+
+#include "content/browser/gpu/shader_disk_cache.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+// Initializes the ShaderCacheFactory singleton instance. The singleton
+// instance is created and used in the thread associated with |task_runner|.
+// |cache_task_runner| is associated with the thread responsible for managing
+// the disk cache.
+CONTENT_EXPORT void InitShaderCacheFactorySingleton(
+    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+    scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner);
+
+// Returns an instance previously created by InitShaderCacheFactorySingleton().
+// This can return nullptr if an instance has not yet been created.
+CONTENT_EXPORT ShaderCacheFactory* GetShaderCacheFactorySingleton();
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_GPU_SHADER_CACHE_FACTORY_H_
diff --git a/content/browser/gpu/shader_disk_cache.cc b/content/browser/gpu/shader_disk_cache.cc
index a609b85..601edec 100644
--- a/content/browser/gpu/shader_disk_cache.cc
+++ b/content/browser/gpu/shader_disk_cache.cc
@@ -20,8 +20,6 @@
 static const base::FilePath::CharType kGpuCachePath[] =
     FILE_PATH_LITERAL("GPUCache");
 
-static ShaderCacheFactory* factory_instance = nullptr;
-
 }  // namespace
 
 // ShaderDiskCacheEntry handles the work of caching/updating the cached
@@ -100,7 +98,8 @@
 
 class ShaderClearHelper : public base::ThreadChecker {
  public:
-  ShaderClearHelper(scoped_refptr<ShaderDiskCache> cache,
+  ShaderClearHelper(ShaderCacheFactory* factory,
+                    scoped_refptr<ShaderDiskCache> cache,
                     const base::FilePath& path,
                     const base::Time& delete_begin,
                     const base::Time& delete_end,
@@ -118,6 +117,7 @@
 
   void DoClearShaderCache(int rv);
 
+  ShaderCacheFactory* factory_;
   scoped_refptr<ShaderDiskCache> cache_;
   OpType op_type_;
   base::FilePath path_;
@@ -319,12 +319,14 @@
 ////////////////////////////////////////////////////////////////////////////////
 // ShaderClearHelper
 
-ShaderClearHelper::ShaderClearHelper(scoped_refptr<ShaderDiskCache> cache,
+ShaderClearHelper::ShaderClearHelper(ShaderCacheFactory* factory,
+                                     scoped_refptr<ShaderDiskCache> cache,
                                      const base::FilePath& path,
                                      const base::Time& delete_begin,
                                      const base::Time& delete_end,
                                      const base::Closure& callback)
-    : cache_(std::move(cache)),
+    : factory_(factory),
+      cache_(std::move(cache)),
       op_type_(VERIFY_CACHE_SETUP),
       path_(path),
       delete_begin_(delete_begin),
@@ -360,7 +362,7 @@
       case TERMINATE:
         callback_.Run();
         // Calling CacheCleared() destroys |this|.
-        ShaderCacheFactory::GetInstance()->CacheCleared(path_);
+        factory_->CacheCleared(path_);
         rv = net::ERR_IO_PENDING;  // Break the loop.
         break;
     }
@@ -370,25 +372,6 @@
 ////////////////////////////////////////////////////////////////////////////////
 // ShaderCacheFactory
 
-// static
-void ShaderCacheFactory::InitInstance(
-    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-    scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner) {
-  if (task_runner->BelongsToCurrentThread()) {
-    CreateFactoryInstance(std::move(cache_task_runner));
-  } else {
-    task_runner->PostTask(FROM_HERE,
-                          base::Bind(&ShaderCacheFactory::CreateFactoryInstance,
-                                     std::move(cache_task_runner)));
-  }
-}
-
-// static
-ShaderCacheFactory* ShaderCacheFactory::GetInstance() {
-  DCHECK(!factory_instance || factory_instance->CalledOnValidThread());
-  return factory_instance;
-}
-
 ShaderCacheFactory::ShaderCacheFactory(
     scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner)
     : cache_task_runner_(std::move(cache_task_runner)) {}
@@ -396,13 +379,6 @@
 ShaderCacheFactory::~ShaderCacheFactory() {
 }
 
-// static
-void ShaderCacheFactory::CreateFactoryInstance(
-    scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner) {
-  DCHECK(!factory_instance);
-  factory_instance = new ShaderCacheFactory(std::move(cache_task_runner));
-}
-
 void ShaderCacheFactory::SetCacheInfo(int32_t client_id,
                                       const base::FilePath& path) {
   DCHECK(CalledOnValidThread());
@@ -429,7 +405,7 @@
   if (iter != shader_cache_map_.end())
     return iter->second;
 
-  ShaderDiskCache* cache = new ShaderDiskCache(path);
+  ShaderDiskCache* cache = new ShaderDiskCache(this, path);
   cache->Init(cache_task_runner_);
   return cache;
 }
@@ -453,7 +429,7 @@
   DCHECK(!callback.is_null());
 
   auto helper = base::MakeUnique<ShaderClearHelper>(
-      GetByPath(path), path, delete_begin, delete_end, callback);
+      this, GetByPath(path), path, delete_begin, delete_end, callback);
 
   // We could receive requests to clear the same path with different
   // begin/end times. So, we keep a list of requests. If we haven't seen this
@@ -499,15 +475,17 @@
 ////////////////////////////////////////////////////////////////////////////////
 // ShaderDiskCache
 
-ShaderDiskCache::ShaderDiskCache(const base::FilePath& cache_path)
-    : cache_available_(false),
+ShaderDiskCache::ShaderDiskCache(ShaderCacheFactory* factory,
+                                 const base::FilePath& cache_path)
+    : factory_(factory),
+      cache_available_(false),
       cache_path_(cache_path),
       is_initialized_(false) {
-  ShaderCacheFactory::GetInstance()->AddToCache(cache_path_, this);
+  factory_->AddToCache(cache_path_, this);
 }
 
 ShaderDiskCache::~ShaderDiskCache() {
-  ShaderCacheFactory::GetInstance()->RemoveFromCache(cache_path_);
+  factory_->RemoveFromCache(cache_path_);
 }
 
 void ShaderDiskCache::Init(
@@ -604,4 +582,3 @@
 }
 
 }  // namespace content
-
diff --git a/content/browser/gpu/shader_disk_cache.h b/content/browser/gpu/shader_disk_cache.h
index dbe7ef0..fd978c9 100644
--- a/content/browser/gpu/shader_disk_cache.h
+++ b/content/browser/gpu/shader_disk_cache.h
@@ -20,6 +20,7 @@
 
 namespace content {
 
+class ShaderCacheFactory;
 class ShaderDiskCacheEntry;
 class ShaderDiskReadHelper;
 class ShaderClearHelper;
@@ -71,7 +72,8 @@
   friend class ShaderDiskReadHelper;
   friend class ShaderCacheFactory;
 
-  explicit ShaderDiskCache(const base::FilePath& cache_path);
+  ShaderDiskCache(ShaderCacheFactory* factory,
+                  const base::FilePath& cache_path);
   ~ShaderDiskCache();
 
   void Init(scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner);
@@ -82,6 +84,7 @@
   void EntryComplete(ShaderDiskCacheEntry* entry);
   void ReadComplete();
 
+  ShaderCacheFactory* factory_;
   bool cache_available_;
   base::FilePath cache_path_;
   bool is_initialized_;
@@ -104,17 +107,9 @@
 class CONTENT_EXPORT ShaderCacheFactory
     : NON_EXPORTED_BASE(public base::ThreadChecker) {
  public:
-  // Initializes the ShaderCacheFactory singleton instance. The singleton
-  // instance is created and used in the thread associated with |task_runner|.
-  // |cache_task_runner| is associated with the thread responsible for managing
-  // the disk cache.
-  static void InitInstance(
-      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+  explicit ShaderCacheFactory(
       scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner);
-
-  // Returns an instance previously created by InitInstance(). This can return
-  // nullptr if an instance has not yet been created.
-  static ShaderCacheFactory* GetInstance();
+  ~ShaderCacheFactory();
 
   // Clear the shader disk cache for the given |path|. This supports unbounded
   // deletes in either direction by using null Time values for either
@@ -143,13 +138,6 @@
  private:
   friend class ShaderClearHelper;
 
-  explicit ShaderCacheFactory(
-      scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner);
-  ~ShaderCacheFactory();
-
-  static void CreateFactoryInstance(
-      scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner);
-
   scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner_;
 
   scoped_refptr<ShaderDiskCache> GetByPath(const base::FilePath& path);
@@ -171,4 +159,3 @@
 }  // namespace content
 
 #endif  // CONTENT_BROWSER_GPU_SHADER_DISK_CACHE_H_
-
diff --git a/content/browser/gpu/shader_disk_cache_unittest.cc b/content/browser/gpu/shader_disk_cache_unittest.cc
index 8062947..ee6592fd 100644
--- a/content/browser/gpu/shader_disk_cache_unittest.cc
+++ b/content/browser/gpu/shader_disk_cache_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
+#include "base/memory/ptr_util.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "content/browser/browser_thread_impl.h"
@@ -25,8 +26,7 @@
  public:
   ShaderDiskCacheTest()
       : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
-    ShaderCacheFactory::InitInstance(
-        base::ThreadTaskRunnerHandle::Get(),
+    factory_ = base::MakeUnique<ShaderCacheFactory>(
         BrowserThread::GetTaskRunnerForThread(BrowserThread::CACHE));
   }
 
@@ -36,15 +36,15 @@
 
   void InitCache() {
     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-    ShaderCacheFactory::GetInstance()->SetCacheInfo(kDefaultClientId,
-                                                        cache_path());
+    factory_->SetCacheInfo(kDefaultClientId, cache_path());
   }
 
+  ShaderCacheFactory* factory() { return factory_.get(); }
+
  private:
-  void TearDown() override {
-    ShaderCacheFactory::GetInstance()->RemoveCacheInfo(kDefaultClientId);
-  }
+  void TearDown() override { factory_->RemoveCacheInfo(kDefaultClientId); }
 
+  std::unique_ptr<ShaderCacheFactory> factory_;
   base::ScopedTempDir temp_dir_;
   content::TestBrowserThreadBundle thread_bundle_;
 
@@ -54,8 +54,7 @@
 TEST_F(ShaderDiskCacheTest, ClearsCache) {
   InitCache();
 
-  scoped_refptr<ShaderDiskCache> cache =
-      ShaderCacheFactory::GetInstance()->Get(kDefaultClientId);
+  scoped_refptr<ShaderDiskCache> cache = factory()->Get(kDefaultClientId);
   ASSERT_TRUE(cache.get() != NULL);
 
   net::TestCompletionCallback available_cb;
diff --git a/content/browser/indexed_db/indexed_db_database_unittest.cc b/content/browser/indexed_db/indexed_db_database_unittest.cc
index 5d85503..953b720 100644
--- a/content/browser/indexed_db/indexed_db_database_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_database_unittest.cc
@@ -377,6 +377,10 @@
 
   void RunPostedTasks() { base::RunLoop().RunUntilIdle(); }
 
+private:
+  // Needs to outlive |db_|.
+  content::TestBrowserThreadBundle thread_bundle_;
+
  protected:
   scoped_refptr<IndexedDBFakeBackingStore> backing_store_;
   scoped_refptr<IndexedDBDatabase> db_;
@@ -389,7 +393,6 @@
 
  private:
   scoped_refptr<MockIndexedDBFactory> factory_;
-  content::TestBrowserThreadBundle thread_bundle_;
 
   DISALLOW_COPY_AND_ASSIGN(IndexedDBDatabaseOperationTest);
 };
diff --git a/content/browser/renderer_host/input/gesture_event_queue.cc b/content/browser/renderer_host/input/gesture_event_queue.cc
index a0a80e3..6952862 100644
--- a/content/browser/renderer_host/input/gesture_event_queue.cc
+++ b/content/browser/renderer_host/input/gesture_event_queue.cc
@@ -163,6 +163,9 @@
     case WebInputEvent::GestureTapCancel:
     case WebInputEvent::GestureTap:
     case WebInputEvent::GestureDoubleTap:
+    case WebInputEvent::GestureLongPress:
+    case WebInputEvent::GestureLongTap:
+    case WebInputEvent::GestureTwoFingerTap:
       if (gesture_event.event.sourceDevice ==
           blink::WebGestureDeviceTouchscreen) {
         return !touchscreen_tap_suppression_controller_.FilterTapEvent(
diff --git a/content/browser/renderer_host/input/input_router_config_helper.cc b/content/browser/renderer_host/input/input_router_config_helper.cc
index 53aaee3..a41f0ec 100644
--- a/content/browser/renderer_host/input/input_router_config_helper.cc
+++ b/content/browser/renderer_host/input/input_router_config_helper.cc
@@ -49,9 +49,16 @@
   config.touchscreen_tap_suppression_config.max_cancel_to_down_time =
       base::TimeDelta::FromMilliseconds(
           gesture_config->fling_max_cancel_to_down_time_in_ms());
+
+  // Tap suppression controller forwards the stashed tapDown and drops the rest
+  // of the stashed events when the tapDownTimer expires. If a fling cancel ack
+  // with |processed = false| arrives before the timer expiration, all stashed
+  // events will be forwarded. The timer is used to avoid waiting for an
+  // arbitrarily late fling cancel ack. Its delay should be large enough for
+  // a long press to get stashed and forwarded if needed.
   config.touchscreen_tap_suppression_config.max_tap_gap_time =
       base::TimeDelta::FromMilliseconds(
-          gesture_config->long_press_time_in_ms());
+          gesture_config->long_press_time_in_ms() + 50);
 
   config.touchpad_tap_suppression_config.enabled =
       gesture_config->fling_touchpad_tap_suppression_enabled();
diff --git a/content/browser/renderer_host/input/tap_suppression_controller.cc b/content/browser/renderer_host/input/tap_suppression_controller.cc
index 78b3a07..008feb2 100644
--- a/content/browser/renderer_host/input/tap_suppression_controller.cc
+++ b/content/browser/renderer_host/input/tap_suppression_controller.cc
@@ -7,13 +7,27 @@
 #include "base/logging.h"
 #include "base/trace_event/trace_event.h"
 #include "content/browser/renderer_host/input/tap_suppression_controller_client.h"
+#include "ui/events/gesture_detection/gesture_configuration.h"
 
 namespace content {
 
+// The tapDownTimer is used to avoid waiting for an arbitrarily late fling
+// cancel ack. While the timer is running, if a fling cancel ack with
+// |Processed = false| arrives, all stashed gesture events get forwarded. If
+// the timer expires, the controller forwards stashed GestureTapDown only, and
+// drops the rest of the stashed events. The timer delay should be large enough
+// for a GestureLongPress to get stashed and forwarded if needed. It's still
+// possible for a GestureLongPress to arrive after the timer expiration. In
+// this case, it will be suppressed if the controller is in SUPPRESSING_TAPS
+// state.
+
 TapSuppressionController::Config::Config()
     : enabled(false),
-      max_cancel_to_down_time(base::TimeDelta::FromMilliseconds(180)),
-      max_tap_gap_time(base::TimeDelta::FromMilliseconds(500)) {
+      max_cancel_to_down_time(base::TimeDelta::FromMilliseconds(180)) {
+  ui::GestureConfiguration* gesture_config =
+      ui::GestureConfiguration::GetInstance();
+  max_tap_gap_time = base::TimeDelta::FromMilliseconds(
+      gesture_config->long_press_time_in_ms() + 50);
 }
 
 TapSuppressionController::TapSuppressionController(
@@ -34,6 +48,7 @@
     case NOTHING:
     case GFC_IN_PROGRESS:
     case LAST_CANCEL_STOPPED_FLING:
+    case SUPPRESSING_TAPS:
       state_ = GFC_IN_PROGRESS;
       break;
     case TAP_DOWN_STASHED:
@@ -46,6 +61,7 @@
   switch (state_) {
     case DISABLED:
     case NOTHING:
+    case SUPPRESSING_TAPS:
       break;
     case GFC_IN_PROGRESS:
       if (processed)
@@ -57,7 +73,9 @@
         TRACE_EVENT0("browser",
                      "TapSuppressionController::GestureFlingCancelAck");
         StopTapDownTimer();
-        client_->ForwardStashedTapDown();
+        // If the fling cancel is not processed, forward all stashed
+        // gesture events.
+        client_->ForwardStashedGestureEvents();
         state_ = NOTHING;
       }  // Else waiting for the timer to release the stashed tap down.
       break;
@@ -89,6 +107,10 @@
         state_ = NOTHING;
         return false;
       }
+    // Stop suppressing tap end events.
+    case SUPPRESSING_TAPS:
+      state_ = NOTHING;
+      return false;
   }
   NOTREACHED() << "Invalid state";
   return false;
@@ -101,12 +123,17 @@
     case GFC_IN_PROGRESS:
       return false;
     case TAP_DOWN_STASHED:
-      state_ = NOTHING;
+      // A tap cancel happens before long tap and two finger tap events. To
+      // drop the latter events as well as the tap cancel, change the state
+      // to "SUPPRESSING_TAPS" when the stashed tap down is dropped.
+      state_ = SUPPRESSING_TAPS;
       StopTapDownTimer();
       client_->DropStashedTapDown();
       return true;
     case LAST_CANCEL_STOPPED_FLING:
       NOTREACHED() << "Invalid tap end on LAST_CANCEL_STOPPED_FLING state";
+    case SUPPRESSING_TAPS:
+      return true;
   }
   return false;
 }
@@ -128,6 +155,7 @@
   switch (state_) {
     case DISABLED:
     case NOTHING:
+    case SUPPRESSING_TAPS:
       NOTREACHED() << "Timer fired on invalid state.";
       break;
     case GFC_IN_PROGRESS:
@@ -138,8 +166,10 @@
     case TAP_DOWN_STASHED:
       TRACE_EVENT0("browser",
                    "TapSuppressionController::TapDownTimerExpired");
+      // When the timer expires, only forward the stashed tap down event, and
+      // drop other stashed gesture events (show press or long press).
       client_->ForwardStashedTapDown();
-      state_ = NOTHING;
+      state_ = SUPPRESSING_TAPS;
       break;
   }
 }
diff --git a/content/browser/renderer_host/input/tap_suppression_controller.h b/content/browser/renderer_host/input/tap_suppression_controller.h
index dc0def5..b238258b 100644
--- a/content/browser/renderer_host/input/tap_suppression_controller.h
+++ b/content/browser/renderer_host/input/tap_suppression_controller.h
@@ -70,6 +70,12 @@
     GFC_IN_PROGRESS,
     TAP_DOWN_STASHED,
     LAST_CANCEL_STOPPED_FLING,
+    // When the stashed TapDown event is dropped or forwarded due to tap down
+    // timer expiration, the controller enters the SUPPRESSING_TAPS state.
+    // This state shows that the controller will suppress LongTap,
+    // TwoFingerTap, and TapCancel gesture events until the next tapDown event
+    // arrives.
+    SUPPRESSING_TAPS,
   };
 
   TapSuppressionControllerClient* client_;
diff --git a/content/browser/renderer_host/input/tap_suppression_controller_client.h b/content/browser/renderer_host/input/tap_suppression_controller_client.h
index d55613c9..0b917a6 100644
--- a/content/browser/renderer_host/input/tap_suppression_controller_client.h
+++ b/content/browser/renderer_host/input/tap_suppression_controller_client.h
@@ -18,9 +18,14 @@
   // Called whenever the deferred tap down (if saved) should be dropped totally.
   virtual void DropStashedTapDown() = 0;
 
-  // Called whenever the deferred tap down (if saved) should be forwarded to the
-  // renderer. The tap down should go back to normal path it was
-  // on before being deferred.
+  // Called whenever the deferred tap down and other gesture events (if saved)
+  // should be forwarded to the renderer. The tap down (and possibly other
+  // gesture events) should go back to normal path they were on before being
+  // deferred.
+  virtual void ForwardStashedGestureEvents() = 0;
+
+  // Called whenever only the deferred tap down (if saved) should be forwarded
+  // to the renderer. Other saved gesture events will be dropped.
   virtual void ForwardStashedTapDown() = 0;
 
  protected:
diff --git a/content/browser/renderer_host/input/tap_suppression_controller_unittest.cc b/content/browser/renderer_host/input/tap_suppression_controller_unittest.cc
index 3dd0834..195a4962 100644
--- a/content/browser/renderer_host/input/tap_suppression_controller_unittest.cc
+++ b/content/browser/renderer_host/input/tap_suppression_controller_unittest.cc
@@ -22,6 +22,7 @@
   using TapSuppressionController::GFC_IN_PROGRESS;
   using TapSuppressionController::TAP_DOWN_STASHED;
   using TapSuppressionController::LAST_CANCEL_STOPPED_FLING;
+  using TapSuppressionController::SUPPRESSING_TAPS;
 
   enum Action {
     NONE                                 = 0,
@@ -104,6 +105,10 @@
   // TapSuppressionControllerClient implementation
   void DropStashedTapDown() override { last_actions_ |= TAP_DOWN_DROPPED; }
 
+  void ForwardStashedGestureEvents() override {
+    last_actions_ |= STASHED_TAP_DOWN_FORWARDED;
+  }
+
   void ForwardStashedTapDown() override {
     last_actions_ |= STASHED_TAP_DOWN_FORWARDED;
   }
@@ -178,7 +183,7 @@
   EXPECT_EQ(MockTapSuppressionController::TAP_UP_SUPPRESSED |
             MockTapSuppressionController::TAP_DOWN_DROPPED,
             tap_suppression_controller_->last_actions());
-  EXPECT_EQ(MockTapSuppressionController::NOTHING,
+  EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
             tap_suppression_controller_->state());
 }
 
@@ -219,7 +224,7 @@
   EXPECT_EQ(MockTapSuppressionController::TAP_UP_SUPPRESSED |
             MockTapSuppressionController::TAP_DOWN_DROPPED,
             tap_suppression_controller_->last_actions());
-  EXPECT_EQ(MockTapSuppressionController::NOTHING,
+  EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
             tap_suppression_controller_->state());
 }
 
@@ -252,14 +257,16 @@
   tap_suppression_controller_->AdvanceTime(TimeDelta::FromMilliseconds(13));
   EXPECT_EQ(MockTapSuppressionController::STASHED_TAP_DOWN_FORWARDED,
             tap_suppression_controller_->last_actions());
-  EXPECT_EQ(MockTapSuppressionController::NOTHING,
+  EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
             tap_suppression_controller_->state());
 
-  // Send TapUp. This TapUp should not be suppressed.
+  // Send TapUp. This TapUp should be still suppressed.
+  // LongTap should be suppressed when the previously suppressed TapDown is
+  // forwarded because of the timer expiration.
   tap_suppression_controller_->SendTapUp();
-  EXPECT_EQ(MockTapSuppressionController::TAP_UP_FORWARDED,
+  EXPECT_EQ(MockTapSuppressionController::TAP_UP_SUPPRESSED,
             tap_suppression_controller_->last_actions());
-  EXPECT_EQ(MockTapSuppressionController::NOTHING,
+  EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
             tap_suppression_controller_->state());
 }
 
@@ -300,7 +307,7 @@
   EXPECT_EQ(MockTapSuppressionController::TAP_UP_SUPPRESSED |
             MockTapSuppressionController::TAP_DOWN_DROPPED,
             tap_suppression_controller_->last_actions());
-  EXPECT_EQ(MockTapSuppressionController::NOTHING,
+  EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
             tap_suppression_controller_->state());
 }
 
@@ -406,7 +413,7 @@
   EXPECT_EQ(MockTapSuppressionController::TAP_UP_SUPPRESSED |
             MockTapSuppressionController::TAP_DOWN_DROPPED,
             tap_suppression_controller_->last_actions());
-  EXPECT_EQ(MockTapSuppressionController::NOTHING,
+  EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
             tap_suppression_controller_->state());
 }
 
@@ -447,7 +454,7 @@
   EXPECT_EQ(MockTapSuppressionController::TAP_UP_SUPPRESSED |
             MockTapSuppressionController::TAP_DOWN_DROPPED,
             tap_suppression_controller_->last_actions());
-  EXPECT_EQ(MockTapSuppressionController::NOTHING,
+  EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
             tap_suppression_controller_->state());
 }
 
@@ -480,14 +487,16 @@
   tap_suppression_controller_->AdvanceTime(TimeDelta::FromMilliseconds(13));
   EXPECT_EQ(MockTapSuppressionController::STASHED_TAP_DOWN_FORWARDED,
             tap_suppression_controller_->last_actions());
-  EXPECT_EQ(MockTapSuppressionController::NOTHING,
+  EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
             tap_suppression_controller_->state());
 
-  // Send TapUp. This TapUp should not be suppressed.
+  // Send TapUp. This TapUp should be still suppressed.
+  // LongTap should be suppressed when the previously suppressed TapDown is
+  // forwarded because of timer expiration.
   tap_suppression_controller_->SendTapUp();
-  EXPECT_EQ(MockTapSuppressionController::TAP_UP_FORWARDED,
+  EXPECT_EQ(MockTapSuppressionController::TAP_UP_SUPPRESSED,
             tap_suppression_controller_->last_actions());
-  EXPECT_EQ(MockTapSuppressionController::NOTHING,
+  EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
             tap_suppression_controller_->state());
 }
 
diff --git a/content/browser/renderer_host/input/touchpad_tap_suppression_controller.cc b/content/browser/renderer_host/input/touchpad_tap_suppression_controller.cc
index d309742..dac3af2 100644
--- a/content/browser/renderer_host/input/touchpad_tap_suppression_controller.cc
+++ b/content/browser/renderer_host/input/touchpad_tap_suppression_controller.cc
@@ -37,6 +37,12 @@
 void TouchpadTapSuppressionController::DropStashedTapDown() {
 }
 
+void TouchpadTapSuppressionController::ForwardStashedGestureEvents() {
+  // Mouse downs are not handled by gesture event filter; so, they are
+  // immediately forwarded to the renderer.
+  client_->SendMouseEventImmediately(stashed_mouse_down_);
+}
+
 void TouchpadTapSuppressionController::ForwardStashedTapDown() {
   // Mouse downs are not handled by gesture event filter; so, they are
   // immediately forwarded to the renderer.
diff --git a/content/browser/renderer_host/input/touchpad_tap_suppression_controller.h b/content/browser/renderer_host/input/touchpad_tap_suppression_controller.h
index 1934ad6..88b08058 100644
--- a/content/browser/renderer_host/input/touchpad_tap_suppression_controller.h
+++ b/content/browser/renderer_host/input/touchpad_tap_suppression_controller.h
@@ -54,6 +54,7 @@
 
   // TapSuppressionControllerClient implementation.
   void DropStashedTapDown() override;
+  void ForwardStashedGestureEvents() override;
   void ForwardStashedTapDown() override;
 
   TouchpadTapSuppressionControllerClient* client_;
diff --git a/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.cc b/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.cc
index a5ffc01..45d5212 100644
--- a/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.cc
+++ b/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.cc
@@ -44,12 +44,24 @@
       stashed_show_press_.reset(new GestureEventWithLatencyInfo(event));
       return true;
 
+    case WebInputEvent::GestureLongPress:
+      // It is possible that a GestureLongPress arrives after tapDownTimer
+      // expiration, in this case it should still get filtered if the
+      // controller suppresses the tap end events.
+      if (!stashed_tap_down_)
+        return controller_.ShouldSuppressTapEnd();
+
+      stashed_long_press_.reset(new GestureEventWithLatencyInfo(event));
+      return true;
+
     case WebInputEvent::GestureTapUnconfirmed:
       return !!stashed_tap_down_;
 
     case WebInputEvent::GestureTapCancel:
     case WebInputEvent::GestureTap:
     case WebInputEvent::GestureDoubleTap:
+    case WebInputEvent::GestureLongTap:
+    case WebInputEvent::GestureTwoFingerTap:
       return controller_.ShouldSuppressTapEnd();
 
     default:
@@ -61,15 +73,27 @@
 void TouchscreenTapSuppressionController::DropStashedTapDown() {
   stashed_tap_down_.reset();
   stashed_show_press_.reset();
+  stashed_long_press_.reset();
+}
+
+void TouchscreenTapSuppressionController::ForwardStashedGestureEvents() {
+  DCHECK(stashed_tap_down_);
+  ScopedGestureEvent tap_down = std::move(stashed_tap_down_);
+  ScopedGestureEvent show_press = std::move(stashed_show_press_);
+  ScopedGestureEvent long_press = std::move(stashed_long_press_);
+  gesture_event_queue_->ForwardGestureEvent(*tap_down);
+  if (show_press)
+    gesture_event_queue_->ForwardGestureEvent(*show_press);
+  if (long_press)
+    gesture_event_queue_->ForwardGestureEvent(*long_press);
 }
 
 void TouchscreenTapSuppressionController::ForwardStashedTapDown() {
   DCHECK(stashed_tap_down_);
   ScopedGestureEvent tap_down = std::move(stashed_tap_down_);
-  ScopedGestureEvent show_press = std::move(stashed_show_press_);
   gesture_event_queue_->ForwardGestureEvent(*tap_down);
-  if (show_press)
-    gesture_event_queue_->ForwardGestureEvent(*show_press);
+  stashed_show_press_.reset();
+  stashed_long_press_.reset();
 }
 
 }  // namespace content
diff --git a/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.h b/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.h
index 3e7623e..c7a3039 100644
--- a/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.h
+++ b/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.h
@@ -40,6 +40,7 @@
  private:
   // TapSuppressionControllerClient implementation.
   void DropStashedTapDown() override;
+  void ForwardStashedGestureEvents() override;
   void ForwardStashedTapDown() override;
 
   GestureEventQueue* gesture_event_queue_;
@@ -47,6 +48,7 @@
   typedef std::unique_ptr<GestureEventWithLatencyInfo> ScopedGestureEvent;
   ScopedGestureEvent stashed_tap_down_;
   ScopedGestureEvent stashed_show_press_;
+  ScopedGestureEvent stashed_long_press_;
 
   // The core controller of tap suppression.
   TapSuppressionController controller_;
diff --git a/content/browser/renderer_host/media/audio_output_authorization_handler.cc b/content/browser/renderer_host/media/audio_output_authorization_handler.cc
index 9c8a1f4..56f27ea1 100644
--- a/content/browser/renderer_host/media/audio_output_authorization_handler.cc
+++ b/content/browser/renderer_host/media/audio_output_authorization_handler.cc
@@ -82,8 +82,8 @@
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   if (!IsValidDeviceId(device_id)) {
-    bad_message::ReceivedBadMessage(render_process_id_,
-                                    bad_message::AOAH_NONSENSE_DEVICE_ID);
+    cb.Run(media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND, false,
+           media::AudioParameters::UnavailableDeviceParams(), std::string());
     return;
   }
 
diff --git a/content/browser/renderer_host/media/audio_output_authorization_handler_unittest.cc b/content/browser/renderer_host/media/audio_output_authorization_handler_unittest.cc
index 9b5c54d..e0e42c5 100644
--- a/content/browser/renderer_host/media/audio_output_authorization_handler_unittest.cc
+++ b/content/browser/renderer_host/media/audio_output_authorization_handler_unittest.cc
@@ -260,8 +260,7 @@
   SyncWithAllThreads();
 }
 
-TEST_F(AudioOutputAuthorizationHandlerTest,
-       AuthorizeInvalidDeviceId_BadMessage) {
+TEST_F(AudioOutputAuthorizationHandlerTest, AuthorizeInvalidDeviceId_NotFound) {
   std::unique_ptr<TestBrowserContext> context =
       base::MakeUnique<TestBrowserContext>();
   std::unique_ptr<MockRenderProcessHost> RPH =
@@ -272,7 +271,10 @@
           GetAudioManager(), GetMediaStreamManager(), RPH->GetID(), kSalt);
   EXPECT_EQ(RPH->bad_msg_count(), 0);
 
-  EXPECT_CALL(listener, MockAuthorizationCallback(_, _, _, _)).Times(0);
+  EXPECT_CALL(listener,
+              MockAuthorizationCallback(
+                  media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND, _, _, _))
+      .Times(1);
 
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
@@ -281,7 +283,9 @@
                   kInvalidDeviceId, SecurityOrigin(), listener.GetCallback())));
 
   SyncWithAllThreads();
-  EXPECT_EQ(RPH->bad_msg_count(), 1);
+  // It is possible to request an invalid device id from JS APIs,
+  // so we don't want to crash the renderer for this.
+  EXPECT_EQ(RPH->bad_msg_count(), 0);
   BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, handler.release());
   SyncWithAllThreads();
   RPH.reset();
diff --git a/content/browser/renderer_host/media/audio_renderer_host_unittest.cc b/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
index 04b7209b..88dc9d37 100644
--- a/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
+++ b/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
@@ -609,9 +609,8 @@
 }
 
 TEST_F(AudioRendererHostTest, CreateInvalidDevice) {
-  Create(kInvalidDeviceId, url::Origin(GURL(kSecurityOrigin)), true, false);
+  Create(kInvalidDeviceId, url::Origin(GURL(kSecurityOrigin)), true, true);
   Close();
-  AssertBadMsgReported();
 }
 
 TEST_F(AudioRendererHostTest, CreateFailsForInvalidRenderFrame) {
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 12fd4ea..9307bcc 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -73,7 +73,7 @@
 #include "content/browser/gpu/compositor_util.h"
 #include "content/browser/gpu/gpu_data_manager_impl.h"
 #include "content/browser/gpu/gpu_process_host.h"
-#include "content/browser/gpu/shader_disk_cache.h"
+#include "content/browser/gpu/shader_cache_factory.h"
 #include "content/browser/histogram_message_filter.h"
 #include "content/browser/indexed_db/indexed_db_context_impl.h"
 #include "content/browser/indexed_db/indexed_db_dispatcher_host.h"
@@ -261,13 +261,13 @@
 #endif
 
 void CacheShaderInfo(int32_t id, base::FilePath path) {
-  if (ShaderCacheFactory::GetInstance())
-    ShaderCacheFactory::GetInstance()->SetCacheInfo(id, path);
+  if (GetShaderCacheFactorySingleton())
+    GetShaderCacheFactorySingleton()->SetCacheInfo(id, path);
 }
 
 void RemoveShaderInfo(int32_t id) {
-  if (ShaderCacheFactory::GetInstance())
-    ShaderCacheFactory::GetInstance()->RemoveCacheInfo(id);
+  if (GetShaderCacheFactorySingleton())
+    GetShaderCacheFactorySingleton()->RemoveCacheInfo(id);
 }
 
 net::URLRequestContext* GetRequestContext(
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index dd33dfe..6141da6d 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -2153,8 +2153,6 @@
       const NativeWebKeyboardEventWithLatencyInfo& event,
       InputEventAckState ack_result) {
   latency_tracker_.OnInputEventAck(event.event, &event.latency, ack_result);
-  for (auto& input_event_observer : input_event_observers_)
-    input_event_observer.OnInputEventAck(event.event);
 
   const bool processed = (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result);
 
@@ -2175,8 +2173,6 @@
     InputEventAckState ack_result) {
   latency_tracker_.OnInputEventAck(mouse_event.event, &mouse_event.latency,
                                    ack_result);
-  for (auto& input_event_observer : input_event_observers_)
-    input_event_observer.OnInputEventAck(mouse_event.event);
 }
 
 void RenderWidgetHostImpl::OnWheelEventAck(
@@ -2184,8 +2180,6 @@
     InputEventAckState ack_result) {
   latency_tracker_.OnInputEventAck(wheel_event.event, &wheel_event.latency,
                                    ack_result);
-  for (auto& input_event_observer : input_event_observers_)
-    input_event_observer.OnInputEventAck(wheel_event.event);
 
   if (!is_hidden() && view_) {
     if (ack_result != INPUT_EVENT_ACK_STATE_CONSUMED &&
@@ -2200,8 +2194,6 @@
     const GestureEventWithLatencyInfo& event,
     InputEventAckState ack_result) {
   latency_tracker_.OnInputEventAck(event.event, &event.latency, ack_result);
-  for (auto& input_event_observer : input_event_observers_)
-    input_event_observer.OnInputEventAck(event.event);
 
   if (view_)
     view_->GestureEventAck(event.event, ack_result);
@@ -2211,8 +2203,6 @@
     const TouchEventWithLatencyInfo& event,
     InputEventAckState ack_result) {
   latency_tracker_.OnInputEventAck(event.event, &event.latency, ack_result);
-  for (auto& input_event_observer : input_event_observers_)
-    input_event_observer.OnInputEventAck(event.event);
 
   if (touch_emulator_ &&
       touch_emulator_->HandleTouchEventAck(event.event, ack_result)) {
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 508ae90e..49da75d 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -1657,6 +1657,11 @@
     const gfx::Point& point,
     RenderWidgetHostViewBase* target_view,
     gfx::Point* transformed_point) {
+  if (target_view == this) {
+    *transformed_point = point;
+    return true;
+  }
+
   // In TransformPointToLocalCoordSpace() there is a Point-to-Pixel conversion,
   // but it is not necessary here because the final target view is responsible
   // for converting before computing the final transform.
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 c7a78ff..5bef4d0 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -1579,6 +1579,11 @@
     const gfx::Point& point,
     RenderWidgetHostViewBase* target_view,
     gfx::Point* transformed_point) {
+  if (target_view == this) {
+    *transformed_point = point;
+    return true;
+  }
+
   return browser_compositor_->GetDelegatedFrameHost()
       ->TransformPointToCoordSpaceForView(point, target_view,
                                           transformed_point);
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index ed7de52..c3014f3 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -589,6 +589,26 @@
   }
 };
 
+//
+// SitePerProcessNonIntegerScaleFactorBrowserTest
+//
+
+class SitePerProcessNonIntegerScaleFactorBrowserTest
+    : public SitePerProcessBrowserTest {
+ public:
+  const double kDeviceScaleFactor = 1.5;
+
+  SitePerProcessNonIntegerScaleFactorBrowserTest() {}
+
+ protected:
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    SitePerProcessBrowserTest::SetUpCommandLine(command_line);
+    command_line->AppendSwitchASCII(
+        switches::kForceDeviceScaleFactor,
+        base::StringPrintf("%f", kDeviceScaleFactor));
+  }
+};
+
 // SitePerProcessIgnoreCertErrorsBrowserTest
 
 class SitePerProcessIgnoreCertErrorsBrowserTest
@@ -8833,4 +8853,59 @@
             child->current_frame_host()->GetProcess());
 }
 
+// Test that MouseDown and MouseUp to the same coordinates do not result in
+// different coordinates after routing. See bug https://crbug.com/670253.
+#if defined(OS_ANDROID)
+// Browser process hit testing is not implemented on Android.
+// https://crbug.com/491334
+#define MAYBE_MouseClickWithNonIntegerScaleFactor \
+  DISABLED_MouseClickWithNonIntegerScaleFactor
+#else
+#define MAYBE_MouseClickWithNonIntegerScaleFactor \
+  MouseClickWithNonIntegerScaleFactor
+#endif
+IN_PROC_BROWSER_TEST_F(SitePerProcessNonIntegerScaleFactorBrowserTest,
+                       MAYBE_MouseClickWithNonIntegerScaleFactor) {
+  GURL initial_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), initial_url));
+
+  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+                            ->GetFrameTree()
+                            ->root();
+
+  RenderWidgetHostViewBase* rwhv = static_cast<RenderWidgetHostViewBase*>(
+      root->current_frame_host()->GetRenderWidgetHost()->GetView());
+
+  RenderWidgetHostInputEventRouter* router =
+      static_cast<WebContentsImpl*>(shell()->web_contents())
+          ->GetInputEventRouter();
+
+  // Create listener for input events.
+  RenderWidgetHostMouseEventMonitor event_monitor(
+      root->current_frame_host()->GetRenderWidgetHost());
+
+  blink::WebMouseEvent mouse_event;
+  mouse_event.type = blink::WebInputEvent::MouseDown;
+  mouse_event.button = blink::WebPointerProperties::Button::Left;
+  mouse_event.x = 75;
+  mouse_event.y = 75;
+  mouse_event.clickCount = 1;
+  event_monitor.ResetEventReceived();
+  router->RouteMouseEvent(rwhv, &mouse_event, ui::LatencyInfo());
+
+  EXPECT_TRUE(event_monitor.EventWasReceived());
+  gfx::Point mouse_down_coords =
+      gfx::Point(event_monitor.event().x, event_monitor.event().y);
+  event_monitor.ResetEventReceived();
+
+  mouse_event.type = blink::WebInputEvent::MouseUp;
+  mouse_event.x = 75;
+  mouse_event.y = 75;
+  router->RouteMouseEvent(rwhv, &mouse_event, ui::LatencyInfo());
+
+  EXPECT_TRUE(event_monitor.EventWasReceived());
+  EXPECT_EQ(mouse_down_coords,
+            gfx::Point(event_monitor.event().x, event_monitor.event().y));
+}
+
 }  // namespace content
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
index 0640453..a2d6035 100644
--- a/content/browser/storage_partition_impl.cc
+++ b/content/browser/storage_partition_impl.cc
@@ -16,7 +16,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "content/browser/browser_main_loop.h"
 #include "content/browser/fileapi/browser_file_system_helper.h"
-#include "content/browser/gpu/shader_disk_cache.h"
+#include "content/browser/gpu/shader_cache_factory.h"
 #include "content/browser/host_zoom_map_impl.h"
 #include "content/browser/notifications/platform_notification_context_impl.h"
 #include "content/common/dom_storage/dom_storage_types.h"
@@ -132,7 +132,7 @@
                                 const base::Time end,
                                 const base::Closure& callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  ShaderCacheFactory::GetInstance()->ClearByPath(
+  GetShaderCacheFactorySingleton()->ClearByPath(
       path, begin, end, base::Bind(&ClearedShaderCache, callback));
 }
 
diff --git a/content/browser/storage_partition_impl_unittest.cc b/content/browser/storage_partition_impl_unittest.cc
index dd0e2ad..6ae89b8 100644
--- a/content/browser/storage_partition_impl_unittest.cc
+++ b/content/browser/storage_partition_impl_unittest.cc
@@ -13,7 +13,7 @@
 #include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "content/browser/browser_thread_impl.h"
-#include "content/browser/gpu/shader_disk_cache.h"
+#include "content/browser/gpu/shader_cache_factory.h"
 #include "content/browser/quota/mock_quota_manager.h"
 #include "content/browser/storage_partition_impl.h"
 #include "content/public/browser/local_storage_usage_info.h"
@@ -602,19 +602,19 @@
   StoragePartitionShaderClearTest()
       : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
         browser_context_(new TestBrowserContext()) {
-    ShaderCacheFactory::InitInstance(
+    InitShaderCacheFactorySingleton(
         base::ThreadTaskRunnerHandle::Get(),
         BrowserThread::GetTaskRunnerForThread(BrowserThread::CACHE));
-    ShaderCacheFactory::GetInstance()->SetCacheInfo(
+    GetShaderCacheFactorySingleton()->SetCacheInfo(
         kDefaultClientId,
-        BrowserContext::GetDefaultStoragePartition(
-            browser_context())->GetPath());
-    cache_ = ShaderCacheFactory::GetInstance()->Get(kDefaultClientId);
+        BrowserContext::GetDefaultStoragePartition(browser_context())
+            ->GetPath());
+    cache_ = GetShaderCacheFactorySingleton()->Get(kDefaultClientId);
   }
 
   ~StoragePartitionShaderClearTest() override {
     cache_ = NULL;
-    ShaderCacheFactory::GetInstance()->RemoveCacheInfo(kDefaultClientId);
+    GetShaderCacheFactorySingleton()->RemoveCacheInfo(kDefaultClientId);
   }
 
   void InitCache() {
diff --git a/content/child/blink_platform_impl_unittest.cc b/content/child/blink_platform_impl_unittest.cc
index 28f7dfb..97140e8e 100644
--- a/content/child/blink_platform_impl_unittest.cc
+++ b/content/child/blink_platform_impl_unittest.cc
@@ -21,8 +21,10 @@
       url::Origin::UnsafelyCreateOriginWithoutNormalization(
           origin.protocol().utf8(), origin.host().utf8(),
           origin.effectivePort());
-  url::Origin non_checked_origin = url::Origin::CreateFromNormalizedTuple(
-      origin.protocol().utf8(), origin.host().utf8(), origin.effectivePort());
+  url::Origin non_checked_origin =
+      url::Origin::CreateFromNormalizedTupleWithSuborigin(
+          origin.protocol().utf8(), origin.host().utf8(),
+          origin.effectivePort(), origin.suborigin().utf8());
   EXPECT_EQ(checked_origin.scheme(), non_checked_origin.scheme());
   EXPECT_EQ(checked_origin.host(), non_checked_origin.host());
   EXPECT_EQ(checked_origin.port(), non_checked_origin.port());
@@ -144,7 +146,7 @@
 }
 
 // This test ensures that WebSecurityOrigins can safely use
-// url::Origin::CreateFromNormalizedTuple when doing conversions.
+// url::Origin::CreateFromNormalizedTupleWithSuborigin when doing conversions.
 TEST(BlinkPlatformTest, WebSecurityOriginNormalization) {
   struct TestCases {
     const char* url;
diff --git a/content/child/service_worker/service_worker_dispatcher.cc b/content/child/service_worker/service_worker_dispatcher.cc
index c1934f51..d0db7de 100644
--- a/content/child/service_worker/service_worker_dispatcher.cc
+++ b/content/child/service_worker/service_worker_dispatcher.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/lazy_instance.h"
+#include "base/memory/ptr_util.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
 #include "base/threading/thread_local.h"
@@ -523,21 +524,15 @@
   if (!callbacks)
     return;
 
-  typedef blink::WebVector<blink::WebServiceWorkerRegistration::Handle*>
-      WebServiceWorkerRegistrationArray;
-  std::unique_ptr<WebServiceWorkerRegistrationArray> registrations(
-      new WebServiceWorkerRegistrationArray(infos.size()));
+  using WebServiceWorkerRegistrationHandles =
+      WebServiceWorkerProvider::WebServiceWorkerRegistrationHandles;
+  std::unique_ptr<WebServiceWorkerRegistrationHandles> registrations =
+      base::MakeUnique<WebServiceWorkerRegistrationHandles>(infos.size());
   for (size_t i = 0; i < infos.size(); ++i) {
-    if (infos[i].handle_id != kInvalidServiceWorkerHandleId) {
-      ServiceWorkerRegistrationObjectInfo info(infos[i]);
-      ServiceWorkerVersionAttributes attr(attrs[i]);
-
-      // WebServiceWorkerGetRegistrationsCallbacks cannot receive an array of
-      // std::unique_ptr<WebServiceWorkerRegistration::Handle>, so create leaky
-      // handles instead.
-      (*registrations)[i] = WebServiceWorkerRegistrationImpl::CreateLeakyHandle(
-          GetOrAdoptRegistration(info, attr));
-    }
+    if (infos[i].handle_id == kInvalidServiceWorkerHandleId)
+      continue;
+    (*registrations)[i] = WebServiceWorkerRegistrationImpl::CreateHandle(
+        GetOrAdoptRegistration(infos[i], attrs[i]));
   }
 
   callbacks->onSuccess(std::move(registrations));
diff --git a/content/child/service_worker/web_service_worker_registration_impl.cc b/content/child/service_worker/web_service_worker_registration_impl.cc
index 48d440e4..de0acf7b 100644
--- a/content/child/service_worker/web_service_worker_registration_impl.cc
+++ b/content/child/service_worker/web_service_worker_registration_impl.cc
@@ -200,14 +200,6 @@
   return base::MakeUnique<HandleImpl>(registration);
 }
 
-blink::WebServiceWorkerRegistration::Handle*
-WebServiceWorkerRegistrationImpl::CreateLeakyHandle(
-    const scoped_refptr<WebServiceWorkerRegistrationImpl>& registration) {
-  if (!registration)
-    return nullptr;
-  return new HandleImpl(registration);
-}
-
 WebServiceWorkerRegistrationImpl::~WebServiceWorkerRegistrationImpl() {
   ServiceWorkerDispatcher* dispatcher =
       ServiceWorkerDispatcher::GetThreadSpecificInstance();
diff --git a/content/child/service_worker/web_service_worker_registration_impl.h b/content/child/service_worker/web_service_worker_registration_impl.h
index 4614444..9dece685 100644
--- a/content/child/service_worker/web_service_worker_registration_impl.h
+++ b/content/child/service_worker/web_service_worker_registration_impl.h
@@ -78,13 +78,6 @@
   static std::unique_ptr<WebServiceWorkerRegistrationHandle> CreateHandle(
       const scoped_refptr<WebServiceWorkerRegistrationImpl>& registration);
 
-  // Same with CreateHandle(), but returns a raw pointer to the handle w/ its
-  // ownership instead. The caller must manage the ownership. This function must
-  // be used only for passing the handle to Blink API that does not support
-  // blink::WebPassOwnPtr.
-  static WebServiceWorkerRegistrationHandle* CreateLeakyHandle(
-      const scoped_refptr<WebServiceWorkerRegistrationImpl>& registration);
-
  private:
   friend class base::RefCounted<WebServiceWorkerRegistrationImpl>;
   ~WebServiceWorkerRegistrationImpl() override;
diff --git a/content/content_resources.grd b/content/content_resources.grd
index 030506ba..39cbab2 100644
--- a/content/content_resources.grd
+++ b/content/content_resources.grd
@@ -55,6 +55,7 @@
         <include name="IDR_MOJO_CODEC_JS" file="../mojo/public/js/codec.js" flattenhtml="true" type="BINDATA" />
         <include name="IDR_MOJO_CONNECTION_JS" file="../mojo/public/js/connection.js" flattenhtml="true" type="BINDATA" />
         <include name="IDR_MOJO_CONNECTOR_JS" file="../mojo/public/js/connector.js" flattenhtml="true" type="BINDATA" />
+        <include name="IDR_MOJO_INTERFACE_TYPES_JS" file="../mojo/public/js/interface_types.js" flattenhtml="true" type="BINDATA" />
         <include name="IDR_MOJO_ROUTER_JS" file="../mojo/public/js/router.js" flattenhtml="true" type="BINDATA" />
         <include name="IDR_MOJO_UNICODE_JS" file="../mojo/public/js/unicode.js" flattenhtml="true" type="BINDATA" />
         <include name="IDR_MOJO_VALIDATOR_JS" file="../mojo/public/js/validator.js" flattenhtml="true" type="BINDATA" />
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn
index 9b1487c..59d3a32 100644
--- a/content/public/android/BUILD.gn
+++ b/content/public/android/BUILD.gn
@@ -76,23 +76,6 @@
     "java/src/org/chromium/content/app/PrivilegedProcessService0.java",
     "java/src/org/chromium/content/app/PrivilegedProcessService1.java",
     "java/src/org/chromium/content/app/PrivilegedProcessService2.java",
-    "java/src/org/chromium/content/app/PrivilegedProcessService3.java",
-    "java/src/org/chromium/content/app/PrivilegedProcessService4.java",
-    "java/src/org/chromium/content/app/PrivilegedProcessService5.java",
-    "java/src/org/chromium/content/app/PrivilegedProcessService6.java",
-    "java/src/org/chromium/content/app/PrivilegedProcessService7.java",
-    "java/src/org/chromium/content/app/PrivilegedProcessService8.java",
-    "java/src/org/chromium/content/app/PrivilegedProcessService9.java",
-    "java/src/org/chromium/content/app/PrivilegedProcessService10.java",
-    "java/src/org/chromium/content/app/PrivilegedProcessService11.java",
-    "java/src/org/chromium/content/app/PrivilegedProcessService12.java",
-    "java/src/org/chromium/content/app/PrivilegedProcessService13.java",
-    "java/src/org/chromium/content/app/PrivilegedProcessService14.java",
-    "java/src/org/chromium/content/app/PrivilegedProcessService15.java",
-    "java/src/org/chromium/content/app/PrivilegedProcessService16.java",
-    "java/src/org/chromium/content/app/PrivilegedProcessService17.java",
-    "java/src/org/chromium/content/app/PrivilegedProcessService18.java",
-    "java/src/org/chromium/content/app/PrivilegedProcessService19.java",
     "java/src/org/chromium/content/app/SandboxedProcessService.java",
     "java/src/org/chromium/content/app/SandboxedProcessService0.java",
     "java/src/org/chromium/content/app/SandboxedProcessService1.java",
diff --git a/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java b/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java
index 376f319..9a9f212 100644
--- a/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java
+++ b/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java
@@ -6,7 +6,6 @@
 
 import android.app.Service;
 import android.content.Intent;
-import android.os.Bundle;
 import android.os.IBinder;
 
 import org.chromium.base.annotations.JNINamespace;
@@ -48,20 +47,4 @@
         stopSelf();
         return mChildProcessServiceImpl.bind(intent, -1);
     }
-
-    /**
-     * Helper method to initialize the params from intent.
-     * @param intent Intent to launch the service.
-     */
-    protected void initializeParams(Intent intent) {
-        mChildProcessServiceImpl.initializeParams(intent);
-    }
-
-    /**
-     * Helper method to get the information about the service from a given bundle.
-     * @param bundle Bundle that contains the information to start the service.
-     */
-    protected void getServiceInfo(Bundle bundle) {
-        mChildProcessServiceImpl.getServiceInfo(bundle);
-    }
 }
diff --git a/content/public/android/java/src/org/chromium/content/app/ChildProcessServiceImpl.java b/content/public/android/java/src/org/chromium/content/app/ChildProcessServiceImpl.java
index a3748f8..40d63878 100644
--- a/content/public/android/java/src/org/chromium/content/app/ChildProcessServiceImpl.java
+++ b/content/public/android/java/src/org/chromium/content/app/ChildProcessServiceImpl.java
@@ -70,8 +70,6 @@
 
     private static AtomicReference<Context> sContext = new AtomicReference<>(null);
     private boolean mLibraryInitialized = false;
-    // Becomes true once the service is bound. Access must synchronize around mMainThread.
-    private boolean mIsBound = false;
 
     /**
      * If >= 0 enables "validation of caller of {@link mBinder}'s methods". A RemoteException
@@ -164,11 +162,7 @@
                     Linker linker = null;
                     boolean requestedSharedRelro = false;
                     if (Linker.isUsed()) {
-                        synchronized (mMainThread) {
-                            while (!mIsBound) {
-                                mMainThread.wait();
-                            }
-                        }
+                        assert mLinkerParams != null;
                         linker = getLinker();
                         if (mLinkerParams.mWaitForSharedRelro) {
                             requestedSharedRelro = true;
@@ -282,28 +276,24 @@
         return mBinder;
     }
 
-    void initializeParams(Intent intent) {
+    private void initializeParams(Intent intent) {
         synchronized (mMainThread) {
-            mCommandLineParams =
-                    intent.getStringArrayExtra(ChildProcessConstants.EXTRA_COMMAND_LINE);
             // mLinkerParams is never used if Linker.isUsed() returns false.
             // See onCreate().
             mLinkerParams = new ChromiumLinkerParams(intent);
             mLibraryProcessType = ChildProcessCreationParams.getLibraryProcessType(intent);
-            mIsBound = true;
             mMainThread.notifyAll();
         }
     }
 
-    void getServiceInfo(Bundle bundle) {
+    private void getServiceInfo(Bundle bundle) {
         // Required to unparcel FileDescriptorInfo.
         bundle.setClassLoader(mHostClassLoader);
         synchronized (mMainThread) {
-            // Allow the command line to be set via bind() intent or setupConnection, but
-            // the FD can only be transferred here.
             if (mCommandLineParams == null) {
                 mCommandLineParams =
                         bundle.getStringArray(ChildProcessConstants.EXTRA_COMMAND_LINE);
+                mMainThread.notifyAll();
             }
             // We must have received the command line by now
             assert mCommandLineParams != null;
diff --git a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService0.java b/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService0.java
index 4976d67e..a3c9c5b8 100644
--- a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService0.java
+++ b/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService0.java
@@ -6,7 +6,7 @@
 
 /**
  * This is needed to register multiple PrivilegedProcess services so that we can have
- * more than one privileged process.
+ * more than one sandboxed process.
  */
 public class PrivilegedProcessService0 extends PrivilegedProcessService {
 
diff --git a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService1.java b/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService1.java
index 0da1fffa..bd16f07 100644
--- a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService1.java
+++ b/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService1.java
@@ -6,7 +6,7 @@
 
 /**
  * This is needed to register multiple PrivilegedProcess services so that we can have
- * more than one privileged process.
+ * more than one sandboxed process.
  */
 public class PrivilegedProcessService1 extends PrivilegedProcessService {
 
diff --git a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService10.java b/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService10.java
deleted file mode 100644
index 2187f15c..0000000
--- a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService10.java
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.content.app;
-
-/**
- * This is needed to register multiple PrivilegedProcess services so that we can have
- * more than one privileged process.
- */
-public class PrivilegedProcessService10 extends PrivilegedProcessService {
-
-}
diff --git a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService11.java b/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService11.java
deleted file mode 100644
index ef91c07..0000000
--- a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService11.java
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.content.app;
-
-/**
- * This is needed to register multiple PrivilegedProcess services so that we can have
- * more than one privileged process.
- */
-public class PrivilegedProcessService11 extends PrivilegedProcessService {
-
-}
diff --git a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService12.java b/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService12.java
deleted file mode 100644
index ada05b6e..0000000
--- a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService12.java
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.content.app;
-
-/**
- * This is needed to register multiple PrivilegedProcess services so that we can have
- * more than one privileged process.
- */
-public class PrivilegedProcessService12 extends PrivilegedProcessService {
-
-}
diff --git a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService13.java b/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService13.java
deleted file mode 100644
index e003b77b..0000000
--- a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService13.java
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.content.app;
-
-/**
- * This is needed to register multiple PrivilegedProcess services so that we can have
- * more than one privileged process.
- */
-public class PrivilegedProcessService13 extends PrivilegedProcessService {
-
-}
diff --git a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService14.java b/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService14.java
deleted file mode 100644
index e2cd356..0000000
--- a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService14.java
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.content.app;
-
-/**
- * This is needed to register multiple PrivilegedProcess services so that we can have
- * more than one privileged process.
- */
-public class PrivilegedProcessService14 extends PrivilegedProcessService {
-
-}
diff --git a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService15.java b/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService15.java
deleted file mode 100644
index 9233e779..0000000
--- a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService15.java
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.content.app;
-
-/**
- * This is needed to register multiple PrivilegedProcess services so that we can have
- * more than one privileged process.
- */
-public class PrivilegedProcessService15 extends PrivilegedProcessService {
-
-}
diff --git a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService16.java b/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService16.java
deleted file mode 100644
index 04dd5efb..0000000
--- a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService16.java
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.content.app;
-
-/**
- * This is needed to register multiple PrivilegedProcess services so that we can have
- * more than one privileged process.
- */
-public class PrivilegedProcessService16 extends PrivilegedProcessService {
-
-}
diff --git a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService17.java b/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService17.java
deleted file mode 100644
index 98c3534..0000000
--- a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService17.java
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.content.app;
-
-/**
- * This is needed to register multiple PrivilegedProcess services so that we can have
- * more than one privileged process.
- */
-public class PrivilegedProcessService17 extends PrivilegedProcessService {
-
-}
diff --git a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService18.java b/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService18.java
deleted file mode 100644
index 769a9a9..0000000
--- a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService18.java
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.content.app;
-
-/**
- * This is needed to register multiple PrivilegedProcess services so that we can have
- * more than one privileged process.
- */
-public class PrivilegedProcessService18 extends PrivilegedProcessService {
-
-}
diff --git a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService19.java b/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService19.java
deleted file mode 100644
index 3303b0f..0000000
--- a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService19.java
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.content.app;
-
-/**
- * This is needed to register multiple PrivilegedProcess services so that we can have
- * more than one privileged process.
- */
-public class PrivilegedProcessService19 extends PrivilegedProcessService {
-
-}
diff --git a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService2.java b/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService2.java
index ea2c482..3f40406 100644
--- a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService2.java
+++ b/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService2.java
@@ -6,7 +6,7 @@
 
 /**
  * This is needed to register multiple PrivilegedProcess services so that we can have
- * more than one privileged process.
+ * more than one sandboxed process.
  */
 public class PrivilegedProcessService2 extends PrivilegedProcessService {
 
diff --git a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService3.java b/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService3.java
deleted file mode 100644
index 9307bb7..0000000
--- a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService3.java
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.content.app;
-
-/**
- * This is needed to register multiple PrivilegedProcess services so that we can have
- * more than one privileged process.
- */
-public class PrivilegedProcessService3 extends PrivilegedProcessService {
-
-}
diff --git a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService4.java b/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService4.java
deleted file mode 100644
index 5ed2799..0000000
--- a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService4.java
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.content.app;
-
-/**
- * This is needed to register multiple PrivilegedProcess services so that we can have
- * more than one privileged process.
- */
-public class PrivilegedProcessService4 extends PrivilegedProcessService {
-
-}
diff --git a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService5.java b/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService5.java
deleted file mode 100644
index 1fc3a90b..0000000
--- a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService5.java
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.content.app;
-
-/**
- * This is needed to register multiple PrivilegedProcess services so that we can have
- * more than one privileged process.
- */
-public class PrivilegedProcessService5 extends PrivilegedProcessService {
-
-}
diff --git a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService6.java b/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService6.java
deleted file mode 100644
index 34ff845..0000000
--- a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService6.java
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.content.app;
-
-/**
- * This is needed to register multiple PrivilegedProcess services so that we can have
- * more than one privileged process.
- */
-public class PrivilegedProcessService6 extends PrivilegedProcessService {
-
-}
diff --git a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService7.java b/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService7.java
deleted file mode 100644
index c8439ab..0000000
--- a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService7.java
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.content.app;
-
-/**
- * This is needed to register multiple PrivilegedProcess services so that we can have
- * more than one privileged process.
- */
-public class PrivilegedProcessService7 extends PrivilegedProcessService {
-
-}
diff --git a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService8.java b/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService8.java
deleted file mode 100644
index 63d9e49..0000000
--- a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService8.java
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.content.app;
-
-/**
- * This is needed to register multiple PrivilegedProcess services so that we can have
- * more than one privileged process.
- */
-public class PrivilegedProcessService8 extends PrivilegedProcessService {
-
-}
diff --git a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService9.java b/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService9.java
deleted file mode 100644
index a5d71b7..0000000
--- a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService9.java
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.content.app;
-
-/**
- * This is needed to register multiple PrivilegedProcess services so that we can have
- * more than one privileged process.
- */
-public class PrivilegedProcessService9 extends PrivilegedProcessService {
-
-}
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildProcessConnectionImpl.java b/content/public/android/java/src/org/chromium/content/browser/ChildProcessConnectionImpl.java
index 99032d4..4eb35a5 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ChildProcessConnectionImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ChildProcessConnectionImpl.java
@@ -130,9 +130,9 @@
                 try {
                     TraceEvent.begin("ChildProcessConnectionImpl.ChildServiceConnection.bind");
                     final Intent intent = createServiceBindIntent();
-                    if (commandLine != null) {
-                        intent.putExtra(ChildProcessConstants.EXTRA_COMMAND_LINE, commandLine);
-                    }
+                    // Note, the intent may be saved and re-used by Android for re-launching the
+                    // child service. Do not pass data that is different for each child; command
+                    // line arguments for example.
                     if (mLinkerParams != null) {
                         mLinkerParams.addIntentExtras(intent);
                     }
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java
index b0c8feb..4d58ca08 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java
@@ -34,7 +34,6 @@
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.LinkedList;
 import java.util.Map;
 import java.util.Queue;
@@ -74,12 +73,6 @@
             for (int i = 0; i < numChildServices; i++) {
                 mFreeConnectionIndices.add(i);
             }
-            // Randomize the order of named child services to workaround this bug:
-            // Android restarts crashed services with the previous intent. If browser crashes and
-            // is restarted at the same time, then it's possible to bind to the restarted service
-            // with stale intent and bundle data. See crbug.com/664341#c84 for an example.
-            // Randomizing the start up order is a pure workaround to make this case less likely.
-            Collections.shuffle(mFreeConnectionIndices);
             mChildClassName = serviceClassName;
             mInSandbox = inSandbox;
         }
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentView.java b/content/public/android/java/src/org/chromium/content/browser/ContentView.java
index af83042..a0857e0 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentView.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentView.java
@@ -288,12 +288,6 @@
         mContentViewCore.onDetachedFromWindow();
     }
 
-    @Override
-    protected void onVisibilityChanged(View changedView, int visibility) {
-        super.onVisibilityChanged(changedView, visibility);
-        mContentViewCore.onVisibilityChanged(changedView, visibility);
-    }
-
     // Implements SmartClipProvider
     @Override
     public void extractSmartClipData(int x, int y, int width, int height) {
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
index a3ad4b87..1ed433c 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
@@ -98,16 +98,6 @@
     // produce little visible difference.
     private static final float ZOOM_CONTROLS_EPSILON = 0.007f;
 
-    private static final ZoomControlsDelegate NO_OP_ZOOM_CONTROLS_DELEGATE =
-            new ZoomControlsDelegate() {
-        @Override
-        public void invokeZoomPicker() {}
-        @Override
-        public void dismissZoomPicker() {}
-        @Override
-        public void updateZoomControls() {}
-    };
-
     // If the embedder adds a JavaScript interface object that contains an indirect reference to
     // the ContentViewCore, then storing a strong ref to the interface object on the native
     // side would prevent garbage collection of the ContentViewCore (as that strong ref would
@@ -276,26 +266,6 @@
     }
 
     /**
-     * An interface for controlling visibility and state of embedder-provided zoom controls.
-     */
-    public interface ZoomControlsDelegate {
-        /**
-         * Called when it's reasonable to show zoom controls.
-         */
-        void invokeZoomPicker();
-
-        /**
-         * Called when zoom controls need to be hidden (e.g. when the view hides).
-         */
-        void dismissZoomPicker();
-
-        /**
-         * Called when page scale has been changed, so the controls can update their state.
-         */
-        void updateZoomControls();
-    }
-
-    /**
      * An interface that allows the embedder to be notified when the results of
      * extractSmartClipData are available.
      */
@@ -318,7 +288,6 @@
     private boolean mAttachedToWindow;
     private final ObserverList<GestureStateListener> mGestureStateListeners;
     private final RewindableIterator<GestureStateListener> mGestureStateListenersIterator;
-    private ZoomControlsDelegate mZoomControlsDelegate;
 
     private PopupZoomer mPopupZoomer;
     private SelectPopup mSelectPopup;
@@ -623,8 +592,6 @@
         long windowNativePointer = windowAndroid.getNativePointer();
         assert windowNativePointer != 0;
 
-        mZoomControlsDelegate = NO_OP_ZOOM_CONTROLS_DELEGATE;
-
         final float dipScale = windowAndroid.getDisplay().getDipScale();
 
         mRenderCoordinates.reset();
@@ -836,7 +803,6 @@
         mWebContentsObserver.destroy();
         mWebContentsObserver = null;
         setSmartClipDataListener(null);
-        setZoomControlsDelegate(null);
         mImeAdapter.resetAndHideKeyboard();
         // TODO(igsolla): address TODO in ContentViewClient because ContentViewClient is not
         // currently a real Null Object.
@@ -1177,14 +1143,12 @@
     private void onScrollBeginEventAck() {
         setTouchScrollInProgress(true);
         hidePastePopup();
-        mZoomControlsDelegate.invokeZoomPicker();
         updateGestureStateListener(GestureEventType.SCROLL_START);
     }
 
     @SuppressWarnings("unused")
     @CalledByNative
     private void onScrollUpdateGestureConsumed() {
-        mZoomControlsDelegate.invokeZoomPicker();
         for (mGestureStateListenersIterator.rewind();
                 mGestureStateListenersIterator.hasNext();) {
             mGestureStateListenersIterator.next().onScrollUpdateGestureConsumed();
@@ -1420,7 +1384,6 @@
         mAttachedToWindow = false;
         mImeAdapter.onViewDetachedFromWindow();
         mJoystickScrollProvider.onViewDetachedFromWindow();
-        mZoomControlsDelegate.dismissZoomPicker();
         removeDisplayAndroidObserver();
         GamepadList.onDetachedFromWindow();
         mAccessibilityManager.removeAccessibilityStateChangeListener(this);
@@ -1435,15 +1398,6 @@
     }
 
     /**
-     * @see View#onVisibilityChanged(android.view.View, int)
-     */
-    public void onVisibilityChanged(View changedView, int visibility) {
-        if (visibility != View.VISIBLE) {
-            mZoomControlsDelegate.dismissZoomPicker();
-        }
-    }
-
-    /**
      * @see View#onCreateInputConnection(EditorInfo)
      */
     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
@@ -1836,14 +1790,6 @@
         if (!mPopupZoomer.isShowing()) mPopupZoomer.setLastTouch(xPix, yPix);
     }
 
-    public void setZoomControlsDelegate(ZoomControlsDelegate zoomControlsDelegate) {
-        if (zoomControlsDelegate == null) {
-            mZoomControlsDelegate = NO_OP_ZOOM_CONTROLS_DELEGATE;
-            return;
-        }
-        mZoomControlsDelegate = zoomControlsDelegate;
-    }
-
     public void updateMultiTouchZoomSupport(boolean supportsMultiTouchZoom) {
         if (mNativeContentViewCore == 0) return;
         nativeSetMultiTouchZoomSupportEnabled(mNativeContentViewCore, supportsMultiTouchZoom);
@@ -1946,7 +1892,6 @@
                 .getContentOffsetYPixBottom()) != 0;
 
         final boolean needHidePopupZoomer = contentSizeChanged || scrollChanged;
-        final boolean needUpdateZoomControls = scaleLimitsChanged || scrollChanged;
 
         if (needHidePopupZoomer) mPopupZoomer.hide(true);
 
@@ -1974,7 +1919,13 @@
             }
         }
 
-        if (needUpdateZoomControls) mZoomControlsDelegate.updateZoomControls();
+        if (scaleLimitsChanged) {
+            for (mGestureStateListenersIterator.rewind();
+                    mGestureStateListenersIterator.hasNext();) {
+                mGestureStateListenersIterator.next().onScaleLimitsChanged(
+                        minPageScaleFactor, maxPageScaleFactor);
+            }
+        }
 
         if (topBarChanged) {
             float topBarTranslate = topBarShownPix - browserControlsHeightDp * deviceScale;
@@ -2333,13 +2284,6 @@
     }
 
     /**
-     * Invokes the graphical zoom picker widget for this ContentView.
-     */
-    public void invokeZoomPicker() {
-        mZoomControlsDelegate.invokeZoomPicker();
-    }
-
-    /**
      * Enables or disables inspection of JavaScript objects added via
      * {@link #addJavascriptInterface(Object, String)} by means of Object.keys() method and
      * &quot;for .. in&quot; loop. Being able to inspect JavaScript objects is useful
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/SelectPopupDropdown.java b/content/public/android/java/src/org/chromium/content/browser/input/SelectPopupDropdown.java
index b9437f0..9410271 100644
--- a/content/public/android/java/src/org/chromium/content/browser/input/SelectPopupDropdown.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/SelectPopupDropdown.java
@@ -44,7 +44,9 @@
             initialSelection = selected[0];
         }
         mDropdownPopupWindow.setInitialSelection(initialSelection);
-        mDropdownPopupWindow.setAdapter(new DropdownAdapter(mContext, items, null));
+        mDropdownPopupWindow.setAdapter(new DropdownAdapter(
+                mContext, items, null /* separators */, null /* backgroundColor */,
+                null /* dividerColor */, null /* dropdownItemHeight */));
         mDropdownPopupWindow.setRtl(rightAligned);
         mDropdownPopupWindow.setOnDismissListener(
                 new PopupWindow.OnDismissListener() {
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/GestureStateListener.java b/content/public/android/java/src/org/chromium/content_public/browser/GestureStateListener.java
index f3df2a8..2854b35 100644
--- a/content/public/android/java/src/org/chromium/content_public/browser/GestureStateListener.java
+++ b/content/public/android/java/src/org/chromium/content_public/browser/GestureStateListener.java
@@ -48,6 +48,11 @@
     public void onScrollEnded(int scrollOffsetY, int scrollExtentY) {}
 
     /*
+     * Called when the min or max scale factor may have been changed.
+     */
+    public void onScaleLimitsChanged(float minPageScaleFactor, float maxPageScaleFactor) {}
+
+    /*
      * Called when the scroll offsets or extents may have changed.
      */
     public void onScrollOffsetOrExtentChanged(int scrollOffsetY, int scrollExtentY) {}
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherTest.java
index d6a45d4..1f10e35 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherTest.java
@@ -250,16 +250,20 @@
         // Start and connect to a new service of an external APK.
         ChildProcessConnectionImpl externalApkConnection =
                 allocateConnection(EXTERNAL_APK_PACKAGE_NAME);
-        assertNotNull(externalApkConnection);
         // Start and connect to a new service for a regular tab.
         ChildProcessConnectionImpl tabConnection = allocateConnection(appContext.getPackageName());
-        assertNotNull(tabConnection);
 
         // Verify that one connection is allocated for an external APK and a regular tab
         // respectively.
         assertEquals(1, ChildProcessLauncher.allocatedSandboxedConnectionsCountForTesting(
                                 appContext, EXTERNAL_APK_PACKAGE_NAME));
         assertEquals(1, allocatedChromeSandboxedConnectionsCount());
+
+        // Verify that connections allocated for an external APK and the regular tab are from
+        // different ChildConnectionAllocators, since both ChildConnectionAllocators start
+        // allocating connections from number 0.
+        assertEquals(0, externalApkConnection.getServiceNumber());
+        assertEquals(0, tabConnection.getServiceNumber());
     }
 
     /**
diff --git a/content/public/app/BUILD.gn b/content/public/app/BUILD.gn
index 620f1706..d09712d 100644
--- a/content/public/app/BUILD.gn
+++ b/content/public/app/BUILD.gn
@@ -21,6 +21,7 @@
 #       //content/public/app:both_sources (source set)
 
 import("//build/config/chrome_build.gni")
+import("//build/config/ui.gni")
 import("//services/service_manager/public/service_manifest.gni")
 
 public_app_shared_sources = [
@@ -42,6 +43,10 @@
   "//content/public/utility:utility_sources",
 ]
 
+if (use_aura) {
+  public_app_shared_deps += [ "//ui/aura" ]
+}
+
 if (is_component_build) {
   source_set("both_sources") {
     # Only the main content shared library can pull this in.
diff --git a/content/public/app/content_main.h b/content/public/app/content_main.h
index 201fca7..0c718bf 100644
--- a/content/public/app/content_main.h
+++ b/content/public/app/content_main.h
@@ -15,6 +15,10 @@
 #include <windows.h>
 #endif
 
+#if defined(USE_AURA)
+#include "ui/aura/env.h"
+#endif
+
 namespace sandbox {
 struct SandboxInterfaceInfo;
 }
@@ -51,6 +55,10 @@
   // Used by browser_tests. If non-null BrowserMain schedules this task to run
   // on the MessageLoop. It's owned by the test code.
   base::Closure* ui_task;
+
+#if defined(USE_AURA)
+  aura::Env::Mode env_mode = aura::Env::Mode::LOCAL;
+#endif
 };
 
 #if defined(OS_ANDROID)
diff --git a/content/public/browser/render_widget_host.h b/content/public/browser/render_widget_host.h
index 7005ece92..0cda573d 100644
--- a/content/public/browser/render_widget_host.h
+++ b/content/public/browser/render_widget_host.h
@@ -243,13 +243,12 @@
   virtual void AddMouseEventCallback(const MouseEventCallback& callback) = 0;
   virtual void RemoveMouseEventCallback(const MouseEventCallback& callback) = 0;
 
-  // Observer for WebInputEvents.
+  // Observer for WebInputEvents (but not input event acks).
   class InputEventObserver {
    public:
     virtual ~InputEventObserver() {}
 
-    virtual void OnInputEvent(const blink::WebInputEvent&) {};
-    virtual void OnInputEventAck(const blink::WebInputEvent&) {};
+    virtual void OnInputEvent(const blink::WebInputEvent&) = 0;
   };
 
   // Add/remove an input event observer.
diff --git a/content/public/common/BUILD.gn b/content/public/common/BUILD.gn
index c0a8a030..dc256d5 100644
--- a/content/public/common/BUILD.gn
+++ b/content/public/common/BUILD.gn
@@ -5,6 +5,7 @@
 import("//build/buildflag_header.gni")
 import("//build/config/chromecast_build.gni")
 import("//build/config/features.gni")
+import("//build/config/ui.gni")
 import("//media/media_options.gni")
 import("//mojo/public/tools/bindings/mojom.gni")
 import("//ppapi/features/features.gni")
@@ -273,6 +274,10 @@
     "//ui/gfx/ipc/skia",
   ]
 
+  if (use_aura) {
+    deps += [ "//ui/aura" ]
+  }
+
   # //content/common needs to include public headers.
   allow_circular_includes_from = [
     "//content/common",
diff --git a/content/public/common/main_function_params.h b/content/public/common/main_function_params.h
index 913e9b26..dac29913 100644
--- a/content/public/common/main_function_params.h
+++ b/content/public/common/main_function_params.h
@@ -25,6 +25,10 @@
 }
 #endif
 
+#if defined(USE_AURA)
+#include "ui/aura/env.h"
+#endif
+
 namespace content {
 
 struct MainFunctionParams {
@@ -50,6 +54,10 @@
   bool zygote_child;
 #endif
 
+#if defined(USE_AURA)
+  aura::Env::Mode env_mode = aura::Env::Mode::LOCAL;
+#endif
+
   // Used by InProcessBrowserTest. If non-null BrowserMain schedules this
   // task to run on the MessageLoop and BrowserInit is not invoked.
   base::Closure* ui_task;
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc
index a39b5f8b..0bac669 100644
--- a/content/public/test/browser_test_utils.cc
+++ b/content/public/test/browser_test_utils.cc
@@ -1531,13 +1531,9 @@
   return false;
 }
 
-bool InputMsgWatcher::HasReceivedAck() const {
-  return ack_result_ != INPUT_EVENT_ACK_STATE_UNKNOWN;
-}
-
 uint32_t InputMsgWatcher::WaitForAck() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  if (HasReceivedAck())
+  if (ack_result_ != INPUT_EVENT_ACK_STATE_UNKNOWN)
     return ack_result_;
   base::RunLoop run_loop;
   base::AutoReset<base::Closure> reset_quit(&quit_, run_loop.QuitClosure());
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h
index 1d05389..e39416c 100644
--- a/content/public/test/browser_test_utils.h
+++ b/content/public/test/browser_test_utils.h
@@ -556,8 +556,6 @@
   InputMsgWatcher(RenderWidgetHost* render_widget_host,
                   blink::WebInputEvent::Type type);
 
-  bool HasReceivedAck() const;
-
   // Wait until ack message occurs, returning the ack result from
   // the message.
   uint32_t WaitForAck();
diff --git a/content/renderer/gamepad_shared_memory_reader.cc b/content/renderer/gamepad_shared_memory_reader.cc
index f1eb932..62dd301c 100644
--- a/content/renderer/gamepad_shared_memory_reader.cc
+++ b/content/renderer/gamepad_shared_memory_reader.cc
@@ -29,14 +29,7 @@
 
 void GamepadSharedMemoryReader::SendStartMessage() {
   if (gamepad_monitor_) {
-    mojo::ScopedSharedBufferHandle buffer_handle;
-    gamepad_monitor_->GamepadStartPolling(&buffer_handle);
-    // TODO(heke): Use mojo::SharedBuffer rather than base::SharedMemory. See
-    // crbug.com/670655.
-    MojoResult result = mojo::UnwrapSharedMemoryHandle(
-        std::move(buffer_handle), &renderer_shared_memory_handle_, nullptr,
-        nullptr);
-    CHECK_EQ(MOJO_RESULT_OK, result);
+    gamepad_monitor_->GamepadStartPolling(&renderer_shared_buffer_handle_);
   }
 }
 
@@ -52,16 +45,15 @@
 
   // If we don't get a valid handle from the browser, don't try to Map (we're
   // probably out of memory or file handles).
-  bool valid_handle = base::SharedMemory::IsHandleValid(
-      renderer_shared_memory_handle_);
+  bool valid_handle = renderer_shared_buffer_handle_.is_valid();
   UMA_HISTOGRAM_BOOLEAN("Gamepad.ValidSharedMemoryHandle", valid_handle);
   if (!valid_handle)
     return;
 
-  renderer_shared_memory_.reset(
-      new base::SharedMemory(renderer_shared_memory_handle_, true));
-  CHECK(renderer_shared_memory_->Map(sizeof(GamepadHardwareBuffer)));
-  void *memory = renderer_shared_memory_->memory();
+  renderer_shared_buffer_mapping_ =
+      renderer_shared_buffer_handle_->Map(sizeof(GamepadHardwareBuffer));
+  CHECK(renderer_shared_buffer_mapping_);
+  void* memory = renderer_shared_buffer_mapping_.get();
   CHECK(memory);
   gamepad_hardware_buffer_ =
       static_cast<GamepadHardwareBuffer*>(memory);
@@ -80,7 +72,7 @@
   blink::WebGamepads read_into;
   TRACE_EVENT0("GAMEPAD", "SampleGamepads");
 
-  if (!base::SharedMemory::IsHandleValid(renderer_shared_memory_handle_))
+  if (!renderer_shared_buffer_handle_.is_valid())
     return;
 
   // Only try to read this many times before failing to avoid waiting here
diff --git a/content/renderer/gamepad_shared_memory_reader.h b/content/renderer/gamepad_shared_memory_reader.h
index af4530f3..05369cb 100644
--- a/content/renderer/gamepad_shared_memory_reader.h
+++ b/content/renderer/gamepad_shared_memory_reader.h
@@ -8,12 +8,11 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "base/memory/shared_memory.h"
 #include "content/public/renderer/renderer_gamepad_provider.h"
 #include "device/base/synchronization/shared_memory_seqlock_buffer.h"
 #include "device/gamepad/public/interfaces/gamepad.mojom.h"
 #include "mojo/public/cpp/bindings/binding.h"
-#include "mojo/public/cpp/system/platform_handle.h"
+#include "mojo/public/cpp/system/buffer.h"
 #include "third_party/WebKit/public/platform/WebGamepads.h"
 
 namespace content {
@@ -42,8 +41,8 @@
   void GamepadDisconnected(int index,
                            const blink::WebGamepad& gamepad) override;
 
-  base::SharedMemoryHandle renderer_shared_memory_handle_;
-  std::unique_ptr<base::SharedMemory> renderer_shared_memory_;
+  mojo::ScopedSharedBufferHandle renderer_shared_buffer_handle_;
+  mojo::ScopedSharedBufferMapping renderer_shared_buffer_mapping_;
   GamepadHardwareBuffer* gamepad_hardware_buffer_;
 
   bool ever_interacted_with_;
diff --git a/content/renderer/history_serialization.cc b/content/renderer/history_serialization.cc
index 7adf199..c9a7b200 100644
--- a/content/renderer/history_serialization.cc
+++ b/content/renderer/history_serialization.cc
@@ -52,7 +52,7 @@
   state->document_sequence_number =
       item.documentSequenceNumber();
   state->page_scale_factor = item.pageScaleFactor();
-  ToNullableString16Vector(item.documentState(), &state->document_state);
+  ToNullableString16Vector(item.getDocumentState(), &state->document_state);
 
   state->http_body.http_content_type = item.httpContentType();
   const WebHTTPBody& http_body = item.httpBody();
diff --git a/content/renderer/mojo_context_state.cc b/content/renderer/mojo_context_state.cc
index 5bba47d3..1a7f1b26 100644
--- a/content/renderer/mojo_context_state.cc
+++ b/content/renderer/mojo_context_state.cc
@@ -66,6 +66,7 @@
     { mojo::kCodecModuleName, IDR_MOJO_CODEC_JS },
     { mojo::kConnectionModuleName, IDR_MOJO_CONNECTION_JS },
     { mojo::kConnectorModuleName, IDR_MOJO_CONNECTOR_JS },
+    { mojo::kInterfaceTypesModuleName, IDR_MOJO_INTERFACE_TYPES_JS },
     { mojo::kRouterModuleName, IDR_MOJO_ROUTER_JS },
     { mojo::kUnicodeModuleName, IDR_MOJO_UNICODE_JS },
     { mojo::kValidatorModuleName, IDR_MOJO_VALIDATOR_JS },
diff --git a/content/renderer/pepper/host_dispatcher_wrapper.cc b/content/renderer/pepper/host_dispatcher_wrapper.cc
index 75b58ef..29a523c 100644
--- a/content/renderer/pepper/host_dispatcher_wrapper.cc
+++ b/content/renderer/pepper/host_dispatcher_wrapper.cc
@@ -83,11 +83,8 @@
   if (host) {
     RenderFrame* render_frame = host->GetRenderFrameForInstance(instance);
     PepperPluginInstance* plugin_instance = host->GetPluginInstance(instance);
-    blink::WebString unused;
     bool is_privileged_context =
-        plugin_instance->GetContainer()
-            ->document()
-            .isSecureContext(unused) &&
+        plugin_instance->GetContainer()->document().isSecureContext() &&
         content::IsOriginSecure(plugin_instance->GetPluginURL());
     render_frame->Send(new FrameHostMsg_DidCreateOutOfProcessPepperInstance(
         plugin_child_id_, instance,
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 5007f28f..28b5013 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -4255,9 +4255,8 @@
   extra_data->set_download_to_network_cache_only(
       is_prefetch &&
       WebURLRequestToResourceType(request) != RESOURCE_TYPE_MAIN_FRAME);
-  WebString error;
   extra_data->set_initiated_in_secure_context(
-      frame->document().isSecureContext(error));
+      frame->document().isSecureContext());
 
   // Renderer process transfers apply only to navigational requests.
   bool is_navigational_request =
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index d3d457c..4012f0f 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -1811,20 +1811,20 @@
 namespace {
 
 static size_t GetMallocUsage() {
-  // Only checks the default process heap.
-  HANDLE heap = ::GetProcessHeap();
-  if (heap == NULL)
+  // Iterate through whichever heap the CRT is using.
+  HANDLE crt_heap = reinterpret_cast<HANDLE>(_get_heap_handle());
+  if (crt_heap == NULL)
     return 0;
-  if (!::HeapLock(heap))
+  if (!::HeapLock(crt_heap))
     return 0 ;
   size_t malloc_usage = 0;
   PROCESS_HEAP_ENTRY heap_entry;
   heap_entry.lpData = NULL;
-  while (::HeapWalk(heap, &heap_entry) != 0) {
+  while (::HeapWalk(crt_heap, &heap_entry) != 0) {
     if ((heap_entry.wFlags & PROCESS_HEAP_ENTRY_BUSY) != 0)
       malloc_usage += heap_entry.cbData;
   }
-  ::HeapUnlock(heap);
+  ::HeapUnlock(crt_heap);
   return malloc_usage;
 }
 
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index a086f7b..e47f7f6 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -1518,7 +1518,6 @@
     return;
   ImeEventGuard guard(this);
   blink::WebInputMethodController* controller = GetInputMethodController();
-  DCHECK(controller);
   if (!controller ||
       !controller->setComposition(
           text, WebVector<WebCompositionUnderline>(underlines), selection_start,
diff --git a/content/shell/android/browsertests_apk/AndroidManifest.xml.jinja2 b/content/shell/android/browsertests_apk/AndroidManifest.xml.jinja2
index f41aa9c..11e6b27 100644
--- a/content/shell/android/browsertests_apk/AndroidManifest.xml.jinja2
+++ b/content/shell/android/browsertests_apk/AndroidManifest.xml.jinja2
@@ -48,7 +48,7 @@
                  android:exported="false" />
         {% endfor %}
 
-        {% set num_privileged_services = 20 %}
+        {% set num_privileged_services = 3 %}
         <meta-data android:name="org.chromium.content.browser.NUM_PRIVILEGED_SERVICES"
                    android:value="{{ num_privileged_services }}"/>
         {% for i in range(num_privileged_services) %}
diff --git a/content/shell/android/linker_test_apk/AndroidManifest.xml.jinja2 b/content/shell/android/linker_test_apk/AndroidManifest.xml.jinja2
index 9f79475..d621791 100644
--- a/content/shell/android/linker_test_apk/AndroidManifest.xml.jinja2
+++ b/content/shell/android/linker_test_apk/AndroidManifest.xml.jinja2
@@ -47,7 +47,7 @@
                  android:exported="false" />
         {% endfor %}
 
-        {% set num_privileged_services = 20 %}
+        {% set num_privileged_services = 3 %}
         <meta-data android:name="org.chromium.content.browser.NUM_PRIVILEGED_SERVICES"
                    android:value="{{ num_privileged_services }}"/>
         {% for i in range(num_privileged_services) %}
diff --git a/content/shell/android/shell_apk/AndroidManifest.xml.jinja2 b/content/shell/android/shell_apk/AndroidManifest.xml.jinja2
index ecca6c27..f2e149f4 100644
--- a/content/shell/android/shell_apk/AndroidManifest.xml.jinja2
+++ b/content/shell/android/shell_apk/AndroidManifest.xml.jinja2
@@ -49,7 +49,7 @@
                  android:exported="false" />
         {% endfor %}
 
-        {% set num_privileged_services = 20 %}
+        {% set num_privileged_services = 3 %}
         <meta-data android:name="org.chromium.content.browser.NUM_PRIVILEGED_SERVICES"
                    android:value="{{ num_privileged_services }}"/>
         {% for i in range(num_privileged_services) %}
diff --git a/content/test/gpu/generate_buildbot_json.py b/content/test/gpu/generate_buildbot_json.py
index 1ae945b..e91fd7d 100755
--- a/content/test/gpu/generate_buildbot_json.py
+++ b/content/test/gpu/generate_buildbot_json.py
@@ -765,10 +765,12 @@
         # added.
         'build_configs': ['Release', 'Release_x64'],
         'swarming_dimension_sets': [
+          # NVIDIA Win 7
           {
             'gpu': '10de:104a',
             'os': 'Windows-2008ServerR2-SP1'
           },
+          # AMD Win 7
           {
             'gpu': '1002:6613',
             'os': 'Windows-2008ServerR2-SP1'
@@ -796,6 +798,7 @@
         # trybots) for the time being, at least until more capacity is added.
         'build_configs': ['Release', 'Release_x64'],
         'swarming_dimension_sets': [
+          # NVIDIA Linux
           {
             'gpu': '10de:104a',
             'os': 'Linux'
@@ -823,6 +826,7 @@
         # Run on Nexus 5X swarmed bots.
         'build_configs': ['android-chromium'],
         'swarming_dimension_sets': [
+          # Nexus 5X
           {
             'device_type': 'bullhead',
             'device_os': 'M',
@@ -846,16 +850,21 @@
     'tester_configs': [
       {
         'fyi_only': True,
-        # TODO(jmadill): Run this on the optional tryservers.
+        # TODO(jmadill): Run this on ANGLE roll tryservers.
         'run_on_optional': False,
-        # Run only on the Win7 Release NVIDIA 32-bit bots (and trybots) for the
-        # time being, at least until more capacity is added.
-        # TODO(jmadill): Run on the Win AMD R7 240 bots once they are swarmed.
+        # Run only on the NVIDIA and AMD Win7 bots (and trybots) for the time
+        # being, at least until more capacity is added.
         'build_configs': ['Release'],
         'swarming_dimension_sets': [
+          # NVIDIA Win 7
           {
             'gpu': '10de:104a',
             'os': 'Windows-2008ServerR2-SP1'
+          },
+          # AMD Win 7
+          {
+            'gpu': '1002:6613',
+            'os': 'Windows-2008ServerR2-SP1'
           }
         ],
       }
@@ -874,12 +883,13 @@
     'tester_configs': [
       {
         'fyi_only': True,
-        # TODO(jmadill): Run this on the optional tryservers.
+        # TODO(jmadill): Run this on ANGLE roll tryservers.
         'run_on_optional': False,
         # Run only on the Linux Release NVIDIA 32-bit bots (and trybots) for
         # the time being, at least until more capacity is added.
         'build_configs': ['Release'],
         'swarming_dimension_sets': [
+          # NVIDIA Linux
           {
             'gpu': '10de:104a',
             'os': 'Linux'
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
index 48874a3f..e57b499 100644
--- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -44,13 +44,6 @@
     self.Flaky('conformance2/query/occlusion-query.html', bug=603168)
     self.Fail('conformance2/glsl3/tricky-loop-conditions.html', bug=483282)
 
-    # This next one fails reliably on Linux AMD and is flaky everywhere
-    # else. Unfortunately, this means the expectation needs to be
-    # complicated to avoid collisions (and unit test failures).
-    self.Flaky('conformance2/misc/uninitialized-test-2.html',
-        ['win', 'mac', 'chromeos', 'android'], bug=671791)
-    self.Flaky('conformance2/misc/uninitialized-test-2.html',
-        ['linux', 'intel', 'nvidia'], bug=671791)
     self.Fail('conformance2/rendering/depth-stencil-feedback-loop.html',
         bug=660844) # WebGL 2.0.1
     self.Fail('conformance2/rendering/rendering-sampling-feedback-loop.html',
diff --git a/content/test/test_blink_web_unit_test_support.cc b/content/test/test_blink_web_unit_test_support.cc
index f4fcdbd..6708ae6d 100644
--- a/content/test/test_blink_web_unit_test_support.cc
+++ b/content/test/test_blink_web_unit_test_support.cc
@@ -52,7 +52,7 @@
 #if BUILDFLAG(ENABLE_WEBRTC)
 #include "content/renderer/media/rtc_certificate.h"
 #include "third_party/WebKit/public/platform/WebRTCCertificateGenerator.h"
-#include "third_party/webrtc/base/rtccertificate.h"
+#include "third_party/webrtc/base/rtccertificate.h"  // nogncheck
 #endif
 
 namespace {
diff --git a/extensions/browser/api/cast_channel/cast_channel_api.cc b/extensions/browser/api/cast_channel/cast_channel_api.cc
index dc4da0f0..b8fd3b2b 100644
--- a/extensions/browser/api/cast_channel/cast_channel_api.cc
+++ b/extensions/browser/api/cast_channel/cast_channel_api.cc
@@ -225,7 +225,7 @@
   channel_info.error_state = error;
   channel_info.connect_info.ip_address = "";
   channel_info.connect_info.port = 0;
-  channel_info.connect_info.auth = cast_channel::CHANNEL_AUTH_TYPE_SSL;
+  channel_info.connect_info.auth = cast_channel::CHANNEL_AUTH_TYPE_SSL_VERIFIED;
   SetResultFromChannelInfo(channel_info);
   SetError("Channel error = " + base::IntToString(error));
 }
diff --git a/extensions/browser/api/cast_channel/cast_channel_api_unittest.cc b/extensions/browser/api/cast_channel/cast_channel_api_unittest.cc
index 6cc9124..0797716e 100644
--- a/extensions/browser/api/cast_channel/cast_channel_api_unittest.cc
+++ b/extensions/browser/api/cast_channel/cast_channel_api_unittest.cc
@@ -22,7 +22,7 @@
   ConnectInfo connect_info;
   connect_info.ip_address = "192.0.0.1";
   connect_info.port = 8009;
-  connect_info.auth = CHANNEL_AUTH_TYPE_SSL;
+  connect_info.auth = CHANNEL_AUTH_TYPE_SSL_VERIFIED;
 
   ip_endpoint.reset(ccof::ParseConnectInfo(connect_info));
   EXPECT_TRUE(ip_endpoint);
diff --git a/extensions/browser/api/cast_channel/cast_channel_apitest.cc b/extensions/browser/api/cast_channel/cast_channel_apitest.cc
index fd972f7..565f616a 100644
--- a/extensions/browser/api/cast_channel/cast_channel_apitest.cc
+++ b/extensions/browser/api/cast_channel/cast_channel_apitest.cc
@@ -108,7 +108,7 @@
     ON_CALL(*mock_cast_socket_, ip_endpoint())
         .WillByDefault(ReturnRef(ip_endpoint_));
     ON_CALL(*mock_cast_socket_, channel_auth())
-        .WillByDefault(Return(cast_channel::CHANNEL_AUTH_TYPE_SSL));
+        .WillByDefault(Return(cast_channel::CHANNEL_AUTH_TYPE_SSL_VERIFIED));
     ON_CALL(*mock_cast_socket_, keep_alive()).WillByDefault(Return(false));
   }
 
@@ -388,16 +388,18 @@
   cast_channel_open_function = CreateOpenFunction(empty_extension);
   std::string error = utils::RunFunctionAndReturnError(
       cast_channel_open_function.get(),
-      "[{\"ipAddress\": \"invalid_ip\", \"port\": 8009, \"auth\": \"ssl\"}]",
+      "[{\"ipAddress\": \"invalid_ip\", \"port\": 8009, \"auth\": "
+      "\"ssl_verified\"}]",
       browser());
   EXPECT_EQ(error, "Invalid connect_info (invalid IP address)");
 
   // Invalid port
   cast_channel_open_function = CreateOpenFunction(empty_extension);
-  error = utils::RunFunctionAndReturnError(
-      cast_channel_open_function.get(),
-      "[{\"ipAddress\": \"127.0.0.1\", \"port\": -200, \"auth\": \"ssl\"}]",
-      browser());
+  error = utils::RunFunctionAndReturnError(cast_channel_open_function.get(),
+                                           "[{\"ipAddress\": \"127.0.0.1\", "
+                                           "\"port\": -200, \"auth\": "
+                                           "\"ssl_verified\"}]",
+                                           browser());
   EXPECT_EQ(error, "Invalid connect_info (invalid port)");
 }
 
@@ -415,7 +417,7 @@
       "\"audioOnly\": false, "
       "\"connectInfo\": "
       "{\"ipAddress\": \"127.0.0.1\", \"port\": 8009, "
-      "\"auth\": \"ssl\"}, \"readyState\": \"open\"}, "
+      "\"auth\": \"ssl_verified\"}, \"readyState\": \"open\"}, "
       "{\"namespace_\": \"foo\", \"sourceId\": \"src\", "
       "\"destinationId\": \"dest\", \"data\": 1235}]",
       browser()));
@@ -430,7 +432,7 @@
       "\"audioOnly\": false, "
       "\"connectInfo\": "
       "{\"ipAddress\": \"127.0.0.1\", \"port\": 8009, "
-      "\"auth\": \"ssl\"}, \"readyState\": \"open\"}, "
+      "\"auth\": \"ssl_verified\"}, \"readyState\": \"open\"}, "
       "{\"namespace_\": \"\", \"sourceId\": \"src\", "
       "\"destinationId\": \"dest\", \"data\": \"data\"}]",
       browser());
@@ -445,7 +447,7 @@
       "\"audioOnly\": false, "
       "\"connectInfo\": "
       "{\"ipAddress\": \"127.0.0.1\", \"port\": 8009, "
-      "\"auth\": \"ssl\"}, \"readyState\": \"open\"}, "
+      "\"auth\": \"ssl_verified\"}, \"readyState\": \"open\"}, "
       "{\"namespace_\": \"foo\", \"sourceId\": \"\", "
       "\"destinationId\": \"dest\", \"data\": \"data\"}]",
       browser());
@@ -460,7 +462,7 @@
       "\"audioOnly\": false, "
       "\"connectInfo\": "
       "{\"ipAddress\": \"127.0.0.1\", \"port\": 8009, "
-      "\"auth\": \"ssl\"}, \"readyState\": \"open\"}, "
+      "\"auth\": \"ssl_verified\"}, \"readyState\": \"open\"}, "
       "{\"namespace_\": \"foo\", \"sourceId\": \"src\", "
       "\"destinationId\": \"\", \"data\": \"data\"}]",
       browser());
diff --git a/extensions/browser/api/cast_channel/cast_socket.cc b/extensions/browser/api/cast_channel/cast_socket.cc
index 5cf9f29..3bb675c 100644
--- a/extensions/browser/api/cast_channel/cast_socket.cc
+++ b/extensions/browser/api/cast_channel/cast_socket.cc
@@ -132,8 +132,6 @@
       ready_state_(READY_STATE_NONE),
       auth_delegate_(nullptr) {
   DCHECK(net_log_);
-  DCHECK(channel_auth_ == CHANNEL_AUTH_TYPE_SSL ||
-         channel_auth_ == CHANNEL_AUTH_TYPE_SSL_VERIFIED);
   net_log_source_.type = net::NetLogSourceType::SOCKET;
   net_log_source_.id = net_log_->NextID();
 }
@@ -436,13 +434,7 @@
     }
     auth_delegate_ = new AuthTransportDelegate(this);
     transport_->SetReadDelegate(base::WrapUnique(auth_delegate_));
-    if (channel_auth_ == CHANNEL_AUTH_TYPE_SSL_VERIFIED) {
-      // Additionally verify the connection with a handshake.
-      SetConnectState(proto::CONN_STATE_AUTH_CHALLENGE_SEND);
-    } else {
-      SetConnectState(proto::CONN_STATE_FINISHED);
-      transport_->Start();
-    }
+    SetConnectState(proto::CONN_STATE_AUTH_CHALLENGE_SEND);
   } else if (result == net::ERR_CONNECTION_TIMED_OUT) {
     SetConnectState(proto::CONN_STATE_FINISHED);
     SetErrorState(CHANNEL_ERROR_CONNECT_TIMEOUT);
diff --git a/extensions/browser/api/cast_channel/cast_socket_unittest.cc b/extensions/browser/api/cast_channel/cast_socket_unittest.cc
index 2201bf9..48e60c8 100644
--- a/extensions/browser/api/cast_channel/cast_socket_unittest.cc
+++ b/extensions/browser/api/cast_channel/cast_socket_unittest.cc
@@ -28,6 +28,7 @@
 #include "extensions/browser/api/cast_channel/cast_transport.h"
 #include "extensions/browser/api/cast_channel/logger.h"
 #include "extensions/common/api/cast_channel/cast_channel.pb.h"
+#include "extensions/common/api/cast_channel/logging.pb.h"
 #include "net/base/address_list.h"
 #include "net/base/net_errors.h"
 #include "net/log/test_net_log.h"
@@ -173,14 +174,6 @@
 
 class TestCastSocket : public CastSocketImpl {
  public:
-  static std::unique_ptr<TestCastSocket> Create(
-      Logger* logger,
-      uint64_t device_capabilities = cast_channel::CastDeviceCapability::NONE) {
-    return std::unique_ptr<TestCastSocket>(
-        new TestCastSocket(CreateIPEndPointForTest(), CHANNEL_AUTH_TYPE_SSL,
-                           kDistantTimeoutMillis, logger, device_capabilities));
-  }
-
   static std::unique_ptr<TestCastSocket> CreateSecure(
       Logger* logger,
       uint64_t device_capabilities = cast_channel::CastDeviceCapability::NONE) {
@@ -372,8 +365,6 @@
     }
   }
 
-  void CreateCastSocket() { socket_ = TestCastSocket::Create(logger_); }
-
   void CreateCastSocketSecure() {
     socket_ = TestCastSocket::CreateSecure(logger_);
   }
@@ -412,68 +403,6 @@
   DISALLOW_COPY_AND_ASSIGN(CastSocketTest);
 };
 
-// Tests connecting and closing the socket.
-TEST_F(CastSocketTest, TestConnectAndClose) {
-  CreateCastSocket();
-  socket_->SetupMockTransport();
-  socket_->SetupTcpConnect(net::SYNCHRONOUS, net::OK);
-  socket_->SetupSslConnect(net::SYNCHRONOUS, net::OK);
-
-  EXPECT_CALL(handler_, OnConnectComplete(CHANNEL_ERROR_NONE));
-  socket_->Connect(std::move(delegate_),
-                   base::Bind(&CompleteHandler::OnConnectComplete,
-                              base::Unretained(&handler_)));
-  RunPendingTasks();
-
-  EXPECT_EQ(cast_channel::READY_STATE_OPEN, socket_->ready_state());
-  EXPECT_EQ(cast_channel::CHANNEL_ERROR_NONE, socket_->error_state());
-
-  EXPECT_CALL(handler_, OnCloseComplete(net::OK));
-  socket_->Close(base::Bind(&CompleteHandler::OnCloseComplete,
-                            base::Unretained(&handler_)));
-  EXPECT_EQ(cast_channel::READY_STATE_CLOSED, socket_->ready_state());
-  EXPECT_EQ(cast_channel::CHANNEL_ERROR_NONE, socket_->error_state());
-}
-
-// Tests that the following connection flow works:
-// - TCP connection succeeds (async)
-// - SSL connection succeeds (async)
-TEST_F(CastSocketTest, TestConnect) {
-  CreateCastSocket();
-  socket_->SetupTcpConnect(net::ASYNC, net::OK);
-  socket_->SetupSslConnect(net::ASYNC, net::OK);
-  socket_->AddReadResult(net::ASYNC, net::ERR_IO_PENDING);
-
-  EXPECT_CALL(handler_, OnConnectComplete(CHANNEL_ERROR_NONE));
-  socket_->Connect(std::move(delegate_),
-                   base::Bind(&CompleteHandler::OnConnectComplete,
-                              base::Unretained(&handler_)));
-  RunPendingTasks();
-
-  EXPECT_EQ(cast_channel::READY_STATE_OPEN, socket_->ready_state());
-  EXPECT_EQ(cast_channel::CHANNEL_ERROR_NONE, socket_->error_state());
-}
-
-// Tests that the following connection flow works:
-// - TCP connection fails (async)
-TEST_F(CastSocketTest, TestConnectFails) {
-  CreateCastSocket();
-  socket_->SetupTcpConnect(net::ASYNC, net::ERR_FAILED);
-
-  EXPECT_CALL(handler_, OnConnectComplete(CHANNEL_ERROR_CONNECT_ERROR));
-  socket_->Connect(std::move(delegate_),
-                   base::Bind(&CompleteHandler::OnConnectComplete,
-                              base::Unretained(&handler_)));
-  RunPendingTasks();
-
-  EXPECT_EQ(cast_channel::READY_STATE_CLOSED, socket_->ready_state());
-  EXPECT_EQ(cast_channel::CHANNEL_ERROR_CONNECT_ERROR, socket_->error_state());
-  EXPECT_EQ(proto::TCP_SOCKET_CONNECT_COMPLETE,
-            logger_->GetLastErrors(socket_->id()).event_type);
-  EXPECT_EQ(net::ERR_FAILED,
-            logger_->GetLastErrors(socket_->id()).net_return_value);
-}
-
 // Tests that the following connection flow works:
 // - TCP connection succeeds (async)
 // - SSL connection succeeds (async)
@@ -692,44 +621,6 @@
             socket_->error_state());
 }
 
-// Test connection error - cert extraction error (async)
-TEST_F(CastSocketTest, TestConnectCertExtractionErrorAsync) {
-  CreateCastSocket();
-  socket_->SetupTcpConnect(net::ASYNC, net::OK);
-  socket_->SetupSslConnect(net::ASYNC, net::OK);
-  // Set cert extraction to fail
-  socket_->SetExtractCertResult(false);
-
-  EXPECT_CALL(handler_, OnConnectComplete(CHANNEL_ERROR_AUTHENTICATION_ERROR));
-  socket_->Connect(std::move(delegate_),
-                   base::Bind(&CompleteHandler::OnConnectComplete,
-                              base::Unretained(&handler_)));
-  RunPendingTasks();
-
-  EXPECT_EQ(cast_channel::READY_STATE_CLOSED, socket_->ready_state());
-  EXPECT_EQ(cast_channel::CHANNEL_ERROR_AUTHENTICATION_ERROR,
-            socket_->error_state());
-}
-
-// Test connection error - cert extraction error (sync)
-TEST_F(CastSocketTest, TestConnectCertExtractionErrorSync) {
-  CreateCastSocket();
-  socket_->SetupTcpConnect(net::SYNCHRONOUS, net::OK);
-  socket_->SetupSslConnect(net::SYNCHRONOUS, net::OK);
-  // Set cert extraction to fail
-  socket_->SetExtractCertResult(false);
-
-  EXPECT_CALL(handler_, OnConnectComplete(CHANNEL_ERROR_AUTHENTICATION_ERROR));
-  socket_->Connect(std::move(delegate_),
-                   base::Bind(&CompleteHandler::OnConnectComplete,
-                              base::Unretained(&handler_)));
-  RunPendingTasks();
-
-  EXPECT_EQ(cast_channel::READY_STATE_CLOSED, socket_->ready_state());
-  EXPECT_EQ(cast_channel::CHANNEL_ERROR_AUTHENTICATION_ERROR,
-            socket_->error_state());
-}
-
 // Test connection error - challenge send fails
 TEST_F(CastSocketTest, TestConnectChallengeSendError) {
   CreateCastSocketSecure();
@@ -890,24 +781,6 @@
   EXPECT_EQ(cast_channel::CHANNEL_ERROR_NONE, socket_->error_state());
 }
 
-// Tests channel policy verification for device with no capabilities.
-TEST_F(CastSocketTest, TestChannelPolicyVerificationCapabilitiesNone) {
-  socket_ =
-      TestCastSocket::Create(logger_, cast_channel::CastDeviceCapability::NONE);
-  EXPECT_TRUE(socket_->TestVerifyChannelPolicyNone());
-  EXPECT_TRUE(socket_->TestVerifyChannelPolicyAudioOnly());
-}
-
-// Tests channel policy verification for device with video out capability.
-TEST_F(CastSocketTest, TestChannelPolicyVerificationCapabilitiesVideoOut) {
-  socket_ = TestCastSocket::Create(
-      logger_, cast_channel::CastDeviceCapability::VIDEO_OUT);
-  EXPECT_FALSE(socket_->audio_only());
-  EXPECT_TRUE(socket_->TestVerifyChannelPolicyNone());
-  EXPECT_FALSE(socket_->audio_only());
-  EXPECT_FALSE(socket_->TestVerifyChannelPolicyAudioOnly());
-  EXPECT_TRUE(socket_->audio_only());
-}
 }  // namespace cast_channel
 }  // namespace api
 }  // namespace extensions
diff --git a/extensions/browser/api/cast_channel/logger.cc b/extensions/browser/api/cast_channel/logger.cc
index eff4c8a..1a33008 100644
--- a/extensions/browser/api/cast_channel/logger.cc
+++ b/extensions/browser/api/cast_channel/logger.cc
@@ -157,10 +157,7 @@
   const net::IPAddress& ip = cast_socket.ip_endpoint().address();
   DCHECK(ip.IsValid());
   aggregated_socket_event.set_endpoint_id(ip.bytes().back());
-  aggregated_socket_event.set_channel_auth_type(cast_socket.channel_auth() ==
-                                                        CHANNEL_AUTH_TYPE_SSL
-                                                    ? proto::SSL
-                                                    : proto::SSL_VERIFIED);
+  aggregated_socket_event.set_channel_auth_type(proto::SSL_VERIFIED);
 }
 
 void Logger::LogSocketEvent(int channel_id, EventType event_type) {
diff --git a/extensions/common/api/cast_channel.idl b/extensions/common/api/cast_channel.idl
index 33af514fd..0d695b6 100644
--- a/extensions/common/api/cast_channel.idl
+++ b/extensions/common/api/cast_channel.idl
@@ -51,8 +51,6 @@
 
   // Authentication methods that may be required to connect to a Cast receiver.
   enum ChannelAuthType {
-    // SSL over TCP.
-    ssl,
     // SSL over TCP with challenge and receiver signature verification.
     ssl_verified
   };
diff --git a/extensions/renderer/dispatcher.cc b/extensions/renderer/dispatcher.cc
index 7e464779..0642390 100644
--- a/extensions/renderer/dispatcher.cc
+++ b/extensions/renderer/dispatcher.cc
@@ -747,6 +747,8 @@
       std::make_pair(mojo::kConnectionModuleName, IDR_MOJO_CONNECTION_JS));
   resources.push_back(
       std::make_pair(mojo::kConnectorModuleName, IDR_MOJO_CONNECTOR_JS));
+  resources.push_back(std::make_pair(mojo::kInterfaceTypesModuleName,
+                                     IDR_MOJO_INTERFACE_TYPES_JS));
   resources.push_back(
       std::make_pair(mojo::kRouterModuleName, IDR_MOJO_ROUTER_JS));
   resources.push_back(
diff --git a/extensions/renderer/request_sender.cc b/extensions/renderer/request_sender.cc
index 896008d..76ed369 100644
--- a/extensions/renderer/request_sender.cc
+++ b/extensions/renderer/request_sender.cc
@@ -102,7 +102,7 @@
   params.request_id = request_id;
   params.has_callback = has_callback;
   params.user_gesture =
-      blink::WebUserGestureIndicator::isProcessingUserGesture();
+      blink::WebUserGestureIndicator::isProcessingUserGestureThreadSafe();
 
   // Set Service Worker specific params to default values.
   params.worker_thread_id = -1;
diff --git a/extensions/renderer/resources/media_router_bindings.js b/extensions/renderer/resources/media_router_bindings.js
index 16c8643..40ebfab8 100644
--- a/extensions/renderer/resources/media_router_bindings.js
+++ b/extensions/renderer/resources/media_router_bindings.js
@@ -206,15 +206,6 @@
     this.mrpm_ = new MediaRouteProvider(this);
 
     /**
-     * The message pipe that connects the Media Router to mrpm_ across
-     * browser/renderer IPC boundaries. Object must remain in scope for the
-     * lifetime of the connection to prevent the connection from closing
-     * automatically.
-     * @type {!mojo.MessagePipe}
-     */
-    this.pipe_ = core.createMessagePipe();
-
-    /**
      * Handle to a KeepAlive service object, which prevents the extension from
      * being suspended as long as it remains in scope.
      * @type {boolean}
@@ -222,16 +213,13 @@
     this.keepAlive_ = null;
 
     /**
-     * The stub used to bind the service delegate to the Mojo interface.
+     * The bindings to bind the service delegate to the Mojo interface.
      * Object must remain in scope for the lifetime of the connection to
      * prevent the connection from closing automatically.
-     * @type {!mojom.MediaRouter}
+     * @type {!bindings.Binding}
      */
-    this.mediaRouteProviderStub_ = connector.bindHandleToStub(
-        this.pipe_.handle0, mediaRouterMojom.MediaRouteProvider);
-
-    // Link mediaRouteProviderStub_ to the provider manager delegate.
-    bindings.StubBindings(this.mediaRouteProviderStub_).delegate = this.mrpm_;
+    this.mediaRouteProviderBinding_ = new bindings.Binding(
+        mediaRouterMojom.MediaRouteProvider, this.mrpm_);
   }
 
   /**
@@ -239,10 +227,11 @@
    * @return {!Promise<string>} Instance ID for the Media Router.
    */
   MediaRouter.prototype.start = function() {
-    return this.service_.registerMediaRouteProvider(this.pipe_.handle1).then(
-        function(result) {
-          return result.instance_id;
-        }.bind(this));
+    return this.service_.registerMediaRouteProvider(
+        this.mediaRouteProviderBinding_.createInterfacePtrAndBind()).then(
+            function(result) {
+      return result.instance_id;
+    }.bind(this));
   }
 
   /**
@@ -716,14 +705,14 @@
   /**
    * Sends a binary message to the route designated by |routeId|.
    * @param {!string} routeId
-   * @param {!Uint8Array} data
+   * @param {!Array<number>} data
    * @return {!Promise.<boolean>} Resolved with true if the data was sent,
    *    or false on failure.
    */
   MediaRouteProvider.prototype.sendRouteBinaryMessage = function(
     routeId, data) {
     this.handlers_.onBeforeInvokeHandler();
-    return this.handlers_.sendRouteBinaryMessage(routeId, data)
+    return this.handlers_.sendRouteBinaryMessage(routeId, new Uint8Array(data))
         .then(function() {
           return {'sent': true};
         }, function() {
diff --git a/gpu/BUILD.gn b/gpu/BUILD.gn
index cca31195..844a14eb 100644
--- a/gpu/BUILD.gn
+++ b/gpu/BUILD.gn
@@ -402,7 +402,7 @@
   libfuzzer_options = [ "max_len=16384" ]
 }
 
-fuzzer_test("gpu_fuzzer_angle") {
+fuzzer_test("gpu_angle_fuzzer") {
   sources = [
     "command_buffer/tests/fuzzer_main.cc",
   ]
diff --git a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_stream_texture_matrix.txt b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_stream_texture_matrix.txt
index 1744f895..62626cf8 100644
--- a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_stream_texture_matrix.txt
+++ b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_stream_texture_matrix.txt
@@ -23,6 +23,8 @@
     of a stream texture.  Intended for use with Android SurfaceTexture, which
     doesn't provide the value until the front buffer is latched.
 
+    Also allows hints about whether an image could be promoted to an overlay.
+
 New Procedures and Functions
 
     The command
@@ -44,6 +46,29 @@
     <transform> Provides an additional transform matrix that is applied
       prior to the the stream texture transformation matrix.
 
+    The command
+
+       void OverlayPromotionHintCHROMIUM(
+               GLuint texture,
+               GLboolean promotion_hint,
+               GLint display_x,
+               GLint display_y)
+
+    Provides a hint about whether the GLImage bound to texture could be promoted
+    to an overlay or not.
+
+    <texture> is the texture id, which should have a stream texture image bound
+      to it.
+    <promotion_hint> indicates whether the GLImage could be promoted.
+    <display_x> is the x coordinate of the origin of the overlay if the image
+      could be promoted.  Otherwise, it is 0.
+    <display_y> is the y coordinate of the origin of the overlay if the image
+      could be promoted.  Otherwise, it is 0.
+
+
+    If <texture> is not a valid texture, or if it doesn't have a stream texture
+    image bound to it, then no action is taken.
+
 Errors
 
     None.
diff --git a/gpu/GLES2/gl2chromium_autogen.h b/gpu/GLES2/gl2chromium_autogen.h
index ad54560b..4a703a8 100644
--- a/gpu/GLES2/gl2chromium_autogen.h
+++ b/gpu/GLES2/gl2chromium_autogen.h
@@ -382,6 +382,8 @@
 #define glGetFragDataIndexEXT GLES2_GET_FUN(GetFragDataIndexEXT)
 #define glUniformMatrix4fvStreamTextureMatrixCHROMIUM \
   GLES2_GET_FUN(UniformMatrix4fvStreamTextureMatrixCHROMIUM)
+#define glOverlayPromotionHintCHROMIUM \
+  GLES2_GET_FUN(OverlayPromotionHintCHROMIUM)
 #define glSwapBuffersWithDamageCHROMIUM \
   GLES2_GET_FUN(SwapBuffersWithDamageCHROMIUM)
 
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index 2cb8a76..dab6327 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -3480,6 +3480,12 @@
     'result': ['uint32_t'],
     'trace_level': 1,
   },
+  'OverlayPromotionHintCHROMIUM': {
+    'decoder_func': 'DoOverlayPromotionHintCHROMIUM',
+    'extension': "CHROMIUM_uniform_stream_texture_matrix",
+    'unit_test': False,
+    'client_test': False,
+  },
   'PauseTransformFeedback': {
     'decoder_func': 'DoPauseTransformFeedback',
     'unit_test': False,
diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h
index 934fe97..ebf22172 100644
--- a/gpu/command_buffer/client/gles2_c_lib_autogen.h
+++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h
@@ -1709,6 +1709,13 @@
   gles2::GetGLContext()->UniformMatrix4fvStreamTextureMatrixCHROMIUM(
       location, transpose, transform);
 }
+void GL_APIENTRY GLES2OverlayPromotionHintCHROMIUM(GLuint texture,
+                                                   GLboolean promotion_hint,
+                                                   GLint display_x,
+                                                   GLint display_y) {
+  gles2::GetGLContext()->OverlayPromotionHintCHROMIUM(texture, promotion_hint,
+                                                      display_x, display_y);
+}
 void GL_APIENTRY GLES2SwapBuffersWithDamageCHROMIUM(GLint x,
                                                     GLint y,
                                                     GLint width,
@@ -3015,6 +3022,10 @@
             glUniformMatrix4fvStreamTextureMatrixCHROMIUM),
     },
     {
+        "glOverlayPromotionHintCHROMIUM",
+        reinterpret_cast<GLES2FunctionPointer>(glOverlayPromotionHintCHROMIUM),
+    },
+    {
         "glSwapBuffersWithDamageCHROMIUM",
         reinterpret_cast<GLES2FunctionPointer>(glSwapBuffersWithDamageCHROMIUM),
     },
diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
index 5cb4479..c893a28 100644
--- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
+++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
@@ -3166,6 +3166,17 @@
   }
 }
 
+void OverlayPromotionHintCHROMIUM(GLuint texture,
+                                  GLboolean promotion_hint,
+                                  GLint display_x,
+                                  GLint display_y) {
+  gles2::cmds::OverlayPromotionHintCHROMIUM* c =
+      GetCmdSpace<gles2::cmds::OverlayPromotionHintCHROMIUM>();
+  if (c) {
+    c->Init(texture, promotion_hint, display_x, display_y);
+  }
+}
+
 void SwapBuffersWithDamageCHROMIUM(GLint x,
                                    GLint y,
                                    GLint width,
diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h
index 0635ca1e..23efadd 100644
--- a/gpu/command_buffer/client/gles2_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_autogen.h
@@ -1199,6 +1199,11 @@
     GLboolean transpose,
     const GLfloat* transform) override;
 
+void OverlayPromotionHintCHROMIUM(GLuint texture,
+                                  GLboolean promotion_hint,
+                                  GLint display_x,
+                                  GLint display_y) override;
+
 void SwapBuffersWithDamageCHROMIUM(GLint x,
                                    GLint y,
                                    GLint width,
diff --git a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
index 7f55484..4dfde269 100644
--- a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
@@ -3488,4 +3488,18 @@
   CheckGLError();
 }
 
+void GLES2Implementation::OverlayPromotionHintCHROMIUM(GLuint texture,
+                                                       GLboolean promotion_hint,
+                                                       GLint display_x,
+                                                       GLint display_y) {
+  GPU_CLIENT_SINGLE_THREAD_CHECK();
+  GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glOverlayPromotionHintCHROMIUM("
+                     << texture << ", "
+                     << GLES2Util::GetStringBool(promotion_hint) << ", "
+                     << display_x << ", " << display_y << ")");
+  helper_->OverlayPromotionHintCHROMIUM(texture, promotion_hint, display_x,
+                                        display_y);
+  CheckGLError();
+}
+
 #endif  // GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_IMPL_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h
index 0055e6c..4f57e64 100644
--- a/gpu/command_buffer/client/gles2_interface_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_autogen.h
@@ -886,6 +886,10 @@
     GLint location,
     GLboolean transpose,
     const GLfloat* transform) = 0;
+virtual void OverlayPromotionHintCHROMIUM(GLuint texture,
+                                          GLboolean promotion_hint,
+                                          GLint display_x,
+                                          GLint display_y) = 0;
 virtual void SwapBuffersWithDamageCHROMIUM(GLint x,
                                            GLint y,
                                            GLint width,
diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
index 75af490..6851bf9 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
@@ -860,6 +860,10 @@
     GLint location,
     GLboolean transpose,
     const GLfloat* transform) override;
+void OverlayPromotionHintCHROMIUM(GLuint texture,
+                                  GLboolean promotion_hint,
+                                  GLint display_x,
+                                  GLint display_y) override;
 void SwapBuffersWithDamageCHROMIUM(GLint x,
                                    GLint y,
                                    GLint width,
diff --git a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
index ce62d915..bc012cd 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
@@ -1163,6 +1163,11 @@
     GLint /* location */,
     GLboolean /* transpose */,
     const GLfloat* /* transform */) {}
+void GLES2InterfaceStub::OverlayPromotionHintCHROMIUM(
+    GLuint /* texture */,
+    GLboolean /* promotion_hint */,
+    GLint /* display_x */,
+    GLint /* display_y */) {}
 void GLES2InterfaceStub::SwapBuffersWithDamageCHROMIUM(GLint /* x */,
                                                        GLint /* y */,
                                                        GLint /* width */,
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
index 9277de1..f69cddc 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
@@ -860,6 +860,10 @@
     GLint location,
     GLboolean transpose,
     const GLfloat* transform) override;
+void OverlayPromotionHintCHROMIUM(GLuint texture,
+                                  GLboolean promotion_hint,
+                                  GLint display_x,
+                                  GLint display_y) override;
 void SwapBuffersWithDamageCHROMIUM(GLint x,
                                    GLint y,
                                    GLint width,
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
index 2d08ece..abeb69d 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
@@ -2488,6 +2488,17 @@
                                                    transform);
 }
 
+void GLES2TraceImplementation::OverlayPromotionHintCHROMIUM(
+    GLuint texture,
+    GLboolean promotion_hint,
+    GLint display_x,
+    GLint display_y) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu",
+                                "GLES2Trace::OverlayPromotionHintCHROMIUM");
+  gl_->OverlayPromotionHintCHROMIUM(texture, promotion_hint, display_x,
+                                    display_y);
+}
+
 void GLES2TraceImplementation::SwapBuffersWithDamageCHROMIUM(GLint x,
                                                              GLint y,
                                                              GLint width,
diff --git a/gpu/command_buffer/cmd_buffer_functions.txt b/gpu/command_buffer/cmd_buffer_functions.txt
index 1f579fdb..9372810 100644
--- a/gpu/command_buffer/cmd_buffer_functions.txt
+++ b/gpu/command_buffer/cmd_buffer_functions.txt
@@ -361,5 +361,6 @@
 
 // Extension CHROMIUM_stream_texture_matrix
 GL_APICALL void         GL_APIENTRY glUniformMatrix4fvStreamTextureMatrixCHROMIUM (GLintUniformLocation location, GLbooleanFalseOnly transpose, const GLfloat* transform);
+GL_APICALL void         GL_APIENTRY glOverlayPromotionHintCHROMIUM (GLidBindTexture texture, GLboolean promotion_hint, GLint display_x, GLint display_y);
 
 GL_APICALL void         GL_APIENTRY glSwapBuffersWithDamageCHROMIUM (GLint x, GLint y, GLint width, GLint height);
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
index ff02094..8383d51 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
@@ -15553,6 +15553,60 @@
               "offset of UniformMatrix4fvStreamTextureMatrixCHROMIUMImmediate "
               "transpose should be 8");
 
+struct OverlayPromotionHintCHROMIUM {
+  typedef OverlayPromotionHintCHROMIUM ValueType;
+  static const CommandId kCmdId = kOverlayPromotionHintCHROMIUM;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+  static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
+
+  static uint32_t ComputeSize() {
+    return static_cast<uint32_t>(sizeof(ValueType));  // NOLINT
+  }
+
+  void SetHeader() { header.SetCmd<ValueType>(); }
+
+  void Init(GLuint _texture,
+            GLboolean _promotion_hint,
+            GLint _display_x,
+            GLint _display_y) {
+    SetHeader();
+    texture = _texture;
+    promotion_hint = _promotion_hint;
+    display_x = _display_x;
+    display_y = _display_y;
+  }
+
+  void* Set(void* cmd,
+            GLuint _texture,
+            GLboolean _promotion_hint,
+            GLint _display_x,
+            GLint _display_y) {
+    static_cast<ValueType*>(cmd)->Init(_texture, _promotion_hint, _display_x,
+                                       _display_y);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  gpu::CommandHeader header;
+  uint32_t texture;
+  uint32_t promotion_hint;
+  int32_t display_x;
+  int32_t display_y;
+};
+
+static_assert(sizeof(OverlayPromotionHintCHROMIUM) == 20,
+              "size of OverlayPromotionHintCHROMIUM should be 20");
+static_assert(offsetof(OverlayPromotionHintCHROMIUM, header) == 0,
+              "offset of OverlayPromotionHintCHROMIUM header should be 0");
+static_assert(offsetof(OverlayPromotionHintCHROMIUM, texture) == 4,
+              "offset of OverlayPromotionHintCHROMIUM texture should be 4");
+static_assert(
+    offsetof(OverlayPromotionHintCHROMIUM, promotion_hint) == 8,
+    "offset of OverlayPromotionHintCHROMIUM promotion_hint should be 8");
+static_assert(offsetof(OverlayPromotionHintCHROMIUM, display_x) == 12,
+              "offset of OverlayPromotionHintCHROMIUM display_x should be 12");
+static_assert(offsetof(OverlayPromotionHintCHROMIUM, display_y) == 16,
+              "offset of OverlayPromotionHintCHROMIUM display_y should be 16");
+
 struct SwapBuffersWithDamageCHROMIUM {
   typedef SwapBuffersWithDamageCHROMIUM ValueType;
   static const CommandId kCmdId = kSwapBuffersWithDamageCHROMIUM;
diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
index 68f1dce..a44c706 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -5214,6 +5214,22 @@
       next_cmd, sizeof(cmd) + RoundSizeToMultipleOfEntries(sizeof(data)));
 }
 
+TEST_F(GLES2FormatTest, OverlayPromotionHintCHROMIUM) {
+  cmds::OverlayPromotionHintCHROMIUM& cmd =
+      *GetBufferAs<cmds::OverlayPromotionHintCHROMIUM>();
+  void* next_cmd =
+      cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<GLboolean>(12),
+              static_cast<GLint>(13), static_cast<GLint>(14));
+  EXPECT_EQ(static_cast<uint32_t>(cmds::OverlayPromotionHintCHROMIUM::kCmdId),
+            cmd.header.command);
+  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+  EXPECT_EQ(static_cast<GLuint>(11), cmd.texture);
+  EXPECT_EQ(static_cast<GLboolean>(12), cmd.promotion_hint);
+  EXPECT_EQ(static_cast<GLint>(13), cmd.display_x);
+  EXPECT_EQ(static_cast<GLint>(14), cmd.display_y);
+  CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
 TEST_F(GLES2FormatTest, SwapBuffersWithDamageCHROMIUM) {
   cmds::SwapBuffersWithDamageCHROMIUM& cmd =
       *GetBufferAs<cmds::SwapBuffersWithDamageCHROMIUM>();
diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
index a69e5e9..3c92dc4 100644
--- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
@@ -328,7 +328,8 @@
   OP(BindFragDataLocationEXTBucket)                        /* 569 */ \
   OP(GetFragDataIndexEXT)                                  /* 570 */ \
   OP(UniformMatrix4fvStreamTextureMatrixCHROMIUMImmediate) /* 571 */ \
-  OP(SwapBuffersWithDamageCHROMIUM)                        /* 572 */
+  OP(OverlayPromotionHintCHROMIUM)                         /* 572 */ \
+  OP(SwapBuffersWithDamageCHROMIUM)                        /* 573 */
 
 enum CommandId {
   kOneBeforeStartPoint =
diff --git a/gpu/command_buffer/service/gl_stream_texture_image.h b/gpu/command_buffer/service/gl_stream_texture_image.h
index daaa158e..5ab4f75 100644
--- a/gpu/command_buffer/service/gl_stream_texture_image.h
+++ b/gpu/command_buffer/service/gl_stream_texture_image.h
@@ -25,6 +25,10 @@
 
   void Flush() override {}
 
+  virtual void NotifyPromotionHint(bool promotion_hint,
+                                   int display_x,
+                                   int display_y) {}
+
  protected:
   ~GLStreamTextureImage() override {}
 
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 1746557..ba6b5ef 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -1672,6 +1672,12 @@
   // Wrapper for glLinkProgram
   void DoLinkProgram(GLuint program);
 
+  // Wrapper for glOverlayPromotionHintCHROMIUIM
+  void DoOverlayPromotionHintCHROMIUM(GLuint client_id,
+                                      GLboolean promotion_hint,
+                                      GLint display_x,
+                                      GLint display_y);
+
   // Wrapper for glReadBuffer
   void DoReadBuffer(GLenum src);
 
@@ -8556,6 +8562,31 @@
   ExitCommandProcessingEarly();
 }
 
+void GLES2DecoderImpl::DoOverlayPromotionHintCHROMIUM(GLuint client_id,
+                                                      GLboolean promotion_hint,
+                                                      GLint display_x,
+                                                      GLint display_y) {
+  if (client_id == 0)
+    return;
+
+  TextureRef* texture_ref = GetTexture(client_id);
+  if (!texture_ref) {
+    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glOverlayPromotionHintCHROMIUM",
+                       "invalid texture id");
+    return;
+  }
+  GLStreamTextureImage* image =
+      texture_ref->texture()->GetLevelStreamTextureImage(
+          GL_TEXTURE_EXTERNAL_OES, 0);
+  if (!image) {
+    LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glOverlayPromotionHintCHROMIUM",
+                       "texture has no StreamTextureImage");
+    return;
+  }
+
+  image->NotifyPromotionHint(promotion_hint != GL_FALSE, display_x, display_y);
+}
+
 void GLES2DecoderImpl::DoReadBuffer(GLenum src) {
   Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
   if (framebuffer) {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
index 1f961d1..2d8c7a4 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
@@ -5107,6 +5107,20 @@
   return error::kNoError;
 }
 
+error::Error GLES2DecoderImpl::HandleOverlayPromotionHintCHROMIUM(
+    uint32_t immediate_data_size,
+    const volatile void* cmd_data) {
+  const volatile gles2::cmds::OverlayPromotionHintCHROMIUM& c =
+      *static_cast<const volatile gles2::cmds::OverlayPromotionHintCHROMIUM*>(
+          cmd_data);
+  GLuint texture = c.texture;
+  GLboolean promotion_hint = static_cast<GLboolean>(c.promotion_hint);
+  GLint display_x = static_cast<GLint>(c.display_x);
+  GLint display_y = static_cast<GLint>(c.display_y);
+  DoOverlayPromotionHintCHROMIUM(texture, promotion_hint, display_x, display_y);
+  return error::kNoError;
+}
+
 bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
   switch (cap) {
     case GL_BLEND:
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h
index e362fde..13cc98e 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h
@@ -945,3 +945,8 @@
     GLint location,
     GLboolean transpose,
     const volatile GLfloat* defaultValue);
+
+error::Error DoOverlayPromotionHintCHROMIUM(GLuint texture,
+                                            GLboolean promotion_hint,
+                                            GLint display_x,
+                                            GLint display_y);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc
index 554200f..5686838 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc
@@ -3309,5 +3309,14 @@
   return error::kNoError;
 }
 
+error::Error GLES2DecoderPassthroughImpl::DoOverlayPromotionHintCHROMIUM(
+    GLuint texture,
+    GLboolean promotion_hint,
+    GLint display_x,
+    GLint display_y) {
+  NOTIMPLEMENTED();
+  return error::kNoError;
+}
+
 }  // namespace gles2
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc
index 6f3935fa..811f0a13 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc
@@ -4130,5 +4130,23 @@
   return error::kNoError;
 }
 
+error::Error GLES2DecoderPassthroughImpl::HandleOverlayPromotionHintCHROMIUM(
+    uint32_t immediate_data_size,
+    const volatile void* cmd_data) {
+  const volatile gles2::cmds::OverlayPromotionHintCHROMIUM& c =
+      *static_cast<const volatile gles2::cmds::OverlayPromotionHintCHROMIUM*>(
+          cmd_data);
+  GLuint texture = c.texture;
+  GLboolean promotion_hint = static_cast<GLboolean>(c.promotion_hint);
+  GLint display_x = static_cast<GLint>(c.display_x);
+  GLint display_y = static_cast<GLint>(c.display_y);
+  error::Error error = DoOverlayPromotionHintCHROMIUM(texture, promotion_hint,
+                                                      display_x, display_y);
+  if (error != error::kNoError) {
+    return error;
+  }
+  return error::kNoError;
+}
+
 }  // namespace gles2
 }  // namespace gpu
diff --git a/ios/chrome/app/application_delegate/memory_warning_helper.h b/ios/chrome/app/application_delegate/memory_warning_helper.h
index 1d720d3f..28a3c07 100644
--- a/ios/chrome/app/application_delegate/memory_warning_helper.h
+++ b/ios/chrome/app/application_delegate/memory_warning_helper.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_CHROME_APP_APPLICATION_DELEGATE_MEMORY_RECOVERY_HELPER_H_
-#define IOS_CHROME_APP_APPLICATION_DELEGATE_MEMORY_RECOVERY_HELPER_H_
+#ifndef IOS_CHROME_APP_APPLICATION_DELEGATE_MEMORY_WARNING_HELPER_H_
+#define IOS_CHROME_APP_APPLICATION_DELEGATE_MEMORY_WARNING_HELPER_H_
 
 #import <Foundation/Foundation.h>
 
@@ -24,4 +24,4 @@
 
 @end
 
-#endif  // IOS_CHROME_APP_APPLICATION_DELEGATE_MEMORY_RECOVERY_HELPER_H_
+#endif  // IOS_CHROME_APP_APPLICATION_DELEGATE_MEMORY_WARNING_HELPER_H_
diff --git a/ios/chrome/browser/BUILD.gn b/ios/chrome/browser/BUILD.gn
index e5b8f4fa..5a7d3de 100644
--- a/ios/chrome/browser/BUILD.gn
+++ b/ios/chrome/browser/BUILD.gn
@@ -5,6 +5,7 @@
 import("//build/buildflag_header.gni")
 import("//build/config/features.gni")
 import("//build/config/ios/rules.gni")
+import("//rlz/features/features.gni")
 import("//third_party/protobuf/proto_library.gni")
 
 declare_args() {
@@ -121,6 +122,7 @@
     "//ios/web",
     "//ios/web:user_agent",
     "//net",
+    "//rlz/features",
     "//url",
   ]
   allow_circular_includes_from = [
@@ -182,6 +184,7 @@
     "//ios/web",
     "//ios/web/public/app",
     "//net",
+    "//rlz/features",
     "//ui/base",
   ]
 
diff --git a/ios/chrome/browser/DEPS b/ios/chrome/browser/DEPS
index 6b5b985..49d7087 100644
--- a/ios/chrome/browser/DEPS
+++ b/ios/chrome/browser/DEPS
@@ -94,6 +94,7 @@
   "+ios/public/provider/web",
   "+ios/web/public",
   "+net",
+  "+rlz/features",
   "+third_party/brotli",
   "+third_party/google_toolbox_for_mac",
   "+ui",
diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_impl.h b/ios/chrome/browser/browser_state/chrome_browser_state_impl.h
index 54d5292..b1a99a1 100644
--- a/ios/chrome/browser/browser_state/chrome_browser_state_impl.h
+++ b/ios/chrome/browser/browser_state/chrome_browser_state_impl.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_CHROME_BROWSER_BROWSER_STATE_CHROME_BROWSER_STATE_IMPL_
-#define IOS_CHROME_BROWSER_BROWSER_STATE_CHROME_BROWSER_STATE_IMPL_
+#ifndef IOS_CHROME_BROWSER_BROWSER_STATE_CHROME_BROWSER_STATE_IMPL_H_
+#define IOS_CHROME_BROWSER_BROWSER_STATE_CHROME_BROWSER_STATE_IMPL_H_
 
 #include <memory>
 
@@ -105,4 +105,4 @@
   DISALLOW_COPY_AND_ASSIGN(ChromeBrowserStateImpl);
 };
 
-#endif  // IOS_CHROME_BROWSER_BROWSER_STATE_CHROME_BROWSER_STATE_IMPL_
+#endif  // IOS_CHROME_BROWSER_BROWSER_STATE_CHROME_BROWSER_STATE_IMPL_H_
diff --git a/ios/chrome/browser/browser_state_metrics/browser_state_metrics.h b/ios/chrome/browser/browser_state_metrics/browser_state_metrics.h
index dc3e048..397c93c 100644
--- a/ios/chrome/browser/browser_state_metrics/browser_state_metrics.h
+++ b/ios/chrome/browser/browser_state_metrics/browser_state_metrics.h
@@ -21,4 +21,4 @@
 
 void LogNumberOfBrowserStates(ios::ChromeBrowserStateManager* manager);
 
-#endif  // IOS_CHROME_BROWSER_BROWSER_STATE_BROWSER_STATE_METRICS_H_
+#endif  // IOS_CHROME_BROWSER_BROWSER_STATE_METRICS_BROWSER_STATE_METRICS_H_
diff --git a/ios/chrome/browser/browsing_data/browsing_data_counter_wrapper.h b/ios/chrome/browser/browsing_data/browsing_data_counter_wrapper.h
index 3428994..14f354c 100644
--- a/ios/chrome/browser/browsing_data/browsing_data_counter_wrapper.h
+++ b/ios/chrome/browser/browsing_data/browsing_data_counter_wrapper.h
@@ -57,4 +57,4 @@
   DISALLOW_COPY_AND_ASSIGN(BrowsingDataCounterWrapper);
 };
 
-#endif  // IOS_CHROME_BROWSER_BROWSING_DATA_BROWSING_DATA_COUNTER_WRAPPER_
+#endif  // IOS_CHROME_BROWSER_BROWSING_DATA_BROWSING_DATA_COUNTER_WRAPPER_H_
diff --git a/ios/chrome/browser/geolocation/CLLocation+OmniboxGeolocation.h b/ios/chrome/browser/geolocation/CLLocation+OmniboxGeolocation.h
index a535714..730b2f8 100644
--- a/ios/chrome/browser/geolocation/CLLocation+OmniboxGeolocation.h
+++ b/ios/chrome/browser/geolocation/CLLocation+OmniboxGeolocation.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_CHROME_BROWSER_GEOLOCATION_CLLOCATION_OMNIBOX_GEOLOCATION_H_
-#define IOS_CHROME_BROWSER_GEOLOCATION_CLLOCATION_OMNIBOX_GEOLOCATION_H_
+#ifndef IOS_CHROME_BROWSER_GEOLOCATION_CLLOCATION_OMNIBOXGEOLOCATION_H_
+#define IOS_CHROME_BROWSER_GEOLOCATION_CLLOCATION_OMNIBOXGEOLOCATION_H_
 
 #import <CoreLocation/CoreLocation.h>
 
@@ -24,4 +24,4 @@
 
 @end
 
-#endif  // IOS_CHROME_BROWSER_GEOLOCATION_CLLOCATION_OMNIBOX_GEOLOCATION_H_
+#endif  // IOS_CHROME_BROWSER_GEOLOCATION_CLLOCATION_OMNIBOXGEOLOCATION_H_
diff --git a/ios/chrome/browser/infobars/confirm_infobar_controller+protected.h b/ios/chrome/browser/infobars/confirm_infobar_controller+protected.h
index 6bf3b7f..04611cc 100644
--- a/ios/chrome/browser/infobars/confirm_infobar_controller+protected.h
+++ b/ios/chrome/browser/infobars/confirm_infobar_controller+protected.h
@@ -16,4 +16,4 @@
 - (void)updateInfobarLabel:(UIView<InfoBarViewProtocol>*)view;
 @end
 
-#endif  // IOS_CHROME_BROWSER_INFOBARS_CONFIRM_INFOBAR_CONTROLLER+PROTECTED_H_
+#endif  // IOS_CHROME_BROWSER_INFOBARS_CONFIRM_INFOBAR_CONTROLLER_PROTECTED_H_
diff --git a/ios/chrome/browser/ios_chrome_main_parts.mm b/ios/chrome/browser/ios_chrome_main_parts.mm
index 722cad2b..0b1e819 100644
--- a/ios/chrome/browser/ios_chrome_main_parts.mm
+++ b/ios/chrome/browser/ios_chrome_main_parts.mm
@@ -52,10 +52,11 @@
 #include "net/http/http_network_layer.h"
 #include "net/http/http_stream_factory.h"
 #include "net/url_request/url_request.h"
+#include "rlz/features/features.h"
 #include "ui/base/l10n/l10n_util_mac.h"
 #include "ui/base/resource/resource_bundle.h"
 
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
 #include "components/rlz/rlz_tracker.h"                        // nogncheck
 #include "ios/chrome/browser/rlz/rlz_tracker_delegate_impl.h"  // nogncheck
 #endif
@@ -172,7 +173,7 @@
   ios::ChromeBrowserState* last_used_browser_state =
       browser_state_manager->GetLastUsedBrowserState();
 
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
   // Init the RLZ library. This just schedules a task on the file thread to be
   // run sometime later. If this is the first run we record the installation
   // event.
@@ -187,7 +188,7 @@
       RLZTrackerDelegateImpl::IsGoogleDefaultSearch(last_used_browser_state),
       RLZTrackerDelegateImpl::IsGoogleHomepage(last_used_browser_state),
       RLZTrackerDelegateImpl::IsGoogleInStartpages(last_used_browser_state));
-#endif  // defined(ENABLE_RLZ)
+#endif  // BUILDFLAG(ENABLE_RLZ)
 
   TranslateServiceIOS::Initialize();
   language_usage_metrics::LanguageUsageMetrics::RecordAcceptLanguages(
diff --git a/ios/chrome/browser/metrics/ios_chrome_stability_metrics_provider.h b/ios/chrome/browser/metrics/ios_chrome_stability_metrics_provider.h
index 23c3969c..6f426cc 100644
--- a/ios/chrome/browser/metrics/ios_chrome_stability_metrics_provider.h
+++ b/ios/chrome/browser/metrics/ios_chrome_stability_metrics_provider.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_CHROME_BROWSER_METRICS_CHROME_STABILITY_METRICS_PROVIDER_H_
-#define IOS_CHROME_BROWSER_METRICS_CHROME_STABILITY_METRICS_PROVIDER_H_
+#ifndef IOS_CHROME_BROWSER_METRICS_IOS_CHROME_STABILITY_METRICS_PROVIDER_H_
+#define IOS_CHROME_BROWSER_METRICS_IOS_CHROME_STABILITY_METRICS_PROVIDER_H_
 
 #include "base/macros.h"
 #include "base/metrics/user_metrics.h"
@@ -43,4 +43,4 @@
   DISALLOW_COPY_AND_ASSIGN(IOSChromeStabilityMetricsProvider);
 };
 
-#endif  // IOS_CHROME_BROWSER_METRICS_CHROME_STABILITY_METRICS_PROVIDER_H_
+#endif  // IOS_CHROME_BROWSER_METRICS_IOS_CHROME_STABILITY_METRICS_PROVIDER_H_
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_manager_setting_migrator_service_factory.h b/ios/chrome/browser/passwords/ios_chrome_password_manager_setting_migrator_service_factory.h
index d8f1f66..8b1a9d4 100644
--- a/ios/chrome/browser/passwords/ios_chrome_password_manager_setting_migrator_service_factory.h
+++ b/ios/chrome/browser/passwords/ios_chrome_password_manager_setting_migrator_service_factory.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_CHROME_BROWSER_PASSWORDS_IOS_PASSWORD_MANAGER_SETTING_MIGRATOR_SERVICE_FACTORY_H_
-#define IOS_CHROME_BROWSER_PASSWORDS_IOS_PASSWORD_MANAGER_SETTING_MIGRATOR_SERVICE_FACTORY_H_
+#ifndef IOS_CHROME_BROWSER_PASSWORDS_IOS_CHROME_PASSWORD_MANAGER_SETTING_MIGRATOR_SERVICE_FACTORY_H_
+#define IOS_CHROME_BROWSER_PASSWORDS_IOS_CHROME_PASSWORD_MANAGER_SETTING_MIGRATOR_SERVICE_FACTORY_H_
 
 #include <memory>
 
@@ -47,4 +47,4 @@
       web::BrowserState* context) const override;
 };
 
-#endif  // IOS_CHROME_BROWSER_PASSWORDS_IOS_PASSWORD_MANAGER_SETTING_MIGRATOR_SERVICE_FACTORY_H_
+#endif  // IOS_CHROME_BROWSER_PASSWORDS_IOS_CHROME_PASSWORD_MANAGER_SETTING_MIGRATOR_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/physical_web/BUILD.gn b/ios/chrome/browser/physical_web/BUILD.gn
index 6a9caf1..5dd0611 100644
--- a/ios/chrome/browser/physical_web/BUILD.gn
+++ b/ios/chrome/browser/physical_web/BUILD.gn
@@ -20,6 +20,7 @@
     "//components/pref_registry",
     "//components/prefs",
     "//ios/chrome/browser",
+    "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/geolocation",
     "//ios/chrome/common/physical_web",
     "//url",
diff --git a/ios/chrome/browser/physical_web/ios_chrome_physical_web_data_source.h b/ios/chrome/browser/physical_web/ios_chrome_physical_web_data_source.h
index 76385430..40d0ebb 100644
--- a/ios/chrome/browser/physical_web/ios_chrome_physical_web_data_source.h
+++ b/ios/chrome/browser/physical_web/ios_chrome_physical_web_data_source.h
@@ -44,4 +44,4 @@
   DISALLOW_COPY_AND_ASSIGN(IOSChromePhysicalWebDataSource);
 };
 
-#endif  // IOS_CHROME_COMMON_PHYSICAL_WEB_IOS_CHROME_PHYSICAL_WEB_DATA_SOURCE_H_
+#endif  // IOS_CHROME_BROWSER_PHYSICAL_WEB_IOS_CHROME_PHYSICAL_WEB_DATA_SOURCE_H_
diff --git a/ios/chrome/browser/physical_web/start_physical_web_discovery.h b/ios/chrome/browser/physical_web/start_physical_web_discovery.h
index d6468b3..43901d1 100644
--- a/ios/chrome/browser/physical_web/start_physical_web_discovery.h
+++ b/ios/chrome/browser/physical_web/start_physical_web_discovery.h
@@ -7,8 +7,20 @@
 
 #include "components/prefs/pref_service.h"
 
+namespace ios {
+class ChromeBrowserState;
+}
+
 // Checks the environment and starts Physical Web discovery if the required
 // conditions are met.
+// Deprecated, use the version below that takes an ios::ChromeBrowserState.
+// TODO(mattreynolds): remove once downstream users have been switched to the
+// new method.
 void StartPhysicalWebDiscovery(PrefService* pref_service, bool is_incognito);
 
+// Checks the environment and starts Physical Web discovery if the required
+// conditions are met.
+void StartPhysicalWebDiscovery(PrefService* pref_service,
+                               ios::ChromeBrowserState* browser_state);
+
 #endif  // IOS_CHROME_BROWSER_PHYSICAL_WEB_START_PHYSICAL_WEB_DISCOVERY_H_
diff --git a/ios/chrome/browser/physical_web/start_physical_web_discovery.mm b/ios/chrome/browser/physical_web/start_physical_web_discovery.mm
index d6f37f0c..e1b9502 100644
--- a/ios/chrome/browser/physical_web/start_physical_web_discovery.mm
+++ b/ios/chrome/browser/physical_web/start_physical_web_discovery.mm
@@ -8,6 +8,7 @@
 
 #include "components/physical_web/data_source/physical_web_data_source.h"
 #include "ios/chrome/browser/application_context.h"
+#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #import "ios/chrome/browser/experimental_flags.h"
 #import "ios/chrome/browser/geolocation/omnibox_geolocation_config.h"
 #include "ios/chrome/browser/physical_web/physical_web_constants.h"
@@ -58,3 +59,8 @@
     GetApplicationContext()->GetPhysicalWebDataSource()->StopDiscovery();
   }
 }
+
+void StartPhysicalWebDiscovery(PrefService* pref_service,
+                               ios::ChromeBrowserState* browser_state) {
+  StartPhysicalWebDiscovery(pref_service, browser_state->IsOffTheRecord());
+}
diff --git a/ios/chrome/browser/search_engines/BUILD.gn b/ios/chrome/browser/search_engines/BUILD.gn
index f101496c..d2226cb 100644
--- a/ios/chrome/browser/search_engines/BUILD.gn
+++ b/ios/chrome/browser/search_engines/BUILD.gn
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/config/features.gni")
+import("//rlz/features/features.gni")
 
 source_set("search_engines") {
   sources = [
@@ -33,6 +34,7 @@
     "//ios/chrome/common",
     "//ios/web",
     "//net",
+    "//rlz/features",
     "//ui/base",
     "//url",
   ]
diff --git a/ios/chrome/browser/search_engines/template_url_service_factory.cc b/ios/chrome/browser/search_engines/template_url_service_factory.cc
index 65b0a25..1a95c85 100644
--- a/ios/chrome/browser/search_engines/template_url_service_factory.cc
+++ b/ios/chrome/browser/search_engines/template_url_service_factory.cc
@@ -20,8 +20,9 @@
 #include "ios/chrome/browser/search_engines/template_url_service_client_impl.h"
 #include "ios/chrome/browser/search_engines/ui_thread_search_terms_data.h"
 #include "ios/chrome/browser/web_data_service_factory.h"
+#include "rlz/features/features.h"
 
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
 #include "components/rlz/rlz_tracker.h"  // nogncheck
 #endif
 
@@ -29,7 +30,7 @@
 namespace {
 
 base::Closure GetDefaultSearchProviderChangedCallback() {
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
   return base::Bind(base::IgnoreResult(&rlz::RLZTracker::RecordProductEvent),
                     rlz_lib::CHROME, rlz::RLZTracker::ChromeOmnibox(),
                     rlz_lib::SET_TO_GOOGLE);
diff --git a/ios/chrome/browser/search_engines/ui_thread_search_terms_data.cc b/ios/chrome/browser/search_engines/ui_thread_search_terms_data.cc
index 44669b1e..03eaaba 100644
--- a/ios/chrome/browser/search_engines/ui_thread_search_terms_data.cc
+++ b/ios/chrome/browser/search_engines/ui_thread_search_terms_data.cc
@@ -18,9 +18,10 @@
 #include "ios/chrome/common/channel_info.h"
 #include "ios/web/public/web_thread.h"
 #include "net/base/escape.h"
+#include "rlz/features/features.h"
 #include "url/gurl.h"
 
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
 #include "components/rlz/rlz_tracker.h"  // nogncheck
 #endif
 
@@ -60,7 +61,7 @@
   DCHECK(!from_app_list);
   DCHECK(thread_checker_.CalledOnValidThread());
   base::string16 rlz_string;
-#if defined(ENABLE_RLZ)
+#if BUILDFLAG(ENABLE_RLZ)
   // For organic brandcode do not use rlz at all.
   std::string brand;
   if (ios::google_brand::GetBrand(&brand) &&
diff --git a/ios/chrome/browser/share_extension/share_extension_item_receiver.h b/ios/chrome/browser/share_extension/share_extension_item_receiver.h
index 5cdd2fd..409d018 100644
--- a/ios/chrome/browser/share_extension/share_extension_item_receiver.h
+++ b/ios/chrome/browser/share_extension/share_extension_item_receiver.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_CHROME_BROWSER_UI_SHARE_EXTENSION_SHARE_EXTENSION_ITEM_RECEIVER_H_
-#define IOS_CHROME_BROWSER_UI_SHARE_EXTENSION_SHARE_EXTENSION_ITEM_RECEIVER_H_
+#ifndef IOS_CHROME_BROWSER_SHARE_EXTENSION_SHARE_EXTENSION_ITEM_RECEIVER_H_
+#define IOS_CHROME_BROWSER_SHARE_EXTENSION_SHARE_EXTENSION_ITEM_RECEIVER_H_
 
 #import <Foundation/Foundation.h>
 
@@ -32,4 +32,4 @@
 
 @end
 
-#endif  // IOS_CHROME_BROWSER_UI_SHARE_EXTENSION_SHARE_EXTENSION_ITEM_RECEIVER_H_
+#endif  // IOS_CHROME_BROWSER_SHARE_EXTENSION_SHARE_EXTENSION_ITEM_RECEIVER_H_
diff --git a/ios/chrome/browser/share_extension/share_extension_service.h b/ios/chrome/browser/share_extension/share_extension_service.h
index f747621..1988966 100644
--- a/ios/chrome/browser/share_extension/share_extension_service.h
+++ b/ios/chrome/browser/share_extension/share_extension_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 IOS_INTERNAL_CHROME_BROWSER_SHARE_EXTENSION_SHARE_EXTENSION_SERVICE_H_
-#define IOS_INTERNAL_CHROME_BROWSER_SHARE_EXTENSION_SHARE_EXTENSION_SERVICE_H_
+#ifndef IOS_CHROME_BROWSER_SHARE_EXTENSION_SHARE_EXTENSION_SERVICE_H_
+#define IOS_CHROME_BROWSER_SHARE_EXTENSION_SHARE_EXTENSION_SERVICE_H_
 
 #include "components/bookmarks/browser/base_bookmark_model_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
@@ -44,4 +44,4 @@
   DISALLOW_COPY_AND_ASSIGN(ShareExtensionService);
 };
 
-#endif  // IOS_INTERNAL_CHROME_BROWSER_SHARE_EXTENSION_SHARE_EXTENSION_SERVICE_H_
+#endif  // IOS_CHROME_BROWSER_SHARE_EXTENSION_SHARE_EXTENSION_SERVICE_H_
diff --git a/ios/chrome/browser/signin/fake_signin_manager_builder.h b/ios/chrome/browser/signin/fake_signin_manager_builder.h
index 1d06ad4..f10af9d 100644
--- a/ios/chrome/browser/signin/fake_signin_manager_builder.h
+++ b/ios/chrome/browser/signin/fake_signin_manager_builder.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_CHROME_BROWSER_SIGNIN_FAKE_SIGNIN_MANAGER_H_
-#define IOS_CHROME_BROWSER_SIGNIN_FAKE_SIGNIN_MANAGER_H_
+#ifndef IOS_CHROME_BROWSER_SIGNIN_FAKE_SIGNIN_MANAGER_BUILDER_H_
+#define IOS_CHROME_BROWSER_SIGNIN_FAKE_SIGNIN_MANAGER_BUILDER_H_
 
 #include <memory>
 
@@ -22,4 +22,4 @@
 
 }  // namespace ios
 
-#endif  // IOS_CHROME_BROWSER_SIGNIN_FAKE_SIGNIN_MANAGER_H_
+#endif  // IOS_CHROME_BROWSER_SIGNIN_FAKE_SIGNIN_MANAGER_BUILDER_H_
diff --git a/ios/chrome/browser/ui/UIView+SizeClassSupport.h b/ios/chrome/browser/ui/UIView+SizeClassSupport.h
index 18b52428..af53dd0e 100644
--- a/ios/chrome/browser/ui/UIView+SizeClassSupport.h
+++ b/ios/chrome/browser/ui/UIView+SizeClassSupport.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_CHROME_BROWSER_UI_UIVIEW_SIZE_CLASS_SUPPORT_H_
-#define IOS_CHROME_BROWSER_UI_UIVIEW_SIZE_CLASS_SUPPORT_H_
+#ifndef IOS_CHROME_BROWSER_UI_UIVIEW_SIZECLASSSUPPORT_H_
+#define IOS_CHROME_BROWSER_UI_UIVIEW_SIZECLASSSUPPORT_H_
 
 #import <UIKit/UIKit.h>
 
@@ -26,4 +26,4 @@
 
 @end
 
-#endif  // IOS_CHROME_BROWSER_UI_UIVIEW_SIZE_CLASS_SUPPORT_H_
+#endif  // IOS_CHROME_BROWSER_UI_UIVIEW_SIZECLASSSUPPORT_H_
diff --git a/ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h b/ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h
index eed6920..50c31f2 100644
--- a/ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h
+++ b/ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_CHROME_BROWSER_UI_UIKIT_CHROME_EXECUTE_COMMAND_H_
-#define IOS_CHROME_BROWSER_UI_UIKIT_CHROME_EXECUTE_COMMAND_H_
+#ifndef IOS_CHROME_BROWSER_UI_COMMANDS_UIKIT_CHROMEEXECUTECOMMAND_H_
+#define IOS_CHROME_BROWSER_UI_COMMANDS_UIKIT_CHROMEEXECUTECOMMAND_H_
 
 #import <UIKit/UIKit.h>
 
@@ -20,4 +20,4 @@
 - (void)chromeExecuteCommand:(id)sender;
 @end
 
-#endif  // IOS_CHROME_BROWSER_UI_UIKIT_CHROME_EXECUTE_COMMAND_H_
+#endif  // IOS_CHROME_BROWSER_UI_COMMANDS_UIKIT_CHROMEEXECUTECOMMAND_H_
diff --git a/ios/chrome/browser/ui/rtl_geometry.h b/ios/chrome/browser/ui/rtl_geometry.h
index f883c64..87cfbad 100644
--- a/ios/chrome/browser/ui/rtl_geometry.h
+++ b/ios/chrome/browser/ui/rtl_geometry.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 RTL_GEOMETRY_H_
-#define RTL_GEOMETRY_H_
+#ifndef IOS_CHROME_BROWSER_UI_RTL_GEOMETRY_H_
+#define IOS_CHROME_BROWSER_UI_RTL_GEOMETRY_H_
 
 #include <CoreGraphics/CoreGraphics.h>
 #import <UIKit/UIKit.h>
@@ -203,4 +203,4 @@
 // smaller sections of views should be determined case by case.
 NSLayoutFormatOptions LayoutOptionForRTLSupport();
 
-#endif  // RTL_GEOMETRY_H_
+#endif  // IOS_CHROME_BROWSER_UI_RTL_GEOMETRY_H_
diff --git a/ios/chrome/browser/ui/webui/crashes_ui.h b/ios/chrome/browser/ui/webui/crashes_ui.h
index 69ac0a93..3eae058 100644
--- a/ios/chrome/browser/ui/webui/crashes_ui.h
+++ b/ios/chrome/browser/ui/webui/crashes_ui.h
@@ -28,4 +28,4 @@
   DISALLOW_COPY_AND_ASSIGN(CrashesUI);
 };
 
-#endif  // CHROME_BROWSER_UI_WEBUI_CRASHES_UI_H_
+#endif  // IOS_CHROME_BROWSER_UI_WEBUI_CRASHES_UI_H_
diff --git a/ios/chrome/browser/web/web_controller_provider_impl.h b/ios/chrome/browser/web/web_controller_provider_impl.h
index 697bd56..4da9e7b 100644
--- a/ios/chrome/browser/web/web_controller_provider_impl.h
+++ b/ios/chrome/browser/web/web_controller_provider_impl.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_INTERNAL_CHROME_BROWSER_WEB_WEB_CONTROLLER_PROVIDER_IMPL_H_
-#define IOS_INTERNAL_CHROME_BROWSER_WEB_WEB_CONTROLLER_PROVIDER_IMPL_H_
+#ifndef IOS_CHROME_BROWSER_WEB_WEB_CONTROLLER_PROVIDER_IMPL_H_
+#define IOS_CHROME_BROWSER_WEB_WEB_CONTROLLER_PROVIDER_IMPL_H_
 
 #include <memory>
 
@@ -33,4 +33,4 @@
   bool suppresses_dialogs_;
 };
 
-#endif  // IOS_INTERNAL_CHROME_BROWSER_WEB_WEB_CONTROLLER_PROVIDER_IMPL_H_
+#endif  // IOS_CHROME_BROWSER_WEB_WEB_CONTROLLER_PROVIDER_IMPL_H_
diff --git a/ios/crnet/CrNet.h b/ios/crnet/CrNet.h
index ce93886e..4b1d4dc 100644
--- a/ios/crnet/CrNet.h
+++ b/ios/crnet/CrNet.h
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#ifndef IOS_CRNET_CRNET_H_
+#define IOS_CRNET_CRNET_H_
+
 #import <Foundation/Foundation.h>
 
 // A block, that takes a request, and returns YES if the request should
@@ -132,3 +135,5 @@
 + (void)clearCacheWithCompletionCallback:(ClearCacheCallback)completionBlock;
 
 @end
+
+#endif  // IOS_CRNET_CRNET_H_
diff --git a/ios/crnet/crnet_consumer/crnet_consumer_app_delegate.h b/ios/crnet/crnet_consumer/crnet_consumer_app_delegate.h
index 7f819d0..cb18ce98 100644
--- a/ios/crnet/crnet_consumer/crnet_consumer_app_delegate.h
+++ b/ios/crnet/crnet_consumer/crnet_consumer_app_delegate.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 CRNET_CONSUMER_APP_DELEGATE_
-#define CRNET_CONSUMER_APP_DELEGATE_
+#ifndef IOS_CRNET_CRNET_CONSUMER_CRNET_CONSUMER_APP_DELEGATE_H_
+#define IOS_CRNET_CRNET_CONSUMER_CRNET_CONSUMER_APP_DELEGATE_H_
 
 #import <UIKit/UIKit.h>
 
@@ -17,4 +17,4 @@
 
 @end
 
-#endif  // CRNET_CONSUMER_APP_DELEGATE_
+#endif  // IOS_CRNET_CRNET_CONSUMER_CRNET_CONSUMER_APP_DELEGATE_H_
diff --git a/ios/crnet/crnet_consumer/crnet_consumer_view_controller.h b/ios/crnet/crnet_consumer/crnet_consumer_view_controller.h
index e8539e9..73f0a42a 100644
--- a/ios/crnet/crnet_consumer/crnet_consumer_view_controller.h
+++ b/ios/crnet/crnet_consumer/crnet_consumer_view_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 CRNET_CONSUMER_VIEW_CONTROLLER_
-#define CRNET_CONSUMER_VIEW_CONTROLLER_
+#ifndef IOS_CRNET_CRNET_CONSUMER_CRNET_CONSUMER_VIEW_CONTROLLER_H_
+#define IOS_CRNET_CRNET_CONSUMER_CRNET_CONSUMER_VIEW_CONTROLLER_H_
 
 #import <Foundation/Foundation.h>
 #import <UIKit/UIKit.h>
@@ -11,4 +11,4 @@
 @interface CrNetConsumerViewController : UIViewController
 @end
 
-#endif  // CRNET_CONSUMER_VIEW_CONTROLLER_
+#endif  // IOS_CRNET_CRNET_CONSUMER_CRNET_CONSUMER_VIEW_CONTROLLER_H_
diff --git a/ios/public/provider/chrome/browser/geolocation_updater_provider.h b/ios/public/provider/chrome/browser/geolocation_updater_provider.h
index eb037ba..9f01d280 100644
--- a/ios/public/provider/chrome/browser/geolocation_updater_provider.h
+++ b/ios/public/provider/chrome/browser/geolocation_updater_provider.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_PUBLIC_PROVIDER_CHROME_BROWSER_GEOLOCATION_UPDATER_H
-#define IOS_PUBLIC_PROVIDER_CHROME_BROWSER_GEOLOCATION_UPDATER_H
+#ifndef IOS_PUBLIC_PROVIDER_CHROME_BROWSER_GEOLOCATION_UPDATER_PROVIDER_H_
+#define IOS_PUBLIC_PROVIDER_CHROME_BROWSER_GEOLOCATION_UPDATER_PROVIDER_H_
 
 #import <CoreLocation/CoreLocation.h>
 #import <Foundation/Foundation.h>
@@ -87,4 +87,4 @@
 
 }  // namespace ios
 
-#endif  // IOS_PUBLIC_PROVIDER_CHROME_BROWSER_GEOLOCATION_UPDATER_H
+#endif  // IOS_PUBLIC_PROVIDER_CHROME_BROWSER_GEOLOCATION_UPDATER_PROVIDER_H_
diff --git a/ios/public/provider/chrome/browser/spotlight/spotlight_provider.h b/ios/public/provider/chrome/browser/spotlight/spotlight_provider.h
index 9e9c5f20..78faeef 100644
--- a/ios/public/provider/chrome/browser/spotlight/spotlight_provider.h
+++ b/ios/public/provider/chrome/browser/spotlight/spotlight_provider.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_PUBLIC_PROVIDER_CHROME_BROWSER_SPOTLIGHT_SPOTLIGHT_PROVIDER_H
-#define IOS_PUBLIC_PROVIDER_CHROME_BROWSER_SPOTLIGHT_SPOTLIGHT_PROVIDER_H
+#ifndef IOS_PUBLIC_PROVIDER_CHROME_BROWSER_SPOTLIGHT_SPOTLIGHT_PROVIDER_H_
+#define IOS_PUBLIC_PROVIDER_CHROME_BROWSER_SPOTLIGHT_SPOTLIGHT_PROVIDER_H_
 
 #import <Foundation/Foundation.h>
 
@@ -36,4 +36,4 @@
   DISALLOW_COPY_AND_ASSIGN(SpotlightProvider);
 };
 
-#endif  // IOS_PUBLIC_PROVIDER_CHROME_BROWSER_SPOTLIGHT_SPOTLIGHT_PROVIDER_H
+#endif  // IOS_PUBLIC_PROVIDER_CHROME_BROWSER_SPOTLIGHT_SPOTLIGHT_PROVIDER_H_
diff --git a/ios/public/provider/chrome/browser/spotlight/test_spotlight_provider.h b/ios/public/provider/chrome/browser/spotlight/test_spotlight_provider.h
index 11eff13d..67f5589 100644
--- a/ios/public/provider/chrome/browser/spotlight/test_spotlight_provider.h
+++ b/ios/public/provider/chrome/browser/spotlight/test_spotlight_provider.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_PUBLIC_PROVIDER_CHROME_BROWSER_SPOTLIGHT_TEST_SPOTLIGHT_PROVIDER_H
-#define IOS_PUBLIC_PROVIDER_CHROME_BROWSER_SPOTLIGHT_TEST_SPOTLIGHT_PROVIDER_H
+#ifndef IOS_PUBLIC_PROVIDER_CHROME_BROWSER_SPOTLIGHT_TEST_SPOTLIGHT_PROVIDER_H_
+#define IOS_PUBLIC_PROVIDER_CHROME_BROWSER_SPOTLIGHT_TEST_SPOTLIGHT_PROVIDER_H_
 
 #import <Foundation/Foundation.h>
 
@@ -19,4 +19,4 @@
   NSArray* GetAdditionalKeywords() override;
 };
 
-#endif  // IOS_PUBLIC_PROVIDER_CHROME_BROWSER_SPOTLIGHT_TEST_SPOTLIGHT_PROVIDER_H
+#endif  // IOS_PUBLIC_PROVIDER_CHROME_BROWSER_SPOTLIGHT_TEST_SPOTLIGHT_PROVIDER_H_
diff --git a/ios/public/provider/chrome/browser/voice/voice_search_controller.h b/ios/public/provider/chrome/browser/voice/voice_search_controller.h
index e2dfb0b..578ec47ebb 100644
--- a/ios/public/provider/chrome/browser/voice/voice_search_controller.h
+++ b/ios/public/provider/chrome/browser/voice/voice_search_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 IOS_PUBLIC_PROVIDER_CHROME_BROWSER_VOICE_VOICE_SEARCH_CONTROLLER_IMPL_H_
-#define IOS_PUBLIC_PROVIDER_CHROME_BROWSER_VOICE_VOICE_SEARCH_CONTROLLER_IMPL_H_
+#ifndef IOS_PUBLIC_PROVIDER_CHROME_BROWSER_VOICE_VOICE_SEARCH_CONTROLLER_H_
+#define IOS_PUBLIC_PROVIDER_CHROME_BROWSER_VOICE_VOICE_SEARCH_CONTROLLER_H_
 
 #include "base/memory/ref_counted.h"
 
@@ -57,4 +57,4 @@
   DISALLOW_COPY_AND_ASSIGN(VoiceSearchController);
 };
 
-#endif  // IOS_PUBLIC_PROVIDER_CHROME_BROWSER_VOICE_VOICE_SEARCH_CONTROLLER_IMPL_H_
+#endif  // IOS_PUBLIC_PROVIDER_CHROME_BROWSER_VOICE_VOICE_SEARCH_CONTROLLER_H_
diff --git a/ios/testing/BUILD.gn b/ios/testing/BUILD.gn
index 9772939..3ad58c9 100644
--- a/ios/testing/BUILD.gn
+++ b/ios/testing/BUILD.gn
@@ -67,6 +67,8 @@
     "data/http_server_files/fullscreen.html",
     "data/http_server_files/history.html",
     "data/http_server_files/history.js",
+    "data/http_server_files/history_go.html",
+    "data/http_server_files/history_go.js",
     "data/http_server_files/memory_usage.html",
     "data/http_server_files/multi_field_form.html",
     "data/http_server_files/pony.html",
diff --git a/ios/testing/data/http_server_files/history_go.html b/ios/testing/data/http_server_files/history_go.html
new file mode 100644
index 0000000..050a07dd1
--- /dev/null
+++ b/ios/testing/data/http_server_files/history_go.html
@@ -0,0 +1,36 @@
+<!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>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>History navigation</title>
+<script type="text/javascript" src="history_go.js"></script>
+</head>
+<body>
+<p></p>
+<div id='on-load-div'></div>
+<br>
+<div id='no-op-div'></div>
+<br>
+<div id='pop-state-received-div'></div>
+<br>
+<div id='state-object-div'></div>
+<br>
+<div id='hash-change-received-div'></div>
+</p>
+
+<input type="button" value="go-no-parameter" id="go-no-parameter"
+    onclick="goNoParameter()" /><br>
+<input type="button" value="go-zero" id="go-zero"
+    onclick="goZero()" /><br>
+<input type="button" value="go-2" id="go-2"
+    onclick="go2()" /><br>
+<input type="button" value="go-back-2" id="go-back-2"
+    onclick="goBack2()" /><br>
+
+</body>
+</html>
diff --git a/ios/testing/data/http_server_files/history_go.js b/ios/testing/data/http_server_files/history_go.js
new file mode 100644
index 0000000..543f186
--- /dev/null
+++ b/ios/testing/data/http_server_files/history_go.js
@@ -0,0 +1,75 @@
+// 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.
+
+// Adds event listeners and populates on-load-div.
+window.onload = function() {
+  window.addEventListener('popstate', onPopstate);
+  window.addEventListener('hashchange', onHashChange);
+  updateOnLoadText('OnLoadText');
+};
+
+// Populates pop-state-received-div and state-object-div upon a popstate event.
+var onPopstate = function(e) {
+  updatePopStateReceivedText(true);
+  updateStateObjectText(e.state);
+};
+
+// Populates hash-change-received-div upon receiving of a hashchange event.
+var onHashChange = function(e) {
+  updateHashChangeReceivedText(true);
+}
+
+var updateOnLoadText = function(text) {
+  document.getElementById('on-load-div').innerHTML = text;
+}
+
+var updateNoOpText = function(text) {
+  document.getElementById('no-op-div').innerHTML = text;
+}
+
+var updatePopStateReceivedText = function(received) {
+  var text = received ? 'PopStateReceived' : '';
+  document.getElementById('pop-state-received-div').innerHTML = text;
+}
+
+var updateStateObjectText = function(state) {
+  document.getElementById('state-object-div').innerHTML = state;
+}
+
+var updateHashChangeReceivedText = function(received) {
+  var text = received ? 'HashChangeReceived' : '';
+  document.getElementById('hash-change-received-div').innerHTML = text;
+}
+
+// Clears all div text an starts a timer that updates no-op-div with "NoOpText"
+// after 1s.  This allows tests to verify that no nagivations occur after a
+// no-op JavaScript call.
+var onButtonTapped = function() {
+  updateOnLoadText('');
+  updateNoOpText('');
+  updatePopStateReceivedText(false);
+  updateStateObjectText('');
+  updateHashChangeReceivedText(false);
+  setTimeout("updateNoOpText('NoOpText')", 1000);
+}
+
+var goNoParameter = function() {
+  onButtonTapped();
+  window.history.go();
+}
+
+var goZero = function() {
+  onButtonTapped();
+  window.history.go(0);
+}
+
+var go2 = function() {
+  onButtonTapped();
+  window.history.go(2);
+}
+
+var goBack2 = function() {
+  onButtonTapped();
+  window.history.go(-2);
+}
diff --git a/ios/web/ios_web_resources.grd b/ios/web/ios_web_resources.grd
index 8894fe3..f17ef25 100644
--- a/ios/web/ios_web_resources.grd
+++ b/ios/web/ios_web_resources.grd
@@ -14,6 +14,7 @@
       <include name="IDR_MOJO_CODEC_JS" file="../../mojo/public/js/codec.js" flattenhtml="true" type="BINDATA" />
       <include name="IDR_MOJO_CONNECTION_JS" file="../../mojo/public/js/connection.js" flattenhtml="true" type="BINDATA" />
       <include name="IDR_MOJO_CONNECTOR_JS" file="../../mojo/public/js/connector.js" flattenhtml="true" type="BINDATA" />
+      <include name="IDR_MOJO_INTERFACE_TYPES_JS" file="../../mojo/public/js/interface_types.js" flattenhtml="true" type="BINDATA" />
       <include name="IDR_MOJO_ROUTER_JS" file="../../mojo/public/js/router.js" flattenhtml="true" type="BINDATA" />
       <include name="IDR_MOJO_UNICODE_JS" file="../../mojo/public/js/unicode.js" flattenhtml="true" type="BINDATA" />
       <include name="IDR_MOJO_VALIDATOR_JS" file="../../mojo/public/js/validator.js" flattenhtml="true" type="BINDATA" />
diff --git a/ios/web/public/crw_browsing_data_store.h b/ios/web/public/crw_browsing_data_store.h
index 529d7e5..5dab276 100644
--- a/ios/web/public/crw_browsing_data_store.h
+++ b/ios/web/public/crw_browsing_data_store.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_WEB_CRW_BROWSING_DATA_STORE_H_
-#define IOS_WEB_CRW_BROWSING_DATA_STORE_H_
+#ifndef IOS_WEB_PUBLIC_CRW_BROWSING_DATA_STORE_H_
+#define IOS_WEB_PUBLIC_CRW_BROWSING_DATA_STORE_H_
 
 #import <Foundation/Foundation.h>
 
@@ -94,4 +94,4 @@
 
 @end
 
-#endif  // IOS_WEB_CRW_BROWSING_DATA_STORE_H_
+#endif  // IOS_WEB_PUBLIC_CRW_BROWSING_DATA_STORE_H_
diff --git a/ios/web/public/crw_browsing_data_store_delegate.h b/ios/web/public/crw_browsing_data_store_delegate.h
index 63fa9649..8686790 100644
--- a/ios/web/public/crw_browsing_data_store_delegate.h
+++ b/ios/web/public/crw_browsing_data_store_delegate.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_WEB_CRW_BROWSING_DATA_STORE_DELEGATE_H_
-#define IOS_WEB_CRW_BROWSING_DATA_STORE_DELEGATE_H_
+#ifndef IOS_WEB_PUBLIC_CRW_BROWSING_DATA_STORE_DELEGATE_H_
+#define IOS_WEB_PUBLIC_CRW_BROWSING_DATA_STORE_DELEGATE_H_
 
 #import <Foundation/Foundation.h>
 
@@ -50,4 +50,4 @@
 
 @end
 
-#endif  // IOS_WEB_CRW_BROWSING_DATA_STORE_DELEGATE_H_
+#endif  // IOS_WEB_PUBLIC_CRW_BROWSING_DATA_STORE_DELEGATE_H_
diff --git a/ios/web/public/favicon_url.h b/ios/web/public/favicon_url.h
index 765c292e..409f329 100644
--- a/ios/web/public/favicon_url.h
+++ b/ios/web/public/favicon_url.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_WEB_PUBLIC_FAVICON_URL_
-#define IOS_WEB_PUBLIC_FAVICON_URL_
+#ifndef IOS_WEB_PUBLIC_FAVICON_URL_H_
+#define IOS_WEB_PUBLIC_FAVICON_URL_H_
 
 #include <vector>
 
@@ -42,4 +42,4 @@
 
 } // namespace web
 
-#endif  // IOS_WEB_PUBLIC_FAVICON_URL_
+#endif  // IOS_WEB_PUBLIC_FAVICON_URL_H_
diff --git a/ios/web/public/load_committed_details.h b/ios/web/public/load_committed_details.h
index bb9a3c17..81dc914 100644
--- a/ios/web/public/load_committed_details.h
+++ b/ios/web/public/load_committed_details.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_WEB_PUBLIC_WEB_LOAD_COMMITTED_DETAILS_H_
-#define IOS_WEB_PUBLIC_WEB_LOAD_COMMITTED_DETAILS_H_
+#ifndef IOS_WEB_PUBLIC_LOAD_COMMITTED_DETAILS_H_
+#define IOS_WEB_PUBLIC_LOAD_COMMITTED_DETAILS_H_
 
 #include "url/gurl.h"
 
@@ -32,4 +32,4 @@
 
 }  // namespace web
 
-#endif  // IOS_WEB_PUBLIC_WEB_LOAD_COMMITTED_DETAILS_H_
+#endif  // IOS_WEB_PUBLIC_LOAD_COMMITTED_DETAILS_H_
diff --git a/ios/web/public/test/mock_image_data_fetcher.h b/ios/web/public/test/mock_image_data_fetcher.h
index 196b68f2..65e7b40 100644
--- a/ios/web/public/test/mock_image_data_fetcher.h
+++ b/ios/web/public/test/mock_image_data_fetcher.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_WEB_PUBLIC_IMAGE_FETCHER_MOCK_IMAGE_DATA_FETCHER_H_
-#define IOS_WEB_PUBLIC_IMAGE_FETCHER_MOCK_IMAGE_DATA_FETCHER_H_
+#ifndef IOS_WEB_PUBLIC_TEST_MOCK_IMAGE_DATA_FETCHER_H_
+#define IOS_WEB_PUBLIC_TEST_MOCK_IMAGE_DATA_FETCHER_H_
 
 #import "ios/web/public/image_fetcher/image_data_fetcher.h"
 
@@ -33,4 +33,4 @@
 
 }  // namespace web
 
-#endif  // IOS_WEB_PUBLIC_IMAGE_FETCHER_MOCK_IMAGE_DATA_FETCHER_H_
+#endif  // IOS_WEB_PUBLIC_TEST_MOCK_IMAGE_DATA_FETCHER_H_
diff --git a/ios/web/public/test/response_providers/string_response_provider.h b/ios/web/public/test/response_providers/string_response_provider.h
index c3e985c..e5a0f9e 100644
--- a/ios/web/public/test/response_providers/string_response_provider.h
+++ b/ios/web/public/test/response_providers/string_response_provider.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_STRING_RESPONSE_PROVIDER_
-#define IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_STRING_RESPONSE_PROVIDER_
+#ifndef IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_STRING_RESPONSE_PROVIDER_H_
+#define IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_STRING_RESPONSE_PROVIDER_H_
 
 #include <string>
 
@@ -33,4 +33,4 @@
 
 }  // namespace web
 
-#endif  // IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_STRING_RESPONSE_PROVIDER_
+#endif  // IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_STRING_RESPONSE_PROVIDER_H_
diff --git a/ios/web/public/test/test_web_client.h b/ios/web/public/test/test_web_client.h
index 60d2a23..1514f112 100644
--- a/ios/web/public/test/test_web_client.h
+++ b/ios/web/public/test/test_web_client.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 WEB_TEST_WEB_PUBLIC_TEST_TEST_WEB_CLIENT_H_
-#define WEB_TEST_WEB_PUBLIC_TEST_TEST_WEB_CLIENT_H_
+#ifndef IOS_WEB_PUBLIC_TEST_TEST_WEB_CLIENT_H_
+#define IOS_WEB_PUBLIC_TEST_TEST_WEB_CLIENT_H_
 
 #import <Foundation/Foundation.h>
 
@@ -58,4 +58,4 @@
 
 }  // namespace web
 
-#endif // WEB_TEST_WEB_PUBLIC_TEST_TEST_WEB_CLIENT_H_
+#endif  // IOS_WEB_PUBLIC_TEST_TEST_WEB_CLIENT_H_
diff --git a/ios/web/public/test/web_js_test.h b/ios/web/public/test/web_js_test.h
index 9bdb0f0..f47ceb49 100644
--- a/ios/web/public/test/web_js_test.h
+++ b/ios/web/public/test/web_js_test.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_INTERNAL_CHROME_BROWSER_WEB_WEB_JS_TEST_H_
-#define IOS_INTERNAL_CHROME_BROWSER_WEB_WEB_JS_TEST_H_
+#ifndef IOS_WEB_PUBLIC_TEST_WEB_JS_TEST_H_
+#define IOS_WEB_PUBLIC_TEST_WEB_JS_TEST_H_
 
 #import <Foundation/Foundation.h>
 
@@ -112,4 +112,4 @@
 
 }  // namespace web
 
-#endif  // IOS_INTERNAL_CHROME_BROWSER_WEB_WEB_JS_TEST_H_
+#endif  // IOS_WEB_PUBLIC_TEST_WEB_JS_TEST_H_
diff --git a/ios/web/public/test/web_view_interaction_test_util.h b/ios/web/public/test/web_view_interaction_test_util.h
index 4edc117..a3c54d8 100644
--- a/ios/web/public/test/web_view_interaction_test_util.h
+++ b/ios/web/public/test/web_view_interaction_test_util.h
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#ifndef IOS_WEB_PUBLIC_TEST_WEB_VIEW_INTERACTION_TEST_UTIL_H_
+#define IOS_WEB_PUBLIC_TEST_WEB_VIEW_INTERACTION_TEST_UTIL_H_
+
 #import <UIKit/UIKit.h>
 
 #include <string>
@@ -43,3 +46,5 @@
                              const std::string& form_id);
 }  // namespace test
 }  // namespace web
+
+#endif  // IOS_WEB_PUBLIC_TEST_WEB_VIEW_INTERACTION_TEST_UTIL_H_
diff --git a/ios/web/test/data/mojo_test.js b/ios/web/test/data/mojo_test.js
index a41a743e..7b3a9e4 100644
--- a/ios/web/test/data/mojo_test.js
+++ b/ios/web/test/data/mojo_test.js
@@ -12,18 +12,19 @@
 function getBrowserProxy() {
   return new Promise(function(resolve, reject) {
     define([
+      'mojo/public/js/bindings',
       'mojo/public/js/connection',
       'ios/web/test/mojo_test.mojom',
       'content/public/renderer/frame_interfaces',
-    ], function(connection, mojom, frameInterfaces) {
+    ], function(bindings, connection, mojom, frameInterfaces) {
       var pageImpl, browserProxy;
 
       /** @constructor */
-      function TestPageImpl() {};
+      function TestPageImpl() {
+        this.binding = new bindings.Binding(mojom.TestPage, this);
+      }
 
       TestPageImpl.prototype = {
-        __proto__: mojom.TestPage.stubClass.prototype,
-
         /** @override */
         handleNativeMessage: function(result) {
           if (result.message == 'ack') {
@@ -39,7 +40,7 @@
           mojom.TestUIHandlerMojo);
       pageImpl = new TestPageImpl();
 
-      browserProxy.setClientPage(connection.bindStubDerivedImpl(pageImpl));
+      browserProxy.setClientPage(pageImpl.binding.createInterfacePtrAndBind());
       resolve(browserProxy);
     });
   });
diff --git a/ios/web/test/web_int_test.h b/ios/web/test/web_int_test.h
index cb6b7a2c..e2c10288 100644
--- a/ios/web/test/web_int_test.h
+++ b/ios/web/test/web_int_test.h
@@ -31,4 +31,4 @@
 
 }  // namespace web
 
-#endif  // IOS_WEB_TEST_WEB_TEST_H_
+#endif  // IOS_WEB_TEST_WEB_INT_TEST_H_
diff --git a/ios/web/web_state/js/resources/core.js b/ios/web/web_state/js/resources/core.js
index c08e679..5562258 100644
--- a/ios/web/web_state/js/resources/core.js
+++ b/ios/web/web_state/js/resources/core.js
@@ -425,7 +425,7 @@
     invokeOnHost_({'command': 'window.history.forward'});
   };
   window.history.go = function(delta) {
-    invokeOnHost_({'command': 'window.history.go', 'value': delta});
+    invokeOnHost_({'command': 'window.history.go', 'value': delta | 0});
   };
   window.history.pushState = function(stateObject, pageTitle, pageUrl) {
     __gCrWeb.message.invokeOnHost(
diff --git a/ios/web/webui/crw_web_ui_manager.mm b/ios/web/webui/crw_web_ui_manager.mm
index 049f041..8100606 100644
--- a/ios/web/webui/crw_web_ui_manager.mm
+++ b/ios/web/webui/crw_web_ui_manager.mm
@@ -252,6 +252,7 @@
       {mojo::kCodecModuleName, IDR_MOJO_CODEC_JS},
       {mojo::kConnectionModuleName, IDR_MOJO_CONNECTION_JS},
       {mojo::kConnectorModuleName, IDR_MOJO_CONNECTOR_JS},
+      {mojo::kInterfaceTypesModuleName, IDR_MOJO_INTERFACE_TYPES_JS},
       {mojo::kRouterModuleName, IDR_MOJO_ROUTER_JS},
       {mojo::kUnicodeModuleName, IDR_MOJO_UNICODE_JS},
       {mojo::kValidatorModuleName, IDR_MOJO_VALIDATOR_JS},
diff --git a/ios/web/webui/url_data_manager_ios_backend.h b/ios/web/webui/url_data_manager_ios_backend.h
index e483c321..48878d6 100644
--- a/ios/web/webui/url_data_manager_ios_backend.h
+++ b/ios/web/webui/url_data_manager_ios_backend.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_INTERNAL_WEB_WEBUI_URL_DATA_MANAGER_BACKEND_IOS_H_
-#define IOS_INTERNAL_WEB_WEBUI_URL_DATA_MANAGER_BACKEND_IOS_H_
+#ifndef IOS_WEB_WEBUI_URL_DATA_MANAGER_IOS_BACKEND_H_
+#define IOS_WEB_WEBUI_URL_DATA_MANAGER_IOS_BACKEND_H_
 
 #include <map>
 #include <memory>
@@ -98,4 +98,4 @@
 
 }  // namespace web
 
-#endif  // IOS_INTERNAL_WEB_WEBUI_URL_DATA_MANAGER_BACKEND_IOS_H_
+#endif  // IOS_WEB_WEBUI_URL_DATA_MANAGER_IOS_BACKEND_H_
diff --git a/ios/web/webui/url_data_source_ios_impl.h b/ios/web/webui/url_data_source_ios_impl.h
index bb9b2b1..4420489 100644
--- a/ios/web/webui/url_data_source_ios_impl.h
+++ b/ios/web/webui/url_data_source_ios_impl.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_INTERNAL_WEB_WEBUI_URL_DATA_SOURCE_IMPL_IOS_H_
-#define IOS_INTERNAL_WEB_WEBUI_URL_DATA_SOURCE_IMPL_IOS_H_
+#ifndef IOS_WEB_WEBUI_URL_DATA_SOURCE_IOS_IMPL_H_
+#define IOS_WEB_WEBUI_URL_DATA_SOURCE_IOS_IMPL_H_
 
 #include <memory>
 
@@ -97,4 +97,4 @@
 
 }  // namespace web
 
-#endif  // IOS_INTERNAL_WEB_WEBUI_URL_DATA_SOURCE_IMPL_IOS_H_
+#endif  // IOS_WEB_WEBUI_URL_DATA_SOURCE_IOS_IMPL_H_
diff --git a/mash/simple_wm/simple_wm.cc b/mash/simple_wm/simple_wm.cc
index 1fad35b4..c77d4a7 100644
--- a/mash/simple_wm/simple_wm.cc
+++ b/mash/simple_wm/simple_wm.cc
@@ -4,11 +4,14 @@
 
 #include "mash/simple_wm/simple_wm.h"
 
+#include "base/observer_list.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/aura/client/aura_constants.h"
+#include "ui/aura/layout_manager.h"
 #include "ui/display/screen_base.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/geometry/mojo/geometry.mojom.h"
+#include "ui/views/controls/button/md_text_button.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/mus/aura_init.h"
 #include "ui/views/mus/mus_client.h"
@@ -26,6 +29,158 @@
 
 }  // namespace
 
+class SimpleWM::WindowListModelObserver {
+ public:
+  virtual void OnWindowAddedOrRemoved() = 0;
+  virtual void OnWindowTitleChanged(size_t index,
+                                    const base::string16& title) = 0;
+};
+
+class SimpleWM::WindowListModel : public aura::WindowObserver {
+ public:
+  explicit WindowListModel(aura::Window* window_container)
+      : window_container_(window_container) {
+    window_container_->AddObserver(this);
+  }
+  ~WindowListModel() override {
+    window_container_->RemoveObserver(this);
+    for (auto window : windows_)
+      window->RemoveObserver(this);
+  }
+
+  size_t GetSize() const {
+    return windows_.size();
+  }
+  base::string16 GetTitle(size_t index) const {
+    return windows_.at(index)->GetTitle();
+  }
+  aura::Window* GetWindow(size_t index) const {
+    return windows_.at(index);
+  }
+
+  void AddObserver(WindowListModelObserver* observer) {
+    observers_.AddObserver(observer);
+  }
+  void RemoveObserver(WindowListModelObserver* observer) {
+    observers_.RemoveObserver(observer);
+  }
+
+ private:
+  // aura::WindowObserver:
+  void OnWindowAdded(aura::Window* window) override {
+    if (window->parent() == window_container_)
+      AddWindow(window);
+    for (auto& observer : observers_)
+      observer.OnWindowAddedOrRemoved();
+  }
+  void OnWillRemoveWindow(aura::Window* window) override {
+    window->RemoveObserver(this);
+    for (auto& observer : observers_)
+      observer.OnWindowAddedOrRemoved();
+    auto it = std::find(windows_.begin(), windows_.end(), window);
+    DCHECK(it != windows_.end());
+    windows_.erase(it);
+  }
+  void OnWindowTitleChanged(aura::Window* window) override {
+    auto it = std::find(windows_.begin(), windows_.end(), window);
+    size_t index = it - windows_.begin();
+    for (auto& observer : observers_)
+      observer.OnWindowTitleChanged(index, window->GetTitle());
+  }
+
+  void AddWindow(aura::Window* window) {
+    window->AddObserver(this);
+    auto it = std::find(windows_.begin(), windows_.end(), window);
+    DCHECK(it == windows_.end());
+    windows_.push_back(window);
+  }
+
+  aura::Window* window_container_;
+  std::vector<aura::Window*> windows_;
+  base::ObserverList<WindowListModelObserver> observers_;
+
+  DISALLOW_COPY_AND_ASSIGN(WindowListModel);
+};
+
+class SimpleWM::WindowListView : public views::WidgetDelegateView,
+                                 public views::ButtonListener,
+                                 public SimpleWM::WindowListModelObserver {
+ public:
+  using ActivateCallback = base::Callback<void(aura::Window*)>;
+
+  WindowListView(WindowListModel* model, ActivateCallback activate_callback)
+      : model_(model), activate_callback_(activate_callback) {
+    model_->AddObserver(this);
+    Rebuild();
+  }
+  ~WindowListView() override {
+    model_->RemoveObserver(this);
+  }
+
+  static const int kButtonSpacing = 5;
+
+  // views::View
+  void Layout() override {
+    int x_offset = kButtonSpacing;
+    for (int i = 0; i < child_count(); ++i) {
+      View* v = child_at(i);
+      gfx::Size ps = v->GetPreferredSize();
+      gfx::Rect bounds(x_offset, kButtonSpacing, ps.width(), ps.height());
+      v->SetBoundsRect(bounds);
+      x_offset = bounds.right() + kButtonSpacing;
+    }
+  }
+  void OnPaint(gfx::Canvas* canvas) override {
+    canvas->DrawColor(SK_ColorLTGRAY);
+  }
+  gfx::Size GetPreferredSize() const override {
+    std::unique_ptr<views::MdTextButton> measure_button(
+        views::MdTextButton::Create(nullptr, base::UTF8ToUTF16("Sample")));
+    int height =
+        measure_button->GetPreferredSize().height() + 2 * kButtonSpacing;
+    return gfx::Size(0, height);
+  }
+
+ private:
+  // views::ButtonListener:
+  void ButtonPressed(views::Button* sender, const ui::Event& event) override {
+    activate_callback_.Run(
+        model_->GetWindow(static_cast<size_t>(sender->tag())));
+  }
+
+  // WindowListModelObserver:
+  void OnWindowAddedOrRemoved() override {
+    Rebuild();
+  }
+  void OnWindowTitleChanged(size_t index,
+                            const base::string16& new_title) override {
+    views::MdTextButton* label =
+        static_cast<views::MdTextButton*>(child_at(static_cast<int>(index)));
+    label->SetText(new_title);
+    Layout();
+  }
+
+  void Rebuild() {
+    RemoveAllChildViews(true);
+
+    size_t size = model_->GetSize();
+    for (size_t i = 0; i < size; ++i) {
+      base::string16 title = model_->GetTitle(i);
+      if (title.empty())
+        title = base::UTF8ToUTF16("Untitled");
+      views::MdTextButton* button = views::MdTextButton::Create(this, title);
+      button->set_tag(static_cast<int>(i));
+      AddChildView(button);
+    }
+    Layout();
+  }
+
+  WindowListModel* model_;
+  ActivateCallback activate_callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(WindowListView);
+};
+
 class SimpleWM::FrameView : public views::WidgetDelegateView,
                             public aura::WindowObserver {
  public:
@@ -38,11 +193,14 @@
  private:
   // views::WidgetDelegateView:
   base::string16 GetWindowTitle() const override {
-    base::string16* title =
+    base::string16* title_from_property =
         client_window_->GetProperty(aura::client::kTitleKey);
-    if (!title)
-      return base::UTF8ToUTF16("(Window)");
-    return *title;
+    base::string16 title = title_from_property ? *title_from_property
+                                               : base::UTF8ToUTF16("(Window)");
+    // TODO(beng): quick hack to cause WindowObserver::OnWindowTitleChanged to
+    //             fire.
+    GetWidget()->GetNativeWindow()->SetTitle(title);
+    return title;
   }
   void Layout() override {
     // Client offsets are applied automatically by the window service.
@@ -63,6 +221,50 @@
   DISALLOW_COPY_AND_ASSIGN(FrameView);
 };
 
+class SimpleWM::DisplayLayoutManager : public aura::LayoutManager {
+ public:
+  DisplayLayoutManager(aura::Window* display_root,
+                       aura::Window* window_root,
+                       SimpleWM::WindowListView* window_list_view)
+      : display_root_(display_root),
+        window_root_(window_root),
+        window_list_view_(window_list_view) {}
+  ~DisplayLayoutManager() override {}
+
+ private:
+  // aura::LayoutManager:
+  void OnWindowResized() override {}
+  void OnWindowAddedToLayout(aura::Window* child) override {
+    Layout();
+  }
+  void OnWillRemoveWindowFromLayout(aura::Window* child) override {}
+  void OnWindowRemovedFromLayout(aura::Window* child) override {}
+  void OnChildWindowVisibilityChanged(aura::Window* child,
+                                      bool visible) override {}
+  void SetChildBounds(aura::Window* child,
+                      const gfx::Rect& requested_bounds) override {
+    SetChildBoundsDirect(child, requested_bounds);
+  }
+
+  void Layout() {
+    gfx::Size ps = window_list_view_->GetPreferredSize();
+    gfx::Rect bounds = display_root_->bounds();
+    gfx::Rect window_root_bounds = bounds;
+    window_root_bounds.set_height(window_root_bounds.height() - ps.height());
+    window_root_->SetBounds(window_root_bounds);
+    gfx::Rect window_list_view_bounds = bounds;
+    window_list_view_bounds.set_height(ps.height());
+    window_list_view_bounds.set_y(window_root_bounds.bottom());
+    window_list_view_->GetWidget()->SetBounds(window_list_view_bounds);
+  }
+
+  aura::Window* display_root_;
+  aura::Window* window_root_;
+  SimpleWM::WindowListView* window_list_view_;
+
+  DISALLOW_COPY_AND_ASSIGN(DisplayLayoutManager);
+};
+
 SimpleWM::SimpleWM() {}
 
 SimpleWM::~SimpleWM() {
@@ -165,7 +367,7 @@
   FrameView* frame_view = new FrameView(client_window);
   params.delegate = frame_view;
   params.native_widget = frame_native_widget;
-  params.parent = root_;
+  params.parent = window_root_;
   params.bounds = gfx::Rect(10, 10, 500, 500);
   frame_widget->Init(params);
   frame_widget->Show();
@@ -194,11 +396,36 @@
     std::unique_ptr<aura::WindowTreeHostMus> window_tree_host,
     const display::Display& display) {
   // Only handles a single root.
-  DCHECK(!root_);
+  DCHECK(!window_root_);
   window_tree_host_ = std::move(window_tree_host);
-  root_ = window_tree_host_->window();
+  window_tree_host_->InitHost();
+  display_root_ = window_tree_host_->window();
+  window_root_ = new aura::Window(nullptr);
+  window_root_->Init(ui::LAYER_NOT_DRAWN);
+  display_root_->AddChild(window_root_);
+  window_root_->Show();
+
+  window_list_model_ = base::MakeUnique<WindowListModel>(window_root_);
+
+  views::Widget* window_list_widget = new views::Widget;
+  views::NativeWidgetAura* window_list_widget_native_widget =
+      new views::NativeWidgetAura(window_list_widget, true);
+  views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL);
+  WindowListView* window_list_view =
+      new WindowListView(window_list_model_.get(),
+                         base::Bind(&SimpleWM::OnWindowListViewItemActivated,
+                                    base::Unretained(this)));
+  params.delegate = window_list_view;
+  params.native_widget = window_list_widget_native_widget;
+  params.parent = display_root_;
+  window_list_widget->Init(params);
+  window_list_widget->Show();
+
+  display_root_->SetLayoutManager(new DisplayLayoutManager(
+      display_root_, window_root_, window_list_view));
+
   DCHECK(window_manager_client_);
-  window_manager_client_->AddActivationParent(root_);
+  window_manager_client_->AddActivationParent(window_root_);
   ui::mojom::FrameDecorationValuesPtr frame_decoration_values =
       ui::mojom::FrameDecorationValues::New();
   frame_decoration_values->normal_client_area_insets.Set(
@@ -206,14 +433,14 @@
   frame_decoration_values->max_title_bar_button_width = 0;
   window_manager_client_->SetFrameDecorationValues(
       std::move(frame_decoration_values));
-  new wm::DefaultActivationClient(root_);
-  aura::client::SetFocusClient(root_, &focus_client_);
+  new wm::DefaultActivationClient(display_root_);
+  aura::client::SetFocusClient(display_root_, &focus_client_);
 }
 
 void SimpleWM::OnWmDisplayRemoved(
     aura::WindowTreeHostMus* window_tree_host) {
   DCHECK_EQ(window_tree_host, window_tree_host_.get());
-  root_ = nullptr;
+  window_root_ = nullptr;
   window_tree_host_.reset();
 }
 
@@ -240,5 +467,10 @@
   return it != client_window_to_frame_view_.end() ? it->second : nullptr;
 }
 
-}  // namespace simple_wm
+void SimpleWM::OnWindowListViewItemActivated(aura::Window* window) {
+  aura::client::ActivationClient* activation_client =
+      aura::client::GetActivationClient(window->GetRootWindow());
+  activation_client->ActivateWindow(window);
+}
 
+}  // namespace simple_wm
diff --git a/mash/simple_wm/simple_wm.h b/mash/simple_wm/simple_wm.h
index f677cc8..d0dc5a0 100644
--- a/mash/simple_wm/simple_wm.h
+++ b/mash/simple_wm/simple_wm.h
@@ -47,7 +47,11 @@
   ~SimpleWM() override;
 
  private:
+  class DisplayLayoutManager;
   class FrameView;
+  class WindowListModel;
+  class WindowListModelObserver;
+  class WindowListView;
 
   // service_manager::Service:
   void OnStart() override;
@@ -93,18 +97,22 @@
 
   FrameView* GetFrameViewForClientWindow(aura::Window* client_window);
 
+  void OnWindowListViewItemActivated(aura::Window* index);
+
   std::unique_ptr<views::AuraInit> aura_init_;
   ::wm::WMState wm_state_;
   std::unique_ptr<display::ScreenBase> screen_;
   aura::PropertyConverter property_converter_;
   aura::test::TestFocusClient focus_client_;
   std::unique_ptr<aura::WindowTreeHostMus> window_tree_host_;
-  aura::Window* root_ = nullptr;
+  aura::Window* display_root_ = nullptr;
+  aura::Window* window_root_ = nullptr;
   aura::WindowManagerClient* window_manager_client_ = nullptr;
   std::unique_ptr<aura::WindowTreeClient> window_tree_client_;
   std::unique_ptr<ui::Gpu> gpu_;
   std::unique_ptr<aura::MusContextFactory> compositor_context_factory_;
   std::map<aura::Window*, FrameView*> client_window_to_frame_view_;
+  std::unique_ptr<WindowListModel> window_list_model_;
 
   bool started_ = false;
 
diff --git a/media/base/demuxer_stream_provider.h b/media/base/demuxer_stream_provider.h
index dba6a6ce..3534550 100644
--- a/media/base/demuxer_stream_provider.h
+++ b/media/base/demuxer_stream_provider.h
@@ -39,6 +39,13 @@
   //   Returns the first stream of the given stream type (which is not allowed
   //   to be DemuxerStream::TEXT), or NULL if that type of stream is not
   //   present.
+  //   NOTE: Once a DemuxerStream pointer is returned from GetStream it is
+  //   guaranteed to stay valid for as long as the Demuxer/DemuxerStreamProvider
+  //   is alive. But make no assumption that once GetStream returned a non-null
+  //   pointer for some stream type then all subsequent calls will also return
+  //   non-null pointer for the same stream type. In MSE Javascript code can
+  //   remove SourceBuffer from a MediaSource at any point and this will make
+  //   some previously existing streams inaccessible/unavailable.
   // Other types:
   //   Should not be called.
   virtual DemuxerStream* GetStream(DemuxerStream::Type type) = 0;
diff --git a/media/remoting/remote_demuxer_stream_adapter.cc b/media/remoting/remote_demuxer_stream_adapter.cc
index cc66c185..d04b194 100644
--- a/media/remoting/remote_demuxer_stream_adapter.cc
+++ b/media/remoting/remote_demuxer_stream_adapter.cc
@@ -116,6 +116,9 @@
     case remoting::pb::RpcMessage::RPC_DS_INITIALIZE:
       Initialize(message->integer_value());
       break;
+    case remoting::pb::RpcMessage::RPC_DS_ENABLEBITSTREAMCONVERTER:
+      EnableBitstreamConverter();
+      break;
     case remoting::pb::RpcMessage::RPC_DS_READUNTIL:
       ReadUntil(std::move(message));
       break;
@@ -175,6 +178,11 @@
                             rpc_broker_, base::Passed(&rpc)));
 }
 
+void RemoteDemuxerStreamAdapter::EnableBitstreamConverter() {
+  DCHECK(media_task_runner_->BelongsToCurrentThread());
+  demuxer_stream_->EnableBitstreamConverter();
+}
+
 void RemoteDemuxerStreamAdapter::ReadUntil(
     std::unique_ptr<remoting::pb::RpcMessage> message) {
   DCHECK(media_task_runner_->BelongsToCurrentThread());
diff --git a/media/remoting/remote_demuxer_stream_adapter.h b/media/remoting/remote_demuxer_stream_adapter.h
index d610cacf..76ad475 100644
--- a/media/remoting/remote_demuxer_stream_adapter.h
+++ b/media/remoting/remote_demuxer_stream_adapter.h
@@ -74,6 +74,7 @@
 
   // RPC message tasks.
   void Initialize(int remote_callback_handle);
+  void EnableBitstreamConverter();
   void ReadUntil(std::unique_ptr<remoting::pb::RpcMessage> message);
   void RequestBuffer(int callback_handle);
   void SendReadAck(int callback_handle);
diff --git a/media/renderers/renderer_impl.cc b/media/renderers/renderer_impl.cc
index 87212d8..210e5cc 100644
--- a/media/renderers/renderer_impl.cc
+++ b/media/renderers/renderer_impl.cc
@@ -131,24 +131,11 @@
   DCHECK_EQ(state_, STATE_UNINITIALIZED);
   DCHECK(!init_cb.is_null());
   DCHECK(client);
-  DCHECK(demuxer_stream_provider->GetStream(DemuxerStream::AUDIO) ||
-         demuxer_stream_provider->GetStream(DemuxerStream::VIDEO));
 
   client_ = client;
   demuxer_stream_provider_ = demuxer_stream_provider;
   init_cb_ = init_cb;
 
-  DemuxerStream* audio_stream =
-      demuxer_stream_provider->GetStream(DemuxerStream::AUDIO);
-  if (audio_stream)
-    audio_stream->SetStreamStatusChangeCB(base::Bind(
-        &RendererImpl::RestartStreamPlayback, weak_this_, audio_stream));
-  DemuxerStream* video_stream =
-      demuxer_stream_provider->GetStream(DemuxerStream::VIDEO);
-  if (video_stream)
-    video_stream->SetStreamStatusChangeCB(base::Bind(
-        &RendererImpl::RestartStreamPlayback, weak_this_, video_stream));
-
   if (HasEncryptedStream() && !cdm_context_) {
     state_ = STATE_INIT_PENDING_CDM;
     return;
@@ -384,19 +371,23 @@
   PipelineStatusCB done_cb =
       base::Bind(&RendererImpl::OnAudioRendererInitializeDone, weak_this_);
 
-  if (!demuxer_stream_provider_->GetStream(DemuxerStream::AUDIO)) {
+  DemuxerStream* audio_stream =
+      demuxer_stream_provider_->GetStream(DemuxerStream::AUDIO);
+  if (!audio_stream) {
     audio_renderer_.reset();
     task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK));
     return;
   }
 
+  audio_stream->SetStreamStatusChangeCB(base::Bind(
+      &RendererImpl::RestartStreamPlayback, weak_this_, audio_stream));
+
   audio_renderer_client_.reset(
       new RendererClientInternal(DemuxerStream::AUDIO, this));
   // Note: After the initialization of a renderer, error events from it may
   // happen at any time and all future calls must guard against STATE_ERROR.
-  audio_renderer_->Initialize(
-      demuxer_stream_provider_->GetStream(DemuxerStream::AUDIO), cdm_context_,
-      audio_renderer_client_.get(), done_cb);
+  audio_renderer_->Initialize(audio_stream, cdm_context_,
+                              audio_renderer_client_.get(), done_cb);
 }
 
 void RendererImpl::OnAudioRendererInitializeDone(PipelineStatus status) {
@@ -429,17 +420,21 @@
   PipelineStatusCB done_cb =
       base::Bind(&RendererImpl::OnVideoRendererInitializeDone, weak_this_);
 
-  if (!demuxer_stream_provider_->GetStream(DemuxerStream::VIDEO)) {
+  DemuxerStream* video_stream =
+      demuxer_stream_provider_->GetStream(DemuxerStream::VIDEO);
+  if (!video_stream) {
     video_renderer_.reset();
     task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK));
     return;
   }
 
+  video_stream->SetStreamStatusChangeCB(base::Bind(
+      &RendererImpl::RestartStreamPlayback, weak_this_, video_stream));
+
   video_renderer_client_.reset(
       new RendererClientInternal(DemuxerStream::VIDEO, this));
   video_renderer_->Initialize(
-      demuxer_stream_provider_->GetStream(DemuxerStream::VIDEO), cdm_context_,
-      video_renderer_client_.get(),
+      video_stream, cdm_context_, video_renderer_client_.get(),
       base::Bind(&RendererImpl::GetWallClockTimes, base::Unretained(this)),
       done_cb);
 }
diff --git a/media/renderers/renderer_impl_unittest.cc b/media/renderers/renderer_impl_unittest.cc
index 1e3e706..9f9fbad 100644
--- a/media/renderers/renderer_impl_unittest.cc
+++ b/media/renderers/renderer_impl_unittest.cc
@@ -150,12 +150,34 @@
   void InitializeWithAudio() {
     CreateAudioStream();
     SetAudioRendererInitializeExpectations(PIPELINE_OK);
+    // There is a potential race between HTMLMediaElement/WMPI shutdown and
+    // renderers being initialized which might result in DemuxerStreamProvider
+    // GetStream suddenly returning NULL (see crbug.com/668604). So we are going
+    // to check here that GetStream will be invoked exactly 3 times during
+    // RendererImpl initialization to help catch potential issues. Currently the
+    // GetStream is invoked once directly from RendererImpl::Initialize, once
+    // indirectly from RendererImpl::Initialize via HasEncryptedStream and once
+    // from RendererImpl::InitializeAudioRenderer.
+    EXPECT_CALL(*demuxer_, GetStream(DemuxerStream::AUDIO))
+        .Times(2)
+        .WillRepeatedly(Return(audio_stream_.get()));
     InitializeAndExpect(PIPELINE_OK);
   }
 
   void InitializeWithVideo() {
     CreateVideoStream();
     SetVideoRendererInitializeExpectations(PIPELINE_OK);
+    // There is a potential race between HTMLMediaElement/WMPI shutdown and
+    // renderers being initialized which might result in DemuxerStreamProvider
+    // GetStream suddenly returning NULL (see crbug.com/668604). So we are going
+    // to check here that GetStream will be invoked exactly 3 times during
+    // RendererImpl initialization to help catch potential issues. Currently the
+    // GetStream is invoked once directly from RendererImpl::Initialize, once
+    // indirectly from RendererImpl::Initialize via HasEncryptedStream and once
+    // from RendererImpl::InitializeVideoRenderer.
+    EXPECT_CALL(*demuxer_, GetStream(DemuxerStream::VIDEO))
+        .Times(2)
+        .WillRepeatedly(Return(video_stream_.get()));
     InitializeAndExpect(PIPELINE_OK);
   }
 
diff --git a/mojo/edk/js/tests/connection_tests.js b/mojo/edk/js/tests/connection_tests.js
index 0b4b2134..2e8fc97f 100644
--- a/mojo/edk/js/tests/connection_tests.js
+++ b/mojo/edk/js/tests/connection_tests.js
@@ -4,14 +4,14 @@
 
 define([
     "gin/test/expect",
-    "mojo/public/js/connection",
+    "mojo/public/js/bindings",
     "mojo/public/js/core",
     "mojo/public/interfaces/bindings/tests/sample_interfaces.mojom",
     "mojo/public/interfaces/bindings/tests/sample_service.mojom",
     "mojo/public/js/threading",
     "gc",
 ], function(expect,
-            connection,
+            bindings,
             core,
             sample_interfaces,
             sample_service,
@@ -35,37 +35,34 @@
     function ServiceImpl() {
     }
 
-    ServiceImpl.prototype = Object.create(
-        sample_service.Service.stubClass.prototype);
-
     ServiceImpl.prototype.frobinate = function(foo, baz, port) {
       expect(foo.name).toBe("Example name");
       expect(baz).toBe(sample_service.Service.BazOptions.REGULAR);
-      expect(core.close(port)).toBe(core.RESULT_OK);
+      expect(port.ptr.isBound()).toBeTruthy();
+      port.ptr.reset();
 
       return Promise.resolve({result: 42});
     };
 
-    var pipe = core.createMessagePipe();
-    var anotherPipe = core.createMessagePipe();
+    var service = new sample_service.ServicePtr();
+    var serviceBinding = new bindings.Binding(sample_service.Service,
+                                              new ServiceImpl(),
+                                              bindings.makeRequest(service));
     var sourcePipe = core.createMessagePipe();
-
-    var connection0 = new connection.Connection(pipe.handle0, ServiceImpl);
-
-    var connection1 = new connection.Connection(
-        pipe.handle1, undefined, sample_service.Service.proxyClass);
+    var port = new sample_service.PortPtr();
+    var portRequest = bindings.makeRequest(port);
 
     var foo = new sample_service.Foo();
     foo.bar = new sample_service.Bar();
     foo.name = "Example name";
     foo.source = sourcePipe.handle0;
-    var promise = connection1.remote.frobinate(
-        foo, sample_service.Service.BazOptions.REGULAR, anotherPipe.handle0)
+    var promise = service.frobinate(
+        foo, sample_service.Service.BazOptions.REGULAR, port)
             .then(function(response) {
       expect(response.result).toBe(42);
 
-      connection0.close();
-      connection1.close();
+      service.ptr.reset();
+      serviceBinding.close();
 
       return Promise.resolve();
     });
@@ -73,38 +70,26 @@
     // sourcePipe.handle1 hasn't been closed yet.
     expect(core.close(sourcePipe.handle1)).toBe(core.RESULT_OK);
 
-    // anotherPipe.handle1 hasn't been closed yet.
-    expect(core.close(anotherPipe.handle1)).toBe(core.RESULT_OK);
+    // portRequest.handle hasn't been closed yet.
+    expect(core.close(portRequest.handle)).toBe(core.RESULT_OK);
 
     return promise;
   }
 
   function testWriteToClosedPipe() {
-    var pipe = core.createMessagePipe();
-    var anotherPipe = core.createMessagePipe();
+    var service = new sample_service.ServicePtr();
+    // Discard the interface request.
+    bindings.makeRequest(service);
 
-    var connection1 = new connection.Connection(
-        pipe.handle1, function() {}, sample_service.Service.proxyClass);
-
-    // Close the other end of the pipe.
-    core.close(pipe.handle0);
-
-    // Not observed yet because we haven't pumped events yet.
-    expect(connection1.encounteredError()).toBeFalsy();
-
-    var promise = connection1.remote.frobinate(
-        null, sample_service.Service.BazOptions.REGULAR, anotherPipe.handle0)
+    var promise = service.frobinate(
+        null, sample_service.Service.BazOptions.REGULAR, null)
             .then(function(response) {
       return Promise.reject("Unexpected response");
     }).catch(function(e) {
       // We should observe the closed pipe.
-      expect(connection1.encounteredError()).toBeTruthy();
       return Promise.resolve();
     });
 
-    // Write failures are not reported.
-    expect(connection1.encounteredError()).toBeFalsy();
-
     return promise;
   }
 
@@ -114,9 +99,6 @@
     function ProviderImpl() {
     }
 
-    ProviderImpl.prototype =
-        Object.create(sample_interfaces.Provider.stubClass.prototype);
-
     ProviderImpl.prototype.echoString = function(a) {
       return Promise.resolve({a: a});
     };
@@ -125,17 +107,13 @@
       return Promise.resolve({a: a, b: b});
     };
 
-    var pipe = core.createMessagePipe();
-
-    var connection0 = new connection.Connection(pipe.handle0, ProviderImpl);
-
-    var connection1 = new connection.Connection(
-        pipe.handle1, undefined, sample_interfaces.Provider.proxyClass);
-
-    var promise = connection1.remote.echoString("hello")
-        .then(function(response) {
+    var provider = new sample_interfaces.ProviderPtr();
+    var providerBinding = new bindings.Binding(sample_interfaces.Provider,
+                                               new ProviderImpl(),
+                                               bindings.makeRequest(provider));
+    var promise = provider.echoString("hello").then(function(response) {
       expect(response.a).toBe("hello");
-      return connection1.remote.echoStrings("hello", "world");
+      return provider.echoStrings("hello", "world");
     }).then(function(response) {
       expect(response.a).toBe("hello");
       expect(response.b).toBe("world");
@@ -143,7 +121,7 @@
       core.readMessage = function() {
         return { result: core.RESULT_UNKNOWN };
       };
-      return connection1.remote.echoString("goodbye");
+      return provider.echoString("goodbye");
     }).then(function() {
       throw Error("Expected echoString to fail.");
     }, function(error) {
diff --git a/mojo/edk/js/tests/sample_service_tests.js b/mojo/edk/js/tests/sample_service_tests.js
index 71aa48c..b9a28458 100644
--- a/mojo/edk/js/tests/sample_service_tests.js
+++ b/mojo/edk/js/tests/sample_service_tests.js
@@ -73,7 +73,7 @@
     ServiceImpl.prototype.frobinate = function(foo, baz, port) {
       checkFoo(foo);
       expect(baz).toBe(sample.Service.BazOptions.EXTRA);
-      bindings.ProxyBindings(port).close();
+      expect(port.ptr.isBound()).toBeTruthy();
       return Promise.resolve({result: 1234});
     };
 
@@ -85,9 +85,10 @@
     var serviceBinding = new bindings.Binding(
         sample.Service, new ServiceImpl(), request);
 
-    var pipe = core.createMessagePipe();
+    var port = new sample.PortPtr();
+    bindings.makeRequest(port);
     var promise = service.frobinate(
-        foo, sample.Service.BazOptions.EXTRA, pipe.handle0)
+        foo, sample.Service.BazOptions.EXTRA, port)
             .then(function(response) {
       expect(response.result).toBe(1234);
 
diff --git a/mojo/public/js/BUILD.gn b/mojo/public/js/BUILD.gn
index eda7e04d..8b23be9 100644
--- a/mojo/public/js/BUILD.gn
+++ b/mojo/public/js/BUILD.gn
@@ -19,6 +19,7 @@
     "constants.cc",
     "constants.h",
     "core.js",
+    "interface_types.js",
     "router.js",
     "support.js",
     "threading.js",
diff --git a/mojo/public/js/bindings.js b/mojo/public/js/bindings.js
index 8d8565c..4ae23116 100644
--- a/mojo/public/js/bindings.js
+++ b/mojo/public/js/bindings.js
@@ -5,35 +5,15 @@
 define("mojo/public/js/bindings", [
   "mojo/public/js/connection",
   "mojo/public/js/core",
-], function(connection, core) {
-
-  // ---------------------------------------------------------------------------
-
-  function InterfacePtrInfo(handle, version) {
-    this.handle = handle;
-    this.version = version;
-  }
-
-  InterfacePtrInfo.prototype.isValid = function() {
-    return core.isHandle(this.handle);
-  }
-
-  // ---------------------------------------------------------------------------
-
-  function InterfaceRequest(handle) {
-    this.handle = handle;
-  }
-
-  InterfaceRequest.prototype.isValid = function() {
-    return core.isHandle(this.handle);
-  }
+  "mojo/public/js/interface_types",
+], function(connection, core, types) {
 
   // ---------------------------------------------------------------------------
 
   function makeRequest(interfacePtr) {
     var pipe = core.createMessagePipe();
-    interfacePtr.ptr.bind(new InterfacePtrInfo(pipe.handle0, 0));
-    return new InterfaceRequest(pipe.handle1);
+    interfacePtr.ptr.bind(new types.InterfacePtrInfo(pipe.handle0, 0));
+    return new types.InterfaceRequest(pipe.handle1);
   }
 
   // ---------------------------------------------------------------------------
@@ -42,50 +22,77 @@
   // |ptr| field of generated interface pointer classes.
   function InterfacePtrController(interfaceType) {
     this.version = 0;
-    this.connection = null;
 
     this.interfaceType_ = interfaceType;
+    this.connection_ = null;
+    // |connection_| is lazily initialized. |handle_| is valid between bind()
+    // and the initialization of |connection_|.
+    this.handle_ = null;
   }
 
   InterfacePtrController.prototype.bind = function(interfacePtrInfo) {
     this.reset();
+
     this.version = interfacePtrInfo.version;
-    this.connection = new connection.Connection(
-      interfacePtrInfo.handle, undefined, this.interfaceType_.proxyClass);
-  }
+    this.handle_ = interfacePtrInfo.handle;
+  };
 
   InterfacePtrController.prototype.isBound = function() {
-    return this.connection !== null;
-  }
+    return this.connection_ !== null || this.handle_ !== null;
+  };
 
   // Although users could just discard the object, reset() closes the pipe
   // immediately.
   InterfacePtrController.prototype.reset = function() {
-    if (!this.isBound())
-      return;
-
     this.version = 0;
-    this.connection.close();
-    this.connection = null;
-  }
+    if (this.connection_) {
+      this.connection_.close();
+      this.connection_ = null;
+    }
+    if (this.handle_) {
+      core.close(this.handle_);
+      this.handle_ = null;
+    }
+  };
 
   InterfacePtrController.prototype.setConnectionErrorHandler
       = function(callback) {
     if (!this.isBound())
       throw new Error("Cannot set connection error handler if not bound.");
-    this.connection.router_.setErrorHandler(callback);
-  }
+
+    this.configureProxyIfNecessary_();
+    this.connection_.router_.setErrorHandler(callback);
+  };
 
   InterfacePtrController.prototype.passInterface = function() {
-    if (!this.isBound())
-      return new InterfacePtrInfo(null, 0);
+    var result;
+    if (this.connection_) {
+      result = new types.InterfacePtrInfo(
+          this.connection_.router_.connector_.handle_, this.version);
+      this.connection_.router_.connector_.handle_ = null;
+    } else {
+      // This also handles the case when this object is not bound.
+      result = new types.InterfacePtrInfo(this.handle_, this.version);
+      this.handle_ = null;
+    }
 
-    var result = new InterfacePtrInfo(
-        this.connection.router_.connector_.handle_, this.version);
-    this.connection.router_.connector_.handle_ = null;
     this.reset();
     return result;
-  }
+  };
+
+  InterfacePtrController.prototype.getProxy = function() {
+    this.configureProxyIfNecessary_();
+    return this.connection_.remote;
+  };
+
+  InterfacePtrController.prototype.configureProxyIfNecessary_ = function() {
+    if (!this.handle_)
+      return;
+
+    this.connection_ = new connection.Connection(
+        this.handle_, undefined, this.interfaceType_.proxyClass);
+    this.handle_ = null;
+  };
 
   // TODO(yzshen): Implement the following methods.
   //   InterfacePtrController.prototype.queryVersion
@@ -119,21 +126,30 @@
 
   Binding.prototype.isBound = function() {
     return this.stub_ !== null;
+  };
+
+  Binding.prototype.createInterfacePtrAndBind = function() {
+    var ptr = new this.interfaceType_.ptrClass();
+    // TODO(yzshen): Set the version of the interface pointer.
+    this.bind(makeRequest(ptr));
+    return ptr;
   }
 
   Binding.prototype.bind = function(request) {
     this.close();
-    this.stub_ = connection.bindHandleToStub(request.handle,
-                                             this.interfaceType_);
-    connection.StubBindings(this.stub_).delegate = this.impl_;
-  }
+    if (request.isValid()) {
+      this.stub_ = connection.bindHandleToStub(request.handle,
+                                               this.interfaceType_);
+      connection.StubBindings(this.stub_).delegate = this.impl_;
+    }
+  };
 
   Binding.prototype.close = function() {
     if (!this.isBound())
       return;
     connection.StubBindings(this.stub_).close();
     this.stub_ = null;
-  }
+  };
 
   Binding.prototype.setConnectionErrorHandler
       = function(callback) {
@@ -141,24 +157,24 @@
       throw new Error("Cannot set connection error handler if not bound.");
     connection.StubBindings(this.stub_).connection.router_.setErrorHandler(
         callback);
-  }
+  };
 
   Binding.prototype.unbind = function() {
     if (!this.isBound())
-      return new InterfaceRequest(null);
+      return new types.InterfaceRequest(null);
 
-    var result = new InterfaceRequest(
+    var result = new types.InterfaceRequest(
         connection.StubBindings(this.stub_).connection.router_.connector_
             .handle_);
     connection.StubBindings(this.stub_).connection.router_.connector_.handle_ =
         null;
     this.close();
     return result;
-  }
+  };
 
   var exports = {};
-  exports.InterfacePtrInfo = InterfacePtrInfo;
-  exports.InterfaceRequest = InterfaceRequest;
+  exports.InterfacePtrInfo = types.InterfacePtrInfo;
+  exports.InterfaceRequest = types.InterfaceRequest;
   exports.makeRequest = makeRequest;
   exports.InterfacePtrController = InterfacePtrController;
   exports.Binding = Binding;
diff --git a/mojo/public/js/codec.js b/mojo/public/js/codec.js
index 70df758..3ee2274 100644
--- a/mojo/public/js/codec.js
+++ b/mojo/public/js/codec.js
@@ -3,9 +3,10 @@
 // found in the LICENSE file.
 
 define("mojo/public/js/codec", [
-  "mojo/public/js/unicode",
   "mojo/public/js/buffer",
-], function(unicode, buffer) {
+  "mojo/public/js/interface_types",
+  "mojo/public/js/unicode",
+], function(buffer, types, unicode) {
 
   var kErrorUnsigned = "Passing negative value to unsigned";
   var kErrorArray = "Passing non Array for array type";
@@ -802,33 +803,54 @@
 
   NullableHandle.encode = Handle.encode;
 
-  function Interface() {
+  function Interface(cls) {
+    this.cls = cls;
   }
 
-  Interface.encodedSize = 8;
+  Interface.prototype.encodedSize = 8;
 
-  Interface.decode = function(decoder) {
-    var handle = decoder.decodeHandle();
-    // Ignore the version field for now.
-    decoder.readUint32();
-
-    return handle;
+  Interface.prototype.decode = function(decoder) {
+    var interfacePtrInfo = new types.InterfacePtrInfo(
+        decoder.decodeHandle(), decoder.readUint32());
+    var interfacePtr = new this.cls();
+    interfacePtr.ptr.bind(interfacePtrInfo);
+    return interfacePtr;
   };
 
-  Interface.encode = function(encoder, val) {
-    encoder.encodeHandle(val);
-    // Set the version field to 0 for now.
-    encoder.writeUint32(0);
+  Interface.prototype.encode = function(encoder, val) {
+    var interfacePtrInfo =
+        val ? val.ptr.passInterface() : new InterfacePtrInfo(null, 0);
+    encoder.encodeHandle(interfacePtrInfo.handle);
+    encoder.writeUint32(interfacePtrInfo.version);
   };
 
-  function NullableInterface() {
+  function NullableInterface(cls) {
+    Interface.call(this, cls);
   }
 
-  NullableInterface.encodedSize = Interface.encodedSize;
+  NullableInterface.prototype = Object.create(Interface.prototype);
 
-  NullableInterface.decode = Interface.decode;
+  function InterfaceRequest() {
+  }
 
-  NullableInterface.encode = Interface.encode;
+  InterfaceRequest.encodedSize = 4;
+
+  InterfaceRequest.decode = function(decoder) {
+    return new types.InterfaceRequest(decoder.decodeHandle());
+  };
+
+  InterfaceRequest.encode = function(encoder, val) {
+    encoder.encodeHandle(val ? val.handle : null);
+  };
+
+  function NullableInterfaceRequest() {
+  }
+
+  NullableInterfaceRequest.encodedSize = InterfaceRequest.encodedSize;
+
+  NullableInterfaceRequest.decode = InterfaceRequest.decode;
+
+  NullableInterfaceRequest.encode = InterfaceRequest.encode;
 
   function MapOf(keyClass, valueClass) {
     this.keyClass = keyClass;
@@ -888,6 +910,8 @@
   exports.NullableHandle = NullableHandle;
   exports.Interface = Interface;
   exports.NullableInterface = NullableInterface;
+  exports.InterfaceRequest = InterfaceRequest;
+  exports.NullableInterfaceRequest = NullableInterfaceRequest;
   exports.MapOf = MapOf;
   exports.NullableMapOf = NullableMapOf;
   return exports;
diff --git a/mojo/public/js/constants.cc b/mojo/public/js/constants.cc
index d29f5cb..2c9b9802 100644
--- a/mojo/public/js/constants.cc
+++ b/mojo/public/js/constants.cc
@@ -11,8 +11,9 @@
 const char kCodecModuleName[] = "mojo/public/js/codec";
 const char kConnectionModuleName[] = "mojo/public/js/connection";
 const char kConnectorModuleName[] = "mojo/public/js/connector";
-const char kUnicodeModuleName[] = "mojo/public/js/unicode";
+const char kInterfaceTypesModuleName[] = "mojo/public/js/interface_types";
 const char kRouterModuleName[] = "mojo/public/js/router";
+const char kUnicodeModuleName[] = "mojo/public/js/unicode";
 const char kValidatorModuleName[] = "mojo/public/js/validator";
 
 }  // namespace mojo
diff --git a/mojo/public/js/constants.h b/mojo/public/js/constants.h
index de75a90..c7cd9911 100644
--- a/mojo/public/js/constants.h
+++ b/mojo/public/js/constants.h
@@ -13,8 +13,9 @@
 extern const char kCodecModuleName[];
 extern const char kConnectionModuleName[];
 extern const char kConnectorModuleName[];
-extern const char kUnicodeModuleName[];
+extern const char kInterfaceTypesModuleName[];
 extern const char kRouterModuleName[];
+extern const char kUnicodeModuleName[];
 extern const char kValidatorModuleName[];
 
 }  // namespace mojo
diff --git a/mojo/public/js/interface_types.js b/mojo/public/js/interface_types.js
new file mode 100644
index 0000000..01ea2d1
--- /dev/null
+++ b/mojo/public/js/interface_types.js
@@ -0,0 +1,52 @@
+// 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.
+
+define("mojo/public/js/interface_types", [
+  "mojo/public/js/core",
+], function(core) {
+
+  // ---------------------------------------------------------------------------
+
+  function InterfacePtrInfo(handle, version) {
+    this.handle = handle;
+    this.version = version;
+  }
+
+  InterfacePtrInfo.prototype.isValid = function() {
+    return core.isHandle(this.handle);
+  };
+
+  InterfacePtrInfo.prototype.close = function() {
+    if (!this.isValid())
+      return;
+
+    core.close(this.handle);
+    this.handle = null;
+    this.version = 0;
+  };
+
+  // ---------------------------------------------------------------------------
+
+  function InterfaceRequest(handle) {
+    this.handle = handle;
+  }
+
+  InterfaceRequest.prototype.isValid = function() {
+    return core.isHandle(this.handle);
+  };
+
+  InterfaceRequest.prototype.close = function() {
+    if (!this.isValid())
+      return;
+
+    core.close(this.handle);
+    this.handle = null;
+  };
+
+  var exports = {};
+  exports.InterfacePtrInfo = InterfacePtrInfo;
+  exports.InterfaceRequest = InterfaceRequest;
+
+  return exports;
+});
diff --git a/mojo/public/js/validator.js b/mojo/public/js/validator.js
index a3f4f00..1328c33 100644
--- a/mojo/public/js/validator.js
+++ b/mojo/public/js/validator.js
@@ -42,12 +42,18 @@
   }
 
   function isInterfaceClass(cls) {
-    return cls === codec.Interface || cls === codec.NullableInterface;
+    return cls instanceof codec.Interface;
+  }
+
+  function isInterfaceRequestClass(cls) {
+    return cls === codec.InterfaceRequest ||
+        cls === codec.NullableInterfaceRequest;
   }
 
   function isNullable(type) {
     return type === codec.NullableString || type === codec.NullableHandle ||
         type === codec.NullableInterface ||
+        type === codec.NullableInterfaceRequest ||
         type instanceof codec.NullableArrayOf ||
         type instanceof codec.NullablePointerTo;
   }
@@ -119,6 +125,7 @@
 
     if (!this.claimHandle(index))
       return validationError.ILLEGAL_HANDLE;
+
     return validationError.NONE;
   };
 
@@ -126,6 +133,10 @@
     return this.validateHandle(offset, nullable);
   };
 
+  Validator.prototype.validateInterfaceRequest = function(offset, nullable) {
+    return this.validateHandle(offset, nullable);
+  };
+
   Validator.prototype.validateStructHeader = function(offset, minNumBytes) {
     if (!codec.isAligned(offset))
       return validationError.MISALIGNED_OBJECT;
@@ -372,6 +383,9 @@
     if (isInterfaceClass(elementType))
       return this.validateInterfaceElements(
           elementsOffset, numElements, nullable);
+    if (isInterfaceRequestClass(elementType))
+      return this.validateInterfaceRequestElements(
+          elementsOffset, numElements, nullable);
     if (isStringClass(elementType))
       return this.validateArrayElements(
           elementsOffset, numElements, codec.Uint8, nullable, [0], 0);
@@ -406,7 +420,7 @@
 
   Validator.prototype.validateInterfaceElements =
       function(offset, numElements, nullable) {
-    var elementSize = codec.Interface.encodedSize;
+    var elementSize = codec.Interface.prototype.encodedSize;
     for (var i = 0; i < numElements; i++) {
       var elementOffset = offset + i * elementSize;
       var err = this.validateInterface(elementOffset, nullable);
@@ -416,6 +430,18 @@
     return validationError.NONE;
   };
 
+  Validator.prototype.validateInterfaceRequestElements =
+      function(offset, numElements, nullable) {
+    var elementSize = codec.InterfaceRequest.encodedSize;
+    for (var i = 0; i < numElements; i++) {
+      var elementOffset = offset + i * elementSize;
+      var err = this.validateInterfaceRequest(elementOffset, nullable);
+      if (err != validationError.NONE)
+        return err;
+    }
+    return validationError.NONE;
+  };
+
   // The elementClass parameter is the element type of the element arrays.
   Validator.prototype.validateArrayElements =
       function(offset, numElements, elementClass, nullable,
diff --git a/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl b/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl
index c479a8b..9441589 100644
--- a/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl
+++ b/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl
@@ -14,7 +14,7 @@
 {%- for method in interface.methods %}
   {{interface.name}}Ptr.prototype.{{method.name|stylize_method}} = function() {
     return {{interface.name}}Proxy.prototype.{{method.name|stylize_method}}
-        .apply(this.ptr.connection.remote, arguments);
+        .apply(this.ptr.getProxy(), arguments);
   };
 
   {{interface.name}}Proxy.prototype.{{method.name|stylize_method}} = function(
@@ -24,7 +24,7 @@
 ) {
     var params = new {{interface.name}}_{{method.name}}_Params();
 {%- for parameter in method.parameters %}
-    params.{{parameter.name}} = {{parameter|js_proxy_method_parameter_value}};
+    params.{{parameter.name}} = {{parameter.name}};
 {%- endfor %}
 
 {%- if method.response_parameters == None %}
@@ -64,7 +64,7 @@
 {%-   set js_method_name = method.name|stylize_method %}
 {%-   set delegate_expr =  "bindings.StubBindings(this).delegate" %}
   {{interface.name}}Stub.prototype.{{js_method_name}} = function({{method.parameters|map(attribute='name')|join(', ')}}) {
-    return {{delegate_expr}} && {{delegate_expr}}.{{js_method_name}} && {{delegate_expr}}.{{js_method_name}}({{method.parameters|map('js_stub_method_parameter_value')|join(', ')}});
+    return {{delegate_expr}} && {{delegate_expr}}.{{js_method_name}} && {{delegate_expr}}.{{js_method_name}}({{method.parameters|map(attribute='name')|join(', ')}});
   }
 {%- endfor %}
 
@@ -171,6 +171,7 @@
 
   var {{interface.name}} = {
     name: '{{namespace|replace(".","::")}}::{{interface.name}}',
+    ptrClass: {{interface.name}}Ptr,
     proxyClass: {{interface.name}}Proxy,
     stubClass: {{interface.name}}Stub,
     validateRequest: validate{{interface.name}}Request,
diff --git a/mojo/public/tools/bindings/generators/js_templates/validation_macros.tmpl b/mojo/public/tools/bindings/generators/js_templates/validation_macros.tmpl
index 3d0be6e..d4e15a7 100644
--- a/mojo/public/tools/bindings/generators/js_templates/validation_macros.tmpl
+++ b/mojo/public/tools/bindings/generators/js_templates/validation_macros.tmpl
@@ -6,7 +6,7 @@
 {%- macro _validate_field(field, offset, name) %}
 {%-   if field|is_string_pointer_field %}
 // validate {{name}}
-err = messageValidator.validateStringPointer({{offset}}, {{field|validate_string_params}})
+err = messageValidator.validateStringPointer({{offset}}, {{field|validate_nullable_params}})
 {{_check_err()}}
 {%-   elif field|is_array_pointer_field %}
 // validate {{name}}
@@ -22,11 +22,15 @@
 {{_check_err()}}
 {%-   elif field|is_interface_field %}
 // validate {{name}}
-err = messageValidator.validateInterface({{offset}}, {{field|validate_interface_params}});
+err = messageValidator.validateInterface({{offset}}, {{field|validate_nullable_params}});
 {{_check_err()}}
-{%-   elif field|is_handle_field or field|is_interface_request_field %}
+{%-   elif field|is_interface_request_field %}
 // validate {{name}}
-err = messageValidator.validateHandle({{offset}}, {{field|validate_handle_params}})
+err = messageValidator.validateInterfaceRequest({{offset}}, {{field|validate_nullable_params}})
+{{_check_err()}}
+{%-   elif field|is_handle_field %}
+// validate {{name}}
+err = messageValidator.validateHandle({{offset}}, {{field|validate_nullable_params}})
 {{_check_err()}}
 {%-   elif field|is_enum_field %}
 // validate {{name}}
diff --git a/mojo/public/tools/bindings/generators/mojom_js_generator.py b/mojo/public/tools/bindings/generators/mojom_js_generator.py
index e57f330..0d774a5 100644
--- a/mojo/public/tools/bindings/generators/mojom_js_generator.py
+++ b/mojo/public/tools/bindings/generators/mojom_js_generator.py
@@ -62,9 +62,10 @@
     return "null"
   if mojom.IsMapKind(field.kind):
     return "null"
-  if mojom.IsInterfaceKind(field.kind) or \
-     mojom.IsInterfaceRequestKind(field.kind):
-    return _kind_to_javascript_default_value[mojom.MSGPIPE]
+  if mojom.IsInterfaceKind(field.kind):
+    return "new %sPtr()" % JavaScriptType(field.kind)
+  if mojom.IsInterfaceRequestKind(field.kind):
+    return "new bindings.InterfaceRequest()"
   if mojom.IsAssociatedKind(field.kind):
     return "null"
   if mojom.IsEnumKind(field.kind):
@@ -124,10 +125,13 @@
     element_type = ElementCodecType(kind.kind)
     return "new codec.%s(%s%s)" % (array_type, element_type, array_length)
   if mojom.IsInterfaceKind(kind):
-    return "codec.%s" % ("NullableInterface" if mojom.IsNullableKind(kind)
-        else "Interface")
+    return "new codec.%s(%sPtr)" % (
+        "NullableInterface" if mojom.IsNullableKind(kind) else "Interface",
+        JavaScriptType(kind))
   if mojom.IsInterfaceRequestKind(kind):
-    return CodecType(mojom.MSGPIPE)
+    return "codec.%s" % (
+        "NullableInterfaceRequest" if mojom.IsNullableKind(kind)
+                                   else "InterfaceRequest")
   if mojom.IsAssociatedInterfaceKind(kind):
     return "codec.AssociatedInterfaceNotSupported"
   if mojom.IsAssociatedInterfaceRequestKind(kind):
@@ -148,7 +152,7 @@
 
 def JavaScriptDecodeSnippet(kind):
   if (kind in mojom.PRIMITIVES or mojom.IsUnionKind(kind) or
-      mojom.IsInterfaceKind(kind) or mojom.IsAssociatedKind(kind)):
+      mojom.IsAnyInterfaceKind(kind)):
     return "decodeStruct(%s)" % CodecType(kind)
   if mojom.IsStructKind(kind):
     return "decodeStructPointer(%s)" % JavaScriptType(kind)
@@ -161,8 +165,6 @@
     return "decodeArrayPointer(%s)" % CodecType(kind.kind)
   if mojom.IsUnionKind(kind):
     return "decodeUnion(%s)" % CodecType(kind)
-  if mojom.IsInterfaceRequestKind(kind):
-    return JavaScriptDecodeSnippet(mojom.MSGPIPE)
   if mojom.IsEnumKind(kind):
     return JavaScriptDecodeSnippet(mojom.INT32)
   raise Exception("No decode snippet for %s" % kind)
@@ -170,7 +172,7 @@
 
 def JavaScriptEncodeSnippet(kind):
   if (kind in mojom.PRIMITIVES or mojom.IsUnionKind(kind) or
-      mojom.IsInterfaceKind(kind) or mojom.IsAssociatedKind(kind)):
+      mojom.IsAnyInterfaceKind(kind)):
     return "encodeStruct(%s, " % CodecType(kind)
   if mojom.IsUnionKind(kind):
     return "encodeStruct(%s, " % JavaScriptType(kind)
@@ -183,8 +185,6 @@
     return "encodeArrayPointer(codec.PackedBool, ";
   if mojom.IsArrayKind(kind):
     return "encodeArrayPointer(%s, " % CodecType(kind.kind)
-  if mojom.IsInterfaceRequestKind(kind):
-    return JavaScriptEncodeSnippet(mojom.MSGPIPE)
   if mojom.IsEnumKind(kind):
     return JavaScriptEncodeSnippet(mojom.INT32)
   raise Exception("No encode snippet for %s" % kind)
@@ -258,42 +258,6 @@
       (nullable, keys_type, values_type, values_nullable)
 
 
-def JavaScriptValidateStringParams(field):
-  nullable = JavaScriptNullableParam(field)
-  return "%s" % (nullable)
-
-
-def JavaScriptValidateHandleParams(field):
-  nullable = JavaScriptNullableParam(field)
-  return "%s" % (nullable)
-
-def JavaScriptValidateInterfaceParams(field):
-  return JavaScriptValidateHandleParams(field)
-
-def JavaScriptProxyMethodParameterValue(parameter):
-  name = parameter.name;
-  if (mojom.IsInterfaceKind(parameter.kind)):
-   type = JavaScriptType(parameter.kind)
-   return "core.isHandle(%s) ? %s : connection.bindImpl" \
-       "(%s, %s)" % (name, name, name, type)
-  if (mojom.IsInterfaceRequestKind(parameter.kind)):
-   type = JavaScriptType(parameter.kind.kind)
-   return "core.isHandle(%s) ? %s : connection.bindProxy" \
-       "(%s, %s)" % (name, name, name, type)
-  return name;
-
-
-def JavaScriptStubMethodParameterValue(parameter):
-  name = parameter.name;
-  if (mojom.IsInterfaceKind(parameter.kind)):
-   type = JavaScriptType(parameter.kind)
-   return "connection.bindHandleToProxy(%s, %s)" % (name, type)
-  if (mojom.IsInterfaceRequestKind(parameter.kind)):
-   type = JavaScriptType(parameter.kind.kind)
-   return "connection.bindHandleToStub(%s, %s)" % (name, type)
-  return name;
-
-
 def TranslateConstants(token):
   if isinstance(token, (mojom.EnumValue, mojom.NamedValue)):
     # Both variable and enum constants are constructed like:
@@ -384,8 +348,6 @@
     "is_string_pointer_field": IsStringPointerField,
     "is_struct_pointer_field": IsStructPointerField,
     "is_union_field": IsUnionField,
-    "js_proxy_method_parameter_value": JavaScriptProxyMethodParameterValue,
-    "js_stub_method_parameter_value": JavaScriptStubMethodParameterValue,
     "js_type": JavaScriptType,
     "payload_size": JavaScriptPayloadSize,
     "stylize_method": generator.StudlyCapsToCamel,
@@ -393,10 +355,8 @@
     "union_encode_snippet": JavaScriptUnionEncodeSnippet,
     "validate_array_params": JavaScriptValidateArrayParams,
     "validate_enum_params": JavaScriptValidateEnumParams,
-    "validate_handle_params": JavaScriptValidateHandleParams,
-    "validate_interface_params": JavaScriptValidateInterfaceParams,
     "validate_map_params": JavaScriptValidateMapParams,
-    "validate_string_params": JavaScriptValidateStringParams,
+    "validate_nullable_params": JavaScriptNullableParam,
     "validate_struct_params": JavaScriptValidateStructParams,
     "validate_union_params": JavaScriptValidateUnionParams,
   }
diff --git a/native_client_sdk/src/tests/nacl_io_test/example.dsc b/native_client_sdk/src/tests/nacl_io_test/example.dsc
index 2fc0aca..c28f852 100644
--- a/native_client_sdk/src/tests/nacl_io_test/example.dsc
+++ b/native_client_sdk/src/tests/nacl_io_test/example.dsc
@@ -29,6 +29,8 @@
         'fake_ppapi/fake_node.h',
         'fake_ppapi/fake_pepper_interface.cc',
         'fake_ppapi/fake_pepper_interface.h',
+        'fake_ppapi/fake_pepper_interface_googledrivefs.cc',
+        'fake_ppapi/fake_pepper_interface_googledrivefs.h',
         'fake_ppapi/fake_pepper_interface_html5_fs.cc',
         'fake_ppapi/fake_pepper_interface_html5_fs.h',
         'fake_ppapi/fake_pepper_interface_url_loader.cc',
diff --git a/native_client_sdk/src/tests/nacl_io_test/fake_ppapi/fake_pepper_interface_googledrivefs.cc b/native_client_sdk/src/tests/nacl_io_test/fake_ppapi/fake_pepper_interface_googledrivefs.cc
new file mode 100644
index 0000000..d0a14a3
--- /dev/null
+++ b/native_client_sdk/src/tests/nacl_io_test/fake_ppapi/fake_pepper_interface_googledrivefs.cc
@@ -0,0 +1,312 @@
+// 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 "fake_ppapi/fake_pepper_interface_googledrivefs.h"
+
+#include <ppapi/c/pp_completion_callback.h>
+#include <ppapi/c/pp_errors.h>
+
+#include "gtest/gtest.h"
+
+#include "fake_ppapi/fake_core_interface.h"
+#include "fake_ppapi/fake_file_ref_interface.h"
+#include "fake_ppapi/fake_pepper_interface_url_loader.h"
+#include "fake_ppapi/fake_util.h"
+#include "fake_ppapi/fake_var_interface.h"
+
+class FakeDriveInstanceResource : public FakeResource {
+ public:
+  FakeDriveInstanceResource() : server_template(NULL) {}
+  static const char* classname() { return "FakeDriveInstanceResource"; }
+
+  FakeGoogleDriveServer* server_template;
+};
+
+class FakeDriveURLLoaderResource : public FakeResource {
+ public:
+  FakeDriveURLLoaderResource() : manager(NULL), server(NULL), response(0) {}
+
+  virtual void Destroy() {
+    EXPECT_TRUE(manager != NULL);
+    if (response != 0)
+      manager->Release(response);
+  }
+
+  static const char* classname() { return "FakeDriveURLLoaderResource"; }
+
+  FakeResourceManager* manager;
+  FakeGoogleDriveServer* server;
+  PP_Resource response;
+  std::string response_body;
+};
+
+class FakeDriveResponseResource : public FakeURLResponseInfoResource {
+ public:
+  FakeDriveResponseResource()
+      : manager(NULL), loader(0), file_ref(0), stream_to_file(false) {}
+
+  virtual void Destroy() {
+    EXPECT_TRUE(manager != NULL);
+    if (loader != 0)
+      manager->Release(loader);
+
+    if (file_ref != 0)
+      manager->Release(file_ref);
+  }
+
+  static const char* classname() { return "FakeDriveResponseResource"; }
+
+  FakeResourceManager* manager;
+  PP_Resource loader;
+  PP_Resource file_ref;
+  bool stream_to_file;
+  std::string body;
+};
+
+FakeGoogleDriveServer::FakeGoogleDriveServer() {}
+
+void FakeGoogleDriveServer::Respond(
+    const std::string& url,
+    const std::string& headers,
+    const std::string& method,
+    const std::string& body,
+    FakeGoogleDriveServerResponse* out_response) {
+  out_response->status_code = STATUSCODE_NOT_IMPLEMENTED;
+}
+
+FakeDriveURLLoaderInterface::FakeDriveURLLoaderInterface(
+    FakeCoreInterface* core_interface)
+    : FakeURLLoaderInterface(core_interface) {}
+
+PP_Resource FakeDriveURLLoaderInterface::Create(PP_Instance instance) {
+  FakeDriveInstanceResource* drive_instance_resource =
+      core_interface_->resource_manager()->Get<FakeDriveInstanceResource>(
+          instance);
+  if (drive_instance_resource == NULL)
+    return 0;
+
+  FakeDriveURLLoaderResource* drive_loader_resource =
+      new FakeDriveURLLoaderResource;
+  drive_loader_resource->manager = core_interface_->resource_manager();
+  drive_loader_resource->server = drive_instance_resource->server_template;
+
+  return CREATE_RESOURCE(core_interface_->resource_manager(),
+                         FakeDriveURLLoaderResource, drive_loader_resource);
+}
+
+int32_t FakeDriveURLLoaderInterface::Open(PP_Resource loader,
+                                          PP_Resource request,
+                                          PP_CompletionCallback callback) {
+  FakeDriveURLLoaderResource* drive_loader_resource =
+      core_interface_->resource_manager()->Get<FakeDriveURLLoaderResource>(
+          loader);
+  if (drive_loader_resource == NULL)
+    return PP_ERROR_BADRESOURCE;
+
+  // Close() has been called. Invalid to call Open() again.
+  if (drive_loader_resource->server == NULL)
+    return PP_ERROR_FAILED;
+
+  FakeURLRequestInfoResource* request_resource =
+      core_interface_->resource_manager()->Get<FakeURLRequestInfoResource>(
+          request);
+  if (request_resource == NULL)
+    return PP_ERROR_BADRESOURCE;
+
+  // Create a response resource.
+  FakeDriveResponseResource* drive_response_resource =
+      new FakeDriveResponseResource;
+  drive_response_resource->manager = drive_loader_resource->manager;
+  drive_loader_resource->response =
+      CREATE_RESOURCE(core_interface_->resource_manager(),
+                      FakeDriveResponseResource, drive_response_resource);
+
+  drive_response_resource->loader = loader;
+  core_interface_->resource_manager()->AddRef(drive_response_resource->loader);
+
+  drive_response_resource->stream_to_file = request_resource->stream_to_file;
+
+  FakeGoogleDriveServerResponse server_response;
+  drive_loader_resource->server->Respond(
+      request_resource->url, request_resource->headers,
+      request_resource->method, request_resource->body, &server_response);
+
+  drive_response_resource->status_code = server_response.status_code;
+  drive_loader_resource->response_body = server_response.body;
+
+  // Call the callback.
+  return RunCompletionCallback(&callback, PP_OK);
+}
+
+PP_Resource FakeDriveURLLoaderInterface::GetResponseInfo(PP_Resource loader) {
+  FakeDriveURLLoaderResource* drive_loader_resource =
+      core_interface_->resource_manager()->Get<FakeDriveURLLoaderResource>(
+          loader);
+  if (drive_loader_resource == NULL)
+    return 0;
+
+  if (drive_loader_resource->response == 0)
+    return 0;
+
+  // Returned resources have an implicit AddRef.
+  core_interface_->resource_manager()->AddRef(drive_loader_resource->response);
+  return drive_loader_resource->response;
+}
+
+int32_t FakeDriveURLLoaderInterface::FinishStreamingToFile(
+    PP_Resource loader,
+    PP_CompletionCallback callback) {
+  FakeDriveURLLoaderResource* drive_loader_resource =
+      core_interface_->resource_manager()->Get<FakeDriveURLLoaderResource>(
+          loader);
+  if (drive_loader_resource == NULL)
+    return PP_ERROR_BADRESOURCE;
+
+  FakeDriveResponseResource* drive_response_resource =
+      core_interface_->resource_manager()->Get<FakeDriveResponseResource>(
+          drive_loader_resource->response);
+  if (drive_response_resource == NULL)
+    return PP_ERROR_BADRESOURCE;
+
+  if (!drive_response_resource->stream_to_file)
+    return PP_ERROR_FAILED;
+
+  drive_response_resource->body = drive_loader_resource->response_body;
+
+  // PPB_URLLoader::FinishStreamingToFile(..) returns 0 even when
+  // the response body size is > 0.
+  return 0;
+}
+
+void FakeDriveURLLoaderInterface::Close(PP_Resource loader) {
+  FakeDriveURLLoaderResource* drive_loader_resource =
+      core_interface_->resource_manager()->Get<FakeDriveURLLoaderResource>(
+          loader);
+  if (drive_loader_resource == NULL)
+    return;
+
+  core_interface_->resource_manager()->Release(drive_loader_resource->response);
+
+  drive_loader_resource->server = NULL;
+  drive_loader_resource->response = 0;
+  drive_loader_resource->response_body.clear();
+}
+
+FakeDriveURLResponseInfoInterface::FakeDriveURLResponseInfoInterface(
+    FakeCoreInterface* core_interface,
+    FakeVarInterface* var_interface,
+    FakeFileRefInterface* file_ref_interface)
+    : FakeURLResponseInfoInterface(core_interface, var_interface),
+      file_ref_interface_(file_ref_interface) {
+  FakeFileSystemResource* file_system_resource = new FakeFileSystemResource;
+  file_system_resource->filesystem = new FakeFilesystem();
+  file_system_resource->opened = true;
+
+  filesystem_resource_ =
+      CREATE_RESOURCE(core_interface_->resource_manager(),
+                      FakeFileSystemResource, file_system_resource);
+}
+
+FakeDriveURLResponseInfoInterface::~FakeDriveURLResponseInfoInterface() {
+  core_interface_->ReleaseResource(filesystem_resource_);
+}
+
+PP_Resource FakeDriveURLResponseInfoInterface::GetBodyAsFileRef(
+    PP_Resource response) {
+  FakeDriveResponseResource* drive_response_resource =
+      core_interface_->resource_manager()->Get<FakeDriveResponseResource>(
+          response);
+  if (drive_response_resource == NULL)
+    return 0;
+
+  if (!drive_response_resource->stream_to_file)
+    return 0;
+
+  FakeDriveURLLoaderResource* drive_loader_resource =
+      core_interface_->resource_manager()->Get<FakeDriveURLLoaderResource>(
+          drive_response_resource->loader);
+  if (drive_loader_resource == NULL)
+    return 0;
+
+  if (drive_loader_resource->server == NULL)
+    return 0;
+
+  if (drive_response_resource->file_ref == 0) {
+    FakeFileSystemResource* file_system_resource =
+        core_interface_->resource_manager()->Get<FakeFileSystemResource>(
+            filesystem_resource_);
+    if (file_system_resource == NULL)
+      return 0;
+
+    char path_buffer[32];
+    snprintf(path_buffer, sizeof(path_buffer), "%u", response);
+
+    FakeNode* fake_node;
+    if (!file_system_resource->filesystem->AddFile(
+            path_buffer, drive_response_resource->body, &fake_node))
+      return 0;
+
+    drive_response_resource->file_ref =
+        file_ref_interface_->Create(filesystem_resource_, path_buffer);
+  }
+
+  // Returned resources have an implicit AddRef.
+  core_interface_->resource_manager()->AddRef(
+      drive_response_resource->file_ref);
+  return drive_response_resource->file_ref;
+}
+
+FakePepperInterfaceGoogleDriveFs::FakePepperInterfaceGoogleDriveFs()
+    : core_interface_(&resource_manager_),
+      var_interface_(&var_manager_),
+      file_ref_interface_(&core_interface_, &var_interface_),
+      drive_url_loader_interface_(&core_interface_),
+      url_request_info_interface_(&core_interface_, &var_interface_),
+      drive_url_response_info_interface_(&core_interface_,
+                                         &var_interface_,
+                                         &file_ref_interface_) {
+  Init();
+}
+
+void FakePepperInterfaceGoogleDriveFs::Init() {
+  FakeDriveInstanceResource* drive_instance_resource =
+      new FakeDriveInstanceResource;
+  drive_instance_resource->server_template = &google_drive_server_template_;
+
+  instance_ =
+      CREATE_RESOURCE(core_interface_.resource_manager(),
+                      FakeDriveInstanceResource, drive_instance_resource);
+}
+
+FakePepperInterfaceGoogleDriveFs::~FakePepperInterfaceGoogleDriveFs() {
+  core_interface_.ReleaseResource(instance_);
+}
+
+nacl_io::CoreInterface* FakePepperInterfaceGoogleDriveFs::GetCoreInterface() {
+  return &core_interface_;
+}
+
+nacl_io::FileRefInterface*
+FakePepperInterfaceGoogleDriveFs::GetFileRefInterface() {
+  return &file_ref_interface_;
+}
+
+nacl_io::URLLoaderInterface*
+FakePepperInterfaceGoogleDriveFs::GetURLLoaderInterface() {
+  return &drive_url_loader_interface_;
+}
+
+nacl_io::URLRequestInfoInterface*
+FakePepperInterfaceGoogleDriveFs::GetURLRequestInfoInterface() {
+  return &url_request_info_interface_;
+}
+
+nacl_io::URLResponseInfoInterface*
+FakePepperInterfaceGoogleDriveFs::GetURLResponseInfoInterface() {
+  return &drive_url_response_info_interface_;
+}
+
+nacl_io::VarInterface* FakePepperInterfaceGoogleDriveFs::GetVarInterface() {
+  return &var_interface_;
+}
diff --git a/native_client_sdk/src/tests/nacl_io_test/fake_ppapi/fake_pepper_interface_googledrivefs.h b/native_client_sdk/src/tests/nacl_io_test/fake_ppapi/fake_pepper_interface_googledrivefs.h
new file mode 100644
index 0000000..33b78861
--- /dev/null
+++ b/native_client_sdk/src/tests/nacl_io_test/fake_ppapi/fake_pepper_interface_googledrivefs.h
@@ -0,0 +1,117 @@
+// 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 LIBRARIES_NACL_IO_TEST_FAKE_PEPPER_INTERFACE_GOOGLEDRIVEFS_H_
+#define LIBRARIES_NACL_IO_TEST_FAKE_PEPPER_INTERFACE_GOOGLEDRIVEFS_H_
+
+#include <string>
+
+#include "nacl_io/pepper_interface_dummy.h"
+#include "sdk_util/macros.h"
+
+#include "fake_ppapi/fake_core_interface.h"
+#include "fake_ppapi/fake_file_ref_interface.h"
+#include "fake_ppapi/fake_pepper_interface_url_loader.h"
+#include "fake_ppapi/fake_var_interface.h"
+#include "fake_ppapi/fake_var_manager.h"
+
+struct FakeGoogleDriveServerResponse {
+  FakeGoogleDriveServerResponse() : status_code(0) {}
+
+  int status_code;
+  std::string body;
+};
+
+class FakeGoogleDriveServer {
+ public:
+  FakeGoogleDriveServer();
+  void Respond(const std::string& url,
+               const std::string& headers,
+               const std::string& method,
+               const std::string& body,
+               FakeGoogleDriveServerResponse* out_response);
+};
+
+class FakeDriveURLLoaderInterface : public FakeURLLoaderInterface {
+ public:
+  explicit FakeDriveURLLoaderInterface(FakeCoreInterface* core_interface);
+
+  virtual PP_Resource Create(PP_Instance instance);
+  virtual int32_t Open(PP_Resource loader,
+                       PP_Resource request_info,
+                       PP_CompletionCallback callback);
+  virtual PP_Resource GetResponseInfo(PP_Resource loader);
+  virtual int32_t FinishStreamingToFile(PP_Resource loader,
+                                        PP_CompletionCallback callback);
+  virtual void Close(PP_Resource loader);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(FakeDriveURLLoaderInterface);
+};
+
+class FakeDriveURLResponseInfoInterface : public FakeURLResponseInfoInterface {
+ public:
+  FakeDriveURLResponseInfoInterface(FakeCoreInterface* core_interface,
+                                    FakeVarInterface* var_interface,
+                                    FakeFileRefInterface* file_ref_interface);
+  ~FakeDriveURLResponseInfoInterface();
+
+  virtual PP_Resource GetBodyAsFileRef(PP_Resource response);
+
+ private:
+  FakeFileRefInterface* file_ref_interface_;
+  PP_Resource filesystem_resource_;
+
+  DISALLOW_COPY_AND_ASSIGN(FakeDriveURLResponseInfoInterface);
+};
+
+// This class is a fake implementation of the interfaces necessary to access
+// the GOOGLEDRIVEFS Filesystem from NaCl.
+//
+// Example:
+//   FakePepperInterfaceGoogleDriveFs ppapi_googledrivefs;
+//   ...
+//   PP_Resource ref_resource =
+//   ppapi_googledrivefs.GetURLLoaderInterface()->Create(
+//       ppapi_googledrivefs.GetInstance());
+//   ...
+//
+// NOTE: This pepper interface creates an instance resource that can only be
+// used with FakePepperInterfaceGoogleDriveFs, not other fake pepper
+// implementations.
+class FakePepperInterfaceGoogleDriveFs : public nacl_io::PepperInterfaceDummy {
+ public:
+  FakePepperInterfaceGoogleDriveFs();
+  ~FakePepperInterfaceGoogleDriveFs();
+
+  virtual PP_Instance GetInstance() { return instance_; }
+  virtual nacl_io::CoreInterface* GetCoreInterface();
+  virtual nacl_io::FileRefInterface* GetFileRefInterface();
+  virtual nacl_io::VarInterface* GetVarInterface();
+  virtual nacl_io::URLLoaderInterface* GetURLLoaderInterface();
+  virtual nacl_io::URLRequestInfoInterface* GetURLRequestInfoInterface();
+  virtual nacl_io::URLResponseInfoInterface* GetURLResponseInfoInterface();
+
+  FakeGoogleDriveServer* server_template() {
+    return &google_drive_server_template_;
+  }
+
+ private:
+  void Init();
+
+  FakeResourceManager resource_manager_;
+  FakeCoreInterface core_interface_;
+  FakeVarInterface var_interface_;
+  FakeVarManager var_manager_;
+  FakeFileRefInterface file_ref_interface_;
+  FakeGoogleDriveServer google_drive_server_template_;
+  FakeDriveURLLoaderInterface drive_url_loader_interface_;
+  FakeURLRequestInfoInterface url_request_info_interface_;
+  FakeDriveURLResponseInfoInterface drive_url_response_info_interface_;
+  PP_Instance instance_;
+
+  DISALLOW_COPY_AND_ASSIGN(FakePepperInterfaceGoogleDriveFs);
+};
+
+#endif  // LIBRARIES_NACL_IO_TEST_FAKE_PEPPER_INTERFACE_GOOGLEDRIVEFS_H_
diff --git a/native_client_sdk/src/tests/nacl_io_test/fake_ppapi/fake_pepper_interface_url_loader.cc b/native_client_sdk/src/tests/nacl_io_test/fake_ppapi/fake_pepper_interface_url_loader.cc
index 1df756d..e52a250c 100644
--- a/native_client_sdk/src/tests/nacl_io_test/fake_ppapi/fake_pepper_interface_url_loader.cc
+++ b/native_client_sdk/src/tests/nacl_io_test/fake_ppapi/fake_pepper_interface_url_loader.cc
@@ -11,6 +11,8 @@
 
 #include "gtest/gtest.h"
 
+#include <ppapi/c/pp_bool.h>
+
 #include "fake_ppapi/fake_util.h"
 #include "nacl_io/osinttypes.h"
 
@@ -470,6 +472,13 @@
       // Throw the value away for now. TODO(binji): add tests for this.
       return PP_TRUE;
     }
+    case PP_URLREQUESTPROPERTY_STREAMTOFILE: {
+      if (value.type != PP_VARTYPE_BOOL)
+        return PP_FALSE;
+
+      request_resource->stream_to_file = PP_ToBool(value.value.as_bool);
+      return PP_TRUE;
+    }
     default:
       EXPECT_TRUE(false) << "Unimplemented property " << property
                          << " in "
diff --git a/native_client_sdk/src/tests/nacl_io_test/fake_ppapi/fake_pepper_interface_url_loader.h b/native_client_sdk/src/tests/nacl_io_test/fake_ppapi/fake_pepper_interface_url_loader.h
index a554eae..0232403 100644
--- a/native_client_sdk/src/tests/nacl_io_test/fake_ppapi/fake_pepper_interface_url_loader.h
+++ b/native_client_sdk/src/tests/nacl_io_test/fake_ppapi/fake_pepper_interface_url_loader.h
@@ -104,9 +104,10 @@
 
   virtual void Close(PP_Resource loader);
 
- private:
+ protected:
   FakeCoreInterface* core_interface_;  // Weak reference.
 
+ private:
   DISALLOW_COPY_AND_ASSIGN(FakeURLLoaderInterface);
 };
 
@@ -139,10 +140,11 @@
                              PP_URLResponseProperty property);
   virtual PP_Resource GetBodyAsFileRef(PP_Resource response);
 
- private:
+ protected:
   FakeCoreInterface* core_interface_;  // Weak reference.
   FakeVarInterface* var_interface_;    // Weak reference.
 
+ private:
   DISALLOW_COPY_AND_ASSIGN(FakeURLResponseInfoInterface);
 };
 
diff --git a/native_client_sdk/src/tests/nacl_io_test/fake_ppapi/fake_util.h b/native_client_sdk/src/tests/nacl_io_test/fake_ppapi/fake_util.h
index a8cb60c..0e77fd1 100644
--- a/native_client_sdk/src/tests/nacl_io_test/fake_ppapi/fake_util.h
+++ b/native_client_sdk/src/tests/nacl_io_test/fake_ppapi/fake_util.h
@@ -12,6 +12,8 @@
 #include "fake_ppapi/fake_filesystem.h"
 #include "fake_ppapi/fake_resource_manager.h"
 
+const int32_t STATUSCODE_NOT_IMPLEMENTED = 501;
+
 class FakeFileRefResource : public FakeResource {
  public:
   FakeFileRefResource() : filesystem(NULL) {}
@@ -42,13 +44,14 @@
 
 class FakeURLRequestInfoResource : public FakeResource {
  public:
-  FakeURLRequestInfoResource() {}
+  FakeURLRequestInfoResource() : stream_to_file(false) {}
   static const char* classname() { return "FakeURLRequestInfoResource"; }
 
   std::string url;
   std::string method;
   std::string headers;
   std::string body;
+  bool stream_to_file;
 };
 
 class FakeURLResponseInfoResource : public FakeResource {
diff --git a/net/cert/cert_verify_proc_blacklist.inc b/net/cert/cert_verify_proc_blacklist.inc
index b2bb554..3ca92f14 100644
--- a/net/cert/cert_verify_proc_blacklist.inc
+++ b/net/cert/cert_verify_proc_blacklist.inc
@@ -5,7 +5,7 @@
 // The certificate(s) that were misissued, and which represent these SPKIs,
 // are stored within net/data/ssl/blacklist. Further details about the
 // rationale is documented in net/data/ssl/blacklist/README.md
-static const size_t kNumBlacklistedSPKIs = 34u;
+static const size_t kNumBlacklistedSPKIs = 36u;
 static const uint8_t
     kBlacklistedSPKIs[kNumBlacklistedSPKIs][crypto::kSHA256Length] = {
         // ead610e6e90b439f2ecb51628b0932620f6ef340bd843fca38d3181b8f4ba197.pem
@@ -24,6 +24,10 @@
         {0x1a, 0xf5, 0x6c, 0x98, 0xff, 0x04, 0x3e, 0xf9, 0x2b, 0xeb, 0xff,
          0x54, 0xce, 0xbb, 0x4d, 0xd6, 0x7a, 0x25, 0xba, 0x95, 0x6c, 0x81,
          0x7f, 0x3e, 0x6d, 0xd3, 0xc1, 0xe5, 0x2e, 0xb5, 0x84, 0xc1},
+        // e28393773da845a679f2080cc7fb44a3b7a1c3792cb7eb7729fdcb6a8d99aea7.pem
+        {0x1f, 0x42, 0x24, 0xce, 0xc8, 0x4f, 0xc9, 0x9c, 0xed, 0x88, 0x1f,
+         0xf6, 0xfc, 0xfd, 0x3e, 0x21, 0xf8, 0xc5, 0x19, 0xc5, 0x47, 0xaa,
+         0x6a, 0x5d, 0xd3, 0xde, 0x24, 0x73, 0x02, 0xce, 0x50, 0xd1},
         // 2c998e761160c3b06d82faa9fdc7545d9bda9eb60310f992aa510a6280b74245.pem
         {0x2c, 0x99, 0x8e, 0x76, 0x11, 0x60, 0xc3, 0xb0, 0x6d, 0x82, 0xfa,
          0xa9, 0xfd, 0xc7, 0x54, 0x5d, 0x9b, 0xda, 0x9e, 0xb6, 0x03, 0x10,
@@ -78,6 +82,10 @@
         {0x9b, 0x8a, 0x93, 0xde, 0xcc, 0xcf, 0xba, 0xfc, 0xf4, 0xd0, 0x4d,
          0x34, 0x42, 0x12, 0x8f, 0xb3, 0x52, 0x18, 0xcf, 0xe4, 0x37, 0xa3,
          0xd8, 0xd0, 0x32, 0x8c, 0x99, 0xf8, 0x90, 0x89, 0xe4, 0x50},
+        // 1c01c6f4dbb2fefc22558b2bca32563f49844acfc32b7be4b0ff599f9e8c7af7.pem
+        {0x9d, 0xd5, 0x5f, 0xc5, 0x73, 0xf5, 0x46, 0xcb, 0x6a, 0x38, 0x31,
+         0xd1, 0x11, 0x2d, 0x87, 0x10, 0xa6, 0xf4, 0xf8, 0x2d, 0xc8, 0x7f,
+         0x5f, 0xae, 0x9d, 0x3a, 0x1a, 0x02, 0x8d, 0xd3, 0x6e, 0x4b},
         // 0d136e439f0ab6e97f3a02a540da9f0641aa554e1d66ea51ae2920d51b2f7217.pem
         // 4fee0163686ecbd65db968e7494f55d84b25486d438e9de558d629d28cd4d176.pem
         // 8a1bd21661c60015065212cc98b1abb50dfd14c872a208e66bae890f25c448af.pem
diff --git a/net/cert/cert_verify_proc_unittest.cc b/net/cert/cert_verify_proc_unittest.cc
index 96ce38c..186854c 100644
--- a/net/cert/cert_verify_proc_unittest.cc
+++ b/net/cert/cert_verify_proc_unittest.cc
@@ -1806,7 +1806,8 @@
 // Disabled on NSS - NSS caches chains/signatures in such a way that cannot
 // be cleared until NSS is cleanly shutdown, which is not presently supported
 // in Chromium.
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+// OSX 10.12+ stops building the chain at the first weak digest.
+#if defined(USE_NSS_CERTS) || defined(OS_IOS) || defined(OS_MACOSX)
 #define MAYBE_VerifyEndEntity DISABLED_VerifyEndEntity
 #else
 #define MAYBE_VerifyEndEntity VerifyEndEntity
@@ -1854,7 +1855,8 @@
 };
 // Disabled on NSS - libpkix does not return constructed chains on error,
 // preventing us from detecting/inspecting the verified chain.
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+// OSX 10.12+ stops building the chain at the first weak digest.
+#if defined(USE_NSS_CERTS) || defined(OS_IOS) || defined(OS_MACOSX)
 #define MAYBE_VerifyIncompleteEndEntity DISABLED_VerifyIncompleteEndEntity
 #else
 #define MAYBE_VerifyIncompleteEndEntity VerifyIncompleteEndEntity
@@ -1879,7 +1881,8 @@
 };
 // NSS does not support MD4 and does not enable MD2 by default, making all
 // permutations invalid.
-#if defined(USE_NSS_CERTS) || defined(OS_IOS)
+// OSX 10.12+ stops building the chain at the first weak digest.
+#if defined(USE_NSS_CERTS) || defined(OS_IOS) || defined(OS_MACOSX)
 #define MAYBE_VerifyMixed DISABLED_VerifyMixed
 #else
 #define MAYBE_VerifyMixed VerifyMixed
diff --git a/net/cert/cert_verify_proc_whitelist.cc b/net/cert/cert_verify_proc_whitelist.cc
index 5c53a77a..53489ff 100644
--- a/net/cert/cert_verify_proc_whitelist.cc
+++ b/net/cert/cert_verify_proc_whitelist.cc
@@ -46,1604 +46,7 @@
       0x21, 0x9f, 0xe0, 0xe9, 0xe3, 0xa3, 0x82, 0xa1,
       0xb3, 0xcb, 0x66, 0xc9, 0x39, 0x55, 0xde, 0x75 },
 };
-
-// SHA-256 hashes of the leaf certificates whitelisted as issued by CNNIC's
-// DV root.
-const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = {
-    { 0x00, 0xc5, 0x9f, 0x5e, 0xf3, 0xb4, 0x6d, 0xbc,
-      0xa0, 0xa8, 0xbb, 0xa5, 0x0a, 0x72, 0xd4, 0xe1,
-      0x83, 0x9a, 0x94, 0xfb, 0x1a, 0x58, 0x5a, 0xd7,
-      0x2a, 0x7a, 0xac, 0x3c, 0x72, 0x56, 0x1f, 0xc0 },
-    { 0x02, 0x01, 0x4e, 0x80, 0xf5, 0xc4, 0xf3, 0x8b,
-      0xa9, 0xd9, 0x04, 0x79, 0x1a, 0x63, 0xf6, 0x4d,
-      0x05, 0xf9, 0xe2, 0x03, 0xa1, 0xf1, 0x2b, 0x06,
-      0xd6, 0x55, 0x94, 0x01, 0x41, 0x0e, 0x73, 0x36 },
-    { 0x02, 0x35, 0x38, 0xe2, 0x48, 0x15, 0x28, 0x75,
-      0x29, 0x2f, 0x2c, 0x83, 0x9a, 0xb3, 0x2b, 0xc7,
-      0x35, 0x1e, 0x2b, 0x29, 0x99, 0x1d, 0x66, 0xae,
-      0xa6, 0x16, 0xcb, 0x0b, 0x26, 0xa5, 0xe3, 0x75 },
-    { 0x02, 0xec, 0x35, 0xf5, 0x83, 0x4c, 0xd2, 0xc3,
-      0x43, 0x33, 0x39, 0x9a, 0xea, 0x6b, 0xda, 0x84,
-      0x68, 0xab, 0x8d, 0x74, 0xef, 0x6c, 0xa5, 0x2d,
-      0x33, 0x7a, 0x30, 0x69, 0x4c, 0x3f, 0x95, 0xa4 },
-    { 0x03, 0xe0, 0x6e, 0x0b, 0x7a, 0x2c, 0xba, 0xe4,
-      0xb6, 0x8b, 0xce, 0x5f, 0x83, 0xe7, 0xa9, 0x31,
-      0x6e, 0xd7, 0x82, 0x3e, 0x8d, 0x94, 0x85, 0x38,
-      0xf1, 0x94, 0x3f, 0xa4, 0x27, 0xd7, 0x91, 0x0e },
-    { 0x04, 0x0f, 0x53, 0x7a, 0x51, 0x95, 0x95, 0xcc,
-      0xff, 0xde, 0x35, 0xe0, 0xd1, 0x28, 0xb7, 0x99,
-      0x92, 0x2b, 0xa9, 0x37, 0xa2, 0xe8, 0x65, 0x84,
-      0x36, 0x62, 0xf1, 0xf4, 0x50, 0x02, 0xb8, 0x2d },
-    { 0x07, 0x19, 0x4f, 0x47, 0xf4, 0xce, 0xd0, 0x96,
-      0xd1, 0x06, 0x8d, 0x34, 0x49, 0x3b, 0x67, 0x37,
-      0x14, 0x45, 0x16, 0x93, 0xa6, 0xa2, 0x71, 0x2f,
-      0x70, 0x8f, 0x59, 0x36, 0x12, 0x11, 0xc6, 0x21 },
-    { 0x07, 0x8f, 0xee, 0x58, 0x8a, 0x2c, 0x55, 0xc8,
-      0xe2, 0xc1, 0x78, 0x71, 0xaa, 0xb6, 0xe4, 0x00,
-      0xb3, 0xfd, 0xbc, 0xdc, 0xf3, 0x91, 0x46, 0xa0,
-      0x89, 0x37, 0xf9, 0xac, 0x06, 0xa1, 0xb8, 0xbd },
-    { 0x08, 0x21, 0x0a, 0xc3, 0xa2, 0x95, 0x56, 0xf6,
-      0x8d, 0x33, 0xb4, 0x40, 0x87, 0x9c, 0x54, 0x63,
-      0x64, 0x04, 0xe9, 0x7c, 0x4d, 0x9f, 0x97, 0x82,
-      0x23, 0xd2, 0x42, 0xab, 0xe5, 0x38, 0x5e, 0x4e },
-    { 0x08, 0xc2, 0xd3, 0x17, 0xa8, 0x4a, 0x3c, 0xbe,
-      0x38, 0xde, 0x64, 0xa2, 0x4d, 0xd4, 0x27, 0x91,
-      0x09, 0xe2, 0xbc, 0x02, 0x2b, 0x93, 0xb1, 0x05,
-      0xa8, 0x94, 0xa5, 0x1a, 0xdc, 0x3e, 0xe5, 0xcc },
-    { 0x09, 0x9f, 0x3e, 0x71, 0xb5, 0x00, 0xd1, 0x5b,
-      0x03, 0x7b, 0x93, 0xaa, 0x5f, 0xb4, 0x16, 0x19,
-      0x0a, 0xd1, 0xdf, 0x86, 0x73, 0xab, 0x31, 0xa8,
-      0xf6, 0xd9, 0x7f, 0x59, 0x5e, 0x8e, 0x16, 0xe9 },
-    { 0x09, 0xeb, 0xdd, 0x1b, 0x7f, 0xfa, 0x4e, 0xd7,
-      0x4b, 0xeb, 0xae, 0x96, 0xba, 0x10, 0x65, 0xdc,
-      0x7d, 0xa1, 0xc5, 0xd3, 0x18, 0x3c, 0xc5, 0x94,
-      0x19, 0xe9, 0x78, 0x36, 0xaf, 0x7f, 0x6d, 0x70 },
-    { 0x0a, 0x01, 0x88, 0x81, 0x2c, 0x9d, 0xe8, 0x8a,
-      0x2f, 0x0a, 0x5c, 0x4c, 0x57, 0xe6, 0xf9, 0xa8,
-      0x15, 0x69, 0xe9, 0xc7, 0x09, 0xc0, 0x95, 0x40,
-      0x80, 0xe5, 0xe4, 0xe6, 0x62, 0x85, 0x6d, 0xf8 },
-    { 0x0a, 0x42, 0x19, 0x7e, 0x48, 0x70, 0xb2, 0x34,
-      0x20, 0xf5, 0x51, 0x9f, 0xb8, 0x39, 0xb6, 0xcc,
-      0x83, 0x03, 0x52, 0x9a, 0xa9, 0x06, 0x9a, 0xd1,
-      0xa0, 0x90, 0x86, 0xcf, 0x6c, 0xba, 0x07, 0xc2 },
-    { 0x0b, 0x03, 0xe1, 0x27, 0xc2, 0xe3, 0x3e, 0xad,
-      0xbc, 0xb0, 0x99, 0x80, 0x46, 0xcc, 0x9b, 0xa7,
-      0x33, 0x46, 0x3e, 0x0c, 0xa6, 0x43, 0x52, 0x27,
-      0x81, 0xb0, 0x3d, 0x81, 0x53, 0x97, 0xeb, 0x4f },
-    { 0x0b, 0x1e, 0x1e, 0x73, 0x43, 0xa0, 0xe9, 0x1c,
-      0x2a, 0x27, 0xdd, 0x2a, 0x4d, 0x7e, 0x6b, 0xf1,
-      0xe8, 0x04, 0x4b, 0x58, 0xce, 0x1a, 0xe8, 0x1e,
-      0x27, 0xd8, 0x14, 0xfd, 0x2d, 0xc0, 0x18, 0x93 },
-    { 0x0b, 0x48, 0xd5, 0x5c, 0xac, 0x84, 0xfd, 0xee,
-      0x15, 0xd8, 0x1a, 0xff, 0x99, 0x07, 0xbb, 0x9a,
-      0x57, 0x11, 0xa9, 0x5c, 0xe2, 0x3a, 0x8d, 0x4d,
-      0x5e, 0x88, 0x62, 0xbf, 0x15, 0xa7, 0x6a, 0x75 },
-    { 0x0b, 0xfe, 0xa1, 0x38, 0x31, 0x67, 0x3e, 0xc9,
-      0x69, 0xd0, 0x5f, 0xd8, 0x67, 0xb6, 0x69, 0xf2,
-      0x71, 0x24, 0xaf, 0xeb, 0x7c, 0x60, 0x8c, 0xfe,
-      0x54, 0xcf, 0x46, 0x33, 0x06, 0xcc, 0x99, 0x2e },
-    { 0x0c, 0xb9, 0x31, 0x93, 0xf1, 0x65, 0x26, 0xe1,
-      0xd1, 0x65, 0x52, 0x11, 0x7b, 0xa2, 0x1a, 0xac,
-      0xb9, 0xf1, 0xd7, 0xa8, 0x93, 0x56, 0xa3, 0x5d,
-      0xe4, 0xf6, 0x65, 0xe9, 0x39, 0x90, 0x79, 0x38 },
-    { 0x0d, 0x16, 0x1b, 0xb9, 0xca, 0x0d, 0x20, 0xe4,
-      0x67, 0x35, 0x89, 0x67, 0x22, 0x78, 0xb0, 0xa3,
-      0xc5, 0xe2, 0x69, 0x30, 0xa4, 0xdc, 0x3a, 0x82,
-      0x16, 0x85, 0x43, 0x24, 0x27, 0xc7, 0x31, 0x5a },
-    { 0x0d, 0x71, 0xc8, 0xca, 0x16, 0x56, 0x59, 0xef,
-      0xaf, 0x69, 0x65, 0x29, 0x28, 0x9a, 0xae, 0x25,
-      0xd9, 0xc4, 0x2a, 0x1b, 0xbb, 0x03, 0x5a, 0x2b,
-      0x8c, 0x61, 0x14, 0x7e, 0x1b, 0x8b, 0x90, 0x52 },
-    { 0x0e, 0xfd, 0x68, 0x73, 0xd6, 0x0e, 0x77, 0x96,
-      0x2d, 0xf6, 0x00, 0x16, 0xdc, 0x3b, 0xaf, 0x9c,
-      0xa7, 0x1e, 0x7d, 0x86, 0x19, 0xe7, 0xeb, 0xaa,
-      0x3a, 0xf2, 0xdc, 0xb5, 0xba, 0x24, 0xde, 0xc2 },
-    { 0x0e, 0xff, 0x3c, 0xff, 0xda, 0x4a, 0x3e, 0x87,
-      0x23, 0x4a, 0x86, 0xc7, 0x0d, 0x49, 0x8c, 0x62,
-      0x60, 0x7f, 0x37, 0x44, 0xea, 0x71, 0xf1, 0x83,
-      0x1d, 0xcf, 0xca, 0xf3, 0xaf, 0x15, 0x56, 0x9c },
-    { 0x10, 0x83, 0x6d, 0xa0, 0xcd, 0x6a, 0xc0, 0x95,
-      0xdd, 0x7a, 0xc3, 0x4d, 0x99, 0x01, 0x90, 0x9a,
-      0x8e, 0xf8, 0x4d, 0x6e, 0xe0, 0x5b, 0x83, 0x43,
-      0x03, 0xd4, 0x7f, 0xc0, 0xa5, 0xf9, 0x14, 0xfa },
-    { 0x11, 0xa4, 0x02, 0x7b, 0x45, 0xfc, 0x9a, 0x6f,
-      0x40, 0x21, 0x25, 0xc3, 0xca, 0x22, 0x68, 0xe0,
-      0x15, 0xa3, 0x1b, 0xa4, 0xfd, 0xb0, 0x05, 0x9d,
-      0x66, 0x6b, 0x73, 0xc8, 0x51, 0xd5, 0x35, 0x92 },
-    { 0x12, 0x6b, 0x1b, 0xa6, 0x38, 0xc7, 0xe6, 0x99,
-      0xbc, 0xbc, 0x54, 0xf5, 0x79, 0xac, 0xd3, 0x9f,
-      0xe6, 0x1d, 0x08, 0x22, 0x5f, 0xe5, 0xb1, 0xf9,
-      0x01, 0x88, 0xb2, 0x3f, 0xd8, 0x43, 0x3e, 0x8e },
-    { 0x13, 0x5d, 0x3e, 0xda, 0x6e, 0x55, 0x9b, 0xf5,
-      0xee, 0x23, 0x0a, 0xa5, 0xba, 0x59, 0xbb, 0x6a,
-      0x2a, 0x0f, 0x07, 0x82, 0x2f, 0xed, 0x38, 0x44,
-      0x7e, 0x6a, 0xbc, 0x5c, 0x23, 0xaa, 0xd0, 0x27 },
-    { 0x13, 0x6a, 0x40, 0x09, 0x81, 0xb1, 0xa3, 0xe0,
-      0x5f, 0xdc, 0xac, 0x20, 0xa2, 0x36, 0xf8, 0x6e,
-      0x94, 0xe5, 0xee, 0x58, 0x59, 0xd8, 0xfd, 0x45,
-      0xe9, 0xe9, 0xc5, 0xa6, 0xc5, 0xc0, 0xa4, 0x13 },
-    { 0x14, 0x21, 0x28, 0xa6, 0x65, 0x1c, 0xdc, 0x18,
-      0x70, 0xc2, 0x67, 0x5e, 0xc0, 0xb0, 0xef, 0x32,
-      0xb5, 0xd4, 0xc1, 0x55, 0x35, 0x8e, 0x7e, 0xd9,
-      0x5a, 0x98, 0xe8, 0x3b, 0x1a, 0xd8, 0xbe, 0x4d },
-    { 0x14, 0x47, 0x25, 0xa6, 0x79, 0x1c, 0x60, 0x0c,
-      0x4c, 0x2c, 0xf3, 0x94, 0x3f, 0x3e, 0xcf, 0x40,
-      0xd6, 0x31, 0xd7, 0x60, 0xe4, 0x51, 0xef, 0x28,
-      0x29, 0xaf, 0xfb, 0xee, 0x74, 0x80, 0xad, 0x17 },
-    { 0x15, 0x27, 0x2a, 0xbc, 0x1f, 0x0c, 0x4d, 0x1d,
-      0x1a, 0x92, 0x08, 0x73, 0x55, 0xa1, 0xe0, 0x42,
-      0x6c, 0x2b, 0xb5, 0xb4, 0x37, 0x30, 0x00, 0xb8,
-      0x2c, 0x2c, 0xca, 0xb7, 0xfa, 0xd6, 0xfa, 0x20 },
-    { 0x15, 0x48, 0x1f, 0xde, 0x4e, 0x3f, 0x72, 0x49,
-      0x66, 0x87, 0xdf, 0x57, 0x5f, 0xb5, 0xb1, 0x27,
-      0xbd, 0x6d, 0xeb, 0x66, 0x1d, 0xd9, 0x07, 0x71,
-      0x8b, 0xa0, 0x65, 0xc7, 0xda, 0x66, 0x76, 0xd1 },
-    { 0x15, 0x5a, 0x88, 0x39, 0x60, 0x8b, 0x77, 0x25,
-      0x34, 0x6a, 0x72, 0x40, 0xe4, 0xe2, 0x50, 0x3a,
-      0xcc, 0x7b, 0x8b, 0xef, 0x0b, 0x1b, 0xe6, 0x15,
-      0xb9, 0x02, 0x4a, 0x88, 0xe6, 0x52, 0x11, 0xf9 },
-    { 0x15, 0x5d, 0x88, 0x6e, 0x99, 0x1d, 0x40, 0x0a,
-      0xbf, 0x2f, 0x83, 0xc2, 0x80, 0xd1, 0x24, 0x6d,
-      0xce, 0x02, 0xa6, 0x28, 0x31, 0x26, 0xc6, 0x17,
-      0xe4, 0x17, 0xd2, 0xb7, 0xea, 0xc1, 0x19, 0x24 },
-    { 0x17, 0x3d, 0xe2, 0x60, 0xe2, 0x2d, 0x76, 0x9d,
-      0x2d, 0x54, 0x99, 0xc8, 0x22, 0x0d, 0x86, 0xed,
-      0xe3, 0x48, 0xda, 0x1e, 0x57, 0xc1, 0xe7, 0xc8,
-      0x15, 0x07, 0xfb, 0x3e, 0x6b, 0xd7, 0x3b, 0x7f },
-    { 0x18, 0x1e, 0xbb, 0x29, 0x8d, 0x20, 0x68, 0x5c,
-      0x48, 0xf7, 0x53, 0x89, 0x80, 0xc5, 0x63, 0xc8,
-      0xf7, 0x48, 0x95, 0x4c, 0xf2, 0x64, 0x41, 0x9a,
-      0x72, 0xfc, 0xc6, 0x34, 0x0a, 0x10, 0x23, 0x80 },
-    { 0x19, 0xff, 0xe6, 0xc6, 0x7a, 0x35, 0x86, 0xfc,
-      0x48, 0x6c, 0xe2, 0x07, 0xfa, 0x2a, 0xf6, 0x62,
-      0xf5, 0x50, 0xfc, 0x51, 0x2f, 0xdd, 0x78, 0x17,
-      0xe3, 0x86, 0xc9, 0x4a, 0x7b, 0xde, 0x37, 0xa9 },
-    { 0x1a, 0x9e, 0xc6, 0x8c, 0xed, 0xb6, 0xbd, 0x94,
-      0x0c, 0x95, 0x34, 0xe6, 0x84, 0xbb, 0x04, 0x9f,
-      0xf1, 0xe2, 0x3b, 0x66, 0xa1, 0x33, 0x01, 0x2f,
-      0xc3, 0x99, 0xeb, 0x4f, 0xb5, 0xd3, 0xaa, 0x35 },
-    { 0x1b, 0x7b, 0xf8, 0xd9, 0xe8, 0x29, 0x3c, 0x53,
-      0xdd, 0x59, 0xec, 0x97, 0xfe, 0x16, 0xf0, 0xea,
-      0xb4, 0x68, 0x5b, 0x95, 0xce, 0x14, 0xd2, 0x62,
-      0x3e, 0x70, 0x94, 0x2c, 0xff, 0x25, 0xe7, 0x30 },
-    { 0x1b, 0xd7, 0xb3, 0x62, 0xbc, 0x14, 0x66, 0xfa,
-      0xc0, 0x5e, 0xc5, 0x9e, 0x12, 0xe8, 0x1b, 0xe7,
-      0x35, 0x38, 0xc4, 0x97, 0x28, 0xf5, 0xad, 0xba,
-      0x2d, 0x81, 0xfc, 0xdb, 0xc4, 0x65, 0x7c, 0x1b },
-    { 0x1b, 0xec, 0xfe, 0x78, 0xce, 0x5e, 0x77, 0xa9,
-      0x77, 0xbb, 0x5f, 0xe3, 0x49, 0x91, 0x06, 0xc6,
-      0x4c, 0xf2, 0xb0, 0x76, 0x16, 0x59, 0x49, 0x04,
-      0x11, 0x17, 0xcd, 0x8a, 0xbc, 0xd9, 0x05, 0xd4 },
-    { 0x1b, 0xf4, 0x8a, 0x83, 0x3c, 0xe4, 0x05, 0x64,
-      0x8c, 0xc0, 0xbd, 0xd3, 0xb5, 0xb8, 0xc1, 0x8e,
-      0xb5, 0x13, 0x15, 0x34, 0x29, 0x3a, 0xb2, 0x63,
-      0x44, 0xb5, 0x00, 0x76, 0x48, 0x11, 0x41, 0xed },
-    { 0x1c, 0x04, 0x82, 0x0f, 0x7b, 0x4a, 0x2f, 0x1e,
-      0x38, 0x5d, 0xe1, 0xde, 0x16, 0xb2, 0x22, 0x6e,
-      0x88, 0x3d, 0x9c, 0x34, 0x66, 0x3e, 0x1b, 0x64,
-      0xe8, 0x5b, 0x98, 0x0e, 0xaf, 0xf0, 0xb9, 0xd3 },
-    { 0x1d, 0x9e, 0xc0, 0x06, 0xa5, 0x26, 0xfa, 0xb5,
-      0xce, 0x2e, 0x71, 0xfd, 0xfc, 0x07, 0xc0, 0x11,
-      0xf7, 0x65, 0x7b, 0xf8, 0x5f, 0x5d, 0x03, 0x52,
-      0xb8, 0xcb, 0x21, 0x8d, 0x4f, 0xcb, 0xc4, 0x43 },
-    { 0x1e, 0x78, 0xf8, 0x08, 0x84, 0xe3, 0x2a, 0x2e,
-      0xa5, 0xad, 0x1e, 0xe8, 0x35, 0x88, 0xac, 0xdb,
-      0x18, 0x4a, 0x4a, 0x6e, 0x87, 0x56, 0x5b, 0xf5,
-      0x03, 0xb5, 0x69, 0x7a, 0xbf, 0xae, 0x64, 0xa4 },
-    { 0x1f, 0x11, 0x85, 0xa5, 0x21, 0xe2, 0x8e, 0x95,
-      0x17, 0x1c, 0xf3, 0x86, 0x07, 0x8a, 0x76, 0x4a,
-      0x9a, 0x3e, 0x71, 0xc2, 0x59, 0xbc, 0xdc, 0x5f,
-      0x8e, 0x66, 0xe1, 0xb5, 0x20, 0x55, 0xa2, 0x6d },
-    { 0x1f, 0x23, 0xd7, 0xa6, 0x38, 0x17, 0x1f, 0x6d,
-      0x09, 0x99, 0x64, 0xe0, 0xfa, 0x01, 0x72, 0x1c,
-      0x06, 0xcc, 0xeb, 0x8e, 0xa2, 0x98, 0xbf, 0xd0,
-      0x04, 0x8e, 0x13, 0x8d, 0x98, 0xfc, 0x36, 0x24 },
-    { 0x1f, 0xc7, 0xf8, 0x10, 0x4e, 0x27, 0xff, 0x2a,
-      0x45, 0x56, 0xf9, 0x1e, 0x05, 0x42, 0x17, 0xc5,
-      0x8f, 0x69, 0x3f, 0x70, 0x36, 0x25, 0x9e, 0x39,
-      0x80, 0xb5, 0x59, 0x5b, 0x04, 0x3d, 0x11, 0x92 },
-    { 0x20, 0x0b, 0x49, 0xbd, 0xd6, 0x35, 0x02, 0x57,
-      0xcc, 0xd4, 0xe6, 0xad, 0xe1, 0xcb, 0x75, 0x13,
-      0x8d, 0xd6, 0xd9, 0x06, 0xfe, 0xf3, 0x49, 0xc0,
-      0xc9, 0x86, 0xa5, 0x1b, 0x29, 0xb9, 0xe5, 0x2d },
-    { 0x21, 0x78, 0xe8, 0x28, 0x3a, 0x73, 0x39, 0x6e,
-      0x08, 0xc0, 0xa1, 0x1a, 0x88, 0x72, 0xfa, 0x4a,
-      0x9f, 0xcc, 0x05, 0x67, 0x0c, 0xee, 0xff, 0xb8,
-      0x95, 0x83, 0x8e, 0xb6, 0x59, 0xde, 0x38, 0xdb },
-    { 0x22, 0x01, 0x71, 0xf7, 0x0e, 0x1f, 0xc3, 0xc4,
-      0xf7, 0x8d, 0xa6, 0xc8, 0xb1, 0xd7, 0x2c, 0x3b,
-      0xa8, 0x31, 0x9a, 0x46, 0xf8, 0x19, 0x2d, 0x1e,
-      0x19, 0xb9, 0xe2, 0x9a, 0xba, 0x18, 0xee, 0x87 },
-    { 0x23, 0x19, 0xcb, 0x3d, 0x58, 0xc6, 0xd5, 0x53,
-      0x62, 0x5d, 0xe5, 0xf4, 0x25, 0x2b, 0xf0, 0x29,
-      0xab, 0x83, 0x05, 0xeb, 0xf2, 0x2f, 0xa2, 0x3e,
-      0x99, 0x73, 0x04, 0x66, 0xde, 0x24, 0xd6, 0xc3 },
-    { 0x23, 0x8a, 0x80, 0xcc, 0x9b, 0x58, 0x9a, 0xdc,
-      0x89, 0xb7, 0xa8, 0xf3, 0x4d, 0xdf, 0x12, 0x48,
-      0x73, 0x4b, 0x9f, 0x7f, 0x78, 0x20, 0xb6, 0x04,
-      0x07, 0x66, 0xc5, 0x41, 0x3a, 0xd2, 0xbd, 0xef },
-    { 0x23, 0x9c, 0x79, 0x5f, 0x0c, 0x55, 0xa5, 0x53,
-      0x16, 0x2a, 0x9c, 0xa0, 0x6e, 0x88, 0x01, 0xe1,
-      0x19, 0xbd, 0xff, 0x54, 0x35, 0x4a, 0x3f, 0x68,
-      0x43, 0xcf, 0x2a, 0x2f, 0xa6, 0x01, 0x75, 0x8e },
-    { 0x24, 0x62, 0x52, 0x48, 0x32, 0xc1, 0x54, 0xd8,
-      0x4d, 0xf5, 0x8e, 0xd7, 0x75, 0x22, 0x3b, 0xbe,
-      0x25, 0x7d, 0xea, 0xf7, 0x0e, 0xf9, 0xd2, 0x08,
-      0x61, 0x4e, 0xc0, 0xf5, 0x97, 0x7f, 0x6d, 0x58 },
-    { 0x24, 0x6d, 0x0c, 0x31, 0x48, 0x72, 0x75, 0x59,
-      0xf9, 0x9a, 0xd0, 0xc1, 0x50, 0x37, 0x70, 0x06,
-      0xb7, 0xa1, 0x7a, 0x60, 0x3a, 0x47, 0x3b, 0x6a,
-      0xac, 0xd2, 0x4e, 0x16, 0xc6, 0xc5, 0x1b, 0x42 },
-    { 0x25, 0x1b, 0xb7, 0xc5, 0x42, 0x33, 0xda, 0x44,
-      0xbf, 0x53, 0xb5, 0x8a, 0xf2, 0x9a, 0xe1, 0x74,
-      0xb9, 0x78, 0xba, 0xdb, 0x89, 0xa9, 0x50, 0xab,
-      0x3e, 0x5f, 0x9b, 0x4d, 0x0d, 0xcd, 0xbc, 0x62 },
-    { 0x26, 0x03, 0xcb, 0xdf, 0x69, 0x75, 0xe3, 0x68,
-      0x83, 0x7f, 0x95, 0x1a, 0x00, 0x49, 0xfd, 0xc3,
-      0xc4, 0xb2, 0x39, 0xf0, 0x82, 0xf6, 0xbf, 0x89,
-      0x5d, 0xb8, 0xf3, 0x27, 0x05, 0xe6, 0x9c, 0xf3 },
-    { 0x27, 0x50, 0x11, 0x93, 0xe4, 0x61, 0xca, 0xce,
-      0x55, 0x32, 0xfa, 0xd5, 0xd5, 0xb2, 0x7e, 0x01,
-      0x16, 0x57, 0x92, 0xe0, 0x4f, 0x24, 0x21, 0x93,
-      0x2f, 0x39, 0x28, 0xaf, 0x9f, 0xcd, 0xa4, 0xf3 },
-    { 0x27, 0xa8, 0x41, 0xae, 0xcf, 0xe0, 0xa1, 0x39,
-      0x37, 0x51, 0xc2, 0x55, 0xf9, 0x06, 0xdb, 0x9e,
-      0x88, 0x6b, 0xba, 0x4d, 0x7c, 0x44, 0xec, 0x63,
-      0xce, 0x7d, 0xc6, 0xde, 0xc1, 0x8b, 0xb9, 0x20 },
-    { 0x28, 0x07, 0x10, 0x60, 0x44, 0x03, 0x45, 0xd0,
-      0x0e, 0x80, 0xb9, 0xd7, 0xcb, 0xe1, 0x87, 0xc1,
-      0xd8, 0xb0, 0xf2, 0xef, 0x5d, 0x0a, 0xac, 0x9c,
-      0xce, 0xef, 0x9a, 0x8c, 0x5a, 0x06, 0xf3, 0x02 },
-    { 0x28, 0xd9, 0x51, 0x84, 0xb5, 0xea, 0x14, 0x0f,
-      0x47, 0x4f, 0x3a, 0xf6, 0xce, 0x70, 0x52, 0xe8,
-      0x59, 0x3c, 0xf3, 0xa5, 0x01, 0x0f, 0x52, 0x24,
-      0x1a, 0x1e, 0x36, 0x64, 0x60, 0xe5, 0x91, 0x9e },
-    { 0x29, 0x01, 0x93, 0xe3, 0x7a, 0x38, 0x87, 0xfd,
-      0x36, 0x15, 0xdf, 0x12, 0x2e, 0x95, 0x21, 0x17,
-      0x42, 0x15, 0xee, 0x68, 0xf7, 0x44, 0xb2, 0xfa,
-      0x35, 0xd2, 0x9c, 0x5d, 0xf1, 0x08, 0xf5, 0x5b },
-    { 0x2a, 0x0f, 0x70, 0x67, 0x6e, 0x18, 0x4d, 0x49,
-      0x39, 0xa4, 0x04, 0xde, 0x35, 0xac, 0x84, 0xab,
-      0x81, 0xaf, 0xec, 0x36, 0x17, 0xe7, 0xe1, 0xbf,
-      0x34, 0x67, 0xd4, 0x19, 0x25, 0x5d, 0xd8, 0x17 },
-    { 0x2a, 0xa6, 0x47, 0x8c, 0xc7, 0x5d, 0x67, 0xa8,
-      0xca, 0x55, 0xb2, 0xe1, 0x63, 0xfd, 0xbb, 0xbc,
-      0x9d, 0x74, 0xb4, 0xe5, 0xf3, 0x7b, 0x7d, 0xbd,
-      0x13, 0xc9, 0x4e, 0x85, 0x8d, 0x40, 0xda, 0xd0 },
-    { 0x2c, 0x82, 0x47, 0x4f, 0x0e, 0xf6, 0xcb, 0x65,
-      0x0a, 0x13, 0xef, 0x20, 0x99, 0x6e, 0x65, 0x7b,
-      0x67, 0x24, 0xf0, 0xa0, 0xd5, 0xee, 0x24, 0x6d,
-      0x26, 0xbb, 0xfa, 0x0a, 0xbb, 0x2c, 0x22, 0xe1 },
-    { 0x2c, 0x9b, 0xe1, 0x2d, 0xa4, 0x99, 0xea, 0xbb,
-      0x2f, 0xfd, 0xf9, 0x91, 0x6f, 0x2b, 0x27, 0x18,
-      0x81, 0x19, 0x5b, 0x74, 0x19, 0xbd, 0x1e, 0xef,
-      0x8d, 0x50, 0x77, 0x2a, 0xb9, 0x46, 0x4a, 0xa8 },
-    { 0x2c, 0xbd, 0xd5, 0x6c, 0xe4, 0xb4, 0x06, 0x09,
-      0xe9, 0xaa, 0x52, 0x1e, 0xaa, 0x76, 0xac, 0x7e,
-      0x55, 0x73, 0x7b, 0xf4, 0x3e, 0x2b, 0x0c, 0x30,
-      0xdd, 0xcf, 0x59, 0x87, 0x2e, 0xab, 0xe7, 0x7b },
-    { 0x2d, 0xde, 0xe4, 0x5f, 0x72, 0x78, 0x38, 0xde,
-      0xad, 0xe6, 0x7e, 0x9c, 0xa7, 0x05, 0xeb, 0xb4,
-      0xc2, 0xe9, 0x40, 0xae, 0x1b, 0x9d, 0x62, 0x35,
-      0x72, 0x18, 0x04, 0x58, 0x31, 0xe9, 0x8f, 0xde },
-    { 0x2e, 0x5d, 0xd2, 0x55, 0x09, 0x6d, 0x64, 0x83,
-      0x10, 0x5c, 0xb6, 0x03, 0x6c, 0x59, 0x17, 0x57,
-      0xfd, 0x98, 0x49, 0x70, 0x66, 0x05, 0x3f, 0x83,
-      0x39, 0xe4, 0xd8, 0xd0, 0xc3, 0x75, 0x49, 0x03 },
-    { 0x2e, 0xd2, 0x05, 0x8f, 0x39, 0xea, 0xba, 0x5c,
-      0xb3, 0xd7, 0xdf, 0x24, 0xca, 0x74, 0xa7, 0x7d,
-      0xdc, 0x12, 0x06, 0x01, 0x52, 0x7b, 0x0f, 0x51,
-      0x06, 0x91, 0x05, 0xca, 0x88, 0x37, 0x6e, 0x20 },
-    { 0x30, 0x7b, 0x09, 0x34, 0xef, 0x97, 0x85, 0xe7,
-      0x08, 0xed, 0x48, 0x1a, 0x99, 0x7a, 0x8a, 0x88,
-      0xb7, 0xbf, 0x22, 0xdd, 0x26, 0xaa, 0x17, 0x17,
-      0x31, 0xb8, 0xf7, 0xe0, 0xd5, 0x97, 0xb7, 0x08 },
-    { 0x30, 0xe0, 0x69, 0x80, 0x9c, 0x79, 0x90, 0xf0,
-      0xb5, 0xf2, 0x66, 0xe8, 0x94, 0x59, 0x96, 0x42,
-      0xe8, 0x53, 0x50, 0xab, 0x82, 0x81, 0x05, 0x34,
-      0xc7, 0xf3, 0xfd, 0x67, 0x0c, 0x1b, 0xeb, 0x18 },
-    { 0x31, 0x53, 0x47, 0x52, 0xb6, 0xf5, 0x48, 0x20,
-      0x91, 0x5c, 0x39, 0x5b, 0xee, 0x97, 0x5b, 0xc5,
-      0x4e, 0x3f, 0x07, 0xc0, 0x8c, 0xd3, 0x4c, 0x5a,
-      0x51, 0x15, 0xde, 0xf0, 0x17, 0xdb, 0x2b, 0x54 },
-    { 0x31, 0xb8, 0x3e, 0x01, 0x90, 0x98, 0x95, 0xbc,
-      0x74, 0x2d, 0x6b, 0xe8, 0x40, 0x0a, 0xde, 0x51,
-      0xb2, 0x09, 0x83, 0xf6, 0x83, 0xa2, 0xaa, 0xee,
-      0xb2, 0x5f, 0x58, 0xdf, 0x98, 0x1b, 0xde, 0x0d },
-    { 0x32, 0xef, 0x13, 0x33, 0x86, 0xbf, 0x0c, 0x63,
-      0xcf, 0x29, 0xd6, 0x2b, 0x0d, 0x76, 0x88, 0x9e,
-      0x9d, 0x9d, 0x53, 0x2e, 0xe4, 0x90, 0x38, 0x94,
-      0x4d, 0xbc, 0x21, 0x49, 0xd8, 0xca, 0xa5, 0xd1 },
-    { 0x33, 0xd1, 0x6c, 0xd9, 0xe8, 0x2e, 0xdf, 0xfd,
-      0x0b, 0x3a, 0xfb, 0x46, 0xa6, 0x84, 0xc5, 0xa0,
-      0xd1, 0x2f, 0x2b, 0x40, 0x58, 0x6d, 0x53, 0x2f,
-      0x6a, 0xab, 0x54, 0xce, 0xbc, 0x42, 0x33, 0xd3 },
-    { 0x34, 0x06, 0x4f, 0xf9, 0x3b, 0x27, 0x4c, 0xf5,
-      0xa7, 0x24, 0xec, 0x19, 0x64, 0x50, 0x4a, 0x71,
-      0x0a, 0xb9, 0x7b, 0xa1, 0x10, 0x3c, 0xd9, 0xb9,
-      0x8c, 0x81, 0xd0, 0xab, 0xcf, 0x3b, 0x19, 0xbd },
-    { 0x34, 0x65, 0xc2, 0xf9, 0xa0, 0xcf, 0x36, 0xe5,
-      0xee, 0xf0, 0x27, 0x1c, 0x52, 0x91, 0x2d, 0x58,
-      0x6f, 0xb2, 0x0b, 0x94, 0x43, 0xe7, 0xd5, 0x82,
-      0xa3, 0xe2, 0x23, 0x93, 0xfa, 0xc8, 0x1b, 0xb4 },
-    { 0x34, 0x87, 0x46, 0xbf, 0xd4, 0x98, 0xc3, 0xf5,
-      0xc8, 0x68, 0x5e, 0xea, 0xac, 0x57, 0x87, 0x2d,
-      0x3b, 0x47, 0xe6, 0x02, 0xf4, 0x97, 0xe9, 0xf0,
-      0x28, 0x54, 0x12, 0x32, 0x59, 0xfb, 0xe1, 0x69 },
-    { 0x36, 0x45, 0xef, 0x7f, 0x5d, 0x15, 0xa5, 0x46,
-      0x7e, 0x85, 0x30, 0x7d, 0xda, 0x15, 0xcb, 0xbb,
-      0x55, 0xb7, 0x30, 0xae, 0xf8, 0xef, 0x9c, 0x71,
-      0x5d, 0x7d, 0x9f, 0xb4, 0x7f, 0xdf, 0x33, 0xad },
-    { 0x36, 0xb4, 0xfe, 0x74, 0x3b, 0x6d, 0xf4, 0x4a,
-      0x71, 0x3e, 0x91, 0x4c, 0xab, 0xfb, 0xf2, 0xbe,
-      0x60, 0x24, 0x9b, 0x46, 0x43, 0x4d, 0x04, 0x43,
-      0x59, 0x12, 0x5a, 0x10, 0x6a, 0x37, 0xeb, 0x1c },
-    { 0x36, 0xf5, 0xa9, 0x7d, 0x79, 0x3f, 0x84, 0x97,
-      0x44, 0xd6, 0xab, 0x39, 0xb7, 0xa8, 0x18, 0xf8,
-      0x17, 0x6e, 0x65, 0x20, 0xdc, 0x86, 0x3d, 0xce,
-      0x43, 0xb3, 0x98, 0xc3, 0x0b, 0x5e, 0xdb, 0x09 },
-    { 0x38, 0x23, 0x4e, 0x55, 0x9d, 0x30, 0x27, 0xd1,
-      0x61, 0xda, 0x8c, 0x98, 0x88, 0x04, 0x9a, 0x4d,
-      0x20, 0xac, 0xf2, 0x00, 0x90, 0xad, 0x1a, 0x22,
-      0x2b, 0x73, 0x9a, 0xc8, 0x6e, 0xb7, 0x6f, 0x06 },
-    { 0x39, 0x02, 0x27, 0xce, 0x88, 0x1c, 0x71, 0x8b,
-      0x59, 0xa6, 0xbc, 0x31, 0x90, 0xd5, 0x17, 0xe7,
-      0x1e, 0x1e, 0x58, 0x66, 0x93, 0xc8, 0xbf, 0x8a,
-      0x30, 0x27, 0x26, 0x20, 0x13, 0xfe, 0x16, 0x63 },
-    { 0x39, 0x21, 0x5c, 0xaa, 0x37, 0x1a, 0xbe, 0x57,
-      0x6a, 0xb9, 0x3b, 0x18, 0xc2, 0xf3, 0x75, 0x5e,
-      0xe2, 0x6f, 0x8c, 0x3a, 0xdb, 0x75, 0x9b, 0x6f,
-      0x34, 0x78, 0x9f, 0xb8, 0xec, 0xf0, 0x54, 0x28 },
-    { 0x39, 0x7d, 0x00, 0x6e, 0xf8, 0xaf, 0xb2, 0x0f,
-      0x43, 0x61, 0xa6, 0xc9, 0x72, 0xf0, 0xc5, 0x7c,
-      0xc0, 0x87, 0x74, 0x01, 0x06, 0x12, 0x78, 0x3f,
-      0xba, 0xbc, 0xb8, 0xd6, 0xf6, 0x03, 0x9e, 0x2c },
-    { 0x3a, 0xcf, 0x85, 0x3c, 0x4e, 0x45, 0x02, 0xbd,
-      0x82, 0xd5, 0x85, 0xd5, 0xe0, 0x82, 0xc4, 0xb3,
-      0xad, 0x03, 0xcd, 0xb6, 0xb5, 0x05, 0xca, 0x80,
-      0x47, 0x19, 0x88, 0xec, 0x4c, 0x58, 0x99, 0x9e },
-    { 0x3a, 0xea, 0x2c, 0xef, 0xae, 0x63, 0x44, 0xff,
-      0xae, 0x67, 0x49, 0x4c, 0x68, 0x4e, 0x1e, 0xbf,
-      0x87, 0x95, 0x40, 0xb5, 0x3d, 0x40, 0xf5, 0x16,
-      0x9f, 0x78, 0x89, 0x7f, 0x1b, 0x38, 0xab, 0x66 },
-    { 0x3b, 0x47, 0x85, 0x0b, 0xf8, 0x4c, 0x4c, 0xf2,
-      0xca, 0x6c, 0x31, 0xb3, 0x78, 0x39, 0xc9, 0x50,
-      0x76, 0x63, 0x70, 0xd7, 0xf4, 0xb6, 0x4a, 0xd0,
-      0x18, 0x55, 0xca, 0xcf, 0xe3, 0x51, 0x2f, 0xc3 },
-    { 0x3b, 0xaa, 0x31, 0x31, 0x70, 0x68, 0xac, 0xe0,
-      0x89, 0xae, 0xb4, 0xa8, 0x8d, 0x7e, 0xde, 0xbe,
-      0x94, 0xab, 0x4a, 0xce, 0x46, 0xbb, 0xd2, 0x68,
-      0x3e, 0x3f, 0xdf, 0xf5, 0x59, 0x30, 0x0f, 0x93 },
-    { 0x3c, 0x38, 0x36, 0x2e, 0x16, 0x8b, 0xb4, 0xa7,
-      0x59, 0xc4, 0x80, 0x55, 0x1c, 0xb1, 0x65, 0x6f,
-      0x6a, 0x96, 0x8b, 0x9b, 0x43, 0xcb, 0xe0, 0xd7,
-      0x39, 0x75, 0x4a, 0xb7, 0x8a, 0x28, 0x87, 0x0e },
-    { 0x3c, 0x84, 0xa8, 0xb3, 0x4d, 0x0f, 0x95, 0xca,
-      0xc6, 0xfa, 0xaa, 0xb6, 0x22, 0xc2, 0x74, 0x46,
-      0xb4, 0xc4, 0x72, 0xdf, 0x34, 0x53, 0xd7, 0x54,
-      0x64, 0xc0, 0x96, 0x23, 0x86, 0x56, 0xb9, 0xd4 },
-    { 0x3d, 0x14, 0x47, 0x2d, 0xce, 0x4a, 0xfd, 0xc2,
-      0x27, 0x6c, 0x81, 0x47, 0x97, 0xc7, 0xbc, 0x7a,
-      0x6c, 0x14, 0xf7, 0x95, 0x3e, 0x7e, 0x9f, 0xea,
-      0x69, 0x51, 0x04, 0x0f, 0x2d, 0xaf, 0xbe, 0x9a },
-    { 0x3e, 0x8e, 0x9b, 0xad, 0x8e, 0xd9, 0xb5, 0x72,
-      0x38, 0x2e, 0x59, 0x8d, 0x2d, 0x73, 0x67, 0xe1,
-      0xfd, 0x6a, 0xf6, 0x95, 0x25, 0x00, 0x9d, 0x67,
-      0xb4, 0xe8, 0xaf, 0x80, 0xd9, 0x15, 0x85, 0x49 },
-    { 0x3f, 0x27, 0xbd, 0xca, 0x9b, 0x0e, 0x42, 0xf3,
-      0xf6, 0xd0, 0x91, 0x2c, 0x92, 0xe2, 0xda, 0x65,
-      0xcb, 0x35, 0x8f, 0x0b, 0x8f, 0x80, 0x5b, 0xec,
-      0x5d, 0xe9, 0x32, 0x51, 0xd9, 0xc4, 0xb1, 0x99 },
-    { 0x3f, 0x2e, 0xa6, 0x4e, 0xfb, 0xd6, 0xbf, 0xc4,
-      0x0a, 0xf0, 0xad, 0x46, 0xa4, 0xa2, 0x57, 0x84,
-      0x19, 0xd8, 0x68, 0x6e, 0x38, 0x98, 0x8b, 0x91,
-      0x47, 0x01, 0x8c, 0x36, 0x29, 0x31, 0xe4, 0xf9 },
-    { 0x3f, 0x4f, 0x28, 0x8b, 0xaf, 0x5b, 0xde, 0x86,
-      0x72, 0xd6, 0xad, 0xd1, 0x50, 0xe3, 0x23, 0x79,
-      0x49, 0x9a, 0x16, 0xc5, 0x81, 0xfb, 0x77, 0x37,
-      0xec, 0x49, 0x80, 0xe4, 0xf9, 0xc3, 0x3d, 0x4d },
-    { 0x3f, 0x92, 0x54, 0x89, 0x64, 0xcc, 0xde, 0xfb,
-      0x29, 0x96, 0x5a, 0x27, 0xc1, 0x6c, 0x2f, 0xed,
-      0x28, 0xd9, 0xb9, 0x14, 0x0e, 0x4f, 0xb5, 0x5b,
-      0x37, 0x22, 0x4c, 0x67, 0xb2, 0xa0, 0x55, 0x1f },
-    { 0x40, 0x58, 0xec, 0x4a, 0x7a, 0x7b, 0xa0, 0xb8,
-      0x65, 0xa7, 0x39, 0xa0, 0x0c, 0x85, 0xf3, 0x44,
-      0x58, 0x79, 0xd6, 0x5e, 0x1d, 0x42, 0x2e, 0xed,
-      0x07, 0x65, 0x5a, 0x8e, 0x3e, 0xc3, 0x18, 0xcf },
-    { 0x41, 0x29, 0x6b, 0x9f, 0xaa, 0xd6, 0x41, 0x33,
-      0xfc, 0xcb, 0xa6, 0xba, 0x74, 0x54, 0x11, 0xec,
-      0xc9, 0x11, 0xfd, 0x8e, 0xd5, 0x41, 0x90, 0x0f,
-      0x9e, 0x20, 0x36, 0x08, 0xee, 0xa3, 0x59, 0x2d },
-    { 0x41, 0x88, 0x71, 0x80, 0x7e, 0xdc, 0xed, 0xa8,
-      0x57, 0xd7, 0xe8, 0x48, 0x31, 0x71, 0x81, 0xe1,
-      0xe8, 0x33, 0xf5, 0x4c, 0x89, 0xa6, 0x11, 0xa2,
-      0x30, 0xad, 0x99, 0x06, 0x5d, 0x45, 0x86, 0x95 },
-    { 0x41, 0xa6, 0x8d, 0xfd, 0x90, 0xda, 0x6d, 0x12,
-      0x09, 0x84, 0x85, 0xbf, 0x6f, 0x87, 0x24, 0x5f,
-      0x4e, 0xc0, 0x54, 0x71, 0xda, 0x59, 0xd0, 0x81,
-      0x06, 0x01, 0x53, 0xa2, 0x22, 0x25, 0x23, 0x7f },
-    { 0x42, 0x08, 0x71, 0xd8, 0xac, 0x49, 0x3c, 0xf9,
-      0x46, 0x8b, 0xb3, 0x76, 0x97, 0x6d, 0x65, 0x5e,
-      0xf0, 0xaf, 0xaa, 0xc2, 0x3d, 0x77, 0x00, 0x92,
-      0x20, 0xc3, 0xaf, 0x8b, 0xdd, 0x37, 0x5a, 0x24 },
-    { 0x42, 0x5d, 0x4e, 0xbf, 0x1b, 0xde, 0x0b, 0xf8,
-      0xd1, 0xdb, 0xd3, 0x3d, 0x8d, 0x16, 0x34, 0xc4,
-      0xfa, 0xfe, 0xb6, 0xf8, 0x05, 0xf1, 0xcc, 0xb5,
-      0x34, 0xac, 0xb7, 0x2a, 0xed, 0xa2, 0xcd, 0x0a },
-    { 0x44, 0x12, 0x63, 0x80, 0xa0, 0x73, 0xfe, 0xa1,
-      0xa2, 0x00, 0x4f, 0x71, 0x1d, 0xf2, 0xca, 0x47,
-      0xc2, 0xc4, 0xb4, 0xff, 0x64, 0x4e, 0x76, 0xaf,
-      0xbe, 0x27, 0x97, 0xc9, 0x63, 0x7c, 0x6a, 0xf9 },
-    { 0x44, 0x25, 0xdd, 0xfb, 0xba, 0xfb, 0xe1, 0xaa,
-      0xce, 0x25, 0x85, 0x70, 0x48, 0x96, 0x9d, 0xc8,
-      0x9d, 0xf5, 0x97, 0x7b, 0xb2, 0xe3, 0x34, 0x7c,
-      0x9c, 0xeb, 0x0e, 0x5a, 0x7b, 0x68, 0xc5, 0x31 },
-    { 0x45, 0x63, 0xcf, 0x13, 0xc2, 0x49, 0x2c, 0xaa,
-      0x92, 0xf5, 0x5b, 0x17, 0x26, 0x3a, 0xdd, 0x72,
-      0x04, 0xa8, 0x0f, 0xe6, 0x24, 0x0c, 0x4d, 0x63,
-      0xe8, 0x39, 0x59, 0x58, 0xf6, 0x94, 0xcd, 0x33 },
-    { 0x45, 0xcb, 0x86, 0xca, 0x97, 0x52, 0x29, 0xb7,
-      0xd5, 0xda, 0xfc, 0x05, 0xeb, 0x0c, 0x53, 0x65,
-      0x82, 0x3a, 0x91, 0xa9, 0x8b, 0x7d, 0xbe, 0x81,
-      0xab, 0x5f, 0x17, 0x8b, 0x2d, 0xa4, 0xad, 0x9e },
-    { 0x46, 0x9b, 0xd8, 0x04, 0xe9, 0x98, 0xae, 0x27,
-      0x9a, 0xc3, 0xfe, 0x1b, 0x52, 0x88, 0x46, 0xe7,
-      0xae, 0xc7, 0x6c, 0x56, 0xb8, 0x0b, 0x40, 0xf3,
-      0x24, 0x20, 0x8f, 0x5a, 0x9f, 0x64, 0x5c, 0xb5 },
-    { 0x46, 0xcd, 0x08, 0x08, 0x8d, 0x36, 0x06, 0x2c,
-      0x56, 0x71, 0x09, 0x2c, 0x02, 0x76, 0x7a, 0x25,
-      0x0d, 0xe7, 0x0b, 0xf3, 0xe1, 0x53, 0x63, 0x69,
-      0x66, 0xe6, 0x6e, 0xc5, 0x7e, 0x8e, 0xe9, 0xf5 },
-    { 0x47, 0x84, 0xf6, 0xcd, 0x59, 0x3d, 0x7b, 0x31,
-      0x2e, 0xb1, 0xf6, 0x19, 0xe1, 0x11, 0xdf, 0x3b,
-      0x48, 0x6d, 0x1b, 0xf8, 0x37, 0x15, 0xad, 0x8d,
-      0xab, 0xa5, 0x72, 0xaf, 0xb2, 0x61, 0xd5, 0xbe },
-    { 0x47, 0x8c, 0xdd, 0x82, 0x3f, 0x81, 0x7d, 0x21,
-      0x8b, 0xf5, 0xdd, 0xa4, 0xc3, 0xe9, 0x9e, 0x7f,
-      0xa3, 0x10, 0x9b, 0x67, 0xbd, 0x0c, 0x9b, 0x1f,
-      0x40, 0x75, 0x96, 0x65, 0xb9, 0xec, 0x3f, 0xf2 },
-    { 0x48, 0xc5, 0xd4, 0xff, 0x5d, 0x08, 0x4a, 0xc1,
-      0x95, 0xb1, 0xa6, 0xa2, 0x19, 0xf8, 0x1b, 0xbd,
-      0xf9, 0xd2, 0xe5, 0xc0, 0x70, 0xec, 0x97, 0xdf,
-      0x3c, 0xb0, 0xb7, 0x3e, 0xf4, 0x70, 0xdc, 0xe9 },
-    { 0x49, 0xdc, 0xf8, 0xfa, 0x68, 0xe9, 0x2b, 0x5c,
-      0x21, 0xfe, 0xf9, 0x3d, 0x26, 0x0c, 0x24, 0x8c,
-      0xe3, 0xbe, 0x98, 0x62, 0x68, 0x68, 0xe7, 0x5a,
-      0x3f, 0x63, 0x34, 0xbb, 0x7d, 0xc1, 0x81, 0xec },
-    { 0x4b, 0x1f, 0xc8, 0x2d, 0x24, 0x72, 0x92, 0x7a,
-      0xc1, 0x7c, 0x58, 0x43, 0x07, 0xcb, 0x96, 0xd6,
-      0xfd, 0xdb, 0x8d, 0x50, 0xa5, 0x29, 0x53, 0x07,
-      0xd3, 0x0c, 0x75, 0x88, 0x59, 0x6a, 0xd4, 0x0b },
-    { 0x4b, 0x51, 0xfc, 0x11, 0x4b, 0xac, 0x8e, 0x2d,
-      0x2a, 0xf2, 0xae, 0x56, 0x84, 0x42, 0x9c, 0xca,
-      0xab, 0x21, 0x39, 0xc9, 0xb3, 0x51, 0xbf, 0x7e,
-      0x1b, 0x03, 0x0a, 0xe8, 0x62, 0x4a, 0xc1, 0x72 },
-    { 0x4c, 0xd0, 0xd6, 0x7e, 0xcc, 0x3b, 0x01, 0xc8,
-      0xc2, 0x63, 0x4e, 0x7a, 0x73, 0x76, 0x12, 0xf6,
-      0x3a, 0x17, 0xff, 0x51, 0x0a, 0x77, 0xa8, 0x04,
-      0xbb, 0x33, 0x1b, 0x2b, 0xe5, 0x8d, 0xfe, 0x0c },
-    { 0x4d, 0xcf, 0xeb, 0xdc, 0x15, 0x4b, 0x0c, 0x85,
-      0x46, 0x7f, 0x6f, 0x52, 0xad, 0x80, 0x4e, 0x19,
-      0x1d, 0x5b, 0xc8, 0x13, 0x51, 0x72, 0x0e, 0xc0,
-      0xd1, 0x9b, 0xd2, 0x5b, 0xf8, 0xf0, 0xa5, 0x53 },
-    { 0x4f, 0x19, 0xdd, 0x12, 0x92, 0x4c, 0xe0, 0xc1,
-      0x4f, 0x82, 0xc0, 0x56, 0xc7, 0xd4, 0x2b, 0xac,
-      0x43, 0xd0, 0x13, 0x3a, 0xaf, 0x89, 0xc1, 0xef,
-      0xdc, 0xfa, 0x3c, 0x3e, 0x47, 0x09, 0x7d, 0x59 },
-    { 0x4f, 0xfb, 0x59, 0x19, 0xbc, 0x38, 0x5c, 0x8c,
-      0x58, 0xe4, 0x62, 0xbf, 0x13, 0x22, 0x10, 0xd8,
-      0xb7, 0x86, 0x12, 0xd0, 0xc2, 0x2a, 0x6b, 0x6a,
-      0x68, 0x2e, 0x0b, 0x9e, 0x9c, 0x9f, 0x9a, 0x44 },
-    { 0x50, 0xf4, 0x78, 0x1e, 0xb1, 0xc1, 0x46, 0x70,
-      0xd9, 0xa5, 0x52, 0xc3, 0x49, 0x5f, 0xb9, 0xf6,
-      0xae, 0x86, 0x8a, 0xb1, 0xc9, 0xd9, 0x83, 0xe0,
-      0x82, 0x68, 0x65, 0xa1, 0x02, 0xec, 0xa6, 0xd3 },
-    { 0x51, 0x6a, 0x2f, 0x33, 0x60, 0xc7, 0x6f, 0xc4,
-      0x6a, 0xb2, 0x88, 0x7f, 0x88, 0xe8, 0xd0, 0x8e,
-      0xfb, 0xd8, 0x44, 0x5a, 0xa7, 0xbb, 0xd2, 0x29,
-      0xdf, 0xc7, 0x1a, 0x90, 0x4f, 0x55, 0xae, 0xb4 },
-    { 0x52, 0x1f, 0x6c, 0x6a, 0x84, 0x36, 0x65, 0x79,
-      0xca, 0x2d, 0xea, 0xeb, 0x23, 0x15, 0xbf, 0x8e,
-      0x53, 0x1c, 0x9f, 0xa4, 0x7b, 0x89, 0x9d, 0xa2,
-      0x72, 0x16, 0xa9, 0x98, 0x82, 0x86, 0xaf, 0xe5 },
-    { 0x52, 0xff, 0x8b, 0x6e, 0x98, 0xb0, 0x96, 0x19,
-      0x90, 0x03, 0xde, 0x97, 0xbc, 0xcf, 0xd2, 0xa7,
-      0xf1, 0xac, 0x57, 0xa8, 0x31, 0x35, 0xb9, 0x55,
-      0xff, 0x68, 0x63, 0x36, 0xa6, 0x91, 0xd5, 0xca },
-    { 0x53, 0x79, 0x64, 0x58, 0xda, 0x97, 0xce, 0x36,
-      0x78, 0xf2, 0xd1, 0xd9, 0xb2, 0xa5, 0xb2, 0xfb,
-      0x30, 0x75, 0xea, 0xfa, 0xf6, 0xff, 0x04, 0x78,
-      0xb5, 0x72, 0xdd, 0xfd, 0x70, 0x99, 0xae, 0xe2 },
-    { 0x53, 0x82, 0xd6, 0xba, 0xb5, 0x78, 0x51, 0xd9,
-      0xb5, 0x8c, 0x17, 0x54, 0x46, 0xbf, 0x2d, 0x1b,
-      0xb7, 0x86, 0xa5, 0x30, 0xfb, 0xf0, 0xae, 0xcd,
-      0x12, 0xea, 0xb8, 0xa9, 0xa5, 0xb4, 0x96, 0x60 },
-    { 0x53, 0x9c, 0xa9, 0xe1, 0xf0, 0x6a, 0xf2, 0x10,
-      0x7f, 0x96, 0xbf, 0x4b, 0x7d, 0xd4, 0xce, 0xcd,
-      0x9e, 0xd1, 0x1a, 0x38, 0xd6, 0x70, 0x91, 0x69,
-      0x9c, 0x56, 0x26, 0xe2, 0x7a, 0x1f, 0x54, 0xa5 },
-    { 0x55, 0x21, 0xf9, 0x63, 0x57, 0x81, 0x58, 0xb8,
-      0xd0, 0xe7, 0xc4, 0x91, 0xcd, 0xb8, 0x5c, 0x3d,
-      0xe9, 0xd5, 0x2e, 0xa5, 0x1f, 0xfc, 0xb0, 0x93,
-      0xd3, 0x12, 0x28, 0x11, 0x13, 0x14, 0x97, 0xeb },
-    { 0x55, 0xd0, 0xeb, 0xe3, 0x2c, 0xba, 0x09, 0xf6,
-      0x58, 0x4d, 0x9e, 0x7b, 0x57, 0x92, 0xa4, 0x03,
-      0xc2, 0x1d, 0x39, 0xd6, 0xe1, 0xf5, 0xe8, 0xed,
-      0x37, 0xb9, 0x3f, 0xa6, 0x1d, 0x88, 0x35, 0x16 },
-    { 0x58, 0x1a, 0xde, 0x64, 0x84, 0x95, 0xb4, 0xb1,
-      0x62, 0x9c, 0x3c, 0x7c, 0x78, 0xef, 0xbe, 0xf2,
-      0x75, 0x06, 0x56, 0x65, 0xb2, 0x41, 0x1c, 0x0e,
-      0x5f, 0xcf, 0xbc, 0x7e, 0xb4, 0xbe, 0x34, 0x0b },
-    { 0x59, 0xc9, 0xe8, 0xdf, 0x03, 0x0b, 0x1c, 0xd5,
-      0x89, 0xa8, 0xb3, 0x4f, 0xe7, 0x42, 0x51, 0xea,
-      0xd5, 0xa5, 0xfb, 0xe9, 0xe6, 0x13, 0x67, 0xca,
-      0x76, 0xaf, 0xd9, 0xdd, 0xd9, 0xc6, 0xf1, 0x6f },
-    { 0x59, 0xe9, 0xfa, 0x2f, 0xf0, 0x76, 0x89, 0x33,
-      0x28, 0x33, 0xc6, 0x40, 0xf5, 0x05, 0xfa, 0x24,
-      0x09, 0xeb, 0x88, 0x93, 0x32, 0x57, 0xc1, 0x93,
-      0xb0, 0x07, 0xd3, 0xa2, 0x89, 0x6a, 0x98, 0x50 },
-    { 0x59, 0xee, 0x9b, 0x36, 0x80, 0xae, 0x20, 0x56,
-      0x83, 0x9c, 0x0b, 0xf6, 0x9e, 0xe6, 0x63, 0x26,
-      0x57, 0x16, 0xa8, 0xe2, 0x4c, 0xc6, 0x49, 0x95,
-      0xfb, 0xa6, 0xcb, 0x6f, 0x0c, 0x12, 0x39, 0xdc },
-    { 0x5a, 0x84, 0xaf, 0xe6, 0x74, 0x05, 0xab, 0xe8,
-      0x4a, 0x0c, 0xd4, 0x2c, 0x2b, 0xa2, 0xe4, 0xc8,
-      0x8f, 0x35, 0xe0, 0xa5, 0x95, 0xe5, 0x69, 0xa3,
-      0xe1, 0x86, 0x69, 0x44, 0x40, 0x5b, 0xe7, 0x36 },
-    { 0x5a, 0x8e, 0x86, 0x21, 0x2c, 0x06, 0x33, 0x94,
-      0x94, 0xf8, 0x5b, 0x5f, 0x85, 0x11, 0xdf, 0x00,
-      0x00, 0x23, 0x94, 0x07, 0x8f, 0xfc, 0x77, 0x4d,
-      0x43, 0x6f, 0x0d, 0x63, 0x86, 0xd7, 0xa6, 0xf7 },
-    { 0x5a, 0xc0, 0x98, 0x2d, 0xa0, 0xc8, 0x3d, 0x0b,
-      0xa9, 0x38, 0x1a, 0x5c, 0xd8, 0x7b, 0x80, 0xd1,
-      0x10, 0xf2, 0x6e, 0xe8, 0x39, 0x27, 0x1b, 0xc2,
-      0x70, 0x60, 0x8f, 0xd1, 0x43, 0x7f, 0x55, 0xb0 },
-    { 0x5c, 0x7f, 0xf0, 0x55, 0xc2, 0xfd, 0x03, 0x3f,
-      0x34, 0xc4, 0xc4, 0xf7, 0xc4, 0xfb, 0x7d, 0xda,
-      0xaa, 0xfb, 0x43, 0x56, 0xc5, 0x60, 0xc9, 0x9e,
-      0xdf, 0xf0, 0x74, 0xda, 0x04, 0xaf, 0x65, 0x7c },
-    { 0x5c, 0xd2, 0x44, 0x6a, 0x8e, 0x4a, 0x0f, 0xa7,
-      0xe3, 0xcd, 0xf8, 0x00, 0x5d, 0xed, 0xce, 0xba,
-      0xe9, 0xe6, 0x81, 0x9a, 0x8a, 0x69, 0x87, 0x31,
-      0x55, 0x5b, 0x7d, 0xc9, 0xd0, 0xa2, 0x3f, 0xc0 },
-    { 0x5c, 0xeb, 0xeb, 0xd8, 0x34, 0x01, 0xb7, 0x0b,
-      0xac, 0xb5, 0x4f, 0x66, 0xa9, 0xb7, 0x78, 0x55,
-      0x69, 0x6e, 0xce, 0x16, 0x7f, 0xe6, 0xc6, 0x0a,
-      0x05, 0x16, 0x8b, 0xe4, 0x39, 0x19, 0xc8, 0x0f },
-    { 0x5f, 0x8b, 0x88, 0x8e, 0xe9, 0x6c, 0x0c, 0x0f,
-      0x5a, 0x91, 0x72, 0x90, 0xac, 0xa6, 0x5a, 0xfd,
-      0x6e, 0xbd, 0xae, 0x05, 0xa0, 0x2a, 0xaf, 0x04,
-      0x29, 0xe9, 0x72, 0xec, 0x01, 0x90, 0xec, 0xfc },
-    { 0x62, 0x2e, 0xc3, 0xbe, 0x7c, 0xf5, 0xe4, 0xe6,
-      0x3f, 0x74, 0x18, 0x69, 0x28, 0x74, 0x40, 0x05,
-      0xcb, 0xb7, 0x8d, 0xf3, 0x06, 0xb8, 0x67, 0xc3,
-      0xfc, 0xad, 0x5e, 0x2b, 0xa7, 0x53, 0x96, 0x83 },
-    { 0x62, 0x6f, 0x7e, 0xb4, 0xfd, 0x9b, 0x71, 0xff,
-      0xaa, 0x0c, 0x8e, 0xc9, 0x65, 0x54, 0x64, 0xe6,
-      0x5e, 0x7f, 0x96, 0xcf, 0xa3, 0x82, 0x73, 0x97,
-      0x41, 0x35, 0x66, 0xaa, 0x2c, 0xc1, 0xe5, 0x72 },
-    { 0x63, 0x64, 0x15, 0x61, 0x77, 0xdc, 0xdf, 0x60,
-      0x4d, 0xf9, 0x1e, 0x31, 0x32, 0x2e, 0x57, 0x74,
-      0x69, 0x1e, 0x0c, 0x41, 0xfa, 0x0d, 0x2f, 0x25,
-      0x7a, 0xd7, 0xf9, 0xf0, 0x25, 0x98, 0x14, 0x45 },
-    { 0x65, 0x66, 0x00, 0xa4, 0x5e, 0x45, 0x6a, 0xba,
-      0x5b, 0x00, 0x8d, 0x87, 0x91, 0x54, 0xb7, 0x69,
-      0x0d, 0x7f, 0x27, 0x31, 0x02, 0x09, 0x7d, 0x8f,
-      0xd8, 0xc3, 0xde, 0xab, 0x30, 0xd8, 0x4a, 0xb2 },
-    { 0x65, 0xed, 0x61, 0xa8, 0x8c, 0x55, 0xef, 0xb0,
-      0x38, 0x07, 0x1a, 0xee, 0xde, 0xf8, 0xe1, 0x83,
-      0xe2, 0x37, 0x38, 0x46, 0x97, 0x26, 0xeb, 0x99,
-      0x68, 0x0c, 0xd2, 0x44, 0x72, 0x73, 0x6b, 0xec },
-    { 0x66, 0x50, 0xb2, 0xea, 0x64, 0x4c, 0x3f, 0x4e,
-      0x8c, 0x9e, 0x3c, 0x46, 0xac, 0xea, 0xc4, 0x52,
-      0x33, 0xd8, 0x66, 0xe3, 0x98, 0xff, 0x90, 0xeb,
-      0x59, 0xb2, 0xc6, 0x25, 0x20, 0x82, 0xac, 0x04 },
-    { 0x66, 0xbe, 0x7e, 0xa1, 0x13, 0x8b, 0xcb, 0xa4,
-      0xde, 0x0b, 0x41, 0x28, 0x5d, 0x9a, 0x13, 0x3f,
-      0xa7, 0xf5, 0x70, 0xa3, 0xc8, 0x13, 0x55, 0x79,
-      0xb8, 0x60, 0x19, 0x9d, 0x0a, 0x51, 0x45, 0x7c },
-    { 0x69, 0x01, 0x4b, 0xbc, 0x84, 0x29, 0xd8, 0x5f,
-      0x41, 0xc2, 0x22, 0xd9, 0x7f, 0x7e, 0xd5, 0x35,
-      0xcf, 0x81, 0x23, 0x9a, 0xf2, 0x7a, 0xcc, 0x88,
-      0x70, 0xdc, 0xd4, 0x08, 0x34, 0x8b, 0x48, 0xba },
-    { 0x69, 0x21, 0x1f, 0x36, 0x3a, 0x2d, 0xbe, 0x01,
-      0x5b, 0x31, 0xcb, 0xd9, 0xfc, 0x5e, 0x94, 0xc2,
-      0xf6, 0xf4, 0x3c, 0x58, 0xdb, 0xde, 0xe9, 0xe3,
-      0xe4, 0x6b, 0x19, 0xd7, 0x59, 0xbb, 0xb8, 0x81 },
-    { 0x69, 0x75, 0x67, 0xbb, 0xac, 0x94, 0xee, 0xc3,
-      0xe6, 0xfa, 0x4a, 0x4e, 0x46, 0xfa, 0x51, 0x74,
-      0x05, 0xf3, 0x77, 0xc0, 0xde, 0xe3, 0xd4, 0x29,
-      0x91, 0x4e, 0x6b, 0x7e, 0xa0, 0x8c, 0xb1, 0xa6 },
-    { 0x6a, 0xac, 0xc5, 0x09, 0x2f, 0x12, 0xbc, 0x94,
-      0xa0, 0xad, 0x0e, 0x9e, 0xf6, 0x36, 0x43, 0x7d,
-      0x36, 0x0d, 0xc7, 0xc9, 0xf1, 0x40, 0x44, 0x17,
-      0xa3, 0x36, 0x91, 0x94, 0x4e, 0x76, 0x31, 0x36 },
-    { 0x6b, 0x4a, 0x8c, 0xb6, 0x07, 0xf5, 0x1c, 0x83,
-      0x0d, 0xe7, 0x20, 0xf4, 0xbb, 0xde, 0xdf, 0x49,
-      0x10, 0x15, 0x13, 0xdf, 0xd1, 0xdb, 0x0b, 0x0a,
-      0x97, 0xcc, 0x3f, 0xdd, 0x9a, 0x39, 0xc6, 0xe7 },
-    { 0x6c, 0x8f, 0xd1, 0xe6, 0xe1, 0x1b, 0xaf, 0xa6,
-      0x17, 0x78, 0x13, 0xa0, 0x44, 0x40, 0xb1, 0xb9,
-      0x6a, 0x1c, 0xdb, 0x7c, 0x2d, 0x70, 0x3f, 0x55,
-      0xde, 0x85, 0x7c, 0x80, 0xa8, 0x9e, 0x73, 0x25 },
-    { 0x6c, 0xc6, 0xdc, 0xda, 0x58, 0xc6, 0x1f, 0xb2,
-      0x86, 0x70, 0xd1, 0xc2, 0x01, 0x76, 0x57, 0xb0,
-      0xc5, 0xd6, 0x1a, 0x26, 0xc9, 0xcb, 0xd1, 0xea,
-      0x75, 0x5c, 0x68, 0x20, 0xb5, 0xf6, 0xd6, 0x7d },
-    { 0x6d, 0x32, 0xf4, 0x93, 0x40, 0x56, 0xee, 0x17,
-      0x14, 0xca, 0x72, 0x70, 0x3f, 0x64, 0x46, 0x9b,
-      0x98, 0x58, 0xfc, 0x39, 0x96, 0x4b, 0x4c, 0x03,
-      0x93, 0xb3, 0x7d, 0xde, 0xab, 0x8b, 0x19, 0x75 },
-    { 0x6e, 0x1a, 0x88, 0x63, 0xf2, 0x93, 0x4b, 0x39,
-      0x01, 0x23, 0x7e, 0x84, 0xd0, 0x76, 0x27, 0x04,
-      0x23, 0x06, 0x78, 0x7f, 0x2d, 0xe0, 0x66, 0x30,
-      0xbd, 0x37, 0xd8, 0x03, 0x94, 0x35, 0xbf, 0xca },
-    { 0x6e, 0x99, 0x8d, 0xdd, 0xf2, 0x93, 0x9b, 0xfe,
-      0x8c, 0xc5, 0x2a, 0x48, 0x0a, 0xc0, 0x6d, 0x69,
-      0x71, 0xc5, 0xa3, 0xda, 0x97, 0xcf, 0x3e, 0xf0,
-      0x1a, 0xf2, 0x9d, 0x74, 0x72, 0x62, 0x31, 0xe2 },
-    { 0x6f, 0x3b, 0xb3, 0x4b, 0x5d, 0x32, 0x91, 0xdf,
-      0xb3, 0xe4, 0x12, 0x71, 0xa1, 0xd7, 0x30, 0xcd,
-      0xbc, 0xff, 0xc1, 0x0b, 0x68, 0x05, 0x9d, 0xcc,
-      0xd3, 0x1c, 0x47, 0x4b, 0xb7, 0x44, 0x16, 0xe5 },
-    { 0x6f, 0xbd, 0xcd, 0xf1, 0xb4, 0x37, 0x9f, 0xc4,
-      0x73, 0xab, 0x5e, 0xea, 0x4e, 0xc2, 0xf4, 0x84,
-      0xce, 0x91, 0xd1, 0x0e, 0x31, 0x34, 0x5f, 0x15,
-      0xa7, 0x6a, 0x84, 0x85, 0xb8, 0xff, 0xfb, 0x7e },
-    { 0x70, 0xb8, 0xec, 0xd5, 0x62, 0xec, 0x3d, 0x9f,
-      0x48, 0x64, 0x75, 0x2a, 0x3a, 0x8c, 0x54, 0x39,
-      0x93, 0xb4, 0x38, 0x72, 0x8f, 0xe2, 0x71, 0x81,
-      0xf4, 0xc0, 0x8d, 0xe6, 0xa0, 0xd8, 0xb7, 0x9a },
-    { 0x72, 0x1b, 0x1f, 0x92, 0x9d, 0xa7, 0xea, 0xf8,
-      0x96, 0x24, 0x64, 0x7b, 0xa3, 0xcc, 0x4e, 0x1e,
-      0xd1, 0x57, 0x54, 0xab, 0x83, 0x6e, 0x33, 0x58,
-      0xb0, 0x35, 0xa1, 0xf2, 0x27, 0x4a, 0x43, 0xbe },
-    { 0x72, 0x81, 0xda, 0x0d, 0x8c, 0xe9, 0xd5, 0x3e,
-      0xa3, 0xd1, 0xf5, 0x93, 0x5c, 0x58, 0x21, 0xea,
-      0x8d, 0x9a, 0xf1, 0xce, 0x0b, 0xca, 0xf8, 0x82,
-      0x5d, 0x78, 0x3f, 0x37, 0xea, 0xc3, 0x4f, 0x40 },
-    { 0x72, 0xe7, 0x49, 0x87, 0x21, 0x0c, 0x7e, 0xf6,
-      0x67, 0x46, 0xe4, 0x9a, 0x96, 0xdf, 0x55, 0xcc,
-      0x6f, 0xad, 0xf7, 0xa6, 0x31, 0xc7, 0xae, 0x3f,
-      0x3e, 0x9e, 0x18, 0x72, 0x3d, 0xe5, 0x2a, 0x6e },
-    { 0x73, 0x3b, 0x42, 0x24, 0x25, 0x8d, 0xee, 0x07,
-      0x0e, 0xdf, 0xa3, 0x41, 0x1f, 0xbc, 0x9b, 0xad,
-      0x31, 0x65, 0xbe, 0x66, 0x0f, 0x34, 0x0a, 0xa2,
-      0x30, 0x8a, 0x5a, 0x33, 0x23, 0xfa, 0xbf, 0xa7 },
-    { 0x74, 0x8e, 0xbb, 0x72, 0xd1, 0x02, 0x04, 0xf4,
-      0x04, 0x10, 0xbe, 0x70, 0x80, 0xbf, 0xe7, 0xee,
-      0x63, 0x1f, 0xc0, 0x4d, 0x1f, 0xdb, 0x50, 0x72,
-      0x04, 0x4b, 0xfa, 0x55, 0x7a, 0xdf, 0x6e, 0x5a },
-    { 0x74, 0xe2, 0xcc, 0xcf, 0x62, 0xd5, 0xb9, 0xf9,
-      0x00, 0xb4, 0x14, 0x73, 0xca, 0x44, 0xe6, 0x87,
-      0x96, 0x38, 0x74, 0x3d, 0x8f, 0xee, 0x66, 0xee,
-      0x71, 0x8c, 0x18, 0xd8, 0xf1, 0x12, 0x15, 0xd1 },
-    { 0x76, 0x98, 0x67, 0x60, 0xac, 0xfe, 0x55, 0x59,
-      0xa2, 0xa2, 0xab, 0x2a, 0x4e, 0x85, 0x49, 0x83,
-      0xc5, 0xfd, 0xe6, 0x73, 0xce, 0x8e, 0xb1, 0x71,
-      0x23, 0x49, 0x48, 0x64, 0x86, 0x7a, 0x98, 0xb1 },
-    { 0x78, 0x0c, 0x33, 0xfe, 0x95, 0x4c, 0xc4, 0xdb,
-      0x39, 0x04, 0xd7, 0x6a, 0x68, 0x58, 0xbc, 0xd1,
-      0x01, 0x7f, 0x52, 0xda, 0x59, 0x9d, 0x36, 0xda,
-      0xe6, 0x66, 0xc0, 0x4e, 0x41, 0xaf, 0x8d, 0xcd },
-    { 0x78, 0xc9, 0x30, 0x40, 0x5a, 0x72, 0x0d, 0x9f,
-      0x00, 0x66, 0xdd, 0x88, 0xa2, 0xa8, 0xda, 0xfb,
-      0xbe, 0x6c, 0xd6, 0x5d, 0x54, 0xb7, 0x76, 0x06,
-      0x42, 0x1b, 0x45, 0x43, 0x8c, 0x65, 0x8a, 0xd4 },
-    { 0x79, 0x8f, 0x83, 0xb1, 0xc4, 0xc6, 0x5c, 0x4d,
-      0x5d, 0xea, 0x13, 0x03, 0x53, 0x53, 0xd8, 0xed,
-      0xe5, 0xd7, 0x1d, 0x99, 0x47, 0xf4, 0x34, 0xfd,
-      0xea, 0x0d, 0xbc, 0x1e, 0xc8, 0x2f, 0x45, 0x35 },
-    { 0x7b, 0xfe, 0x47, 0xae, 0xba, 0x8b, 0x0a, 0x3a,
-      0x94, 0x5a, 0x88, 0xd8, 0xef, 0x18, 0x91, 0xc9,
-      0x89, 0x97, 0x8a, 0xbf, 0x12, 0x2e, 0xc5, 0xe0,
-      0x51, 0x4b, 0xe3, 0x6c, 0x3a, 0x7f, 0x22, 0x9b },
-    { 0x7d, 0x20, 0xc7, 0xa9, 0x27, 0x26, 0x2b, 0xe7,
-      0x38, 0xd2, 0x58, 0xd0, 0xfd, 0x97, 0x6e, 0x9a,
-      0xf3, 0x6e, 0xf7, 0x99, 0x5f, 0x05, 0xe2, 0x87,
-      0x6a, 0x29, 0xae, 0xbc, 0x3a, 0x24, 0xaa, 0xce },
-    { 0x7e, 0x2e, 0xdb, 0x9d, 0x38, 0xf9, 0x29, 0x3c,
-      0xdd, 0xd6, 0x03, 0xb1, 0x75, 0xc9, 0xb2, 0x05,
-      0xac, 0x0b, 0x55, 0x3a, 0x4b, 0xf5, 0xfb, 0x08,
-      0xc2, 0x46, 0xec, 0xf9, 0xc8, 0x49, 0xdb, 0x28 },
-    { 0x7f, 0x95, 0x9b, 0x06, 0x34, 0xda, 0x94, 0xfa,
-      0xca, 0xda, 0xb0, 0x21, 0xcf, 0x94, 0x20, 0x78,
-      0x16, 0x00, 0x36, 0x13, 0xef, 0x09, 0xeb, 0x54,
-      0xf6, 0x48, 0x60, 0x50, 0x08, 0x19, 0x02, 0x75 },
-    { 0x7f, 0x9a, 0x69, 0xcf, 0xa2, 0xf5, 0x0c, 0x13,
-      0xe1, 0xb7, 0x11, 0xdd, 0x6b, 0x14, 0x69, 0x2b,
-      0xdb, 0x77, 0xd9, 0xff, 0xd8, 0xc1, 0x10, 0xae,
-      0x5d, 0x05, 0xa4, 0xcb, 0x73, 0x12, 0x37, 0x48 },
-    { 0x7f, 0xcc, 0xa8, 0xb5, 0xf5, 0xe3, 0x3b, 0xca,
-      0x6d, 0xe0, 0x9c, 0x14, 0xaf, 0xbb, 0xe0, 0xc3,
-      0x41, 0x21, 0xac, 0xbb, 0x22, 0x22, 0x9f, 0x44,
-      0xee, 0x5c, 0x3f, 0x4d, 0xde, 0x73, 0x50, 0x55 },
-    { 0x80, 0x20, 0x56, 0xe1, 0xdb, 0x9d, 0x9b, 0x73,
-      0x21, 0xd1, 0xff, 0xbb, 0xe1, 0x2f, 0x5c, 0xbe,
-      0xde, 0xc3, 0x6d, 0x0b, 0x5e, 0xc2, 0xa4, 0xe1,
-      0x8d, 0x99, 0x54, 0x36, 0x4c, 0xec, 0x81, 0x29 },
-    { 0x80, 0x97, 0x63, 0x4c, 0xe3, 0x3d, 0x41, 0x53,
-      0x3d, 0x41, 0x5d, 0xaf, 0xdb, 0x8b, 0xa1, 0x91,
-      0xc0, 0x30, 0x52, 0xac, 0x8b, 0xaa, 0x25, 0x54,
-      0x34, 0x77, 0x3a, 0x16, 0x4b, 0x91, 0x1d, 0x6e },
-    { 0x80, 0xd0, 0x17, 0x09, 0x34, 0xd2, 0x2a, 0xea,
-      0x73, 0x3f, 0x11, 0x5e, 0x52, 0x42, 0xc6, 0xb8,
-      0x6d, 0x7f, 0xcf, 0xb4, 0x90, 0x4e, 0x65, 0xb7,
-      0xb7, 0xb9, 0x07, 0xf2, 0xca, 0x94, 0xed, 0x71 },
-    { 0x81, 0x1d, 0xf2, 0xf4, 0x73, 0x6f, 0x85, 0x62,
-      0xe2, 0x02, 0xfd, 0x00, 0x75, 0x32, 0xf1, 0xde,
-      0x40, 0x17, 0x86, 0x1e, 0xfa, 0xbe, 0x67, 0x34,
-      0x20, 0xc2, 0x7f, 0x2e, 0x2a, 0x33, 0xfa, 0xc1 },
-    { 0x81, 0x1e, 0x37, 0x86, 0x37, 0xb1, 0xd2, 0xcb,
-      0xb1, 0x89, 0xaf, 0xd6, 0x74, 0x95, 0xfe, 0x8a,
-      0xb9, 0xd8, 0x3a, 0x74, 0x2e, 0x35, 0x8c, 0xbb,
-      0xdb, 0xd1, 0x54, 0x98, 0xbf, 0x9c, 0x7b, 0x56 },
-    { 0x81, 0xa0, 0xf1, 0xd0, 0x29, 0x46, 0x8e, 0xe8,
-      0x66, 0x36, 0x4a, 0x19, 0x8a, 0x26, 0x08, 0x58,
-      0x30, 0xc2, 0xa4, 0x16, 0xe4, 0x9e, 0x22, 0x4c,
-      0xe8, 0x09, 0x66, 0xfc, 0xc4, 0x99, 0xd6, 0x36 },
-    { 0x82, 0x56, 0x8b, 0x3b, 0xb3, 0xc6, 0x55, 0xd7,
-      0xf2, 0x2d, 0x8c, 0x97, 0xa5, 0x66, 0x9c, 0xc8,
-      0x34, 0xa2, 0xdd, 0x7c, 0xda, 0xe7, 0x5a, 0x26,
-      0x45, 0x59, 0x55, 0x16, 0x46, 0x55, 0x8e, 0x14 },
-    { 0x82, 0x7c, 0x8c, 0x80, 0x11, 0x1f, 0xf2, 0x21,
-      0xc3, 0xeb, 0x1e, 0xf5, 0xc0, 0xd5, 0xd4, 0x34,
-      0x48, 0x31, 0x86, 0xe2, 0x09, 0x00, 0x75, 0x63,
-      0x15, 0x8e, 0x9e, 0x76, 0xd2, 0x79, 0x0f, 0x1c },
-    { 0x82, 0x92, 0x67, 0xc5, 0xad, 0x70, 0xe5, 0x45,
-      0x18, 0x02, 0x3a, 0xb7, 0x85, 0xfa, 0x3c, 0xde,
-      0xd6, 0x6f, 0x42, 0x5d, 0xe1, 0xf3, 0x2f, 0xcd,
-      0x72, 0x1b, 0x49, 0x46, 0x3a, 0x5a, 0x5f, 0x5b },
-    { 0x83, 0x34, 0xea, 0xb8, 0x1c, 0x60, 0x4e, 0x99,
-      0xd5, 0x40, 0x51, 0x3e, 0xf2, 0xe3, 0x7a, 0xba,
-      0x71, 0x4f, 0x07, 0xb2, 0xba, 0x01, 0x0a, 0xd7,
-      0x1d, 0xc4, 0xe1, 0x1a, 0x92, 0x18, 0xc1, 0x8c },
-    { 0x83, 0x54, 0x7a, 0xca, 0x3c, 0xed, 0x73, 0xdf,
-      0x99, 0x14, 0xf3, 0x15, 0x60, 0x74, 0x63, 0x79,
-      0x29, 0x4c, 0x76, 0x0e, 0xf9, 0xa8, 0xb7, 0x6e,
-      0x00, 0x06, 0x46, 0xc7, 0x39, 0x07, 0x21, 0x65 },
-    { 0x83, 0x89, 0xc8, 0x79, 0xb6, 0x3b, 0x82, 0x9d,
-      0x2d, 0x39, 0xa8, 0xcf, 0xb7, 0x87, 0xe7, 0x72,
-      0x77, 0xd5, 0xcf, 0xa3, 0xe3, 0x6f, 0xda, 0xcb,
-      0xab, 0x4d, 0x18, 0xb2, 0xb0, 0x4e, 0x32, 0x94 },
-    { 0x84, 0x23, 0xb3, 0xf1, 0xcc, 0x85, 0x2b, 0x49,
-      0xcf, 0x81, 0xb7, 0xd5, 0xff, 0x51, 0xa7, 0xa5,
-      0x6a, 0x84, 0x78, 0x3a, 0x2d, 0xf7, 0x43, 0x61,
-      0xff, 0x2e, 0xee, 0x0f, 0x92, 0x12, 0xc1, 0x59 },
-    { 0x84, 0x7b, 0x5f, 0x1e, 0xeb, 0x2a, 0x44, 0x13,
-      0xc8, 0xfa, 0x37, 0x98, 0x21, 0x97, 0x37, 0xe1,
-      0x92, 0xba, 0x72, 0x72, 0xa1, 0x08, 0xb7, 0x17,
-      0x28, 0xa8, 0xd1, 0x65, 0x17, 0xf6, 0x1e, 0x9d },
-    { 0x85, 0x31, 0xb2, 0xbf, 0xc5, 0x45, 0x79, 0xe8,
-      0xf1, 0x8f, 0x27, 0xb2, 0xe6, 0xec, 0xc0, 0xf8,
-      0x90, 0x64, 0xee, 0x86, 0x87, 0x0e, 0xcc, 0x8b,
-      0xbe, 0x0c, 0xe6, 0x86, 0xec, 0xda, 0x2c, 0x17 },
-    { 0x85, 0x76, 0x0f, 0x59, 0x51, 0x90, 0xe9, 0xb4,
-      0x67, 0x8b, 0xbf, 0x44, 0xef, 0xb5, 0xcf, 0x8f,
-      0x6b, 0x19, 0x37, 0xa9, 0xb8, 0x6b, 0x31, 0xb7,
-      0x51, 0xbe, 0xcf, 0x72, 0x18, 0x03, 0xb0, 0x1c },
-    { 0x85, 0xf0, 0x79, 0x36, 0xb4, 0x29, 0x1f, 0x36,
-      0xd9, 0xb7, 0x5f, 0x42, 0xe8, 0xb7, 0xee, 0x8a,
-      0x64, 0xe6, 0x32, 0xa1, 0x18, 0x11, 0x65, 0xfe,
-      0x72, 0xb4, 0x88, 0x23, 0xc3, 0xd9, 0x9d, 0x9d },
-    { 0x86, 0x12, 0x9f, 0xe7, 0x61, 0x99, 0x4d, 0x7b,
-      0x64, 0xe4, 0x02, 0x85, 0x8f, 0x88, 0xc5, 0x2b,
-      0x3e, 0xb9, 0xc0, 0x71, 0xff, 0xbe, 0x80, 0x02,
-      0x80, 0xac, 0x8c, 0x0c, 0x6f, 0x79, 0xe7, 0xa6 },
-    { 0x86, 0x19, 0x6b, 0x0f, 0xd3, 0x0f, 0x8f, 0x57,
-      0x56, 0x98, 0xb5, 0xee, 0xf2, 0x69, 0xd0, 0x69,
-      0x2f, 0x88, 0xad, 0xea, 0xc4, 0x83, 0x6a, 0x62,
-      0x67, 0xab, 0xc8, 0x36, 0x23, 0x34, 0x00, 0x86 },
-    { 0x86, 0xcf, 0xec, 0xbe, 0x82, 0xba, 0xdb, 0x93,
-      0x14, 0x75, 0xf1, 0x9e, 0xcd, 0x6e, 0xa6, 0x7d,
-      0x59, 0xc2, 0xc7, 0x00, 0x78, 0xb6, 0xcc, 0x56,
-      0xbf, 0xdc, 0x27, 0x55, 0x47, 0x67, 0xf2, 0x3f },
-    { 0x86, 0xd1, 0x8b, 0xcd, 0xde, 0x16, 0x45, 0x42,
-      0x48, 0x6e, 0x56, 0x44, 0x2c, 0xe1, 0xb8, 0x8b,
-      0x1a, 0x10, 0x73, 0x7c, 0xbd, 0x5e, 0xa4, 0xaa,
-      0xb8, 0xd5, 0xb8, 0xaf, 0x51, 0xf5, 0x29, 0x09 },
-    { 0x87, 0x5f, 0x57, 0x42, 0x4c, 0x90, 0x2b, 0x24,
-      0xe8, 0x1c, 0x27, 0xd1, 0xca, 0xf2, 0x74, 0xb1,
-      0x7d, 0x72, 0x0d, 0xf8, 0x07, 0x8b, 0x6f, 0x2a,
-      0x5c, 0x3b, 0xb8, 0xd8, 0xdf, 0xf0, 0x55, 0x00 },
-    { 0x88, 0x8d, 0x6d, 0x77, 0xd8, 0x1c, 0x62, 0x91,
-      0xcb, 0x84, 0xd9, 0xd6, 0x56, 0x27, 0x82, 0xfd,
-      0x2e, 0xb3, 0x42, 0x5d, 0x49, 0x1e, 0x68, 0x74,
-      0x20, 0x28, 0x4b, 0x76, 0xa1, 0xde, 0xbf, 0xab },
-    { 0x89, 0xaf, 0x0e, 0x54, 0xc7, 0x62, 0x77, 0x86,
-      0x93, 0x52, 0x9d, 0x0a, 0x95, 0x0b, 0x78, 0x33,
-      0xf5, 0xea, 0xba, 0xf3, 0x42, 0x79, 0x72, 0x60,
-      0x7f, 0xb2, 0xc7, 0x0c, 0x96, 0xa3, 0x21, 0x61 },
-    { 0x89, 0xda, 0xc7, 0x89, 0x6b, 0x46, 0xf2, 0xfc,
-      0x8b, 0xea, 0x62, 0x11, 0xff, 0x98, 0xb6, 0x1f,
-      0xaa, 0x15, 0x7b, 0xa8, 0xc4, 0xad, 0x6f, 0xd1,
-      0x75, 0x92, 0x75, 0xce, 0x39, 0x41, 0xc3, 0x28 },
-    { 0x8a, 0x09, 0x85, 0xbf, 0x86, 0xe8, 0xc9, 0xb9,
-      0x17, 0xec, 0x84, 0xda, 0x2a, 0x56, 0x73, 0x1e,
-      0x75, 0x2a, 0xa0, 0xdc, 0x52, 0x87, 0xc2, 0xbf,
-      0x39, 0x51, 0x0b, 0xb3, 0xf0, 0xf2, 0x0a, 0xd1 },
-    { 0x8a, 0xaf, 0x36, 0x3c, 0xc9, 0xd8, 0x44, 0x15,
-      0xa7, 0xeb, 0x0d, 0x72, 0xda, 0x08, 0xb3, 0x58,
-      0x80, 0x68, 0x55, 0x9c, 0xb0, 0xa9, 0xae, 0x92,
-      0xb8, 0xf4, 0x60, 0x2e, 0xda, 0x23, 0x82, 0xaa },
-    { 0x8a, 0xb2, 0x77, 0x62, 0xf4, 0xa2, 0xe3, 0x11,
-      0x22, 0x04, 0x96, 0x98, 0x39, 0x99, 0xc8, 0xc4,
-      0x60, 0x96, 0x3d, 0xfc, 0x1b, 0x88, 0x51, 0x11,
-      0x1d, 0xa4, 0x1d, 0x3f, 0x3b, 0x0a, 0x6e, 0x94 },
-    { 0x8a, 0xd1, 0xd5, 0x48, 0x95, 0x27, 0xb5, 0x28,
-      0xe5, 0xb5, 0xd6, 0xa5, 0x95, 0x78, 0x87, 0x08,
-      0x88, 0x8a, 0x3f, 0xb1, 0x9f, 0x2c, 0x7c, 0x8b,
-      0x38, 0x07, 0x0e, 0x1f, 0x38, 0x98, 0x96, 0x8b },
-    { 0x8a, 0xdb, 0x49, 0xd4, 0x15, 0x53, 0x56, 0x70,
-      0x5b, 0x64, 0x42, 0x6a, 0x99, 0x0f, 0x58, 0xb3,
-      0xa0, 0x71, 0xef, 0x78, 0x2e, 0x6c, 0x09, 0x53,
-      0x07, 0xd7, 0x74, 0x74, 0xd5, 0xb5, 0x7a, 0x62 },
-    { 0x8b, 0x3a, 0x10, 0x35, 0xc3, 0xfd, 0xf3, 0x45,
-      0xfb, 0x70, 0x80, 0x44, 0x83, 0xa5, 0x04, 0x49,
-      0xa3, 0xd7, 0x60, 0xc6, 0xba, 0x48, 0xf5, 0xb8,
-      0x2d, 0x6b, 0xb2, 0x62, 0xed, 0x9d, 0xe3, 0x73 },
-    { 0x8b, 0x3a, 0x75, 0xcb, 0xc3, 0x62, 0xd2, 0x35,
-      0x57, 0x0e, 0x5d, 0xe7, 0x04, 0x29, 0x38, 0x70,
-      0x8a, 0x1b, 0x0f, 0xce, 0xb4, 0x59, 0x86, 0x2a,
-      0x38, 0x67, 0xb7, 0x34, 0xcd, 0xcb, 0x97, 0x94 },
-    { 0x8c, 0x3e, 0x7c, 0x1d, 0xcc, 0x7d, 0xd8, 0xe7,
-      0xd8, 0xbf, 0x7b, 0x5b, 0x3a, 0xe5, 0xe0, 0x27,
-      0x2e, 0x81, 0x1a, 0xb9, 0xf3, 0xc3, 0xc5, 0x38,
-      0xe5, 0x74, 0x71, 0x77, 0xe6, 0x2d, 0x62, 0x92 },
-    { 0x8c, 0x7c, 0x65, 0x7b, 0xda, 0x13, 0xca, 0x62,
-      0xf2, 0x9a, 0x65, 0xc6, 0xd5, 0x19, 0x3a, 0x93,
-      0xcf, 0x6c, 0x58, 0x77, 0x18, 0xad, 0xca, 0x67,
-      0x15, 0x8e, 0x97, 0xd3, 0x6a, 0x62, 0x3e, 0xca },
-    { 0x8c, 0xa6, 0x79, 0x62, 0xc4, 0xa8, 0x09, 0x13,
-      0x33, 0xf2, 0x4e, 0xfd, 0x60, 0xee, 0x70, 0xcf,
-      0xed, 0xdb, 0xd6, 0x41, 0x59, 0x04, 0x70, 0x9e,
-      0x78, 0x5c, 0x33, 0x1b, 0x1e, 0xf5, 0x8f, 0x8e },
-    { 0x8e, 0x18, 0xfd, 0xbd, 0xb0, 0x08, 0x16, 0x00,
-      0x35, 0xfa, 0xf5, 0x01, 0x5b, 0xe7, 0xda, 0xf4,
-      0x63, 0xb5, 0xc4, 0x14, 0xea, 0xbc, 0x8b, 0x89,
-      0xf3, 0xdb, 0xa2, 0x05, 0xab, 0x09, 0xa6, 0x43 },
-    { 0x8f, 0x10, 0x10, 0x47, 0x93, 0xe8, 0x55, 0x42,
-      0xbc, 0x06, 0x04, 0xd6, 0xcf, 0x21, 0x5f, 0x78,
-      0x80, 0xbd, 0x6a, 0x4d, 0xd0, 0xfd, 0xf1, 0xe7,
-      0xa5, 0xb9, 0xca, 0x12, 0x46, 0xf5, 0xc4, 0x09 },
-    { 0x8f, 0x71, 0x27, 0x76, 0x2e, 0xe7, 0x51, 0x69,
-      0xbd, 0xc3, 0x5b, 0x04, 0xa7, 0x28, 0xe9, 0xd3,
-      0x1b, 0x7e, 0x4d, 0x37, 0x89, 0xaa, 0x2c, 0x46,
-      0xd8, 0xa3, 0x1b, 0x3d, 0xfa, 0x81, 0xa9, 0x7e },
-    { 0x8f, 0x94, 0x15, 0x92, 0x6f, 0x40, 0x49, 0xea,
-      0x41, 0x8a, 0x30, 0x7c, 0x76, 0x36, 0xe4, 0x9b,
-      0x14, 0x4f, 0xa5, 0x3e, 0x52, 0xe1, 0x04, 0x15,
-      0x5f, 0x58, 0x03, 0x5e, 0x45, 0x41, 0xcd, 0x6e },
-    { 0x90, 0xe2, 0x51, 0x86, 0x7f, 0x6b, 0x0c, 0x14,
-      0xbd, 0x9b, 0x51, 0x0c, 0xfd, 0xa8, 0x48, 0x49,
-      0x72, 0xfd, 0xf0, 0xe0, 0x6d, 0xc1, 0x1f, 0x5d,
-      0x1d, 0x59, 0x0b, 0xe3, 0xfc, 0x38, 0xdf, 0xf0 },
-    { 0x91, 0x90, 0xf8, 0x25, 0x51, 0x0c, 0x65, 0x98,
-      0xe1, 0x9d, 0x17, 0xdb, 0xbe, 0x6e, 0x7c, 0x82,
-      0x31, 0x86, 0x9c, 0xa7, 0xf6, 0xe3, 0x07, 0xa2,
-      0xc2, 0xcc, 0x54, 0x77, 0x8d, 0x4a, 0x89, 0xb3 },
-    { 0x92, 0x3f, 0x0f, 0x8c, 0x40, 0x5a, 0x02, 0xe6,
-      0x82, 0xc4, 0xb4, 0x66, 0x5a, 0x7e, 0xe7, 0x16,
-      0xaa, 0x57, 0xe0, 0xa5, 0x86, 0xc2, 0x4a, 0x16,
-      0x5a, 0xad, 0x7e, 0x5b, 0xda, 0x22, 0x78, 0x24 },
-    { 0x92, 0x71, 0x44, 0x12, 0x1c, 0x23, 0x63, 0x57,
-      0x07, 0xe9, 0x40, 0x7f, 0x7f, 0xff, 0x6a, 0x64,
-      0x63, 0x5d, 0x7c, 0xe9, 0x06, 0x66, 0xd4, 0x29,
-      0x94, 0x09, 0x7a, 0xf4, 0x0c, 0x31, 0x36, 0xfb },
-    { 0x94, 0xdc, 0x80, 0x07, 0x49, 0x1d, 0xa8, 0xbf,
-      0xb7, 0x39, 0x14, 0xad, 0xce, 0xf7, 0x1a, 0x12,
-      0x41, 0x58, 0xba, 0xd1, 0x7b, 0xa8, 0x8f, 0xa9,
-      0x46, 0x57, 0x9b, 0xbc, 0x2d, 0x64, 0x97, 0x8d },
-    { 0x95, 0x68, 0x33, 0xae, 0xe6, 0x61, 0x19, 0x26,
-      0xe9, 0x52, 0x72, 0xa1, 0xf5, 0x88, 0xf9, 0x2a,
-      0xf5, 0x2c, 0xae, 0x70, 0x7a, 0xcd, 0xcc, 0x82,
-      0x63, 0x99, 0x7b, 0xfa, 0x8c, 0x71, 0x9c, 0xa8 },
-    { 0x95, 0x89, 0xda, 0xc9, 0xec, 0xe7, 0x6d, 0xf5,
-      0x72, 0x01, 0x96, 0xdc, 0x58, 0x6d, 0x17, 0x9d,
-      0x73, 0x5d, 0xf7, 0x17, 0x92, 0x6c, 0x06, 0x1e,
-      0xa7, 0x0c, 0x40, 0x85, 0x64, 0x8f, 0xf3, 0x12 },
-    { 0x96, 0xa4, 0x59, 0x90, 0xfc, 0xd0, 0x1c, 0x9c,
-      0x2a, 0xf0, 0x64, 0x5f, 0x87, 0xb9, 0x69, 0x8b,
-      0x05, 0xaf, 0xe6, 0x94, 0x32, 0xeb, 0x57, 0x01,
-      0x08, 0x20, 0x13, 0xba, 0xc5, 0xb0, 0x55, 0x60 },
-    { 0x96, 0xeb, 0x44, 0xaa, 0x6a, 0x20, 0x49, 0xe6,
-      0xba, 0xff, 0xe6, 0xb5, 0x21, 0xc4, 0xad, 0x8c,
-      0x58, 0x77, 0x26, 0xca, 0xa0, 0x12, 0xe8, 0xfb,
-      0x8e, 0x8e, 0x21, 0x89, 0x77, 0xbf, 0x1d, 0xf6 },
-    { 0x97, 0x4f, 0x51, 0xa6, 0x04, 0x68, 0x48, 0xfa,
-      0xa7, 0xb3, 0x3f, 0xd2, 0x39, 0x13, 0x86, 0x42,
-      0x8b, 0xd5, 0x24, 0xea, 0xeb, 0xa8, 0x01, 0x4e,
-      0x6d, 0x1f, 0xe2, 0x54, 0x38, 0x3f, 0x41, 0x79 },
-    { 0x97, 0x8d, 0x6f, 0x1e, 0x9a, 0xa3, 0xa3, 0xce,
-      0xb1, 0xad, 0xa6, 0x09, 0xe2, 0x00, 0x95, 0xfb,
-      0xc3, 0x3a, 0x6b, 0xbc, 0x6a, 0x21, 0xd8, 0x0a,
-      0x4e, 0xcb, 0x27, 0x3c, 0x60, 0xac, 0x2a, 0xc7 },
-    { 0x99, 0xa5, 0x5f, 0x76, 0xcb, 0xea, 0x0f, 0x3e,
-      0x60, 0x71, 0xd3, 0x82, 0x18, 0x1a, 0xf6, 0xcb,
-      0x25, 0xbd, 0xc5, 0x87, 0x5e, 0x29, 0xf0, 0xf4,
-      0xd7, 0x19, 0xa9, 0xd3, 0x5b, 0x5b, 0xd6, 0xbf },
-    { 0x9a, 0x4b, 0x49, 0x93, 0xb4, 0xed, 0x8c, 0x27,
-      0xe7, 0x7f, 0x3c, 0x8a, 0xaf, 0xdb, 0xdc, 0x11,
-      0x1a, 0x36, 0xb7, 0x3c, 0xca, 0xdb, 0x87, 0x04,
-      0x98, 0x25, 0x00, 0xd1, 0xb0, 0xf1, 0x09, 0xf2 },
-    { 0x9a, 0xae, 0x9d, 0x45, 0xaa, 0x04, 0x03, 0x06,
-      0x4b, 0xc5, 0xa7, 0x4d, 0xd0, 0x32, 0x5d, 0xa4,
-      0x1e, 0x12, 0xcf, 0x58, 0x6c, 0x46, 0x2e, 0xe0,
-      0x6c, 0x2b, 0xb4, 0x56, 0xf8, 0x44, 0x1c, 0x4f },
-    { 0x9b, 0x8f, 0x9f, 0xc4, 0xaf, 0xa7, 0x04, 0x0d,
-      0x4e, 0x59, 0x4d, 0x66, 0x7c, 0x44, 0x44, 0xb5,
-      0x25, 0x88, 0x20, 0xc0, 0x8f, 0x89, 0x91, 0x0e,
-      0xd3, 0x42, 0x1c, 0xb4, 0xa9, 0x7b, 0xb7, 0x9e },
-    { 0x9c, 0x70, 0x8d, 0x5b, 0xab, 0x37, 0xf5, 0xb6,
-      0xbc, 0x8a, 0x77, 0x53, 0x12, 0x57, 0x2a, 0xb2,
-      0x79, 0x21, 0x6d, 0x55, 0x6d, 0xa7, 0x4a, 0xc2,
-      0xa7, 0xc0, 0x41, 0xe8, 0xce, 0xb0, 0xbe, 0x0a },
-    { 0x9d, 0x6b, 0xdf, 0xcf, 0x0c, 0xbf, 0xfe, 0xea,
-      0x3b, 0x1a, 0xc7, 0xe9, 0x63, 0xcb, 0xb5, 0xf2,
-      0x7f, 0xbd, 0xa8, 0x9d, 0x27, 0x77, 0xf6, 0x0e,
-      0x56, 0x5b, 0x27, 0x78, 0x54, 0xef, 0xb0, 0x19 },
-    { 0x9d, 0xac, 0x33, 0x14, 0xb2, 0x5b, 0xb7, 0x9a,
-      0x39, 0xcd, 0x01, 0xec, 0x4b, 0x33, 0xa1, 0x2f,
-      0x47, 0x51, 0x2f, 0x54, 0x09, 0xff, 0x09, 0x5d,
-      0x40, 0xaa, 0xd6, 0x20, 0x84, 0xef, 0x15, 0xbe },
-    { 0x9f, 0x24, 0x5c, 0x0a, 0x0e, 0xc6, 0x3a, 0xaa,
-      0xcb, 0xf9, 0x69, 0xc6, 0xfc, 0x24, 0xa1, 0x07,
-      0x15, 0x83, 0xb7, 0x79, 0xa5, 0x8a, 0xb6, 0x23,
-      0xdd, 0x15, 0x31, 0xa2, 0xca, 0x9f, 0x87, 0x51 },
-    { 0x9f, 0xaf, 0x1c, 0x11, 0xa3, 0xc7, 0xe2, 0x41,
-      0xf8, 0x63, 0x71, 0x97, 0xe8, 0x99, 0x68, 0xdb,
-      0x86, 0x6a, 0xd0, 0x1a, 0x5d, 0x4e, 0xd5, 0x34,
-      0x59, 0x48, 0x65, 0xb9, 0x70, 0x75, 0xf2, 0x60 },
-    { 0xa0, 0x05, 0x20, 0xb9, 0x68, 0xbf, 0xcb, 0x63,
-      0x40, 0x87, 0x9f, 0xa8, 0x43, 0x82, 0x0c, 0xec,
-      0x95, 0x45, 0x86, 0x0f, 0xe2, 0x9e, 0x2f, 0x8f,
-      0xee, 0x00, 0xb0, 0x0f, 0xf8, 0x43, 0x42, 0x74 },
-    { 0xa0, 0xc2, 0xd2, 0x07, 0xa4, 0x7e, 0x18, 0xd0,
-      0x37, 0x14, 0xd5, 0xb3, 0x44, 0x5d, 0x88, 0xbe,
-      0x81, 0xff, 0x5e, 0x1d, 0x16, 0x07, 0x3d, 0xc1,
-      0x16, 0x6b, 0xb5, 0x44, 0x8f, 0xf6, 0x52, 0xdf },
-    { 0xa1, 0x50, 0x03, 0x2f, 0x4e, 0xf5, 0xd4, 0xfe,
-      0xb0, 0xae, 0x4a, 0xe1, 0xcd, 0x54, 0x35, 0xba,
-      0x04, 0xa9, 0xb6, 0xa0, 0xf9, 0x0e, 0x2f, 0x3c,
-      0x4b, 0x8a, 0x7b, 0x69, 0xe7, 0xc8, 0x7e, 0x43 },
-    { 0xa1, 0x97, 0x7d, 0x0c, 0x92, 0x7c, 0x21, 0xeb,
-      0x47, 0x6f, 0x67, 0xbe, 0xfe, 0xd6, 0xcf, 0x2c,
-      0x61, 0xb7, 0x45, 0xf0, 0xce, 0x8d, 0x26, 0x58,
-      0x3d, 0x03, 0xb2, 0x70, 0x02, 0xd5, 0xcd, 0xaf },
-    { 0xa2, 0x6c, 0x37, 0x5e, 0xb3, 0x19, 0x6e, 0x28,
-      0x3b, 0xec, 0x60, 0x3d, 0xb6, 0xbb, 0xda, 0xe2,
-      0x49, 0x55, 0xe4, 0xba, 0x91, 0x0c, 0xd4, 0x2d,
-      0x9e, 0xac, 0x55, 0xca, 0xc6, 0x10, 0x3a, 0xb9 },
-    { 0xa3, 0xa4, 0xfc, 0x03, 0xe1, 0x75, 0xf2, 0x68,
-      0x02, 0x57, 0x46, 0x34, 0xde, 0x70, 0x7d, 0x2f,
-      0x92, 0xf4, 0xd0, 0xcb, 0x90, 0xcd, 0xb6, 0x1d,
-      0xd1, 0x95, 0x8b, 0xcf, 0x0c, 0x55, 0x20, 0x86 },
-    { 0xa6, 0x62, 0xfc, 0x81, 0xc9, 0x09, 0x34, 0xb9,
-      0xb4, 0xd6, 0x30, 0xb5, 0xd8, 0x2e, 0x86, 0xf2,
-      0x36, 0x3e, 0xc1, 0x5c, 0xcf, 0xcd, 0xaf, 0xa7,
-      0xa2, 0x0c, 0x9b, 0x4e, 0x3a, 0x90, 0x0d, 0xd1 },
-    { 0xa6, 0xa4, 0xa3, 0xf6, 0x1f, 0xa5, 0x8c, 0xe9,
-      0x70, 0xb4, 0x58, 0xb7, 0xc3, 0x7c, 0x05, 0x2e,
-      0xad, 0x1e, 0xb2, 0x0b, 0x85, 0x67, 0xe3, 0x51,
-      0xad, 0x8e, 0x6f, 0xba, 0x49, 0xc2, 0x69, 0x2c },
-    { 0xa6, 0xde, 0x6c, 0x3b, 0x8c, 0x14, 0x05, 0xcb,
-      0xe1, 0x2d, 0xb4, 0x09, 0x97, 0x61, 0x71, 0xac,
-      0xb5, 0x1f, 0xb3, 0xdc, 0xfb, 0xb7, 0x6e, 0xe3,
-      0x84, 0x95, 0x39, 0xcd, 0x8a, 0xb0, 0x66, 0xdf },
-    { 0xa8, 0x53, 0xad, 0xc1, 0xc2, 0x18, 0x59, 0xaf,
-      0x7c, 0x46, 0x2b, 0x4a, 0xa0, 0xa5, 0x74, 0xca,
-      0x9f, 0xee, 0xfb, 0x18, 0x5a, 0x1f, 0xdb, 0xb6,
-      0xc1, 0x0e, 0x17, 0xd6, 0x01, 0xb7, 0x09, 0x8f },
-    { 0xa8, 0xdf, 0xf0, 0x6a, 0x17, 0x35, 0xb4, 0x6d,
-      0x17, 0xda, 0xeb, 0xc3, 0x43, 0x43, 0x18, 0x31,
-      0x3b, 0x2d, 0x9e, 0x7c, 0x3e, 0xf4, 0x8f, 0x28,
-      0x53, 0x75, 0x35, 0x13, 0xe1, 0xb2, 0x53, 0xa8 },
-    { 0xa8, 0xe3, 0x8c, 0x6e, 0xc0, 0x93, 0xf5, 0xaf,
-      0x53, 0x88, 0xf1, 0xe7, 0x66, 0xd7, 0x5f, 0xfb,
-      0x57, 0xdd, 0xbe, 0x3e, 0x9d, 0xc2, 0xe0, 0xbe,
-      0x57, 0xbb, 0x88, 0x36, 0x46, 0xc5, 0xc0, 0x32 },
-    { 0xa9, 0x0b, 0x8d, 0xe1, 0x7f, 0x6b, 0x68, 0x37,
-      0x56, 0x21, 0x2d, 0xb3, 0xab, 0x34, 0x89, 0x6e,
-      0x91, 0x70, 0x93, 0x11, 0x3e, 0x47, 0xca, 0x35,
-      0x96, 0x2e, 0xac, 0xca, 0x9c, 0xb3, 0x86, 0xf0 },
-    { 0xaa, 0x4b, 0xb3, 0x6f, 0x51, 0xd3, 0xc5, 0x33,
-      0xb5, 0x27, 0x23, 0xcf, 0x66, 0xa5, 0xa9, 0x9f,
-      0xc1, 0x2f, 0x11, 0xd4, 0xcc, 0x12, 0x87, 0x56,
-      0xa5, 0xa3, 0xe8, 0x9c, 0x57, 0xbb, 0x97, 0x51 },
-    { 0xaa, 0xeb, 0xfe, 0x2d, 0x21, 0xb7, 0xe5, 0x35,
-      0x1b, 0xb9, 0x99, 0x69, 0x44, 0x44, 0x19, 0xef,
-      0x21, 0xc9, 0x68, 0x8c, 0xe0, 0x53, 0x24, 0x88,
-      0x84, 0xca, 0xb0, 0xb8, 0x95, 0x10, 0x30, 0xff },
-    { 0xab, 0x41, 0x28, 0x10, 0x9c, 0xab, 0x8a, 0x58,
-      0x7c, 0x8f, 0xf4, 0xc7, 0xf6, 0x87, 0x34, 0x49,
-      0x98, 0x18, 0xd1, 0x3f, 0x52, 0x26, 0x76, 0xd0,
-      0x66, 0xb3, 0x52, 0x17, 0x6f, 0xd2, 0x35, 0x96 },
-    { 0xab, 0x80, 0xd9, 0xba, 0x0a, 0xef, 0xad, 0x7b,
-      0xec, 0xce, 0x7f, 0x5e, 0x61, 0x59, 0x9a, 0xf5,
-      0x26, 0x69, 0xbf, 0x59, 0x50, 0x7f, 0x8e, 0xf1,
-      0x99, 0x13, 0xc4, 0x2e, 0xe1, 0x29, 0xda, 0xf0 },
-    { 0xab, 0xeb, 0x6a, 0xa0, 0xd1, 0xb0, 0xe0, 0x49,
-      0xd6, 0x9d, 0xf8, 0x3a, 0xdd, 0x19, 0xf7, 0x26,
-      0x8a, 0x38, 0xde, 0x6c, 0x00, 0x72, 0x60, 0x68,
-      0xc2, 0xee, 0xe4, 0x55, 0x44, 0xf6, 0xd6, 0x7a },
-    { 0xac, 0x1b, 0x4c, 0x64, 0x6c, 0xae, 0xfb, 0x10,
-      0x8a, 0x54, 0xca, 0xb5, 0x4a, 0x96, 0xe9, 0x66,
-      0x6e, 0x72, 0xa8, 0x20, 0x22, 0x44, 0xef, 0x3d,
-      0x7c, 0xa9, 0x34, 0xdf, 0xcc, 0x24, 0xfc, 0xa7 },
-    { 0xad, 0x69, 0x54, 0x5f, 0x9f, 0x85, 0x25, 0x5f,
-      0xe4, 0x16, 0x51, 0x3d, 0x94, 0xdb, 0x31, 0x50,
-      0x5f, 0x38, 0x4b, 0x52, 0x3c, 0x2c, 0xa2, 0x6e,
-      0xdc, 0x0a, 0x54, 0x9a, 0x8f, 0x16, 0x26, 0xf9 },
-    { 0xae, 0x03, 0x19, 0xfe, 0xa6, 0xa6, 0x5e, 0x84,
-      0xe8, 0x54, 0xb5, 0x15, 0x50, 0xea, 0x44, 0x4f,
-      0xa3, 0xb8, 0xbb, 0x50, 0xae, 0x93, 0x74, 0x01,
-      0x3c, 0xfe, 0xf3, 0x88, 0x73, 0x5d, 0x0b, 0xd3 },
-    { 0xaf, 0x1f, 0x37, 0x1f, 0x34, 0x84, 0x57, 0x51,
-      0x65, 0x2d, 0xc7, 0x48, 0x23, 0xf3, 0x01, 0x5c,
-      0x5a, 0x11, 0xca, 0x65, 0x3f, 0x28, 0x70, 0x1e,
-      0xdd, 0x4a, 0x7e, 0x0d, 0x23, 0x17, 0x1b, 0xbb },
-    { 0xaf, 0x6b, 0x80, 0x51, 0x47, 0x14, 0x0a, 0x0e,
-      0x41, 0x81, 0xd8, 0x6a, 0x7e, 0x8f, 0x07, 0x69,
-      0xb6, 0x1d, 0x46, 0xd7, 0xb6, 0xfa, 0xc6, 0xe6,
-      0xf9, 0x59, 0x6d, 0xe9, 0x4a, 0xa8, 0xe2, 0xe8 },
-    { 0xb0, 0x5c, 0x14, 0x33, 0x61, 0x75, 0x9b, 0xe1,
-      0x52, 0xfd, 0x76, 0xa5, 0xff, 0xa4, 0x87, 0x2d,
-      0xd4, 0x2e, 0xa0, 0x60, 0xae, 0x40, 0xa3, 0x83,
-      0x13, 0xb7, 0xb5, 0x4a, 0xec, 0x06, 0x73, 0xc2 },
-    { 0xb0, 0xe0, 0xe1, 0x6c, 0x5f, 0x69, 0x1f, 0x66,
-      0xa9, 0x57, 0x3b, 0xd3, 0xcf, 0x43, 0xf9, 0xdf,
-      0xd2, 0xad, 0x3e, 0x56, 0x15, 0x54, 0x63, 0x7f,
-      0x1e, 0x7b, 0x71, 0x91, 0x4d, 0x62, 0x73, 0x38 },
-    { 0xb2, 0xdc, 0x86, 0x25, 0x6c, 0xcf, 0xf4, 0xbb,
-      0x14, 0xfd, 0x70, 0x27, 0x9f, 0xcc, 0x3c, 0xe9,
-      0x25, 0xc5, 0x1f, 0xb7, 0x17, 0xe5, 0x87, 0x6f,
-      0x29, 0x1b, 0xa1, 0x70, 0x73, 0x43, 0x85, 0x68 },
-    { 0xb3, 0x0d, 0x88, 0x44, 0x30, 0x43, 0xf5, 0xf3,
-      0x72, 0x32, 0xbb, 0x9b, 0xac, 0xb9, 0x94, 0xc5,
-      0xba, 0xe9, 0x3a, 0x46, 0xfc, 0x87, 0xf1, 0x51,
-      0x29, 0xc9, 0x74, 0x69, 0xa5, 0x81, 0x4e, 0xca },
-    { 0xb3, 0x1a, 0xf0, 0xc2, 0xe5, 0x1e, 0xa2, 0x1c,
-      0x91, 0x04, 0xf9, 0x4f, 0xaa, 0x66, 0xe0, 0xcc,
-      0xc0, 0x41, 0x34, 0xd5, 0x80, 0x9a, 0x2a, 0x26,
-      0x70, 0xa3, 0xb7, 0xbc, 0x7d, 0xd9, 0x64, 0xf8 },
-    { 0xb3, 0xf4, 0xb1, 0x6f, 0x8e, 0xce, 0xbb, 0x41,
-      0x47, 0x4f, 0x92, 0x4f, 0xee, 0xf9, 0xb0, 0xbd,
-      0x97, 0x9b, 0x36, 0x36, 0xc3, 0x4f, 0xf2, 0x72,
-      0x3f, 0x67, 0x3c, 0x8e, 0xee, 0x2a, 0xf1, 0x52 },
-    { 0xb5, 0xe5, 0xdc, 0xde, 0xcb, 0x8d, 0xeb, 0x27,
-      0x13, 0x4f, 0x02, 0xa5, 0x18, 0x79, 0x43, 0x16,
-      0xf0, 0x8f, 0xaf, 0x9c, 0x2b, 0x1f, 0xda, 0xd6,
-      0xd4, 0x86, 0x61, 0xf5, 0x7e, 0xa6, 0x45, 0xd9 },
-    { 0xb7, 0x06, 0xde, 0x1b, 0xd1, 0xee, 0x2f, 0x4c,
-      0xec, 0x6c, 0xe0, 0x92, 0x02, 0x2b, 0x49, 0x32,
-      0x81, 0xe2, 0x9a, 0x21, 0x73, 0x50, 0x8c, 0x9b,
-      0xd0, 0xfb, 0xc2, 0xc3, 0xd9, 0x68, 0xe3, 0xe7 },
-    { 0xb7, 0xa2, 0xae, 0x06, 0x06, 0xaa, 0x2c, 0xfb,
-      0x27, 0x01, 0xb3, 0xb2, 0x77, 0xf4, 0xd7, 0x12,
-      0x54, 0x70, 0x48, 0x7e, 0xfd, 0x94, 0x05, 0x85,
-      0x7f, 0xfc, 0xe4, 0xbf, 0x29, 0x10, 0x5e, 0x68 },
-    { 0xb8, 0x74, 0x36, 0x95, 0x1c, 0xec, 0x37, 0x7e,
-      0xef, 0x73, 0xde, 0x4b, 0x74, 0xf2, 0x83, 0xc4,
-      0x2b, 0x2c, 0xcb, 0x1c, 0xa3, 0x7c, 0x5b, 0x30,
-      0xaa, 0xd6, 0x55, 0xa7, 0x40, 0x1a, 0x3d, 0x2f },
-    { 0xb9, 0x8d, 0x83, 0x38, 0x55, 0xc3, 0x67, 0x88,
-      0x62, 0xb6, 0x2f, 0x36, 0x50, 0xdb, 0x00, 0xa3,
-      0x45, 0xf4, 0x6a, 0x0e, 0x8e, 0x01, 0x1a, 0x20,
-      0x01, 0x3f, 0xd8, 0xed, 0xce, 0x25, 0x27, 0x0d },
-    { 0xba, 0x51, 0xaf, 0xf5, 0xd5, 0xd3, 0x10, 0x5f,
-      0x34, 0xa2, 0xb3, 0x3a, 0x83, 0xe3, 0xad, 0xfd,
-      0x12, 0xd7, 0x9c, 0xa6, 0x05, 0x90, 0x9d, 0x96,
-      0x03, 0x3e, 0x32, 0xa5, 0xcf, 0x2f, 0x71, 0xf6 },
-    { 0xbb, 0x5c, 0xb3, 0x78, 0xb7, 0xb9, 0x48, 0x7f,
-      0xa6, 0x1b, 0xc0, 0x91, 0x3d, 0xa1, 0xdf, 0x26,
-      0xa1, 0xcf, 0xef, 0xf7, 0x45, 0x2d, 0x9b, 0xa3,
-      0x6c, 0xac, 0x47, 0xa8, 0x5c, 0x7f, 0xf3, 0x48 },
-    { 0xbc, 0x14, 0x2e, 0xba, 0xc2, 0x78, 0xa8, 0xfe,
-      0x8c, 0xa8, 0xbc, 0x2c, 0x62, 0xfb, 0xcc, 0x40,
-      0x17, 0xff, 0x24, 0x96, 0x98, 0xbe, 0xed, 0xfb,
-      0x1e, 0xf3, 0x6f, 0x37, 0x5f, 0xb3, 0x9f, 0x72 },
-    { 0xbd, 0x2e, 0x2f, 0x37, 0xc9, 0x66, 0xc3, 0x86,
-      0xd9, 0x70, 0x44, 0xfd, 0xe3, 0xe3, 0xf9, 0x00,
-      0xfb, 0x1a, 0x0b, 0x04, 0x03, 0xb5, 0x81, 0x72,
-      0x5f, 0x34, 0xe3, 0xc1, 0x90, 0x05, 0x60, 0x56 },
-    { 0xbe, 0xb9, 0x09, 0x0c, 0x92, 0xd1, 0x6b, 0xd0,
-      0x5a, 0xf3, 0x91, 0x5a, 0x39, 0xcc, 0x2a, 0xfa,
-      0x9f, 0x6a, 0x8a, 0x6f, 0xbe, 0xd4, 0xfe, 0x54,
-      0xd9, 0xde, 0x32, 0x49, 0x23, 0xb3, 0x93, 0x5a },
-    { 0xbf, 0x38, 0xe6, 0xae, 0x32, 0x0f, 0x69, 0x16,
-      0x16, 0x0d, 0xa6, 0x06, 0x86, 0x83, 0xbf, 0x49,
-      0xf2, 0xb2, 0x2b, 0x25, 0x24, 0x84, 0x63, 0x68,
-      0xf5, 0x04, 0x51, 0x81, 0x52, 0x40, 0x25, 0x9a },
-    { 0xbf, 0x60, 0xae, 0xb3, 0x91, 0xc0, 0xfb, 0xd0,
-      0x49, 0x53, 0x52, 0x6d, 0xa9, 0xfd, 0x59, 0x96,
-      0x9a, 0x82, 0xf1, 0xee, 0x81, 0xa7, 0x97, 0x98,
-      0xa4, 0x17, 0x1e, 0x14, 0x59, 0x39, 0x19, 0x67 },
-    { 0xbf, 0xf4, 0x3a, 0x97, 0x20, 0x48, 0x2d, 0x13,
-      0x4c, 0xd5, 0xee, 0x8a, 0x88, 0x99, 0xe1, 0xa7,
-      0x36, 0xbf, 0x54, 0xa2, 0xb7, 0x86, 0x26, 0x9c,
-      0x0d, 0xcb, 0x8b, 0xa1, 0x92, 0xa8, 0x1f, 0xa4 },
-    { 0xc0, 0x09, 0xa1, 0xbe, 0x5b, 0xe8, 0xaf, 0xb5,
-      0x25, 0x8e, 0x12, 0x85, 0x5c, 0x64, 0xd0, 0x4d,
-      0x13, 0xe8, 0xcc, 0xc4, 0x7b, 0x02, 0xbf, 0x3b,
-      0x51, 0xc6, 0xe1, 0x18, 0x05, 0xae, 0xec, 0xeb },
-    { 0xc0, 0x9f, 0xfa, 0x0e, 0xdd, 0x16, 0xba, 0x55,
-      0xf2, 0x3c, 0xea, 0xf7, 0x2b, 0x11, 0x34, 0xe9,
-      0x28, 0xdb, 0xa1, 0xc2, 0x34, 0x5a, 0x5a, 0xb5,
-      0x63, 0x1e, 0x25, 0x41, 0x24, 0x05, 0x4a, 0xdb },
-    { 0xc0, 0xab, 0xd1, 0xc3, 0x56, 0x2f, 0xbc, 0x7f,
-      0xf7, 0xbd, 0x38, 0x95, 0x54, 0x60, 0xc3, 0xfc,
-      0x43, 0x55, 0x0d, 0x97, 0x7f, 0x25, 0xe3, 0x43,
-      0xd4, 0x9c, 0xd4, 0xaf, 0xad, 0xf2, 0x09, 0x3c },
-    { 0xc0, 0xfe, 0xb7, 0x2a, 0x5f, 0x33, 0x16, 0x5c,
-      0x0d, 0xc7, 0xc4, 0x24, 0x7e, 0x23, 0xf3, 0x8c,
-      0xc6, 0x1f, 0x25, 0x24, 0x42, 0xb2, 0xf6, 0x13,
-      0x40, 0x92, 0xde, 0x3b, 0xad, 0x7e, 0x45, 0x0d },
-    { 0xc1, 0x77, 0x12, 0x97, 0xa4, 0xe8, 0xdc, 0x53,
-      0x75, 0x19, 0x5e, 0x1b, 0x63, 0x04, 0x2b, 0x59,
-      0x19, 0x09, 0xf1, 0xd7, 0xeb, 0x5d, 0x25, 0xf2,
-      0x97, 0xae, 0x7a, 0x61, 0xc1, 0x53, 0x8f, 0x9e },
-    { 0xc1, 0x86, 0xbe, 0x26, 0xe4, 0x47, 0x89, 0x7c,
-      0x48, 0x3c, 0x43, 0xfd, 0xc0, 0x86, 0xe2, 0x60,
-      0x74, 0x17, 0xeb, 0x3e, 0xa7, 0x88, 0xec, 0x03,
-      0x10, 0xa7, 0x9d, 0xa9, 0x24, 0x1d, 0x16, 0xde },
-    { 0xc1, 0xde, 0x5f, 0xa3, 0x92, 0x13, 0x68, 0x58,
-      0x11, 0xa5, 0xba, 0x93, 0x12, 0x1d, 0xe7, 0xa3,
-      0x95, 0x98, 0x4e, 0x84, 0x44, 0x4e, 0x58, 0xf1,
-      0x63, 0xb7, 0xa6, 0x20, 0xae, 0x3b, 0xbf, 0xa8 },
-    { 0xc2, 0xad, 0xdf, 0x99, 0xcf, 0xc4, 0x2c, 0xe0,
-      0xe5, 0xa0, 0x93, 0xbc, 0xbf, 0x87, 0x40, 0x7c,
-      0x61, 0x1f, 0x9d, 0x0a, 0xbf, 0x2a, 0x35, 0xd6,
-      0xe8, 0x03, 0xa3, 0x8e, 0xcb, 0x92, 0xc7, 0xb3 },
-    { 0xc2, 0xe7, 0x92, 0x11, 0x6a, 0x05, 0x00, 0x00,
-      0xbd, 0x47, 0x59, 0x1d, 0x93, 0x04, 0x71, 0xe6,
-      0x17, 0x4c, 0x93, 0x85, 0xf5, 0xdc, 0x32, 0xb7,
-      0x62, 0x31, 0x65, 0x5f, 0xc8, 0x5e, 0x22, 0xe2 },
-    { 0xc3, 0x79, 0x03, 0xc5, 0x3a, 0xe6, 0x02, 0xec,
-      0x96, 0x9e, 0xc3, 0x3f, 0x63, 0xfe, 0x9a, 0xb2,
-      0x0c, 0x39, 0x5f, 0x83, 0x0d, 0x30, 0xe4, 0xee,
-      0x9d, 0x8d, 0xd9, 0x05, 0x92, 0x1e, 0xc1, 0xa0 },
-    { 0xc3, 0xcf, 0x54, 0x16, 0xa5, 0x31, 0xaf, 0x4b,
-      0xfa, 0xe8, 0x9c, 0x45, 0x14, 0x3f, 0x20, 0xcc,
-      0x1b, 0x3e, 0x18, 0x1d, 0x29, 0xc2, 0xd0, 0xe8,
-      0xff, 0x7d, 0x3f, 0x2a, 0x66, 0xb1, 0x82, 0xfe },
-    { 0xc4, 0x98, 0xa1, 0xb6, 0x9f, 0x54, 0x40, 0x86,
-      0x17, 0x47, 0x47, 0x71, 0x5a, 0x27, 0x4d, 0x3f,
-      0xb5, 0x90, 0x19, 0xbe, 0x09, 0x21, 0x31, 0xbc,
-      0xfa, 0xa8, 0x3a, 0x39, 0x5f, 0x7e, 0x57, 0x3c },
-    { 0xc4, 0xe2, 0x8d, 0xd8, 0x3f, 0xe3, 0x0c, 0x96,
-      0x33, 0x8c, 0xef, 0x77, 0x73, 0xc6, 0xdf, 0xca,
-      0x6c, 0xe4, 0xfa, 0x96, 0x41, 0xbe, 0xab, 0x38,
-      0x05, 0xa8, 0xef, 0xb6, 0xcd, 0xc3, 0xcf, 0x0a },
-    { 0xc5, 0x00, 0xb8, 0x3f, 0x3e, 0x06, 0x6c, 0xd1,
-      0xdd, 0x0e, 0xbc, 0xd7, 0x3d, 0xd4, 0x01, 0x61,
-      0xb9, 0x25, 0x9a, 0xa7, 0x7a, 0xb8, 0xa6, 0x47,
-      0xe8, 0x57, 0x1f, 0xf3, 0x37, 0xcf, 0x94, 0x6d },
-    { 0xc5, 0x29, 0x5b, 0xa6, 0xe2, 0x7e, 0x72, 0x10,
-      0x22, 0xfe, 0xb2, 0x1e, 0x78, 0xeb, 0x7b, 0x03,
-      0x57, 0xc9, 0xcd, 0x56, 0x5b, 0xd0, 0xe5, 0x96,
-      0x72, 0xf6, 0x66, 0x34, 0x2b, 0x79, 0x94, 0x9d },
-    { 0xc6, 0x12, 0x75, 0x6b, 0xa5, 0x42, 0x34, 0x4a,
-      0xdc, 0x1b, 0x80, 0xe9, 0x38, 0x84, 0x5a, 0x1e,
-      0xd6, 0xe9, 0x38, 0xfe, 0xf4, 0x0d, 0x04, 0xec,
-      0x86, 0x55, 0x8f, 0x4b, 0x21, 0x05, 0x2f, 0xd2 },
-    { 0xc6, 0x17, 0xe0, 0x85, 0x5b, 0xf1, 0x4f, 0xbf,
-      0x21, 0xaf, 0x00, 0x82, 0x25, 0xca, 0xbe, 0x40,
-      0x4f, 0x73, 0x8c, 0x27, 0x8a, 0x4a, 0x42, 0x87,
-      0xf1, 0xee, 0x38, 0x01, 0x27, 0xc5, 0x61, 0xfa },
-    { 0xc6, 0xa4, 0x24, 0xbf, 0x7c, 0xfe, 0x31, 0x72,
-      0x74, 0x7a, 0x47, 0x14, 0xa0, 0xef, 0xb9, 0x17,
-      0x93, 0x8c, 0x5e, 0xbd, 0x59, 0x12, 0x9d, 0xed,
-      0x7a, 0x81, 0x18, 0xc7, 0xf6, 0x59, 0xd1, 0x33 },
-    { 0xc6, 0xad, 0x1d, 0x7a, 0x14, 0x1a, 0x91, 0x75,
-      0x2d, 0x31, 0xfb, 0xc1, 0x06, 0x16, 0xbf, 0x1c,
-      0xa2, 0xfb, 0x5b, 0x02, 0xe8, 0x46, 0xb5, 0x9e,
-      0x63, 0x34, 0x6b, 0x31, 0x92, 0xa7, 0x52, 0x92 },
-    { 0xc7, 0x01, 0x83, 0x64, 0x38, 0xf3, 0x7b, 0xea,
-      0x8a, 0x88, 0x16, 0x10, 0x63, 0x70, 0x86, 0xf8,
-      0x8d, 0x9a, 0x11, 0x5e, 0x00, 0x92, 0x46, 0xd2,
-      0x7f, 0x48, 0x9f, 0xa7, 0x18, 0x51, 0x88, 0xa8 },
-    { 0xc7, 0xff, 0x8e, 0xfd, 0xec, 0xdf, 0x00, 0xd1,
-      0xfc, 0x8d, 0x55, 0x2d, 0x2a, 0x70, 0x70, 0xe5,
-      0xe3, 0x3d, 0x42, 0xe5, 0x90, 0xf5, 0x86, 0xc6,
-      0xae, 0xde, 0x03, 0x2b, 0x2d, 0x86, 0x7b, 0xd5 },
-    { 0xc7, 0xff, 0xb4, 0x9f, 0xbc, 0x94, 0x72, 0x24,
-      0x5c, 0x8e, 0x95, 0xde, 0x62, 0x9a, 0xf5, 0xc1,
-      0xbf, 0xea, 0xc5, 0x50, 0x04, 0xc1, 0x54, 0x82,
-      0x3a, 0x58, 0xba, 0xe8, 0x05, 0x6e, 0x3c, 0x64 },
-    { 0xc8, 0x37, 0xd6, 0xf2, 0xab, 0x14, 0x79, 0x91,
-      0x42, 0xed, 0x3c, 0x79, 0xbe, 0xd9, 0x44, 0x1e,
-      0x92, 0x50, 0xbd, 0x05, 0x20, 0x25, 0xad, 0x8a,
-      0xf4, 0x40, 0x41, 0xac, 0x19, 0xef, 0xbb, 0x4c },
-    { 0xc9, 0x72, 0xf4, 0xf9, 0x6e, 0x71, 0x33, 0xe1,
-      0x6e, 0x55, 0x57, 0xa0, 0x57, 0xb1, 0xd4, 0x2b,
-      0xa9, 0x2d, 0x98, 0x5c, 0xae, 0xe7, 0x3c, 0xaf,
-      0xda, 0xeb, 0x55, 0xec, 0xa2, 0xe4, 0xab, 0xb0 },
-    { 0xc9, 0x78, 0x37, 0x2c, 0x9e, 0x11, 0x60, 0x71,
-      0xb6, 0x1b, 0x90, 0x92, 0xa9, 0xaa, 0x96, 0x81,
-      0x62, 0x36, 0x55, 0xa6, 0x6f, 0x4f, 0xcb, 0xc4,
-      0xd3, 0xa6, 0x7e, 0xfd, 0x56, 0x72, 0x48, 0x30 },
-    { 0xca, 0x55, 0x6f, 0x82, 0xc9, 0x68, 0x4c, 0x9a,
-      0xf3, 0x55, 0x7d, 0x3e, 0x2d, 0x88, 0xaf, 0x92,
-      0xed, 0x25, 0x9c, 0x20, 0xff, 0xd1, 0xdd, 0xe9,
-      0xf7, 0x9d, 0x6b, 0x92, 0xc6, 0x1e, 0xe1, 0xb9 },
-    { 0xca, 0xbe, 0x25, 0x56, 0xf1, 0xbb, 0x56, 0x57,
-      0x0c, 0xef, 0x3a, 0x87, 0x03, 0x32, 0x71, 0xa1,
-      0xf2, 0x1d, 0x09, 0xb7, 0xfd, 0x04, 0x12, 0x83,
-      0x18, 0xe5, 0xe7, 0xbc, 0xe3, 0xa2, 0x01, 0xe2 },
-    { 0xca, 0xdc, 0xd5, 0xae, 0x1b, 0x75, 0x6a, 0xb7,
-      0x41, 0xb3, 0x56, 0x9c, 0x42, 0xa5, 0x41, 0x1f,
-      0x09, 0x3e, 0x4e, 0x1f, 0x01, 0x2e, 0xc5, 0x79,
-      0x91, 0xcb, 0xd6, 0xdb, 0xe0, 0x8f, 0xaa, 0xc1 },
-    { 0xcb, 0x7a, 0x43, 0x8d, 0x16, 0xe4, 0xa5, 0xf3,
-      0xc5, 0x6f, 0xdf, 0x19, 0x1e, 0x1d, 0xaf, 0x9f,
-      0x32, 0x5c, 0x65, 0x0b, 0xd6, 0x2f, 0x07, 0xc4,
-      0x67, 0x71, 0x72, 0x07, 0x35, 0x1a, 0xe3, 0x29 },
-    { 0xcc, 0x30, 0xd8, 0x19, 0xde, 0x54, 0x05, 0xf6,
-      0x49, 0xc8, 0xb7, 0xa8, 0x14, 0x8f, 0x26, 0xd7,
-      0x71, 0x08, 0x3e, 0xc5, 0x18, 0xf9, 0xb6, 0x6f,
-      0xf5, 0x47, 0xf2, 0x82, 0x2d, 0x11, 0x93, 0x6d },
-    { 0xcc, 0x65, 0xcd, 0xc5, 0x33, 0x62, 0xd4, 0x21,
-      0x62, 0x7e, 0xae, 0xf5, 0xd0, 0xc8, 0xe4, 0xc4,
-      0xe2, 0x40, 0xad, 0xe0, 0xc9, 0xd4, 0x20, 0xbe,
-      0x67, 0x1e, 0x70, 0xf0, 0xfb, 0xac, 0x8d, 0x0a },
-    { 0xcd, 0xb1, 0x62, 0x53, 0xd2, 0x2e, 0xd5, 0xd4,
-      0x26, 0xcf, 0xa1, 0xb0, 0x5c, 0xec, 0xd8, 0x6e,
-      0xf1, 0xb7, 0xde, 0xaa, 0x07, 0xc5, 0x70, 0x5e,
-      0xbb, 0xaf, 0x7d, 0x9a, 0x80, 0x7d, 0x56, 0x16 },
-    { 0xcd, 0xc0, 0x39, 0xf3, 0xa2, 0xd1, 0xbb, 0xa5,
-      0xe8, 0x09, 0x4e, 0x55, 0x23, 0xcf, 0x60, 0x47,
-      0x09, 0x7d, 0x4b, 0x3c, 0xd4, 0xec, 0x4e, 0xd6,
-      0xaa, 0x8e, 0xb7, 0xb4, 0xd8, 0xb5, 0x77, 0x7d },
-    { 0xcd, 0xc4, 0xea, 0x92, 0x02, 0xe3, 0x3e, 0xdd,
-      0x0f, 0x2d, 0x3a, 0xe8, 0x6a, 0xca, 0xc7, 0xfb,
-      0x25, 0x35, 0x4b, 0x02, 0x23, 0x5b, 0x09, 0x33,
-      0xaa, 0x81, 0xa3, 0x13, 0xb5, 0xfd, 0xfe, 0xec },
-    { 0xce, 0x4c, 0x2f, 0x8f, 0x16, 0x46, 0x8a, 0x58,
-      0x88, 0xe9, 0x0f, 0x73, 0x4e, 0x4d, 0x22, 0x02,
-      0xdf, 0xad, 0xbf, 0xa6, 0x6f, 0x5b, 0x35, 0x75,
-      0x2b, 0xaa, 0x76, 0x21, 0xa7, 0x60, 0xb0, 0x88 },
-    { 0xce, 0x81, 0x44, 0x58, 0x54, 0x03, 0x1f, 0x3d,
-      0x0f, 0x5c, 0x88, 0x75, 0x46, 0x4d, 0xcd, 0x5b,
-      0xa6, 0xc8, 0x90, 0xf4, 0x49, 0xb3, 0x20, 0x7b,
-      0xca, 0x2b, 0xc9, 0x61, 0x82, 0x2d, 0x27, 0xc4 },
-    { 0xcf, 0xa0, 0xc0, 0x0c, 0xb2, 0xfb, 0x4b, 0x85,
-      0x7a, 0xad, 0x22, 0xb1, 0x3a, 0x90, 0xe3, 0x46,
-      0xa0, 0x3e, 0x6b, 0x79, 0xab, 0xd5, 0xd2, 0x75,
-      0xb5, 0x43, 0x24, 0x68, 0x17, 0x92, 0xd6, 0xd1 },
-    { 0xd0, 0xf5, 0x93, 0xc1, 0xa8, 0x1b, 0x1e, 0xf8,
-      0x51, 0x69, 0x81, 0xee, 0x56, 0xf1, 0xd5, 0x98,
-      0xa2, 0xa6, 0x03, 0x48, 0x8c, 0x67, 0x8c, 0x1b,
-      0x7b, 0xbe, 0xa6, 0x44, 0x6b, 0x00, 0x83, 0xad },
-    { 0xd2, 0x90, 0x3c, 0xa2, 0x55, 0x17, 0x27, 0xed,
-      0x01, 0x71, 0xcc, 0x4a, 0x43, 0xb3, 0xca, 0xe0,
-      0x09, 0xb7, 0x47, 0xb9, 0xf4, 0xf8, 0x48, 0x72,
-      0x92, 0x27, 0xbf, 0x59, 0x02, 0xf2, 0x3e, 0x47 },
-    { 0xd2, 0xe8, 0xa1, 0x23, 0x7a, 0x93, 0xf5, 0x78,
-      0xd1, 0xba, 0x8f, 0x09, 0xe4, 0xff, 0x10, 0x7b,
-      0x62, 0x35, 0x78, 0x85, 0x42, 0xaa, 0x61, 0x83,
-      0xd1, 0x76, 0xdb, 0xf1, 0xc8, 0x8d, 0xcf, 0xb6 },
-    { 0xd5, 0x04, 0x88, 0x96, 0x86, 0x07, 0x29, 0xa8,
-      0xfa, 0x5d, 0x23, 0x57, 0x81, 0x2b, 0xa5, 0x6c,
-      0xbe, 0x84, 0xc9, 0xab, 0x7d, 0x14, 0xdf, 0x47,
-      0x64, 0xe0, 0xb6, 0x62, 0x0f, 0xa3, 0x20, 0x10 },
-    { 0xd5, 0x41, 0xa7, 0x7e, 0x13, 0x6e, 0x9e, 0x70,
-      0x3b, 0xb9, 0x9f, 0x80, 0x68, 0xcf, 0xee, 0x86,
-      0xa4, 0xb9, 0xf0, 0x89, 0xe0, 0x2d, 0x0c, 0x6c,
-      0xb6, 0xd4, 0xa3, 0x94, 0x6c, 0x6b, 0x16, 0x7a },
-    { 0xd5, 0x83, 0x94, 0x96, 0xcd, 0xc8, 0x5b, 0xe3,
-      0xd1, 0xf1, 0xac, 0x65, 0x2e, 0xfa, 0x92, 0xbe,
-      0xa3, 0xb0, 0x61, 0xc1, 0x3d, 0xad, 0x5a, 0x82,
-      0x11, 0x22, 0xcf, 0xe9, 0xc7, 0x1a, 0x5a, 0x32 },
-    { 0xd5, 0xa4, 0xee, 0x46, 0x95, 0xb5, 0x65, 0xa6,
-      0x7e, 0x50, 0x48, 0x66, 0xfe, 0x5b, 0xa3, 0xc0,
-      0xed, 0xca, 0xee, 0xd5, 0x2a, 0xd0, 0xaf, 0x07,
-      0xe6, 0x79, 0x17, 0x73, 0x85, 0x12, 0xc8, 0xf5 },
-    { 0xd6, 0x25, 0xc0, 0x59, 0x2b, 0x25, 0xdc, 0x03,
-      0xaa, 0x7e, 0x87, 0x8e, 0x6a, 0x85, 0x09, 0x1b,
-      0xaa, 0x07, 0x8d, 0x26, 0x8b, 0xbd, 0xb4, 0x9f,
-      0x09, 0x67, 0x94, 0x08, 0x61, 0x2d, 0x1e, 0xfe },
-    { 0xd6, 0xd1, 0xb3, 0x5c, 0xbc, 0x12, 0xfb, 0x1c,
-      0x70, 0xa0, 0xb4, 0x3b, 0xa5, 0x9a, 0xb3, 0xd3,
-      0x22, 0x5f, 0x37, 0x32, 0x64, 0xdd, 0x87, 0xfb,
-      0xca, 0x00, 0x61, 0xec, 0x1c, 0x4d, 0xa1, 0x1a },
-    { 0xd7, 0x32, 0x49, 0x74, 0xb5, 0x60, 0x09, 0x62,
-      0x17, 0x61, 0xf7, 0xc0, 0xff, 0x68, 0x9d, 0xde,
-      0x47, 0x74, 0x99, 0x85, 0xe1, 0xee, 0x8b, 0x5c,
-      0x89, 0x61, 0xdd, 0x8f, 0x6a, 0x78, 0xbb, 0xf5 },
-    { 0xd9, 0x2e, 0x3e, 0xe3, 0x82, 0xc8, 0xdc, 0xaf,
-      0xa0, 0x39, 0x3d, 0x9f, 0x9a, 0x00, 0xbf, 0x4c,
-      0xd9, 0xd5, 0x64, 0x26, 0x2b, 0x18, 0x0f, 0x68,
-      0x16, 0x0b, 0x20, 0x34, 0xc5, 0x44, 0xd1, 0x0a },
-    { 0xd9, 0x65, 0xf7, 0x41, 0x62, 0x04, 0xda, 0x83,
-      0x1a, 0xf6, 0x6b, 0xfa, 0x8f, 0x90, 0xd1, 0x41,
-      0xe9, 0x93, 0xf0, 0x00, 0x21, 0x33, 0xf2, 0x8d,
-      0xe9, 0x7f, 0x56, 0x4a, 0x1d, 0x60, 0x4e, 0xcc },
-    { 0xda, 0xdf, 0x97, 0x13, 0x34, 0x14, 0xad, 0x51,
-      0x3f, 0xc7, 0x50, 0x14, 0xe9, 0x56, 0x65, 0xda,
-      0xd7, 0x76, 0xb1, 0x50, 0x4b, 0x15, 0x67, 0x43,
-      0x4f, 0xd8, 0x2a, 0x79, 0xa2, 0x20, 0xe9, 0xa1 },
-    { 0xda, 0xff, 0xd4, 0x05, 0x6f, 0xc3, 0x68, 0xfa,
-      0x64, 0x8d, 0x0e, 0xd8, 0x9b, 0x5d, 0xe0, 0xee,
-      0x93, 0x1f, 0x1b, 0x33, 0x84, 0x78, 0xab, 0xf5,
-      0x69, 0x29, 0xa9, 0x4d, 0x3b, 0xd6, 0x1d, 0x46 },
-    { 0xde, 0xcd, 0xb9, 0xfc, 0x1d, 0xde, 0xc9, 0x7e,
-      0x09, 0xc3, 0x02, 0x6a, 0xce, 0xb7, 0x6b, 0xda,
-      0xe9, 0xde, 0xb6, 0x62, 0x75, 0x1d, 0xda, 0x34,
-      0x9d, 0x2f, 0xa6, 0xbd, 0x75, 0xca, 0x59, 0x14 },
-    { 0xde, 0xd1, 0x9a, 0xd5, 0xde, 0x99, 0x65, 0xd9,
-      0x22, 0x5c, 0x1b, 0xba, 0x5f, 0xb4, 0xd8, 0x90,
-      0xc8, 0xe5, 0xc0, 0x35, 0xe4, 0x85, 0x27, 0x52,
-      0xb6, 0x69, 0xb0, 0x40, 0x0f, 0x24, 0xf1, 0x74 },
-    { 0xdf, 0x30, 0xbf, 0x8d, 0x1b, 0xf9, 0x37, 0x8e,
-      0x43, 0x3e, 0xf9, 0xe1, 0xb3, 0xa2, 0x28, 0xa0,
-      0x7e, 0x36, 0x58, 0xa5, 0xbc, 0x43, 0x88, 0x23,
-      0x45, 0x4d, 0xb0, 0x6a, 0x67, 0x94, 0x4c, 0x6e },
-    { 0xe0, 0x0b, 0xd7, 0x86, 0xd1, 0xf2, 0xf4, 0x46,
-      0xc4, 0xba, 0x83, 0x99, 0xd4, 0xd8, 0xd5, 0xa0,
-      0xd1, 0x98, 0x57, 0x8f, 0x42, 0x99, 0xfd, 0xfd,
-      0xaf, 0xf7, 0x8c, 0x3f, 0x67, 0x71, 0xf3, 0x94 },
-    { 0xe0, 0x8b, 0x2c, 0xc2, 0x7a, 0xe8, 0xe2, 0xef,
-      0x1a, 0x33, 0x01, 0x7a, 0x9a, 0xc2, 0x5d, 0xda,
-      0xfb, 0x5e, 0xa1, 0x12, 0xc9, 0x56, 0xb0, 0x02,
-      0xfe, 0x6c, 0x79, 0x80, 0x14, 0xaa, 0x90, 0x65 },
-    { 0xe1, 0xb2, 0xe8, 0x6b, 0x0d, 0xa8, 0x69, 0xe9,
-      0x25, 0x26, 0x6c, 0x1b, 0x56, 0x88, 0x34, 0x5a,
-      0x17, 0xb0, 0xf6, 0xe2, 0xa2, 0x14, 0x94, 0x54,
-      0x7e, 0xac, 0x09, 0x7c, 0x8b, 0xf5, 0x3c, 0x5a },
-    { 0xe1, 0xd6, 0x44, 0xa0, 0x96, 0xbd, 0x8a, 0x6c,
-      0xac, 0xbb, 0xda, 0x3e, 0x7f, 0xc3, 0x38, 0xea,
-      0xdd, 0xc1, 0x2f, 0x23, 0x6c, 0x72, 0x61, 0xe4,
-      0x5f, 0x8a, 0xd2, 0xd8, 0x42, 0x42, 0x4f, 0x72 },
-    { 0xe2, 0x24, 0x10, 0xb5, 0xa6, 0x7f, 0xed, 0xc2,
-      0x64, 0x69, 0x4c, 0x44, 0x9d, 0x84, 0xfa, 0x1a,
-      0x02, 0xbc, 0x8b, 0x21, 0x28, 0xc1, 0x25, 0x60,
-      0x71, 0x58, 0xc9, 0x1b, 0x05, 0x38, 0x6c, 0x6a },
-    { 0xe2, 0xa8, 0x47, 0xc3, 0xf0, 0x9b, 0xeb, 0x6f,
-      0x05, 0x68, 0x6f, 0x17, 0x79, 0x1b, 0x05, 0xf1,
-      0xfe, 0x25, 0xf7, 0x71, 0x86, 0x9c, 0x42, 0x63,
-      0xa5, 0x5b, 0x94, 0x18, 0x77, 0xe4, 0x79, 0x04 },
-    { 0xe2, 0xf3, 0x9a, 0x9d, 0x48, 0xa3, 0x22, 0x10,
-      0x55, 0xb3, 0xc8, 0xa3, 0xeb, 0x14, 0x39, 0xd6,
-      0xb8, 0x73, 0x01, 0x3e, 0xe4, 0xd0, 0x97, 0x12,
-      0x20, 0x64, 0xf2, 0x7e, 0xc0, 0x3d, 0xd4, 0xda },
-    { 0xe2, 0xf5, 0xde, 0x57, 0xcd, 0x67, 0x24, 0x9a,
-      0x7e, 0x1f, 0x45, 0x5b, 0x85, 0xc0, 0x6f, 0x0d,
-      0x80, 0x9e, 0x75, 0xa5, 0x5c, 0x6b, 0x05, 0x48,
-      0x16, 0xe0, 0x19, 0x89, 0x9a, 0x3a, 0x02, 0xff },
-    { 0xe4, 0xf1, 0xde, 0x31, 0xcd, 0xaa, 0x6d, 0x9e,
-      0xb1, 0xaa, 0xfd, 0x10, 0x81, 0x27, 0xa2, 0xf0,
-      0xa8, 0xfb, 0x6d, 0xa8, 0x5a, 0x04, 0x14, 0xad,
-      0x24, 0x99, 0x47, 0xc4, 0x8d, 0x24, 0x92, 0xc5 },
-    { 0xe6, 0x44, 0xd1, 0x1c, 0x37, 0x07, 0x0f, 0x89,
-      0x69, 0x33, 0x08, 0x17, 0x8d, 0x6b, 0xe4, 0x95,
-      0x94, 0x96, 0x92, 0xc1, 0xfb, 0xeb, 0x30, 0xed,
-      0x32, 0x9b, 0x74, 0x02, 0x7f, 0xcf, 0xfd, 0x48 },
-    { 0xe6, 0xb0, 0xf2, 0xe2, 0x5b, 0xd5, 0x16, 0xe4,
-      0xbb, 0xa3, 0x7a, 0x2b, 0xf2, 0xe2, 0xc7, 0x2a,
-      0x1e, 0x53, 0x9c, 0x60, 0x30, 0xf3, 0xcf, 0x9b,
-      0xbe, 0x5e, 0x79, 0x72, 0x8d, 0x68, 0x64, 0x78 },
-    { 0xe6, 0xe5, 0x4d, 0xe7, 0xb4, 0x97, 0x54, 0xd3,
-      0x57, 0xb0, 0xa8, 0xd9, 0x4a, 0x4d, 0x4f, 0x80,
-      0xac, 0xd1, 0x99, 0x4c, 0xcc, 0x1c, 0x99, 0x08,
-      0xe9, 0xf0, 0xd9, 0x21, 0xe4, 0x28, 0xb8, 0x38 },
-    { 0xe7, 0x0c, 0xbb, 0x7a, 0xf7, 0xaa, 0x20, 0xb9,
-      0x89, 0x0b, 0xc1, 0xf9, 0xfa, 0x00, 0xd8, 0x09,
-      0x0b, 0x5a, 0xc9, 0x82, 0x5e, 0xa9, 0xd2, 0xfd,
-      0xf7, 0x7c, 0xa4, 0xda, 0xe9, 0x44, 0x51, 0xb2 },
-    { 0xe8, 0x16, 0xf9, 0x92, 0x94, 0xa1, 0x3a, 0xc2,
-      0xfa, 0x2b, 0xfb, 0x76, 0xc2, 0x2d, 0xfa, 0x71,
-      0xbc, 0x3d, 0xa4, 0x8f, 0x67, 0x1e, 0xf7, 0x7c,
-      0x00, 0xaa, 0x8e, 0x45, 0x9b, 0x7c, 0xc8, 0x2a },
-    { 0xe9, 0xd4, 0x98, 0x51, 0xbf, 0x78, 0x37, 0x6d,
-      0x54, 0x08, 0x2d, 0x1e, 0xb8, 0x2b, 0xd2, 0xdc,
-      0x96, 0x82, 0x07, 0x09, 0xb7, 0x77, 0x2d, 0x3f,
-      0xbc, 0xa3, 0x90, 0x08, 0x8b, 0x54, 0xc4, 0x53 },
-    { 0xe9, 0xf5, 0x71, 0xc7, 0x71, 0x64, 0xab, 0xea,
-      0xe1, 0x85, 0x28, 0x37, 0x5c, 0xfd, 0xc7, 0x21,
-      0x9a, 0x6b, 0xde, 0x46, 0x1b, 0x19, 0x73, 0xbe,
-      0x2b, 0xb8, 0xbd, 0xf0, 0xda, 0x78, 0xb2, 0xb4 },
-    { 0xeb, 0x11, 0x63, 0xaa, 0xef, 0xe8, 0xfd, 0x88,
-      0xe1, 0x32, 0x7b, 0x48, 0xa9, 0xc0, 0x06, 0x2e,
-      0x06, 0xf0, 0xa6, 0xea, 0xa0, 0xa0, 0x18, 0x24,
-      0x7f, 0x9f, 0xa4, 0xe3, 0x4e, 0x3a, 0x47, 0x4c },
-    { 0xec, 0x4b, 0xbd, 0xeb, 0x15, 0x12, 0x1d, 0x96,
-      0x76, 0x4d, 0x6c, 0x01, 0xb2, 0x7e, 0xd5, 0xae,
-      0x86, 0x46, 0x5c, 0x46, 0xd5, 0xa4, 0x0e, 0x34,
-      0xae, 0xfc, 0x09, 0x2d, 0x3e, 0x8b, 0xb1, 0x76 },
-    { 0xec, 0x5f, 0xa4, 0x73, 0x12, 0x1e, 0x3f, 0x49,
-      0xf0, 0x95, 0x3a, 0x2a, 0x91, 0x83, 0x39, 0xe3,
-      0x6f, 0x3c, 0xb6, 0xb8, 0xd8, 0xb8, 0x9e, 0x91,
-      0x74, 0x23, 0xda, 0xce, 0xac, 0xe6, 0xd5, 0x8a },
-    { 0xec, 0xce, 0x4e, 0x52, 0x82, 0xfd, 0x2e, 0xe0,
-      0x03, 0xa4, 0x03, 0x2c, 0x80, 0xd3, 0x32, 0x1a,
-      0x69, 0x47, 0x25, 0x98, 0x94, 0x59, 0x09, 0xcb,
-      0x25, 0x55, 0x7a, 0xa8, 0x47, 0x74, 0x2d, 0xdf },
-    { 0xed, 0x5b, 0xb8, 0x6a, 0x95, 0xa5, 0xfe, 0x2b,
-      0x17, 0x08, 0xf2, 0x56, 0x75, 0x4a, 0x89, 0xc4,
-      0x29, 0x67, 0x9b, 0x30, 0x75, 0x8e, 0xe0, 0x12,
-      0x2b, 0x9e, 0x50, 0x85, 0x8d, 0xe2, 0x10, 0x4b },
-    { 0xed, 0xc1, 0xbf, 0x3e, 0xfb, 0xf7, 0xe1, 0xd9,
-      0x5e, 0x19, 0xc5, 0x5e, 0xca, 0xe7, 0x7e, 0x83,
-      0x69, 0x46, 0xab, 0x0a, 0x26, 0xa7, 0x8e, 0x32,
-      0xa4, 0x72, 0xc9, 0xd3, 0x6c, 0x69, 0xce, 0xcd },
-    { 0xed, 0xf4, 0xdf, 0x97, 0x2c, 0xad, 0x6c, 0x47,
-      0x0b, 0xab, 0x5d, 0x66, 0x42, 0xf6, 0x60, 0xb8,
-      0x42, 0xd6, 0xc9, 0x73, 0x07, 0x44, 0x93, 0xe4,
-      0xef, 0x1b, 0xbf, 0x31, 0x1a, 0x92, 0x79, 0x95 },
-    { 0xee, 0x34, 0xe1, 0xa1, 0x9b, 0xc8, 0x89, 0xf8,
-      0x5f, 0x7f, 0x0f, 0x5b, 0xf8, 0x72, 0xb1, 0xac,
-      0x56, 0x5e, 0xc6, 0xf1, 0x9d, 0xb5, 0x17, 0xba,
-      0x4e, 0xd7, 0x55, 0xc4, 0x18, 0x5f, 0x69, 0xe8 },
-    { 0xef, 0x36, 0xa2, 0x29, 0x89, 0x65, 0xe4, 0x98,
-      0x84, 0x59, 0xb9, 0x21, 0x6a, 0xb3, 0x3c, 0x3c,
-      0xa8, 0x42, 0xd2, 0x16, 0x83, 0xb6, 0x2a, 0x2b,
-      0xf1, 0x53, 0x0d, 0x30, 0xb0, 0xae, 0x78, 0x25 },
-    { 0xef, 0xaf, 0xca, 0x84, 0x90, 0x30, 0x7b, 0x0f,
-      0x62, 0x2b, 0xf4, 0x3a, 0x0e, 0xb3, 0xc5, 0x1a,
-      0xcb, 0xdd, 0xde, 0xdc, 0x23, 0x92, 0xf1, 0x61,
-      0xac, 0xed, 0x16, 0x71, 0xa6, 0x53, 0x60, 0x7e },
-    { 0xef, 0xd1, 0xe0, 0xe7, 0x3f, 0xa8, 0x71, 0x00,
-      0xb7, 0x6a, 0x93, 0x23, 0x49, 0xc4, 0x5d, 0x09,
-      0xb2, 0x8b, 0x2d, 0x8a, 0x00, 0x17, 0x19, 0xa5,
-      0x8d, 0xfa, 0xcc, 0x74, 0x84, 0xc7, 0xcf, 0x42 },
-    { 0xf0, 0x6b, 0x35, 0x95, 0x36, 0xd1, 0x34, 0x32,
-      0x8b, 0x36, 0x00, 0x4d, 0xa9, 0xa9, 0x19, 0x0c,
-      0x3a, 0x76, 0x69, 0xe8, 0x27, 0x8d, 0xb9, 0xf7,
-      0x58, 0x57, 0xc4, 0x8d, 0x64, 0x4b, 0xe2, 0x03 },
-    { 0xf0, 0xcf, 0xc7, 0x79, 0x13, 0x39, 0x7d, 0xe2,
-      0x38, 0xed, 0xb5, 0x9f, 0x0f, 0x99, 0x23, 0xc6,
-      0xd4, 0x11, 0x0a, 0x4b, 0x3a, 0xc8, 0xac, 0x76,
-      0x55, 0x6a, 0x0c, 0x92, 0x44, 0xf0, 0x3f, 0xc1 },
-    { 0xf2, 0xb1, 0x95, 0x84, 0x6e, 0xe2, 0xb9, 0xab,
-      0x5f, 0x18, 0xe6, 0x80, 0x21, 0xf8, 0xdf, 0x7c,
-      0x0b, 0x60, 0x58, 0xde, 0xde, 0x86, 0xc5, 0xd5,
-      0x90, 0xf2, 0xe8, 0x64, 0x3a, 0xfe, 0x04, 0x52 },
-    { 0xf2, 0xe5, 0x30, 0x0c, 0x39, 0xf2, 0x86, 0xc6,
-      0x78, 0x99, 0x90, 0x9c, 0x7c, 0xe7, 0x35, 0x9b,
-      0x09, 0x45, 0xd2, 0xaf, 0xd3, 0x4a, 0x6d, 0xd6,
-      0x9e, 0x08, 0xcd, 0xa5, 0x44, 0xc8, 0x7b, 0x3a },
-    { 0xf3, 0x0c, 0x0a, 0xed, 0x70, 0x6d, 0x22, 0x55,
-      0x5f, 0x07, 0x09, 0x6a, 0xf4, 0xb8, 0xbe, 0xdc,
-      0x16, 0x3c, 0x0f, 0x6e, 0xd5, 0x34, 0x6e, 0xfc,
-      0x28, 0xe8, 0xcf, 0xaf, 0x84, 0x2f, 0xa5, 0xd9 },
-    { 0xf6, 0x13, 0xd5, 0x90, 0x46, 0xd1, 0x66, 0x71,
-      0xd3, 0xc5, 0x60, 0x17, 0x6f, 0x3d, 0x77, 0xfd,
-      0xc5, 0x1e, 0x5f, 0x57, 0xb5, 0xe4, 0x8a, 0xe7,
-      0xa4, 0xb9, 0x70, 0x0a, 0x11, 0xd4, 0x69, 0x3a },
-    { 0xf6, 0x54, 0x6b, 0x2f, 0xfe, 0x2b, 0xae, 0xf7,
-      0x35, 0xe8, 0x25, 0x67, 0xa6, 0xe2, 0x36, 0x75,
-      0x03, 0x94, 0xc1, 0x19, 0x14, 0x09, 0x87, 0x0c,
-      0x6f, 0xbe, 0x95, 0x2d, 0x08, 0xa3, 0x3a, 0xba },
-    { 0xf8, 0x64, 0x44, 0x3e, 0x2f, 0x63, 0x9e, 0x7c,
-      0xff, 0xd2, 0x42, 0x21, 0xf6, 0x1b, 0xbf, 0xf0,
-      0x7c, 0xce, 0x5c, 0x61, 0xdd, 0xb1, 0x68, 0xb3,
-      0xb4, 0x04, 0xd7, 0xc8, 0xcd, 0xca, 0x18, 0xb2 },
-    { 0xf8, 0x94, 0xf9, 0x67, 0x36, 0x9c, 0xe7, 0xcf,
-      0xa3, 0x1a, 0xc1, 0x9a, 0x66, 0x65, 0xb0, 0xc4,
-      0x24, 0xba, 0x40, 0x8a, 0xd5, 0xd3, 0x65, 0xf1,
-      0x68, 0xd8, 0xbe, 0xeb, 0x79, 0xf4, 0x89, 0xf3 },
-    { 0xf8, 0xcf, 0x1e, 0x08, 0x6a, 0x6a, 0x06, 0x3f,
-      0xad, 0x25, 0x74, 0x25, 0xaa, 0xe7, 0x20, 0x01,
-      0x40, 0x05, 0xb4, 0x15, 0x91, 0x2d, 0xbb, 0x8c,
-      0x0b, 0xc9, 0x99, 0xaf, 0x48, 0x48, 0xcf, 0xe5 },
-    { 0xfb, 0x9a, 0xf7, 0x9d, 0xea, 0x18, 0xaf, 0x62,
-      0x99, 0x85, 0x0e, 0x25, 0x15, 0x9b, 0x4f, 0xb2,
-      0x24, 0xcb, 0xb0, 0xf1, 0x4e, 0xad, 0x7e, 0x85,
-      0xf6, 0x0c, 0x2a, 0xb2, 0x09, 0xea, 0x45, 0x0d },
-    { 0xfb, 0xc4, 0xc9, 0xba, 0xcf, 0xe3, 0xda, 0x64,
-      0x13, 0x18, 0x26, 0x6b, 0x72, 0x58, 0x56, 0x00,
-      0x35, 0xbc, 0x64, 0x60, 0x8e, 0x34, 0xb9, 0x90,
-      0xca, 0x92, 0xa5, 0x52, 0xf3, 0x14, 0x21, 0x61 },
-    { 0xfb, 0xed, 0xd3, 0x88, 0x89, 0xf0, 0xb4, 0x1f,
-      0x73, 0x4d, 0xe2, 0xf4, 0xc9, 0xd6, 0xf2, 0x7c,
-      0x8d, 0x4a, 0xa9, 0xab, 0x73, 0x64, 0x91, 0xe1,
-      0x64, 0xe1, 0x21, 0xb7, 0xbc, 0xaf, 0x44, 0xe8 },
-    { 0xfc, 0x01, 0xa5, 0x5a, 0x36, 0xcc, 0x8b, 0x7b,
-      0x7c, 0xa2, 0xea, 0xb0, 0x84, 0x60, 0xc2, 0x8d,
-      0x1d, 0x6c, 0xd8, 0x9c, 0x57, 0x59, 0x94, 0x05,
-      0xd5, 0x37, 0x4b, 0x91, 0xaa, 0xeb, 0xc8, 0x79 },
-    { 0xfc, 0x4d, 0x9a, 0x37, 0xe5, 0xf7, 0x32, 0x72,
-      0xd0, 0xa9, 0xdf, 0xcc, 0xe9, 0x03, 0x12, 0xc7,
-      0x52, 0xe1, 0xb5, 0x2e, 0xb6, 0x54, 0xc4, 0x2c,
-      0x36, 0x94, 0x4b, 0x90, 0x2a, 0x30, 0x41, 0x07 },
-    { 0xfc, 0x56, 0xdb, 0xa1, 0xe7, 0xaf, 0xbd, 0xaa,
-      0x07, 0x33, 0xc6, 0x91, 0x1c, 0x5f, 0x1f, 0x18,
-      0x28, 0xcb, 0x12, 0x98, 0x31, 0x40, 0x1a, 0x3c,
-      0xfd, 0xea, 0xa7, 0x24, 0x62, 0x95, 0x35, 0x94 },
-    { 0xfc, 0x83, 0xc2, 0x89, 0x89, 0x5a, 0x92, 0x08,
-      0xc9, 0xb1, 0x7a, 0x16, 0xbc, 0xe5, 0xce, 0x80,
-      0xe8, 0xf4, 0xa0, 0x77, 0x21, 0x25, 0x29, 0xce,
-      0x0b, 0xc7, 0xf5, 0x42, 0xc6, 0xcb, 0xde, 0x1a },
-    { 0xfc, 0xa6, 0x23, 0x5d, 0x2a, 0xa4, 0xb1, 0xb2,
-      0x51, 0x50, 0x78, 0x57, 0xb4, 0xf0, 0x08, 0xdf,
-      0xd5, 0x27, 0x04, 0x2c, 0xe0, 0x45, 0x01, 0xaa,
-      0xe2, 0x9d, 0xd2, 0x05, 0xbb, 0xef, 0xce, 0x0d },
-    { 0xfc, 0xe7, 0x34, 0xe1, 0x2b, 0x8e, 0xfb, 0x43,
-      0x12, 0x71, 0xbf, 0xf6, 0x7a, 0x7a, 0x0a, 0x93,
-      0xb2, 0x19, 0xdd, 0x5e, 0x5d, 0xcc, 0x12, 0x58,
-      0x59, 0x4d, 0x96, 0xfc, 0xe1, 0x93, 0xb8, 0x60 },
-    { 0xfd, 0x9c, 0xfe, 0x14, 0xda, 0xd8, 0x97, 0x8c,
-      0x5b, 0xc8, 0x88, 0x93, 0x8f, 0x16, 0xf3, 0xb3,
-      0x98, 0xf7, 0x63, 0xa3, 0xad, 0xaf, 0xaa, 0x4a,
-      0xd9, 0x41, 0xb7, 0xe3, 0x87, 0xeb, 0x4f, 0x4a },
-    { 0xfd, 0xed, 0x92, 0xcb, 0x40, 0x91, 0x66, 0x82,
-      0x3a, 0x35, 0xe2, 0x17, 0xf3, 0x0b, 0x38, 0xc4,
-      0x86, 0xf8, 0x3e, 0xf2, 0xd4, 0xf2, 0x7b, 0x05,
-      0xf1, 0x8c, 0x74, 0x49, 0x81, 0x33, 0x9a, 0x1c },
-    { 0xfe, 0x26, 0xb2, 0xa6, 0x45, 0xa3, 0x1a, 0x91,
-      0x11, 0x00, 0x09, 0x9a, 0xa9, 0xa2, 0x93, 0x9f,
-      0x49, 0xe9, 0xfb, 0xea, 0x64, 0x48, 0x7b, 0xdf,
-      0x68, 0xa5, 0x23, 0x70, 0x32, 0x92, 0xd6, 0xa0 },
-    { 0xfe, 0x42, 0x1b, 0x24, 0x4e, 0x0e, 0x81, 0x6d,
-      0x9f, 0x26, 0xb3, 0x52, 0xc8, 0x31, 0xd9, 0x30,
-      0xe1, 0xc1, 0xc5, 0xd2, 0xfa, 0x4e, 0x0a, 0x1c,
-      0x77, 0x96, 0xa1, 0xf2, 0x02, 0x0e, 0xf1, 0x67 },
-    { 0xfe, 0x4f, 0x35, 0x6c, 0x7f, 0x9b, 0xfc, 0x17,
-      0xff, 0xcb, 0x68, 0xd0, 0x76, 0x4e, 0xcb, 0x2a,
-      0x87, 0xca, 0xa0, 0xae, 0x4c, 0xb5, 0x66, 0x62,
-      0x21, 0x04, 0xd3, 0x6f, 0xfb, 0x52, 0xcb, 0x29 },
-    { 0xff, 0x82, 0x6e, 0x2d, 0x0c, 0xb7, 0x71, 0x68,
-      0x68, 0x67, 0x5a, 0xe4, 0xb4, 0x31, 0xb6, 0x37,
-      0x1e, 0x9f, 0x0c, 0xdf, 0xcc, 0xb4, 0x9d, 0x43,
-      0xba, 0x30, 0x49, 0xbf, 0xdd, 0x2c, 0x41, 0xb1 },
-    { 0xff, 0xdc, 0x6b, 0x85, 0xfe, 0x7b, 0x10, 0x83,
-      0xb5, 0x41, 0x6f, 0x80, 0x6f, 0xc2, 0x44, 0xb9,
-      0xe4, 0xdf, 0x42, 0x99, 0xfb, 0xe3, 0xf6, 0x81,
-      0xaf, 0x3f, 0x5c, 0xf4, 0x22, 0x5a, 0x8e, 0xaf },
-};
-
-// SHA-256 hashes of leaf certificates issued by CNNIC's EV root.
-const uint8_t kCNNICEVWhitelist[][crypto::kSHA256Length] = {
-    { 0xb5, 0xef, 0x42, 0xc4, 0xbc, 0xed, 0xf1, 0x7b,
-      0xec, 0xc7, 0x5b, 0xf4, 0x63, 0x66, 0x49, 0xce,
-      0xbf, 0xf8, 0x71, 0x1b, 0xce, 0xff, 0xfa, 0x69,
-      0x5c, 0xc2, 0x52, 0xfa, 0x57, 0x4d, 0x42, 0x18 },
-    { 0xb6, 0x82, 0x3c, 0x9d, 0xbc, 0x8e, 0x8c, 0x05,
-      0x4b, 0xcf, 0x60, 0xf2, 0x38, 0x21, 0xac, 0x6c,
-      0x58, 0x19, 0x73, 0x51, 0xea, 0xcf, 0xa5, 0x57,
-      0x4c, 0xf0, 0x41, 0xb4, 0xce, 0x6b, 0x84, 0x04 },
-    { 0xdf, 0x69, 0xf9, 0x6a, 0x85, 0x67, 0x8f, 0x6c,
-      0xaf, 0x3f, 0xde, 0x25, 0xec, 0xfb, 0x5d, 0xf4,
-      0x74, 0x70, 0x87, 0xc2, 0xaf, 0x3b, 0x00, 0x65,
-      0xfb, 0x15, 0x10, 0x55, 0xcb, 0xcb, 0xa8, 0xc1 },
-    { 0xee, 0x0c, 0xf6, 0x2b, 0x9d, 0x8e, 0x42, 0xa2,
-      0x23, 0xb9, 0xa9, 0x60, 0xb5, 0xe9, 0x67, 0x0c,
-      0xcc, 0x34, 0x6d, 0x89, 0x93, 0x8f, 0xfa, 0x5d,
-      0xf7, 0x98, 0x65, 0xe4, 0x13, 0xd6, 0x31, 0x54 },
-};
-
-const PublicKeyWhitelist kBuiltinWhitelist[] = {
-    // C=CN, O=China Internet Network Information Center,
-    // CN=China Internet Network Information Center EV Certificates Root
-    // Expires: August 31 2030.
-    { { 0x9d, 0xd5, 0x5f, 0xc5, 0x73, 0xf5, 0x46, 0xcb,
-        0x6a, 0x38, 0x31, 0xd1, 0x11, 0x2d, 0x87, 0x10,
-        0xa6, 0xf4, 0xf8, 0x2d, 0xc8, 0x7f, 0x5f, 0xae,
-        0x9d, 0x3a, 0x1a, 0x02, 0x8d, 0xd3, 0x6e, 0x4b },
-      kCNNICEVWhitelist, arraysize(kCNNICEVWhitelist)
-    },
-    // C=CN, O=CNNIC, CN=CNNIC ROOT
-    // Expires: April 16 2027.
-    { { 0x1f, 0x42, 0x24, 0xce, 0xc8, 0x4f, 0xc9, 0x9c,
-        0xed, 0x88, 0x1f, 0xf6, 0xfc, 0xfd, 0x3e, 0x21,
-        0xf8, 0xc5, 0x19, 0xc5, 0x47, 0xaa, 0x6a, 0x5d,
-        0xd3, 0xde, 0x24, 0x73, 0x02, 0xce, 0x50, 0xd1 },
-      kCNNICDVWhitelist, arraysize(kCNNICDVWhitelist)
-    },
-};
 // clang-format on
-const size_t kBuiltinWhitelistSize = arraysize(kBuiltinWhitelist);
-
-const PublicKeyWhitelist* g_whitelist = kBuiltinWhitelist;
-size_t g_whitelist_size = kBuiltinWhitelistSize;
-
-// Comparator to compare a SHA256HashValue with a uint8_t array containing a
-// raw SHA-256 hash. Return value follows memcmp semantics.
-int CompareSHA256HashValueToRawHash(const void* key, const void* element) {
-  const SHA256HashValue* search_key =
-      reinterpret_cast<const SHA256HashValue*>(key);
-  return memcmp(search_key->data, element, sizeof(search_key->data));
-}
 
 // Comparator to compare a (SHA-256) HashValue with a uint8_t array containing
 // a raw SHA-256 hash. Return value follows memcmp semantics.
@@ -1671,36 +74,8 @@
          cert.valid_start() > last_wosign_cert)) {
       return true;
     }
-
-    // Check the public key whitelist.
-    for (size_t i = 0; i < g_whitelist_size; ++i) {
-      if (memcmp(hash.data(), g_whitelist[i].public_key,
-                 crypto::kSHA256Length) != 0) {
-        continue;
-      }
-      const SHA256HashValue leaf_hash =
-          X509Certificate::CalculateFingerprint256(cert.os_cert_handle());
-      void* result = bsearch(
-          &leaf_hash, g_whitelist[i].whitelist, g_whitelist[i].whitelist_size,
-          crypto::kSHA256Length, CompareSHA256HashValueToRawHash);
-      if (result == nullptr)
-        return true;  // Hash was not found on the public key whitelist.
-      break;
-    }
   }
   return false;
 }
 
-void SetCertificateWhitelistForTesting(const PublicKeyWhitelist* whitelist,
-                                       size_t whitelist_size) {
-  if (whitelist == nullptr || whitelist_size == 0) {
-    g_whitelist = kBuiltinWhitelist;
-    g_whitelist_size = kBuiltinWhitelistSize;
-    return;
-  }
-
-  g_whitelist = whitelist;
-  g_whitelist_size = whitelist_size;
-}
-
 }  // namespace net
diff --git a/net/cert/cert_verify_proc_whitelist.h b/net/cert/cert_verify_proc_whitelist.h
index f1582c9..6456320 100644
--- a/net/cert/cert_verify_proc_whitelist.h
+++ b/net/cert/cert_verify_proc_whitelist.h
@@ -16,15 +16,6 @@
 
 class X509Certificate;
 
-// PublicKeyWhitelist contains a SHA-256 SPKI hash and a pointer to an array
-// of SHA-256 certificate hashes that have been publicly disclosed and
-// whitelisted.
-struct PublicKeyWhitelist {
-  uint8_t public_key[crypto::kSHA256Length];
-  const uint8_t (*whitelist)[crypto::kSHA256Length];
-  size_t whitelist_size;
-};
-
 // Returns true if |cert| has been issued by a CA that is constrained from
 // issuing new certificates and |cert| is not within the whitelist of
 // existing certificates. Returns false if |cert| was issued by an
@@ -36,12 +27,6 @@
 IsNonWhitelistedCertificate(const X509Certificate& cert,
                             const HashValueVector& public_key_hashes);
 
-// Sets the certificate whitelist for testing. Supply nullptr/0 to reset to
-// the built-in whitelist.
-void NET_EXPORT_PRIVATE
-SetCertificateWhitelistForTesting(const PublicKeyWhitelist* whitelist,
-                                  size_t whitelist_size);
-
 }  // namespace net
 
 #endif  // NET_CERT_CERT_VERIFY_PROC_WHITELIST_H_
diff --git a/net/cert/cert_verify_proc_whitelist_unittest.cc b/net/cert/cert_verify_proc_whitelist_unittest.cc
index 7919573..2732035 100644
--- a/net/cert/cert_verify_proc_whitelist_unittest.cc
+++ b/net/cert/cert_verify_proc_whitelist_unittest.cc
@@ -14,176 +14,6 @@
 
 namespace {
 
-HashValue GetTestHashValue(uint8_t label, HashValueTag tag) {
-  HashValue hash_value(tag);
-  memset(hash_value.data(), label, hash_value.size());
-  return hash_value;
-}
-
-HashValueVector GetFakeHashValues() {
-  HashValueVector public_key_hashes;
-
-  // Fake "root" hash
-  public_key_hashes.push_back(GetTestHashValue(0x00, HASH_VALUE_SHA256));
-  public_key_hashes.push_back(GetTestHashValue(0x01, HASH_VALUE_SHA1));
-  // Fake "intermediate" hash
-  public_key_hashes.push_back(GetTestHashValue(0x02, HASH_VALUE_SHA256));
-  public_key_hashes.push_back(GetTestHashValue(0x03, HASH_VALUE_SHA1));
-  // Fake "leaf" hash
-  public_key_hashes.push_back(GetTestHashValue(0x04, HASH_VALUE_SHA256));
-  public_key_hashes.push_back(GetTestHashValue(0x05, HASH_VALUE_SHA1));
-
-  return public_key_hashes;
-}
-
-// The SHA-256 hash of the leaf cert "ok_cert.pem"; obtainable either
-// via X509Certificate::CalculateFingerprint256 or
-// openssl x509 -inform pem -in ok_cert.pem -outform der | openssl
-//   dgst -sha256 -c
-const uint8_t kWhitelistCerts[][crypto::kSHA256Length] = {
-    /* clang-format off */
-  { 0xf4, 0x42, 0xdd, 0x66, 0xfa, 0x10, 0x70, 0x65,
-    0xd1, 0x7e, 0xd9, 0xbb, 0x7c, 0xa9, 0x3c, 0x79,
-    0x63, 0xbe, 0x01, 0xa7, 0x54, 0x18, 0xab, 0x2f,
-    0xc3, 0x9a, 0x14, 0x53, 0xc3, 0x83, 0xa0, 0x5a },
-    /* clang-format on */
-};
-
-TEST(CertVerifyProcWhitelistTest, AcceptsWhitelistedEEByRoot) {
-  scoped_refptr<X509Certificate> cert =
-      ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
-  ASSERT_TRUE(cert);
-
-  // clang-format off
-  const PublicKeyWhitelist kWhitelist[] = {
-      { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-        kWhitelistCerts, arraysize(kWhitelistCerts)
-      },
-  };
-  // clang-format on
-
-  SetCertificateWhitelistForTesting(kWhitelist, arraysize(kWhitelist));
-
-  HashValueVector public_key_hashes = GetFakeHashValues();
-
-  // Should return false, indicating this cert is acceptable because of
-  // it being whitelisted.
-  EXPECT_FALSE(IsNonWhitelistedCertificate(*cert, public_key_hashes));
-
-  SetCertificateWhitelistForTesting(nullptr, 0);
-}
-
-TEST(CertVerifyProcWhitelistTest, AcceptsWhitelistedEEByIntermediate) {
-  scoped_refptr<X509Certificate> cert =
-      ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
-  ASSERT_TRUE(cert);
-
-  // clang-format off
-  const PublicKeyWhitelist kWhitelist[] = {
-      { { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
-          0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
-          0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
-          0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 },
-        kWhitelistCerts, arraysize(kWhitelistCerts)
-      },
-  };
-  // clang-format on
-
-  SetCertificateWhitelistForTesting(kWhitelist, arraysize(kWhitelist));
-
-  HashValueVector public_key_hashes = GetFakeHashValues();
-
-  // Should return false, indicating this cert is acceptable because of
-  // it being whitelisted.
-  EXPECT_FALSE(IsNonWhitelistedCertificate(*cert, public_key_hashes));
-
-  SetCertificateWhitelistForTesting(nullptr, 0);
-}
-
-TEST(CertVerifyProcWhitelistTest, RejectsNonWhitelistedEE) {
-  scoped_refptr<X509Certificate> cert =
-      ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem");
-  ASSERT_TRUE(cert);
-
-  // clang-format off
-  const PublicKeyWhitelist kWhitelist[] = {
-      { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-        kWhitelistCerts, arraysize(kWhitelistCerts)
-      },
-  };
-  // clang-format on
-
-  SetCertificateWhitelistForTesting(kWhitelist, arraysize(kWhitelist));
-
-  HashValueVector public_key_hashes = GetFakeHashValues();
-
-  // Should return true, indicating this certificate chains to a constrained
-  // root and is not whitelisted.
-  EXPECT_TRUE(IsNonWhitelistedCertificate(*cert, public_key_hashes));
-
-  SetCertificateWhitelistForTesting(nullptr, 0);
-}
-
-TEST(CertVerifyProcWhitelistTest, RejectsNonWhitelistedEEByIntermediate) {
-  scoped_refptr<X509Certificate> cert =
-      ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem");
-  ASSERT_TRUE(cert);
-
-  // clang-format off
-  const PublicKeyWhitelist kWhitelist[] = {
-      { { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
-          0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
-          0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
-          0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 },
-        kWhitelistCerts, arraysize(kWhitelistCerts)
-      },
-  };
-  // clang-format on
-
-  SetCertificateWhitelistForTesting(kWhitelist, arraysize(kWhitelist));
-
-  HashValueVector public_key_hashes = GetFakeHashValues();
-
-  // Should return true, indicating this certificate chains to a constrained
-  // root and is not whitelisted.
-  EXPECT_TRUE(IsNonWhitelistedCertificate(*cert, public_key_hashes));
-
-  SetCertificateWhitelistForTesting(nullptr, 0);
-}
-
-TEST(CertVerifyProcWhitelistTest, AcceptsUnconstrainedLeaf) {
-  scoped_refptr<X509Certificate> cert =
-      ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
-  ASSERT_TRUE(cert);
-
-  // clang-format off
-  const PublicKeyWhitelist kWhitelist[] = {
-      { { 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
-          0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
-          0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
-          0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 },
-        kWhitelistCerts, arraysize(kWhitelistCerts)
-      },
-  };
-  // clang-format on
-
-  SetCertificateWhitelistForTesting(kWhitelist, arraysize(kWhitelist));
-
-  HashValueVector public_key_hashes = GetFakeHashValues();
-
-  // Should return false, because the chain (as indicated by
-  // public_key_hashes) is not constrained.
-  EXPECT_FALSE(IsNonWhitelistedCertificate(*cert, public_key_hashes));
-
-  SetCertificateWhitelistForTesting(nullptr, 0);
-}
-
 TEST(CertVerifyProcWhitelistTest, HandlesWosignCerts) {
   scoped_refptr<X509Certificate> cert =
       ImportCertFromFile(GetTestCertsDirectory(), "wosign_before_oct_21.pem");
diff --git a/net/cert/cert_verify_proc_win.cc b/net/cert/cert_verify_proc_win.cc
index b17fc0c..a13117a7 100644
--- a/net/cert/cert_verify_proc_win.cc
+++ b/net/cert/cert_verify_proc_win.cc
@@ -8,16 +8,12 @@
 #include <string>
 #include <vector>
 
-#include "base/debug/crash_logging.h"
-#include "base/debug/dump_without_crashing.h"
 #include "base/memory/free_deleter.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/sha1.h"
-#include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_local.h"
-#include "base/time/time.h"
 #include "crypto/capi_util.h"
 #include "crypto/scoped_capi_types.h"
 #include "crypto/sha2.h"
@@ -899,47 +895,6 @@
   ~ScopedThreadLocalCRLSet() { g_revocation_injector.Get().SetCRLSet(nullptr); }
 };
 
-// Sends a crash dump (without actually crashing) when the system time
-// falls within the validity period of every certificate in
-// |verified_cert|'s chain. This is to investigate reports of odd
-// certificate errors that report ERR_CERT_DATE_INVALID when the
-// certificate chain's dates appear to be valid.
-//
-// TODO(estark): remove this after obtaining diagnostic data from
-// Canary. https://crbug.com/672906
-void MaybeDumpCertificateDateError(
-    const scoped_refptr<X509Certificate>& verified_cert,
-    DWORD error_status,
-    DWORD info_status) {
-  const base::Time now = base::Time::NowFromSystemTime();
-  // If the leaf certificate is expired or not yet valid, nothing is odd.
-  if (now >= verified_cert->valid_expiry() ||
-      now <= verified_cert->valid_start()) {
-    return;
-  }
-  // Repeat the check for the rest of the certificates in the chain; if
-  // any of them is expired or not yet valid, nothing is odd.
-  X509Certificate::OSCertHandles intermediates =
-      verified_cert->GetIntermediateCertificates();
-  for (const auto& intermediate : intermediates) {
-    base::Time valid_start =
-        base::Time::FromFileTime(intermediate->pCertInfo->NotBefore);
-    base::Time valid_expiry =
-        base::Time::FromFileTime(intermediate->pCertInfo->NotAfter);
-    if (now >= valid_expiry || now <= valid_start)
-      return;
-  }
-  // None of the certificates in the chain appear to be expired or
-  // not-yet-valid, so send a crash dump for diagnostics.
-  base::debug::ScopedCrashKey error_status_crash_key(
-      "cert_verify_proc_win_date_error_error_status",
-      base::IntToString(error_status));
-  base::debug::ScopedCrashKey info_status_crash_key(
-      "cert_verify_proc_win_date_error_info_status",
-      base::IntToString(info_status));
-  base::debug::DumpWithoutCrashing();
-}
-
 }  // namespace
 
 CertVerifyProcWin::CertVerifyProcWin() {}
@@ -1215,17 +1170,6 @@
   verify_result->cert_status |= MapCertChainErrorStatusToCertStatus(
       chain_context->TrustStatus.dwErrorStatus);
 
-  // Send some diagnostic data in the event of certificate date errors
-  // that occur on chains with validity periods that are valid according
-  // to the system clock.
-  // TODO(estark): remove this after obtaining diagnostic data from
-  // Canary. https://crbug.com/672906
-  if (verify_result->cert_status & CERT_STATUS_DATE_INVALID) {
-    MaybeDumpCertificateDateError(verify_result->verified_cert,
-                                  chain_context->TrustStatus.dwErrorStatus,
-                                  chain_context->TrustStatus.dwInfoStatus);
-  }
-
   // Flag certificates that have a Subject common name with a NULL character.
   if (CertSubjectCommonNameHasNull(cert_handle))
     verify_result->cert_status |= CERT_STATUS_INVALID;
diff --git a/net/data/ssl/blacklist/1c01c6f4dbb2fefc22558b2bca32563f49844acfc32b7be4b0ff599f9e8c7af7.pem b/net/data/ssl/blacklist/1c01c6f4dbb2fefc22558b2bca32563f49844acfc32b7be4b0ff599f9e8c7af7.pem
new file mode 100644
index 0000000..b5e4f9a
--- /dev/null
+++ b/net/data/ssl/blacklist/1c01c6f4dbb2fefc22558b2bca32563f49844acfc32b7be4b0ff599f9e8c7af7.pem
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIID9zCCAt+gAwIBAgIESJ8AATANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMC
+Q04xMjAwBgNVBAoMKUNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24g
+Q2VudGVyMUcwRQYDVQQDDD5DaGluYSBJbnRlcm5ldCBOZXR3b3JrIEluZm9ybWF0
+aW9uIENlbnRlciBFViBDZXJ0aWZpY2F0ZXMgUm9vdDAeFw0xMDA4MzEwNzExMjVa
+Fw0zMDA4MzEwNzExMjVaMIGKMQswCQYDVQQGEwJDTjEyMDAGA1UECgwpQ2hpbmEg
+SW50ZXJuZXQgTmV0d29yayBJbmZvcm1hdGlvbiBDZW50ZXIxRzBFBgNVBAMMPkNo
+aW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyIEVWIENlcnRp
+ZmljYXRlcyBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm35z
+7r07eKpkQ0H1UN+U8i6yjUqORlTSIRLIOTJCBumD1Z9S7eVnAztUwYyZmczpwA//
+DdmEEbK40ctb3B75aDFk4Zv6dOtouSCV98YPjUesWgbdYavi7NifFy2cyjw1l1Vx
+zUOFsUcW9SxTgHbP0wBkvUCZ3czY28Sf1hNfQYOL+Q2HklY0bBoQCxfVWhyXWIQ8
+hBouXJE0bhlffxdpxWXvayHG1VA6v2G5BY3vbzQ6sm8UY78WO5upKv23KzhmBsUs
+4qpnHkWnjQRmQvaPK++IIGmPMowUc9orhpFjIpryp9vOiYurXccUwVswah+xt54u
+gQEC7c+WXmPbqOY4twIDAQABo2MwYTAfBgNVHSMEGDAWgBR8cks5x8DbYqVPm6oY
+NJKiyoOCWTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4E
+FgQUfHJLOcfA22KlT5uqGDSSosqDglkwDQYJKoZIhvcNAQEFBQADggEBACrDx0M3
+j92tpLIM7twUbY8opJhJywyA6vPtI2Z1fcXTIWd50XPFtQO3WKwMVC/GVhMPMdoG
+52U7HW8228gd+f2ABsqjPWYWqJ1MFn3AlUa1UeTiH9fqBk1jjZaM7+czV0I664zB
+echNdn3e9rG3geCg+aF4RhcaVpjwTj2rHO3sOdwHSPdj/gauwqRcalsyiMXHM4Ws
+ZkJHwlgkmeHlPuV1LI5D1l08eB6olYIpUNHRFrrvwb562bTYzB5MRuF3sTGrvSrI
+zo9uoV1/A3U05K2JRVRevq4opbs/eHnrc7MKDf2+yfdWrPa37S+bISnHOLaVxATy
+wy39FCqQmbkHzJ8=
+-----END CERTIFICATE-----
diff --git a/net/data/ssl/blacklist/README.md b/net/data/ssl/blacklist/README.md
index 332bd47..937390a2 100644
--- a/net/data/ssl/blacklist/README.md
+++ b/net/data/ssl/blacklist/README.md
@@ -8,6 +8,17 @@
 
 ## Compromises & Misissuances
 
+### China Internet Network Information Center (CNNIC)
+
+For details, see <https://security.googleblog.com/2015/03/maintaining-digital-certificate-security.html>
+
+As a result of misissuance of a sub-CA certificate, CNNIC end-entity
+certificates were temporarily whitelisted, and then trust in the root fully
+removed.
+
+  * [1c01c6f4dbb2fefc22558b2bca32563f49844acfc32b7be4b0ff599f9e8c7af7.pem](1c01c6f4dbb2fefc22558b2bca32563f49844acfc32b7be4b0ff599f9e8c7af7.pem)
+  * [e28393773da845a679f2080cc7fb44a3b7a1c3792cb7eb7729fdcb6a8d99aea7.pem](e28393773da845a679f2080cc7fb44a3b7a1c3792cb7eb7729fdcb6a8d99aea7.pem)
+
 ### Comodo
 
 For details, see <https://www.comodo.com/Comodo-Fraud-Incident-2011-03-23.html>,
diff --git a/net/data/ssl/blacklist/e28393773da845a679f2080cc7fb44a3b7a1c3792cb7eb7729fdcb6a8d99aea7.pem b/net/data/ssl/blacklist/e28393773da845a679f2080cc7fb44a3b7a1c3792cb7eb7729fdcb6a8d99aea7.pem
new file mode 100644
index 0000000..c81744b
--- /dev/null
+++ b/net/data/ssl/blacklist/e28393773da845a679f2080cc7fb44a3b7a1c3792cb7eb7729fdcb6a8d99aea7.pem
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJD
+TjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2
+MDcwOTE0WhcNMjcwNDE2MDcwOTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMF
+Q05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzDo+/hn7E7SIX1mlwh
+IhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tizVHa6
+dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZO
+V/kbZKKTVrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrC
+GHn2emU1z5DrvTOTn1OrczvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gN
+v7Sg2Ca+I19zN38m5pIEo3/PIKe38zrKy5nLAgMBAAGjczBxMBEGCWCGSAGG+EIB
+AQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscCwQ7vptU7ETAPBgNVHRMB
+Af8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991SlgrHAsEO
+76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnK
+OOK5Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvH
+ugDnuL8BV8F3RTIMO/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7Hgvi
+yJA/qIYM/PmLXoXLT1tLYhFHxUV8BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fL
+buXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2G8kS1sHNzYDzAgE8yGnLRUhj
+2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5mmxE=
+-----END CERTIFICATE-----
diff --git a/net/data/ssl/certificates/README b/net/data/ssl/certificates/README
index 962978b..4645ec8 100644
--- a/net/data/ssl/certificates/README
+++ b/net/data/ssl/certificates/README
@@ -246,6 +246,14 @@
 - client_4.key
 - client_4.pk8
 - client_4_ca.pem
+- client_5.pem
+- client_5.key
+- client_5.pk8
+- client_5_ca.pem
+- client_6.pem
+- client_6.key
+- client_6.pk8
+- client_6_ca.pem
 - client_root_ca.pem
      This is a set of files used to unit test SSL client certificate
      authentication.
@@ -263,6 +271,10 @@
        Alternative Name fields recognized by Chrome OS.
      - client_4.pem is similar to client_2.pem but is a P-256 ECDSA key rather
        than RSA.
+     - client_5.pem is similar to client_2.pem but is a P-384 ECDSA key rather
+       than RSA.
+     - client_6.pem is similar to client_2.pem but is a P-521 ECDSA key rather
+       than RSA.
      - client_root_ca.pem is the CA certificate which signed client_*_ca.pem.
 
 ===== From net/data/ssl/scripts/generate-bad-eku-certs.sh
diff --git a/net/data/ssl/certificates/client_1.key b/net/data/ssl/certificates/client_1.key
index ea61cc8..0389e2208 100644
--- a/net/data/ssl/certificates/client_1.key
+++ b/net/data/ssl/certificates/client_1.key
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-MIIEpAIBAAKCAQEAm6YXgn7EzskCJawNsyffHz5P/wgyL9LkkYDzyFXqSGl2Rs66
-YlPkfBQVHAJXXcRMZL6GJ0qi32cpWgEsbXSk1zAiySVDayNej+jXNsQRoa9HE1lG
-6SvH5ojlGhiRV9r9c2a55L6HePnG3B9BTU1nPT01fGqnYpaUxVDxqwMHeG1xdfvx
-SEvrDsKWjYOSxVgbXGGDTwhMhA1rF1X+e9yimag0UxsB1IhNxd5YCJVRyaVTnxM+
-KmUe0OUYAXuKMGFGeT0W99M7YA3v6o2ZbPy3LZ07lwuP8w6egk5pjDo8v81FCUZn
-Vhv/xHVr/1JH98X+heE6eCq4yC+NXrdLiLGzywIDAQABAoIBACa5VuYHhg1wYxFe
-UfY9uDw8s4he0KWnUWiF7aDtByHG4z9QlXx7JMBd+raCOpxAh0UVRakm34i3UMls
-u1HsEErdVfo3RCO2pAMnyct9UmmogwVkU8kVNGG9s0ofzKFQAXihmSQ45tmJQxlm
-yUdjN4k73j+7BTP5BMBmmAmU8lnadWGIX97WG6hbB5mjfzIGlZM11kUlaIFnm9/f
-UbrazpB6CdTeS5eML4ikLYfSoM/5r6r1gT01B8q16ZDEW5/mSmAgTPvyEY4XdKpZ
-te2KOJFs9EfPn1VgSpN5ebnwRVnXKEYM6VRi2Ssn5YwQs8zS1+Fd95VBANVwS+yj
-rehgaqECgYEAzK6Ru/iCJj4ecSXiuIN15H9mAcAG6WQmuPCLUc0eyvUZ0Mj57yjg
-irJjflScLcotR/YdBUfUX+//XDBiQ9lVWCmFtHwWoynMBC4p+mBcVbId1LEk/kn4
-Oyx2Zkp7ccIpOe5JU8788GSroZzvQs9Ic2AI3hz/vC+igokNQJiUd5ECgYEAwqxZ
-x2tLz1vNLDlfXhaFkhpttJoUV+rQteV9SsEqcAOBLgBqk49hwFTInQELpEtrzfo9
-3IW1C7C/e378OOlw+fBnBtmkTDfPy9XJd6b+VQWHsk/t1g2D2qYO0htrfwNpIe5V
-Ns15MGiMV7kA8KELx+gAokSUws90StTqtJFG35sCgYEAxMSRr23w2IjhRQ8RzSX8
-AQWEb+xF+LriCuqcVLBniN9lyPRcadEXQ97IjRsT5WU2cLamIXxzKyOSjvKolOdr
-B00rj123eXXl/qLOkjdurKeFzAHcOWWs8F4HGMFDuRHaBioQbjRPr15oLP6seMLC
-uL+65qRkKWp1xR2yEsZb/DECgYAbwLRf4KUDH8RFPLyizjUmmgvvxlOGIRy2Acx1
-3sntBCLjav3GoZc+8xdSgralKndo+vbcvFcOHpl9wqG0f1sy1pnpeReaIg7GsWiy
-XSU++7XXrttqO60De877FxuhFNxlEPQnBu3y/8SaMO64X00tp56Hg51tlGOw01/O
-dDOVZwKBgQCKvxUHZPD6Q+M5HI/HmFxsHj9SsSl2sACErQMk7ru/aimuz9YPBXks
-KeMzjIeRqtJadK9KQCBeGWmOFTLezgt+mceXn92nfNYMfdSkLzlyKZM2FW9Kk1Z/
-7YduboDUCiGg2PMn/qZPUiko3vkR6B3es/G+VC16mCrh9GksfsGHVg==
+MIIEpQIBAAKCAQEAyYDjdJs5t0m2REDwka5GhFCGi8cPzDTgEKaqZj3wzRX/T8m/
+/jIRTK1ZfHxuzT61GnGOiut8XSw28a7/WY0/1/cc3nTGm0PuvKmBjrilQCZ9Y8kb
+LC+lEQaD1y/TMErQN9W5/dE/bU91Cg0zIXJgX9a0pGyWeM7C87q9DRky/WwbN6eS
+89fAsRNPILn7fDiSB8X3d27fv/mfWgw9pz0lew3hY4nppOulvBdaRKgxJKX8KTBS
+cy3osDwkB+urQLamGsP/7igjIGy5yKOw8nXsnf1Gq+GDhS0E4Ca6seNEAOiXaAGC
+W7wfNyBP+aVHj0CNvDPN147I/PfGKG1ZSvdipwIDAQABAoIBAQCXSQF8pp4qklkZ
+3XfAqIuhA6RAhW/C7V/coIUGxjJoh79r9BkFjCmY2/13jSTTS+VEuUU/35U7jtqh
+kbV9UqNATfOKwTnrkJFJbCotMUxAYaV6qZ6RCiRwJ+gMQ4fXlhPGF9zQR63LMAC7
+TzW4QttAmT5+xFgk03di7izKDMVPpedFlbpBPClBvf5nFiQAGY8jIhyyT0rKuoTN
+iowciprIKeDg32vFCJAiIWgV687tTByjknpxYkH7H00kWctXklTKV44hSB07ayC7
+dMkskH+X2LHxxFj/YP6goYjlN3c+cW7SDnwoRyZUNuhU7N8Xo62Rp94axhvKekJ0
+t58nLwehAoGBAP/CXyZmyPWOfcrxO7OgpM/MQuGqF7etS57t6EphLhyTQOWCGK5Z
+OS8Zun9/JOKxLPpjxQJpETfSBg1Q7KFRpzpnkd7db2GFP1+gz3bbeO3hsR6pfcQs
+DxlUx/GHvX+i7c3wHfVgoBYG+cUugt44CzjYulLF/O5OZORGhujtxog1AoGBAMmx
+cXb7naEgwa1dkRP7+OfbEN+gyJKN0D0bn/TRhaRaAoFUTGRqnvpbGMTsU5o9eOnh
+pNhwBX1U/t/7nd9TcgCEqPBCKGAGOou29hq9rZ6whEvAF/rZXdzigaMGJF7MRq3l
+XtNPC4+B9BJmoVxEu/l6dAI0HYwYaNFdEk9SZjLrAoGBANRABp7j5hqDKjnlgNpN
+kvkwVsDYW95+3qcCYSh5Bb+JJO5SzRDD0wUXoQJ2DbJjvyP88F5Tu4pLreIXKomm
+LdX2ZcRCmFCiODmwRvwon28rQcZkeo720YEALv5u3AC0wg2KHBKrIa+mElplgw3Q
+DOAcXGSdEo7iWDBpp0RfL8eRAoGAI5kU7KomPR0Z8e5Uv9E2Mj3g8YdgPzWWbmKk
+zcH5M3PLg2YMgaCr5IYVjhQkAVIeODFiNe03mtJYldHEIHmK4nqHkrgqhiAzTxuA
+vmGB9kMzZmdGFDkvLuAvf0WDP9QQGXslTGhkIvUNzf2dNzrObo7lUMo/+M0KGwGx
+TJy/evcCgYEA2rvXrdrpTMq9RwmjZejX5FjKvCTME1n5RE/I7kOgr3J4FShhDRyU
+1wlVvQe7C6W59MVGF+9OAhth/lPDagv3WsBK0r6luabm3QwakAZLQqjpbD7Anw+Q
+0+KEtl2M7PI8gwY8lrdFSEC2tJYp8iu/ahniyVxZjf5mEic6BnqIx/4=
 -----END RSA PRIVATE KEY-----
diff --git a/net/data/ssl/certificates/client_1.pem b/net/data/ssl/certificates/client_1.pem
index 33573d3..9e52061 100644
--- a/net/data/ssl/certificates/client_1.pem
+++ b/net/data/ssl/certificates/client_1.pem
@@ -5,31 +5,31 @@
     Signature Algorithm: sha256WithRSAEncryption
         Issuer: CN=B CA
         Validity
-            Not Before: Oct  4 18:53:24 2016 GMT
-            Not After : Oct  2 18:53:24 2026 GMT
+            Not Before: Dec  9 20:18:57 2016 GMT
+            Not After : Dec  7 20:18:57 2026 GMT
         Subject: CN=Client Cert A
         Subject Public Key Info:
             Public Key Algorithm: rsaEncryption
                 Public-Key: (2048 bit)
                 Modulus:
-                    00:9b:a6:17:82:7e:c4:ce:c9:02:25:ac:0d:b3:27:
-                    df:1f:3e:4f:ff:08:32:2f:d2:e4:91:80:f3:c8:55:
-                    ea:48:69:76:46:ce:ba:62:53:e4:7c:14:15:1c:02:
-                    57:5d:c4:4c:64:be:86:27:4a:a2:df:67:29:5a:01:
-                    2c:6d:74:a4:d7:30:22:c9:25:43:6b:23:5e:8f:e8:
-                    d7:36:c4:11:a1:af:47:13:59:46:e9:2b:c7:e6:88:
-                    e5:1a:18:91:57:da:fd:73:66:b9:e4:be:87:78:f9:
-                    c6:dc:1f:41:4d:4d:67:3d:3d:35:7c:6a:a7:62:96:
-                    94:c5:50:f1:ab:03:07:78:6d:71:75:fb:f1:48:4b:
-                    eb:0e:c2:96:8d:83:92:c5:58:1b:5c:61:83:4f:08:
-                    4c:84:0d:6b:17:55:fe:7b:dc:a2:99:a8:34:53:1b:
-                    01:d4:88:4d:c5:de:58:08:95:51:c9:a5:53:9f:13:
-                    3e:2a:65:1e:d0:e5:18:01:7b:8a:30:61:46:79:3d:
-                    16:f7:d3:3b:60:0d:ef:ea:8d:99:6c:fc:b7:2d:9d:
-                    3b:97:0b:8f:f3:0e:9e:82:4e:69:8c:3a:3c:bf:cd:
-                    45:09:46:67:56:1b:ff:c4:75:6b:ff:52:47:f7:c5:
-                    fe:85:e1:3a:78:2a:b8:c8:2f:8d:5e:b7:4b:88:b1:
-                    b3:cb
+                    00:c9:80:e3:74:9b:39:b7:49:b6:44:40:f0:91:ae:
+                    46:84:50:86:8b:c7:0f:cc:34:e0:10:a6:aa:66:3d:
+                    f0:cd:15:ff:4f:c9:bf:fe:32:11:4c:ad:59:7c:7c:
+                    6e:cd:3e:b5:1a:71:8e:8a:eb:7c:5d:2c:36:f1:ae:
+                    ff:59:8d:3f:d7:f7:1c:de:74:c6:9b:43:ee:bc:a9:
+                    81:8e:b8:a5:40:26:7d:63:c9:1b:2c:2f:a5:11:06:
+                    83:d7:2f:d3:30:4a:d0:37:d5:b9:fd:d1:3f:6d:4f:
+                    75:0a:0d:33:21:72:60:5f:d6:b4:a4:6c:96:78:ce:
+                    c2:f3:ba:bd:0d:19:32:fd:6c:1b:37:a7:92:f3:d7:
+                    c0:b1:13:4f:20:b9:fb:7c:38:92:07:c5:f7:77:6e:
+                    df:bf:f9:9f:5a:0c:3d:a7:3d:25:7b:0d:e1:63:89:
+                    e9:a4:eb:a5:bc:17:5a:44:a8:31:24:a5:fc:29:30:
+                    52:73:2d:e8:b0:3c:24:07:eb:ab:40:b6:a6:1a:c3:
+                    ff:ee:28:23:20:6c:b9:c8:a3:b0:f2:75:ec:9d:fd:
+                    46:ab:e1:83:85:2d:04:e0:26:ba:b1:e3:44:00:e8:
+                    97:68:01:82:5b:bc:1f:37:20:4f:f9:a5:47:8f:40:
+                    8d:bc:33:cd:d7:8e:c8:fc:f7:c6:28:6d:59:4a:f7:
+                    62:a7
                 Exponent: 65537 (0x10001)
         X509v3 extensions:
             X509v3 Basic Constraints: critical
@@ -37,36 +37,36 @@
             X509v3 Extended Key Usage: 
                 TLS Web Server Authentication, TLS Web Client Authentication
     Signature Algorithm: sha256WithRSAEncryption
-         19:9b:41:39:61:cf:f8:0f:62:98:43:1a:a4:fb:0b:71:f2:f0:
-         c4:b5:39:bb:dc:d1:d7:33:44:89:66:13:ff:0a:5a:66:02:74:
-         6a:8d:8a:dc:a0:e0:d0:cc:8d:5f:1c:c0:34:c6:58:02:76:3b:
-         b5:1a:81:a5:a7:a1:c5:81:14:52:0f:21:37:06:2d:dc:dc:9c:
-         d0:d1:98:03:ac:d3:b5:12:0b:f8:b4:84:d8:bc:be:4d:27:fa:
-         df:16:6e:dd:0a:33:b7:87:50:7e:fe:c6:8d:84:b2:2d:7f:58:
-         88:21:af:09:64:5e:4a:2d:f0:56:d4:3e:a3:dc:4c:aa:92:41:
-         04:c1:6e:56:46:d5:36:69:0d:2a:f6:f0:29:d3:7c:ac:b7:cf:
-         7f:18:bc:76:fa:8c:5a:76:81:67:db:b2:91:97:05:7d:14:da:
-         26:d5:67:fe:c5:d2:6a:2c:5f:f4:96:3a:e4:0e:f5:15:95:05:
-         57:de:b5:e5:96:b2:10:99:4a:b2:3a:ac:d2:ae:64:30:31:54:
-         f0:b9:9f:1d:56:e8:da:e9:4e:42:e3:26:3d:f7:8c:3e:9c:dd:
-         42:77:9d:0c:67:52:73:94:c4:73:42:c2:b7:96:a4:44:4a:d5:
-         e9:3d:b1:46:aa:38:0b:1f:7f:ae:01:c6:07:da:40:3b:c0:22:
-         61:c4:cb:80
+         1f:ef:f9:19:b9:64:e7:15:e2:7f:4f:e0:9e:66:f0:2a:b8:8f:
+         4e:63:0c:7c:d5:a0:37:68:d2:c8:c2:9a:7b:e1:bd:13:31:c8:
+         ca:ce:96:c0:13:0a:bd:5e:f2:3c:8a:4d:0a:82:61:7e:35:0b:
+         fc:07:83:82:6e:cc:97:18:ff:32:68:08:5b:1a:34:35:ca:f0:
+         d2:19:d0:f0:35:66:c8:0b:44:ac:94:75:28:d8:cc:c1:b7:32:
+         df:93:cb:94:48:43:c7:cc:06:d3:b8:6c:6a:b2:c0:9f:f7:ef:
+         dd:36:c0:81:f9:e8:f0:7f:1c:d9:c5:92:31:91:de:88:a6:8d:
+         0c:9e:e5:bf:a9:91:69:09:24:b1:5b:70:45:10:e1:8c:38:99:
+         c3:06:95:da:6a:c5:02:20:f8:25:e2:0c:b2:76:e5:01:1c:4b:
+         0b:77:5a:ec:ff:99:37:fc:38:ff:17:cb:42:1d:c2:2f:2f:1f:
+         d1:be:d5:c6:22:89:e9:73:9c:ff:a9:03:77:cb:28:e5:e8:7e:
+         0d:80:d4:75:88:ab:79:0b:bc:e3:98:1f:6e:0b:44:e2:c4:8a:
+         e6:6c:1d:74:30:6a:84:a7:2d:84:96:c4:7c:a9:25:39:8e:c8:
+         50:df:0f:41:3f:4b:cb:92:c9:92:ed:2a:73:f1:7d:c3:cf:60:
+         a7:af:ab:85
 -----BEGIN CERTIFICATE-----
 MIIC0jCCAbqgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwEQiBD
-QTAeFw0xNjEwMDQxODUzMjRaFw0yNjEwMDIxODUzMjRaMBgxFjAUBgNVBAMMDUNs
-aWVudCBDZXJ0IEEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCbpheC
-fsTOyQIlrA2zJ98fPk//CDIv0uSRgPPIVepIaXZGzrpiU+R8FBUcAlddxExkvoYn
-SqLfZylaASxtdKTXMCLJJUNrI16P6Nc2xBGhr0cTWUbpK8fmiOUaGJFX2v1zZrnk
-vod4+cbcH0FNTWc9PTV8aqdilpTFUPGrAwd4bXF1+/FIS+sOwpaNg5LFWBtcYYNP
-CEyEDWsXVf573KKZqDRTGwHUiE3F3lgIlVHJpVOfEz4qZR7Q5RgBe4owYUZ5PRb3
-0ztgDe/qjZls/LctnTuXC4/zDp6CTmmMOjy/zUUJRmdWG//EdWv/Ukf3xf6F4Tp4
-KrjIL41et0uIsbPLAgMBAAGjLzAtMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYI
-KwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQAZm0E5Yc/4D2KY
-Qxqk+wtx8vDEtTm73NHXM0SJZhP/ClpmAnRqjYrcoODQzI1fHMA0xlgCdju1GoGl
-p6HFgRRSDyE3Bi3c3JzQ0ZgDrNO1Egv4tITYvL5NJ/rfFm7dCjO3h1B+/saNhLIt
-f1iIIa8JZF5KLfBW1D6j3EyqkkEEwW5WRtU2aQ0q9vAp03yst89/GLx2+oxadoFn
-27KRlwV9FNom1Wf+xdJqLF/0ljrkDvUVlQVX3rXllrIQmUqyOqzSrmQwMVTwuZ8d
-Vuja6U5C4yY994w+nN1Cd50MZ1JzlMRzQsK3lqREStXpPbFGqjgLH3+uAcYH2kA7
-wCJhxMuA
+QTAeFw0xNjEyMDkyMDE4NTdaFw0yNjEyMDcyMDE4NTdaMBgxFjAUBgNVBAMMDUNs
+aWVudCBDZXJ0IEEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJgON0
+mzm3SbZEQPCRrkaEUIaLxw/MNOAQpqpmPfDNFf9Pyb/+MhFMrVl8fG7NPrUacY6K
+63xdLDbxrv9ZjT/X9xzedMabQ+68qYGOuKVAJn1jyRssL6URBoPXL9MwStA31bn9
+0T9tT3UKDTMhcmBf1rSkbJZ4zsLzur0NGTL9bBs3p5Lz18CxE08guft8OJIHxfd3
+bt+/+Z9aDD2nPSV7DeFjiemk66W8F1pEqDEkpfwpMFJzLeiwPCQH66tAtqYaw//u
+KCMgbLnIo7Dydeyd/Uar4YOFLQTgJrqx40QA6JdoAYJbvB83IE/5pUePQI28M83X
+jsj898YobVlK92KnAgMBAAGjLzAtMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYI
+KwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQAf7/kZuWTnFeJ/
+T+CeZvAquI9OYwx81aA3aNLIwpp74b0TMcjKzpbAEwq9XvI8ik0KgmF+NQv8B4OC
+bsyXGP8yaAhbGjQ1yvDSGdDwNWbIC0SslHUo2MzBtzLfk8uUSEPHzAbTuGxqssCf
+9+/dNsCB+ejwfxzZxZIxkd6Ipo0MnuW/qZFpCSSxW3BFEOGMOJnDBpXaasUCIPgl
+4gyyduUBHEsLd1rs/5k3/Dj/F8tCHcIvLx/RvtXGIonpc5z/qQN3yyjl6H4NgNR1
+iKt5C7zjmB9uC0TixIrmbB10MGqEpy2ElsR8qSU5jshQ3w9BP0vLksmS7Spz8X3D
+z2Cnr6uF
 -----END CERTIFICATE-----
diff --git a/net/data/ssl/certificates/client_1.pk8 b/net/data/ssl/certificates/client_1.pk8
index 19db6db3..12bf489c 100644
--- a/net/data/ssl/certificates/client_1.pk8
+++ b/net/data/ssl/certificates/client_1.pk8
Binary files differ
diff --git a/net/data/ssl/certificates/client_1_ca.pem b/net/data/ssl/certificates/client_1_ca.pem
index 88723ce6..9d61c0a 100644
--- a/net/data/ssl/certificates/client_1_ca.pem
+++ b/net/data/ssl/certificates/client_1_ca.pem
@@ -5,31 +5,31 @@
     Signature Algorithm: sha256WithRSAEncryption
         Issuer: CN=C Root CA
         Validity
-            Not Before: Oct  4 18:53:24 2016 GMT
-            Not After : Oct  2 18:53:24 2026 GMT
+            Not Before: Dec  9 20:18:57 2016 GMT
+            Not After : Dec  7 20:18:57 2026 GMT
         Subject: CN=B CA
         Subject Public Key Info:
             Public Key Algorithm: rsaEncryption
                 Public-Key: (2048 bit)
                 Modulus:
-                    00:a5:56:c7:9d:32:e7:3d:17:ac:59:ca:f4:07:65:
-                    25:3e:65:7c:d9:3d:f4:0e:73:eb:b9:0b:a1:7b:4b:
-                    69:ab:ee:a3:50:49:2f:25:33:4d:2d:ac:00:32:17:
-                    34:0d:c9:bf:83:7d:b4:e5:d5:82:89:6f:ad:41:78:
-                    56:1d:05:bc:48:cc:0c:43:95:81:e3:e8:12:2d:67:
-                    74:68:12:61:8e:03:24:88:2c:57:28:8e:3d:10:77:
-                    da:dc:78:b6:b4:72:92:56:0e:4a:0c:c6:f7:0a:44:
-                    f5:56:5d:72:7a:a8:1d:bc:16:e8:95:25:4d:50:b6:
-                    2e:22:05:fd:d5:20:47:a4:32:37:52:38:61:90:9a:
-                    aa:40:a8:db:91:80:00:89:e6:2c:17:5d:7c:5f:6f:
-                    2d:b2:b7:cf:71:a1:55:11:d8:fd:3b:9b:61:8f:1c:
-                    80:dd:da:90:8c:82:04:63:36:7c:b1:28:38:56:bc:
-                    6e:c0:b3:b9:4e:96:2b:3f:62:2a:e5:5f:f1:73:3c:
-                    53:a8:5f:03:d0:63:31:36:ac:00:61:30:ab:ad:d9:
-                    aa:ab:5d:22:83:28:cc:f1:f7:88:f5:9a:be:57:c5:
-                    e1:46:da:a3:88:55:a7:3c:f9:1c:17:bb:72:01:1d:
-                    dd:8e:a0:b0:a3:d1:91:74:ae:94:58:c0:f5:30:63:
-                    5c:91
+                    00:b3:87:98:77:4f:45:bb:de:87:86:1f:8b:1e:b2:
+                    26:cb:56:a3:d3:10:85:5e:95:ed:aa:c3:87:17:f4:
+                    40:86:bf:d7:e0:4a:ea:43:95:ce:b9:22:2a:c4:90:
+                    f0:24:34:81:f2:5b:58:47:d3:d8:9b:eb:fc:90:4b:
+                    54:41:6d:6a:c0:5d:82:56:49:47:c4:ab:29:48:a4:
+                    23:05:fa:4f:a3:9e:83:65:5a:fd:57:c2:5a:4c:13:
+                    bf:eb:75:ff:4d:f9:c1:5b:65:32:7d:bb:0d:e3:20:
+                    6a:4c:b3:28:fc:01:11:68:c0:9c:4b:f6:a5:df:68:
+                    0e:b2:c1:6f:b3:69:5f:53:35:2c:b9:3b:f8:c2:48:
+                    3b:3f:8f:d1:9f:76:b1:3a:1a:22:7f:fd:28:e6:6e:
+                    1c:96:95:c3:37:6f:c4:5a:24:28:25:5b:f6:a0:85:
+                    f0:47:33:fa:9d:3b:38:cf:b1:d1:c9:06:d8:25:03:
+                    bc:00:50:fe:08:dc:0d:d8:b1:87:94:8e:dc:74:ac:
+                    2c:53:44:91:4c:67:0a:71:5e:d3:df:c6:58:ee:00:
+                    fe:96:fd:2f:96:f8:9f:35:5a:4e:be:ca:c1:5a:55:
+                    f8:4d:85:77:3d:a9:d6:aa:75:0f:b9:82:07:c4:89:
+                    9e:9a:e6:39:f8:39:d2:be:62:cd:ca:43:a2:55:bf:
+                    0b:81
                 Exponent: 65537 (0x10001)
         X509v3 extensions:
             X509v3 Basic Constraints: critical
@@ -37,35 +37,35 @@
             X509v3 Key Usage: critical
                 Certificate Sign, CRL Sign
     Signature Algorithm: sha256WithRSAEncryption
-         41:1f:59:af:b3:83:87:87:bc:b3:2d:62:66:35:76:21:f2:bb:
-         e5:d4:87:23:a3:ab:4f:2b:ef:d0:ee:53:6f:17:b0:d4:6a:93:
-         8e:74:71:7b:c5:36:f4:7b:87:3a:ab:84:b0:40:c5:3b:a0:e7:
-         a1:18:e6:3f:8d:8d:a8:49:b5:da:c7:4b:26:e4:ea:b9:2d:85:
-         b2:1d:01:70:bb:78:08:a6:c7:11:6b:0a:6f:5d:b0:d7:b5:72:
-         ec:51:46:26:bc:7e:e1:bd:1e:5e:d6:44:cf:d0:1b:55:ef:a9:
-         5e:16:73:05:59:9f:ff:00:2e:5b:4e:29:7b:c4:2e:5c:46:9c:
-         56:0a:78:d9:0b:10:83:9e:ff:8a:e3:57:ec:f1:d1:a3:85:26:
-         2f:97:e6:d0:6f:5e:c8:cb:53:e7:28:64:ab:27:14:f4:b2:4b:
-         52:80:e2:d1:ef:50:ba:db:34:5c:95:a4:3f:ac:5b:eb:15:c5:
-         d6:cb:4b:76:fb:f6:cd:2f:d9:ef:d4:cb:1c:85:52:8b:f2:2b:
-         1b:ce:e3:0f:ed:07:44:11:8b:d8:b8:5c:41:ab:e1:36:0d:7e:
-         3f:86:ff:0c:0f:f5:5e:ff:f6:b8:0a:ac:f0:3b:5d:c5:b7:ef:
-         f1:80:7c:26:b9:a2:ee:17:a8:e7:cb:c4:f4:5c:51:ff:57:53:
-         ee:a2:d3:66
+         99:1e:ab:d0:ab:f7:27:85:ed:91:bc:b0:3e:af:57:a8:31:1d:
+         8e:e8:4b:bc:3e:b4:82:c9:6c:62:3a:8d:48:be:a1:0a:42:27:
+         11:18:ef:47:53:b2:46:5f:d0:de:31:4e:c3:de:e8:c5:f6:24:
+         09:69:25:c9:e6:f8:1e:1a:b1:27:63:ff:07:8b:7b:e9:80:b5:
+         68:d4:94:54:b6:fe:c6:a6:3b:61:01:f9:89:a2:50:f2:9b:a0:
+         02:2a:85:bd:13:5a:43:45:a7:b7:7c:eb:1a:69:95:04:dc:c0:
+         17:13:da:c8:73:fd:0b:94:a2:fe:af:e7:18:b4:b1:90:21:99:
+         ad:f8:06:9a:6d:c1:e1:3b:f4:85:69:91:6d:68:84:9f:e9:09:
+         30:08:f6:11:87:99:67:8f:16:cc:59:43:38:95:5e:fa:9d:c5:
+         4a:2d:55:f2:3d:1a:49:5c:12:66:ea:40:2d:a1:de:08:40:a4:
+         b3:dc:19:8a:23:04:a6:cf:a6:9b:2e:d0:2a:3c:5f:fa:4c:bb:
+         5a:62:d0:0b:a4:f6:8c:06:42:54:b4:c6:63:e0:f1:f0:11:a8:
+         ec:57:3d:93:6c:0c:67:a5:5a:8a:52:c5:37:b6:c3:7e:54:05:
+         b0:82:d9:32:8a:a7:12:83:39:d9:bc:81:ce:db:e9:ad:e9:b7:
+         5d:1d:6d:3a
 -----BEGIN CERTIFICATE-----
 MIICwjCCAaqgAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwFDESMBAGA1UEAwwJQyBS
-b290IENBMB4XDTE2MTAwNDE4NTMyNFoXDTI2MTAwMjE4NTMyNFowDzENMAsGA1UE
-AwwEQiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKVWx50y5z0X
-rFnK9AdlJT5lfNk99A5z67kLoXtLaavuo1BJLyUzTS2sADIXNA3Jv4N9tOXVgolv
-rUF4Vh0FvEjMDEOVgePoEi1ndGgSYY4DJIgsVyiOPRB32tx4trRyklYOSgzG9wpE
-9VZdcnqoHbwW6JUlTVC2LiIF/dUgR6QyN1I4YZCaqkCo25GAAInmLBddfF9vLbK3
-z3GhVRHY/TubYY8cgN3akIyCBGM2fLEoOFa8bsCzuU6WKz9iKuVf8XM8U6hfA9Bj
-MTasAGEwq63ZqqtdIoMozPH3iPWavlfF4Ubao4hVpzz5HBe7cgEd3Y6gsKPRkXSu
-lFjA9TBjXJECAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
-AQYwDQYJKoZIhvcNAQELBQADggEBAEEfWa+zg4eHvLMtYmY1diHyu+XUhyOjq08r
-79DuU28XsNRqk450cXvFNvR7hzqrhLBAxTug56EY5j+NjahJtdrHSybk6rkthbId
-AXC7eAimxxFrCm9dsNe1cuxRRia8fuG9Hl7WRM/QG1XvqV4WcwVZn/8ALltOKXvE
-LlxGnFYKeNkLEIOe/4rjV+zx0aOFJi+X5tBvXsjLU+coZKsnFPSyS1KA4tHvULrb
-NFyVpD+sW+sVxdbLS3b79s0v2e/UyxyFUovyKxvO4w/tB0QRi9i4XEGr4TYNfj+G
-/wwP9V7/9rgKrPA7XcW37/GAfCa5ou4XqOfLxPRcUf9XU+6i02Y=
+b290IENBMB4XDTE2MTIwOTIwMTg1N1oXDTI2MTIwNzIwMTg1N1owDzENMAsGA1UE
+AwwEQiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALOHmHdPRbve
+h4Yfix6yJstWo9MQhV6V7arDhxf0QIa/1+BK6kOVzrkiKsSQ8CQ0gfJbWEfT2Jvr
+/JBLVEFtasBdglZJR8SrKUikIwX6T6Oeg2Va/VfCWkwTv+t1/035wVtlMn27DeMg
+akyzKPwBEWjAnEv2pd9oDrLBb7NpX1M1LLk7+MJIOz+P0Z92sToaIn/9KOZuHJaV
+wzdvxFokKCVb9qCF8Ecz+p07OM+x0ckG2CUDvABQ/gjcDdixh5SO3HSsLFNEkUxn
+CnFe09/GWO4A/pb9L5b4nzVaTr7KwVpV+E2Fdz2p1qp1D7mCB8SJnprmOfg50r5i
+zcpDolW/C4ECAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQELBQADggEBAJkeq9Cr9yeF7ZG8sD6vV6gxHY7oS7w+tILJ
+bGI6jUi+oQpCJxEY70dTskZf0N4xTsPe6MX2JAlpJcnm+B4asSdj/weLe+mAtWjU
+lFS2/samO2EB+YmiUPKboAIqhb0TWkNFp7d86xpplQTcwBcT2shz/QuUov6v5xi0
+sZAhma34BpptweE79IVpkW1ohJ/pCTAI9hGHmWePFsxZQziVXvqdxUotVfI9Gklc
+EmbqQC2h3ghApLPcGYojBKbPppsu0Co8X/pMu1pi0Auk9owGQlS0xmPg8fARqOxX
+PZNsDGelWopSxTe2w35UBbCC2TKKpxKDOdm8gc7b6a3pt10dbTo=
 -----END CERTIFICATE-----
diff --git a/net/data/ssl/certificates/client_2.key b/net/data/ssl/certificates/client_2.key
index e10b152..92cae727 100644
--- a/net/data/ssl/certificates/client_2.key
+++ b/net/data/ssl/certificates/client_2.key
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-MIIEowIBAAKCAQEA68lLXfm1qfzrGYiXtXmYfa/gwbcSGLTcu3VTD9Cow2A465PP
-wp6bs6Qu3eFgwr7mceQ72pU410+zEwxo1bqHorcc1qhemDBLEaL5cu1KEyw3GN97
-kJTxOMR4zahR8IvDpnYRzjTtmZOuLUpZ7Lo3oOouLDQ6OpoOw9mLu2I7RtVc8cQC
-iyOnQVWKeSbDQ/+or/m3DUbQq+Wyg9TTjDWAAbqxu3mP5Jf8nd8I/xAbRxe0jBSW
-8hiZ++Yxjo/kLVkI+s4TBFVV3dau2b5oHGMsFoBFCaTIyE+4KZAKZAdptvxuh1ic
-F/GhSZy3+H1w122uYmq7KA7pG32sBaQUl0iwnQIDAQABAoIBAGNOKlHwI9TuUs40
-O0ERb2owMwcjZZnGQtko9szIYuu2kQKXBH/BcW5djeehTrF22XPKXnMXOhNk29T/
-+v9ZSlr7qEe4Le8HF/bbnxgKXJJqouH07gPc1yPDi+WCKNCY7NQlEia5IAD4s/kb
-QXh0jY1WVBAGByg7TlCqRTGsk66myy3qA7Ii65Y1upiGFfDczpQL5mUKaBTjz3HC
-/DMr4GRuFOw5NkhELu9SOENZGSwuzpk6gNDVYDXJ+uo9bvH9EIB9S1KIoAoa+yr2
-L9LUcG9vwOuMNh7qN66nAGxGzoI8qh6kHVgfyTcF11NwaFutSIsGQTRKeANxiq2I
-IkbT3EECgYEA/QGxkv9iC/oJfe9gWlUeEFJsqlmLp2ii0HrH9KnywT5sgicd0//3
-eCU1KI8LygABbHb3hmFQRAwf2gFq0u1MBqXQQ4nVsrNtPVzNGGOkfk5T9DIu4vBN
-L9Qw29ULYDbaHaC1BFymwnMsOOsKctiMmsiklhyCWBczcHmE+gn+6ykCgYEA7pNx
-on/qgrCp9P8mMdBqjOmc5740Pbqu5JShYJkja1fv7IVLhGEuifdwGWge6ZfjaXPV
-wq7P7mbXa2Dreqc0LkxUrdAffZitsXckhNswSDToZzf7JB9GAnkcMKlLcJHbO0Kf
-jJALGpPknLg8XbpqsT+/GAS1GBNbL4Rz/MovPFUCgYBkJEt494SDYRBovFrS5mXj
-5/wC4TaZqJzpD/AdMzdWrbKdQYZY5zO4ZmHID/aGmcH2gJAwrEvs4y+oRm9V1X8G
-EpOAaAohlUtjwlubj7UIGVC5kzNjt+GVUNOV75l1F8D1gSqk81c+GAAk90NHedcN
-XOVoVRhybZx6pF6x6UrxIQKBgDc8EbIClYO+bQrYy7n6u8B2Eaqhoays/PLU6mvX
-6Jhgmp6S2cIDUegFToHDVmzUioUOmW3iVSenzbYBkWMrNOyHJY+8QJ4ubABLSjws
-FwiQn0HOdymMyAOokHs/psSgMDaPHStI6hk0JliWWvuEPlFdJdvksxyo1pKwwr3C
-/Z6lAoGBAIr0S/O5rYrEHchJ6yr+YtJa6vIowOSUvijG2L4ghVY63v/Ke5vzwmOZ
-wuPh0D6atpKPIq5p3eGlgq12cJHGwaybVP9C3C9vD+MlhMttOy7Ez9aVFILE9nt/
-hSrOTRwYYXLs0txl7K40Ja2hjIRXw1TQU37V4wADNa+GhPpUfg9y
+MIIEpAIBAAKCAQEA4IzClfxmgklkJHuaB4JlLIR6Z8ehIjoJ868C8YA5I23PDxHI
+G6W+l3F98IFAaO41q4VU/IimBRMIRiGZOkHgBi/NQS1nu11IQKxl1azljs2zvzLC
+V9j220CNyDqvsxv13/26W+rbjsZ+0VdIN+lh6RY9AhhDcA5BvN6vjZOFR02ypIin
+oSOKnhZOMLRVsosPuKS1qlaXCrWD8Z7n1tD4koZ6+9YiYCVgZ7pKNTIS8kR8b3Pj
+pm+8Q+FVR+HZWoYySE1n/w6vDmK47TUUI2vdBHpnKbis//DjVHrsDQ1ZqqvxRwDS
+FLtIoMwuMyO3rWuqsa2FnvgJbvA9XD4Pv3F3jwIDAQABAoIBAQCTe2ACarhZMiLX
+42aTMA2LY6eRqggnFr+akYP5YiIlJuYsG522qvG3Pg9de0b2pB4T/YqIIqgIBSwW
+A9ND9ChTZ+oDuPK8mNPvxktMQDa1yF0aYxhJ4nKgJpH4xLLJjL+80kUoQeTarXx1
+ukHwlxR7puODELSaUILUrd3XuuB6p06I3KBIzkGx0BqVRFmCk/nAaCZLA8WJcUmD
+rfYFPTc/2Jm7xH+Wzhd86evT1yIpTCu7VNdXuzFHLFesxeFSb49cRrJLlKEWT3B8
+7jRjhqclZvJ2jTvMEx8I48vIW40jrs5dGWFqzYRo0rbelI/BRwDQsGEDyHLwZdRG
+qAg158bhAoGBAPLAr2sGQhI0+v5GWMuqELgCJlqmDP9gP/6pU2E8CkmTefu8MsVx
+UzFaAN+WFr0wqpVuCTVczSZSF10/SwM4mNsTb6vc9CQ9uK655vTIiFLR8NTZOxAK
+sVyJKCRB0Ejf9nufSJaLZetW3QQTxWLmrhmVjKPjJOYsKLHfye3Oz7VLAoGBAOzN
+xt1Fgi2XgnASI+D3e7hwa/9obfCPdwB1kdyPq8A2sZBTzGdnixY5IcbwQmK4Ekuj
+d9gnaRqg/WKUoR/5PduYvxo1JErBh+itu/mdSpSd71465Do/Q5mQbV+MAnyWTPak
+mtBKs6W22Sk1+NSuoA4mX+oC8m29uDho8b+bIdBNAoGAWXTmcAM7X+hEQmX8HPmL
+9bNdHPSqP4Xhr2AIyQFOLTT6s+jzsM0FQl+PiNWPhaKkijKllBOhyihgUc2cQBCg
+S8NK2MOw+JYCM+lwEe7ARfz1ygpPeKboG1i0AUB7mA9ojr/xCQFPyr0U74a1q6+k
+our4jACNvYCycnIswMUAyCcCgYBh/vJKBYbOuUFogYlJgwE3HYcD5kKA5832abEY
+FnicDcZDlPok3KupYbFBs5G1arlfheGFmSGcvHy/fASFx846fyaugMlpClflCWid
+7uK7R/SUCUkDdcTS2vr4LGenCUgGVa4ffpqDfHy32jcERNPFp0nP/LI4ieefqIZK
+pbdDjQKBgQCEqdGn6ZB+dg3i2RK544RfNqQaVmDw0czmxl3xRnUEfElA7ZSmE4Lt
+Dx9bmXoXYAjMz3Elh3+3pIq4BjlKsPK18zZPAGQnVxoSnUtW9tVI+bc/yFk2irfo
+UtSDxMR8dcUd4vjE2WHIgBnJEbGj+PkMqjMimMZqQDhr4UI2OTe7Zw==
 -----END RSA PRIVATE KEY-----
diff --git a/net/data/ssl/certificates/client_2.pem b/net/data/ssl/certificates/client_2.pem
index 1f7a03a..abc9dde 100644
--- a/net/data/ssl/certificates/client_2.pem
+++ b/net/data/ssl/certificates/client_2.pem
@@ -5,31 +5,31 @@
     Signature Algorithm: sha256WithRSAEncryption
         Issuer: CN=E CA
         Validity
-            Not Before: Oct  4 18:53:24 2016 GMT
-            Not After : Oct  2 18:53:24 2026 GMT
+            Not Before: Dec  9 20:18:57 2016 GMT
+            Not After : Dec  7 20:18:57 2026 GMT
         Subject: CN=Client Cert D
         Subject Public Key Info:
             Public Key Algorithm: rsaEncryption
                 Public-Key: (2048 bit)
                 Modulus:
-                    00:eb:c9:4b:5d:f9:b5:a9:fc:eb:19:88:97:b5:79:
-                    98:7d:af:e0:c1:b7:12:18:b4:dc:bb:75:53:0f:d0:
-                    a8:c3:60:38:eb:93:cf:c2:9e:9b:b3:a4:2e:dd:e1:
-                    60:c2:be:e6:71:e4:3b:da:95:38:d7:4f:b3:13:0c:
-                    68:d5:ba:87:a2:b7:1c:d6:a8:5e:98:30:4b:11:a2:
-                    f9:72:ed:4a:13:2c:37:18:df:7b:90:94:f1:38:c4:
-                    78:cd:a8:51:f0:8b:c3:a6:76:11:ce:34:ed:99:93:
-                    ae:2d:4a:59:ec:ba:37:a0:ea:2e:2c:34:3a:3a:9a:
-                    0e:c3:d9:8b:bb:62:3b:46:d5:5c:f1:c4:02:8b:23:
-                    a7:41:55:8a:79:26:c3:43:ff:a8:af:f9:b7:0d:46:
-                    d0:ab:e5:b2:83:d4:d3:8c:35:80:01:ba:b1:bb:79:
-                    8f:e4:97:fc:9d:df:08:ff:10:1b:47:17:b4:8c:14:
-                    96:f2:18:99:fb:e6:31:8e:8f:e4:2d:59:08:fa:ce:
-                    13:04:55:55:dd:d6:ae:d9:be:68:1c:63:2c:16:80:
-                    45:09:a4:c8:c8:4f:b8:29:90:0a:64:07:69:b6:fc:
-                    6e:87:58:9c:17:f1:a1:49:9c:b7:f8:7d:70:d7:6d:
-                    ae:62:6a:bb:28:0e:e9:1b:7d:ac:05:a4:14:97:48:
-                    b0:9d
+                    00:e0:8c:c2:95:fc:66:82:49:64:24:7b:9a:07:82:
+                    65:2c:84:7a:67:c7:a1:22:3a:09:f3:af:02:f1:80:
+                    39:23:6d:cf:0f:11:c8:1b:a5:be:97:71:7d:f0:81:
+                    40:68:ee:35:ab:85:54:fc:88:a6:05:13:08:46:21:
+                    99:3a:41:e0:06:2f:cd:41:2d:67:bb:5d:48:40:ac:
+                    65:d5:ac:e5:8e:cd:b3:bf:32:c2:57:d8:f6:db:40:
+                    8d:c8:3a:af:b3:1b:f5:df:fd:ba:5b:ea:db:8e:c6:
+                    7e:d1:57:48:37:e9:61:e9:16:3d:02:18:43:70:0e:
+                    41:bc:de:af:8d:93:85:47:4d:b2:a4:88:a7:a1:23:
+                    8a:9e:16:4e:30:b4:55:b2:8b:0f:b8:a4:b5:aa:56:
+                    97:0a:b5:83:f1:9e:e7:d6:d0:f8:92:86:7a:fb:d6:
+                    22:60:25:60:67:ba:4a:35:32:12:f2:44:7c:6f:73:
+                    e3:a6:6f:bc:43:e1:55:47:e1:d9:5a:86:32:48:4d:
+                    67:ff:0e:af:0e:62:b8:ed:35:14:23:6b:dd:04:7a:
+                    67:29:b8:ac:ff:f0:e3:54:7a:ec:0d:0d:59:aa:ab:
+                    f1:47:00:d2:14:bb:48:a0:cc:2e:33:23:b7:ad:6b:
+                    aa:b1:ad:85:9e:f8:09:6e:f0:3d:5c:3e:0f:bf:71:
+                    77:8f
                 Exponent: 65537 (0x10001)
         X509v3 extensions:
             X509v3 Basic Constraints: critical
@@ -37,36 +37,36 @@
             X509v3 Extended Key Usage: 
                 TLS Web Server Authentication, TLS Web Client Authentication
     Signature Algorithm: sha256WithRSAEncryption
-         9f:d0:6e:8b:08:58:16:b5:78:3f:05:bb:59:bc:cf:74:1c:88:
-         b0:7e:10:c5:71:9d:b5:08:05:59:ca:f0:c8:64:49:96:82:8b:
-         14:0c:da:9d:be:a2:8b:37:df:e1:69:bc:8e:f4:be:80:3f:f9:
-         8a:1d:7a:70:37:3c:18:a0:92:27:10:e3:74:ca:fa:b8:db:f2:
-         c6:a5:32:66:85:88:29:3a:4e:64:95:85:b4:43:37:8a:6d:48:
-         f4:12:2f:b2:d0:66:c9:b7:88:ad:b8:a7:1f:97:59:bf:d9:0d:
-         d6:ce:ff:5f:75:2f:d2:e0:69:c8:d6:17:b9:fd:3c:ed:fd:1f:
-         47:14:f8:ef:0b:33:2a:1c:14:25:d1:82:90:d3:67:1b:ea:b0:
-         f7:5b:78:a9:9d:28:1b:d3:cd:8d:bd:30:c2:7e:12:32:dd:83:
-         cc:57:47:b3:e7:0c:79:b5:f8:a0:f4:f0:d8:29:1b:9b:fb:2f:
-         a9:1c:cb:a9:84:14:29:c7:23:b8:85:88:d9:78:5f:c7:a4:c6:
-         1b:bd:6e:70:2e:a2:be:31:98:c7:9c:35:1d:44:59:f8:31:83:
-         87:ee:a9:c7:ab:f5:6f:e6:8a:cc:49:5f:23:fd:7c:a4:61:01:
-         9b:51:d8:b0:85:9a:bf:1d:9d:62:3e:b0:7c:e0:5e:57:ed:69:
-         3c:f3:8c:54
+         95:de:33:2f:e2:11:c2:6d:64:4a:5f:98:69:cb:a3:c6:bd:a1:
+         0f:00:9c:32:c8:83:c7:05:14:21:e3:ab:fa:7a:f8:43:36:95:
+         6c:85:8b:b5:ee:2c:fc:4b:77:95:8a:bf:2f:89:c1:cc:c2:21:
+         99:40:c4:01:be:2a:4a:5b:d9:61:06:16:b0:5d:3f:27:ad:e3:
+         57:5c:41:89:fb:3b:dc:73:45:ac:05:e2:dd:89:95:74:09:30:
+         68:3c:3f:e8:bc:e6:94:4a:ed:4c:74:90:ad:a0:a4:97:c0:04:
+         9b:13:81:a5:24:76:db:4c:49:8f:80:f9:7c:7f:8b:f9:de:45:
+         65:5d:03:b2:c7:99:3b:56:b1:f8:29:7e:b4:69:fe:f9:29:b3:
+         b6:59:bd:51:b1:02:97:5b:db:29:5e:9a:b5:1f:75:42:0f:7e:
+         58:bc:e3:3f:39:ea:7b:12:c7:68:06:c0:e4:78:f4:e9:b4:9b:
+         4c:fc:94:06:a3:1a:37:8b:3d:cd:67:f9:f4:e9:87:20:6c:07:
+         71:62:85:78:35:96:9c:ef:98:59:33:50:83:7a:32:ad:22:01:
+         3a:20:05:05:05:b0:62:9d:4e:20:94:1b:05:cc:7d:bb:ba:98:
+         a0:51:d2:50:b5:cb:d8:97:0f:42:13:65:2a:14:b8:cd:f2:24:
+         5f:0e:6e:6b
 -----BEGIN CERTIFICATE-----
 MIIC0jCCAbqgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwERSBD
-QTAeFw0xNjEwMDQxODUzMjRaFw0yNjEwMDIxODUzMjRaMBgxFjAUBgNVBAMMDUNs
-aWVudCBDZXJ0IEQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDryUtd
-+bWp/OsZiJe1eZh9r+DBtxIYtNy7dVMP0KjDYDjrk8/CnpuzpC7d4WDCvuZx5Dva
-lTjXT7MTDGjVuoeitxzWqF6YMEsRovly7UoTLDcY33uQlPE4xHjNqFHwi8OmdhHO
-NO2Zk64tSlnsujeg6i4sNDo6mg7D2Yu7YjtG1VzxxAKLI6dBVYp5JsND/6iv+bcN
-RtCr5bKD1NOMNYABurG7eY/kl/yd3wj/EBtHF7SMFJbyGJn75jGOj+QtWQj6zhME
-VVXd1q7ZvmgcYywWgEUJpMjIT7gpkApkB2m2/G6HWJwX8aFJnLf4fXDXba5iarso
-DukbfawFpBSXSLCdAgMBAAGjLzAtMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYI
-KwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQCf0G6LCFgWtXg/
-BbtZvM90HIiwfhDFcZ21CAVZyvDIZEmWgosUDNqdvqKLN9/habyO9L6AP/mKHXpw
-NzwYoJInEON0yvq42/LGpTJmhYgpOk5klYW0QzeKbUj0Ei+y0GbJt4ituKcfl1m/
-2Q3Wzv9fdS/S4GnI1he5/Tzt/R9HFPjvCzMqHBQl0YKQ02cb6rD3W3ipnSgb082N
-vTDCfhIy3YPMV0ez5wx5tfig9PDYKRub+y+pHMuphBQpxyO4hYjZeF/HpMYbvW5w
-LqK+MZjHnDUdRFn4MYOH7qnHq/Vv5orMSV8j/XykYQGbUdiwhZq/HZ1iPrB84F5X
-7Wk884xU
+QTAeFw0xNjEyMDkyMDE4NTdaFw0yNjEyMDcyMDE4NTdaMBgxFjAUBgNVBAMMDUNs
+aWVudCBDZXJ0IEQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDgjMKV
+/GaCSWQke5oHgmUshHpnx6EiOgnzrwLxgDkjbc8PEcgbpb6XcX3wgUBo7jWrhVT8
+iKYFEwhGIZk6QeAGL81BLWe7XUhArGXVrOWOzbO/MsJX2PbbQI3IOq+zG/Xf/bpb
+6tuOxn7RV0g36WHpFj0CGENwDkG83q+Nk4VHTbKkiKehI4qeFk4wtFWyiw+4pLWq
+VpcKtYPxnufW0PiShnr71iJgJWBnuko1MhLyRHxvc+Omb7xD4VVH4dlahjJITWf/
+Dq8OYrjtNRQja90EemcpuKz/8ONUeuwNDVmqq/FHANIUu0igzC4zI7eta6qxrYWe
++Alu8D1cPg+/cXePAgMBAAGjLzAtMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYI
+KwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQCV3jMv4hHCbWRK
+X5hpy6PGvaEPAJwyyIPHBRQh46v6evhDNpVshYu17iz8S3eVir8vicHMwiGZQMQB
+vipKW9lhBhawXT8nreNXXEGJ+zvcc0WsBeLdiZV0CTBoPD/ovOaUSu1MdJCtoKSX
+wASbE4GlJHbbTEmPgPl8f4v53kVlXQOyx5k7VrH4KX60af75KbO2Wb1RsQKXW9sp
+Xpq1H3VCD35YvOM/Oep7EsdoBsDkePTptJtM/JQGoxo3iz3NZ/n06YcgbAdxYoV4
+NZac75hZM1CDejKtIgE6IAUFBbBinU4glBsFzH27upigUdJQtcvYlw9CE2UqFLjN
+8iRfDm5r
 -----END CERTIFICATE-----
diff --git a/net/data/ssl/certificates/client_2.pk8 b/net/data/ssl/certificates/client_2.pk8
index 731e39c3..ad3ca5d5 100644
--- a/net/data/ssl/certificates/client_2.pk8
+++ b/net/data/ssl/certificates/client_2.pk8
Binary files differ
diff --git a/net/data/ssl/certificates/client_2_ca.pem b/net/data/ssl/certificates/client_2_ca.pem
index dd58ffa7..78080961 100644
--- a/net/data/ssl/certificates/client_2_ca.pem
+++ b/net/data/ssl/certificates/client_2_ca.pem
@@ -5,31 +5,31 @@
     Signature Algorithm: sha256WithRSAEncryption
         Issuer: CN=C Root CA
         Validity
-            Not Before: Oct  4 18:53:24 2016 GMT
-            Not After : Oct  2 18:53:24 2026 GMT
+            Not Before: Dec  9 20:18:57 2016 GMT
+            Not After : Dec  7 20:18:57 2026 GMT
         Subject: CN=E CA
         Subject Public Key Info:
             Public Key Algorithm: rsaEncryption
                 Public-Key: (2048 bit)
                 Modulus:
-                    00:a2:7e:a3:fd:c1:d7:78:cd:57:ac:67:54:37:69:
-                    fb:72:6f:1d:8f:d0:47:0f:11:14:ab:42:d8:3d:6a:
-                    34:2b:d6:38:07:df:16:1d:c6:62:eb:d7:12:e1:86:
-                    83:f2:dd:8f:97:09:94:8f:1b:ff:3b:84:9b:48:e5:
-                    0d:43:6b:ae:bb:75:88:1c:c6:3a:7f:d8:12:d9:7c:
-                    12:18:6d:e2:f0:88:d4:3e:5a:93:b3:af:c1:79:a1:
-                    b6:a3:f7:56:46:21:e6:7d:6e:36:ea:ba:4b:52:f7:
-                    a9:45:0b:83:09:2c:09:22:8a:67:5a:8f:88:60:b0:
-                    11:07:25:9b:c2:6a:3c:63:4c:0e:69:45:ce:9d:ba:
-                    c9:d4:01:fb:78:56:38:08:8f:e5:d6:ff:ac:e4:04:
-                    fa:26:cf:d2:05:33:57:a3:8e:80:c0:b6:40:d5:d3:
-                    ca:85:17:30:b2:24:f4:19:af:c5:48:a4:ed:c0:49:
-                    c1:a4:b7:89:29:ba:e5:2d:37:78:1c:d6:3e:9b:03:
-                    fa:bc:7b:e2:76:a6:70:f3:1b:9d:b2:4b:fc:72:7b:
-                    77:89:50:bb:88:2f:b5:b6:a2:c7:33:27:b7:d1:1a:
-                    7c:d4:58:e3:5e:88:ca:f8:49:c3:cd:cc:0f:93:4b:
-                    3c:fd:75:c3:7b:6f:bf:d3:db:ba:2e:31:7b:a7:a5:
-                    42:c5
+                    00:c3:39:c3:5a:8e:ff:f2:1d:cc:26:91:5d:15:9e:
+                    ca:e0:fb:cf:99:5f:13:3d:c6:37:59:8b:ce:cc:76:
+                    0e:1c:9f:b6:49:5b:09:97:63:9d:e1:00:74:44:fb:
+                    2f:53:f3:d5:03:92:77:97:53:74:7e:d2:da:d3:a3:
+                    f4:c1:91:6a:83:ff:89:fe:73:46:56:ca:6d:51:0d:
+                    57:16:3d:3e:e8:fc:00:d9:4a:7a:7d:93:84:06:12:
+                    c5:ff:31:b3:a6:eb:96:18:71:b8:56:5c:2f:ab:78:
+                    e2:53:dd:15:d8:65:c8:f6:96:14:dc:15:cf:2a:39:
+                    ed:e1:08:1b:84:29:c7:1c:78:67:c8:e0:72:58:4e:
+                    33:7f:cb:ef:71:82:db:45:1d:7c:0c:d0:f5:4c:af:
+                    85:6b:14:61:50:87:34:42:fe:45:a3:3c:a3:53:57:
+                    1d:ac:11:c8:cf:2f:5e:cb:78:87:39:a1:41:3f:69:
+                    21:5c:1e:19:02:a3:6c:91:d3:1b:4e:50:fc:a4:b1:
+                    03:87:c0:58:b1:fe:cd:58:5e:53:ed:c9:d6:5d:9e:
+                    a3:fb:0d:e0:a0:8e:3d:c9:9e:9e:83:07:61:c7:30:
+                    5a:ca:29:93:04:af:5e:f3:57:2e:c2:d8:c8:ae:7f:
+                    5c:a4:27:fa:cd:55:a2:fd:89:d2:0b:87:24:6b:7b:
+                    fb:19
                 Exponent: 65537 (0x10001)
         X509v3 extensions:
             X509v3 Basic Constraints: critical
@@ -37,35 +37,35 @@
             X509v3 Key Usage: critical
                 Certificate Sign, CRL Sign
     Signature Algorithm: sha256WithRSAEncryption
-         92:8b:93:94:03:04:91:3f:4d:8b:f3:90:53:ee:73:b5:33:c7:
-         61:ea:0f:a5:59:9b:f0:0d:4f:7d:48:0d:5a:58:e7:1f:68:f6:
-         d6:58:75:33:a5:d2:b7:65:6a:28:40:bc:0e:1e:78:ee:9a:13:
-         3c:b0:8b:8f:98:72:86:50:3a:a3:bf:6d:f0:21:95:a8:73:d0:
-         dd:e5:0e:25:b1:62:76:65:69:1f:ee:26:82:ab:be:a4:a8:30:
-         a7:41:34:07:57:2f:8b:ab:25:af:cb:23:a5:79:cf:b2:a2:17:
-         02:a7:aa:50:92:6e:0d:9b:ff:c9:22:38:b4:0f:47:94:d2:80:
-         7f:92:30:00:ec:5b:22:e2:a6:71:5e:e8:8f:0d:2f:38:2c:29:
-         47:6a:7f:20:0a:e2:42:cb:b7:6e:2b:29:0f:03:55:94:84:5f:
-         e7:47:bf:ae:75:88:05:4e:42:ac:78:57:9d:9c:e2:77:d2:17:
-         42:55:ba:f8:77:ee:61:d6:e8:ec:aa:e0:7a:a6:65:c6:35:80:
-         08:3d:39:a6:70:8c:9e:6d:7a:ee:e7:cf:36:46:98:00:c8:7b:
-         b8:84:7f:9d:9f:bd:31:4f:99:25:6e:76:9a:5d:46:3e:40:70:
-         c6:a8:03:f3:98:9c:be:fb:f6:ad:c2:8d:e3:f9:7d:93:3a:78:
-         da:b3:d7:dc
+         67:d4:6c:cf:cd:54:81:67:2a:c2:c4:66:c7:76:9c:b0:8b:6b:
+         ef:b8:ae:a9:b3:d6:f8:47:91:d5:97:0b:bd:1a:87:21:8c:ce:
+         be:0c:80:d5:a5:25:0d:0a:c7:ed:be:cb:8c:6d:08:e8:de:a5:
+         33:89:e6:87:df:2b:f4:54:b3:c2:94:15:0d:36:5e:1a:aa:c0:
+         b0:03:3c:24:c6:a1:81:91:ca:fe:db:0f:59:1b:d6:4e:48:0b:
+         52:d3:e7:07:d7:b1:ca:b2:22:e4:d4:37:a4:3c:87:3c:0a:11:
+         a6:10:2a:ed:86:2a:bb:db:10:7e:f3:a5:fc:10:ab:80:5b:07:
+         58:7c:22:76:3e:9b:9c:72:79:0d:dc:85:f8:e7:c2:0f:17:aa:
+         01:dd:8e:24:27:77:4e:23:03:da:88:e0:df:e6:ca:b4:84:56:
+         a1:dc:9f:e0:93:94:97:d2:98:cd:32:6d:73:84:f9:3e:4c:96:
+         b3:51:07:b8:9f:66:32:d1:ac:53:0e:17:a9:6f:29:d1:7b:73:
+         b3:55:9b:cc:8f:8b:e5:49:fd:fd:f2:30:d6:d0:f7:03:06:12:
+         e3:66:2d:0d:a1:da:28:04:04:29:b8:40:6e:0e:6f:31:48:cb:
+         54:f7:e2:89:22:d8:05:e0:f5:7e:48:b3:96:ff:6b:ef:e7:fe:
+         71:1d:0b:77
 -----BEGIN CERTIFICATE-----
 MIICwjCCAaqgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwFDESMBAGA1UEAwwJQyBS
-b290IENBMB4XDTE2MTAwNDE4NTMyNFoXDTI2MTAwMjE4NTMyNFowDzENMAsGA1UE
-AwwERSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKJ+o/3B13jN
-V6xnVDdp+3JvHY/QRw8RFKtC2D1qNCvWOAffFh3GYuvXEuGGg/Ldj5cJlI8b/zuE
-m0jlDUNrrrt1iBzGOn/YEtl8Ehht4vCI1D5ak7OvwXmhtqP3VkYh5n1uNuq6S1L3
-qUULgwksCSKKZ1qPiGCwEQclm8JqPGNMDmlFzp26ydQB+3hWOAiP5db/rOQE+ibP
-0gUzV6OOgMC2QNXTyoUXMLIk9BmvxUik7cBJwaS3iSm65S03eBzWPpsD+rx74nam
-cPMbnbJL/HJ7d4lQu4gvtbaixzMnt9EafNRY416IyvhJw83MD5NLPP11w3tvv9Pb
-ui4xe6elQsUCAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
-AQYwDQYJKoZIhvcNAQELBQADggEBAJKLk5QDBJE/TYvzkFPuc7Uzx2HqD6VZm/AN
-T31IDVpY5x9o9tZYdTOl0rdlaihAvA4eeO6aEzywi4+YcoZQOqO/bfAhlahz0N3l
-DiWxYnZlaR/uJoKrvqSoMKdBNAdXL4urJa/LI6V5z7KiFwKnqlCSbg2b/8kiOLQP
-R5TSgH+SMADsWyLipnFe6I8NLzgsKUdqfyAK4kLLt24rKQ8DVZSEX+dHv651iAVO
-Qqx4V52c4nfSF0JVuvh37mHW6Oyq4HqmZcY1gAg9OaZwjJ5teu7nzzZGmADIe7iE
-f52fvTFPmSVudppdRj5AcMaoA/OYnL779q3CjeP5fZM6eNqz19w=
+b290IENBMB4XDTE2MTIwOTIwMTg1N1oXDTI2MTIwNzIwMTg1N1owDzENMAsGA1UE
+AwwERSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMM5w1qO//Id
+zCaRXRWeyuD7z5lfEz3GN1mLzsx2DhyftklbCZdjneEAdET7L1Pz1QOSd5dTdH7S
+2tOj9MGRaoP/if5zRlbKbVENVxY9Puj8ANlKen2ThAYSxf8xs6brlhhxuFZcL6t4
+4lPdFdhlyPaWFNwVzyo57eEIG4Qpxxx4Z8jgclhOM3/L73GC20UdfAzQ9UyvhWsU
+YVCHNEL+RaM8o1NXHawRyM8vXst4hzmhQT9pIVweGQKjbJHTG05Q/KSxA4fAWLH+
+zVheU+3J1l2eo/sN4KCOPcmenoMHYccwWsopkwSvXvNXLsLYyK5/XKQn+s1Vov2J
+0guHJGt7+xkCAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQELBQADggEBAGfUbM/NVIFnKsLEZsd2nLCLa++4rqmz1vhH
+kdWXC70ahyGMzr4MgNWlJQ0Kx+2+y4xtCOjepTOJ5offK/RUs8KUFQ02XhqqwLAD
+PCTGoYGRyv7bD1kb1k5IC1LT5wfXscqyIuTUN6Q8hzwKEaYQKu2GKrvbEH7zpfwQ
+q4BbB1h8InY+m5xyeQ3chfjnwg8XqgHdjiQnd04jA9qI4N/myrSEVqHcn+CTlJfS
+mM0ybXOE+T5MlrNRB7ifZjLRrFMOF6lvKdF7c7NVm8yPi+VJ/f3yMNbQ9wMGEuNm
+LQ2h2igEBCm4QG4ObzFIy1T34oki2AXg9X5Is5b/a+/n/nEdC3c=
 -----END CERTIFICATE-----
diff --git a/net/data/ssl/certificates/client_3.key b/net/data/ssl/certificates/client_3.key
index 20498ba..c2b341fe 100644
--- a/net/data/ssl/certificates/client_3.key
+++ b/net/data/ssl/certificates/client_3.key
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-MIIEpAIBAAKCAQEAqblhT1L+ZDRTZ0fYWCIjgpdv0ILn9ws9204VFTjf3jU+66wZ
-m9iN2+j62y/68iBFkt/107YqA2so3o0kS6o7Izt+EQg+o5ZvvHM3fVSR/IGejHbt
-1fbk9o7oblbikOtRpfOQ2EXZ+h2RASE6YTE66lrE6RruAOaWYsoLpzepHDlOEj6t
-q+24LIalckzKOQNNYfwpuLzbMomVCmIaKNaObesGM5pbj+hz4S8ehCH7CzgnsYOg
-x/7tecyrV6XPW7OEDLm4GoyQIlnxvk1GDIVje6caSW+OzqL65SlkAwLcaN95tmub
-IgdZr6H/upzmXdRh3kCBLgKWAqpUJNSzxBjj/wIDAQABAoIBACvRiKYKL1N/jujj
-S5+1cKWOo3eZ1HmblWTBTAAmpuWfqZb+3720sytLgziDsq5AVrYMzFLUfRRU3kBX
-AD/ou0vlWC7dig6CEGb++ByLcQVYEa8CJXVQQNzHGIskM2pm1rWZpJOxtQ02BPHd
-ukzNgQBwXtYv9bKV1c27jDan0ClQ1nj14TK8k2LLCDYd3O9Zbfm+5fKqsJIjDFm6
-rPeltV8yFBsZPxBJAQUNTR0fnq5mYLrCm8ARWYbLxbbWSjInXStrwVuaG8P/T7Om
-sl6Jj7eRClM6HrCtJMukgAQ1f6Rg882MVKKv8sjVO0ZHIZrg+e3TLPLrngXYeLxP
-NgrJgUECgYEA2J5Ee5cVyvbJITD71dVHcZc8QcaBVFBsSCcw0ZQ4LgUmS/z3ERYq
-mpdXzU1bTAOOMujOjiv9qYXn800DqRiDML384/cQz9DNkUth2eSQjk2Ryp9x5z+Y
-CeeMrzTtPK+SRfbC12UnNkZqwg+OrVgQUswbgOt2tM/9Bx5ujo6kuDsCgYEAyJSX
-ouGtWU7wys3ffmrmYlc0G/hGXxvqunpD8YR61fxyIMb1M9FfqObbCWaD7tkboEfe
-u6l7+d+4eJO2Gv++68asqHPsNQeq0qqAVPVNVusD+Uw9DPK4yxfbtn0lbALikCAB
-VT4yudolYsZA0b6tHApSG2bZkr3lXSwLFmljCw0CgYEAtT3m6smE8Gb/7geADm/+
-8Omq/xXJy/PmRZCU5iXvw4GHg3jKd79mMiaCzkH1K2qmJa5odMgV2ysw4X8Emwzp
-Z3TvDQYBSP/Zn8HEw3zb/lSksTYrJWMuIMteCJJuFKKJ7oQCjhoSbvUICgreQ+c0
-8THZqUpZ7ftAKB6sPhbXd1UCgYEAsYjL+nBTtcOoX2j/U26dAhf7WHJVHyOfjHRh
-pOjErJhoD9jp+XZtfBrxbo2dYxApYqGaZHHr+MvrBFaBjb4lp5zO/76zKHDj4tjl
-A82nKbKUbtjrBIXlyGUSpKB6OfMHw9eANon57gRGqPmfL8bchAAiknxjQX3xAJnW
-Kn0XHBUCgYAnpq1dGwdknEcVnVMsoZQirc6UK39u8KIH6S7P2QhSzc6pXOeC8HGj
-H6zvc3LtddSj8tCWfGDGVWp4v9TIWHOZbmmg20iU93j7Xi53cL3zB6TaAa467tj9
-0JFgB4tk1zKLggwkF26Sf3m+kkPDGwm4+jmk8TfV7VZ9yCZQY5Onig==
+MIIEpQIBAAKCAQEAs1wyu8BIKDebRat4oOpyEyZdRu5xxCSc7ai2gTXXcroKrqlO
+IGESIuAAZ4BwvqzvA7LUsDr8xauFewRLYYV6F2xDNmcLGXx0uGXpHP3w30K8DP0J
+fk99OMBSceUrGYCCqmnCNmu3LQf0dGK/jpDtRxpkJKxMuNIq0J2GCMEYnj7eTxJc
+ZKQrhkMSgWcMjFbkFkY8Kc9OGOpPZl+01nNfHpOt38kGZczcQrrphkIIoaul/CLT
+I1eg2myA3sX5nMURZZyy3/PWyL2qr0Bm7c5fBEYX5pLqZMiz5CDL4EQJFR985OAH
+zSJ8vaAGZTXUPhwHYY8BUyIlhZN1c0LHwcASnwIDAQABAoIBAQCxZ/WKfdMhbHb5
+v3ROffadeGn0ue7vWmOaMzFpto7HHLtqLW5oWnts4XGk7ocWIsk7OExlj8Lr5g7e
+Mc45xKORvXTxv5Rb/h0ZMzwTgB4bRs/obPRR6l/qnVgu7cTmsZUM6BTAbWS+dsrV
+v8LHShRYKwN4vrAYc1EEDXtA93XZNp9OBsVRdHJbeV4PIXqdzr3lScbXHNNs+dSF
+i6pZ/VrCHWmp9H1NXQuicAHr5aTvRMvFpfNtFSpOo7xEX+4cbVTk2b5TwxBa5TTj
+oew8/h2IsU1OmytQ1zya9Xtpw9GIMOnWg5Ce2dAyoBIkmhQwYcJyYTMM34vul/eD
+k0u0cxFxAoGBAOPM4x1mjD6tuQHFYBivBySU1CpdI0taem3GCijCUj/7tHPA+7FZ
++DhtnYF4b9q/X9EHRoosCWY07/tImYZT7ziiEFITRZL/m/hA239M9zuop7+9Tp3W
+M2oTkTGQOn5qKNg8TplYinpHmpGD7VURUczsdmo28rgp9Ubu1h5CwHv3AoGBAMmQ
+Nz/wgVCPVnZ66AsHiwLcAZ99aZg5961XVgyUXpWSQ0wNYKYWsYwYhYCeVRmwImSA
+NavYq0+AxTgnZrwhXXkvKXYfkLhh6aePRqyPaT3AUfp4akNe/S24HW3zO9Z0BzG6
+Ca8+oERpQ6hZ92WB1yikVoUqIaw+oIn5mzjkouSZAoGBAJ7z/p4rSj0KN4gW06El
+sJREDW+qIdCYx8kFYV1jisT+u8HxrS7pmpy1UCxhf5th4lgW/Y+4fq6EzdfHpujm
+dIxN+ZlrvSZ/mbO2ffLsH6/PVY4jaFIWfzXLhYrSGx7OsMWB/05dS/NbN23GYrrz
+JOMbNN2UjfUXwgDG8z2WUn2tAoGAbzJzeH+7J3FcNtLJTsRjiTlMX+t1JLjeDa//
+1cLIh2WAYOWEazxbyLkCdZljw18rKhyc/2fx4lNc+gSqpaEWizNcgUEaus2xdHIT
+gEFBwwJld3OU1AQEUoOfILguS7oI+gLzMs2u5u7Xl3nChSpjQ5Wd8arzlq2aLWQZ
+oQJpZwkCgYEAt1rJPy0pThzwYvpYEiYS2HmVEa7PWvtD19qDPOC6AaoPJzmP3J4u
+KmJXdk6g01R8G/QMb52V9Uen9m8YcCRyZqTTjWUDH7fDpuS7M+OkeRX/ytp4TCL0
+WejDMpu98bDTWvUBXdzQfUhwAVb/CMpX4rLtRdLZt8JT14OCDbpgogE=
 -----END RSA PRIVATE KEY-----
diff --git a/net/data/ssl/certificates/client_3.pem b/net/data/ssl/certificates/client_3.pem
index 4f5ad24..ccd6022 100644
--- a/net/data/ssl/certificates/client_3.pem
+++ b/net/data/ssl/certificates/client_3.pem
@@ -5,66 +5,66 @@
     Signature Algorithm: sha256WithRSAEncryption
         Issuer: CN=E CA
         Validity
-            Not Before: Oct  4 18:53:24 2016 GMT
-            Not After : Oct  2 18:53:24 2026 GMT
+            Not Before: Dec  9 20:18:57 2016 GMT
+            Not After : Dec  7 20:18:57 2026 GMT
         Subject: CN=Client Cert F
         Subject Public Key Info:
             Public Key Algorithm: rsaEncryption
                 Public-Key: (2048 bit)
                 Modulus:
-                    00:a9:b9:61:4f:52:fe:64:34:53:67:47:d8:58:22:
-                    23:82:97:6f:d0:82:e7:f7:0b:3d:db:4e:15:15:38:
-                    df:de:35:3e:eb:ac:19:9b:d8:8d:db:e8:fa:db:2f:
-                    fa:f2:20:45:92:df:f5:d3:b6:2a:03:6b:28:de:8d:
-                    24:4b:aa:3b:23:3b:7e:11:08:3e:a3:96:6f:bc:73:
-                    37:7d:54:91:fc:81:9e:8c:76:ed:d5:f6:e4:f6:8e:
-                    e8:6e:56:e2:90:eb:51:a5:f3:90:d8:45:d9:fa:1d:
-                    91:01:21:3a:61:31:3a:ea:5a:c4:e9:1a:ee:00:e6:
-                    96:62:ca:0b:a7:37:a9:1c:39:4e:12:3e:ad:ab:ed:
-                    b8:2c:86:a5:72:4c:ca:39:03:4d:61:fc:29:b8:bc:
-                    db:32:89:95:0a:62:1a:28:d6:8e:6d:eb:06:33:9a:
-                    5b:8f:e8:73:e1:2f:1e:84:21:fb:0b:38:27:b1:83:
-                    a0:c7:fe:ed:79:cc:ab:57:a5:cf:5b:b3:84:0c:b9:
-                    b8:1a:8c:90:22:59:f1:be:4d:46:0c:85:63:7b:a7:
-                    1a:49:6f:8e:ce:a2:fa:e5:29:64:03:02:dc:68:df:
-                    79:b6:6b:9b:22:07:59:af:a1:ff:ba:9c:e6:5d:d4:
-                    61:de:40:81:2e:02:96:02:aa:54:24:d4:b3:c4:18:
-                    e3:ff
+                    00:b3:5c:32:bb:c0:48:28:37:9b:45:ab:78:a0:ea:
+                    72:13:26:5d:46:ee:71:c4:24:9c:ed:a8:b6:81:35:
+                    d7:72:ba:0a:ae:a9:4e:20:61:12:22:e0:00:67:80:
+                    70:be:ac:ef:03:b2:d4:b0:3a:fc:c5:ab:85:7b:04:
+                    4b:61:85:7a:17:6c:43:36:67:0b:19:7c:74:b8:65:
+                    e9:1c:fd:f0:df:42:bc:0c:fd:09:7e:4f:7d:38:c0:
+                    52:71:e5:2b:19:80:82:aa:69:c2:36:6b:b7:2d:07:
+                    f4:74:62:bf:8e:90:ed:47:1a:64:24:ac:4c:b8:d2:
+                    2a:d0:9d:86:08:c1:18:9e:3e:de:4f:12:5c:64:a4:
+                    2b:86:43:12:81:67:0c:8c:56:e4:16:46:3c:29:cf:
+                    4e:18:ea:4f:66:5f:b4:d6:73:5f:1e:93:ad:df:c9:
+                    06:65:cc:dc:42:ba:e9:86:42:08:a1:ab:a5:fc:22:
+                    d3:23:57:a0:da:6c:80:de:c5:f9:9c:c5:11:65:9c:
+                    b2:df:f3:d6:c8:bd:aa:af:40:66:ed:ce:5f:04:46:
+                    17:e6:92:ea:64:c8:b3:e4:20:cb:e0:44:09:15:1f:
+                    7c:e4:e0:07:cd:22:7c:bd:a0:06:65:35:d4:3e:1c:
+                    07:61:8f:01:53:22:25:85:93:75:73:42:c7:c1:c0:
+                    12:9f
                 Exponent: 65537 (0x10001)
         X509v3 extensions:
             X509v3 Subject Alternative Name: 
                 email:santest@example.com, othername:<unsupported>
     Signature Algorithm: sha256WithRSAEncryption
-         5f:d8:99:71:11:d1:1f:ae:7e:4a:fa:85:ff:f6:18:60:e0:c3:
-         e8:8c:8d:7b:51:b9:ed:ea:26:e8:2b:ff:d8:5c:1e:98:cb:c6:
-         a5:e8:ef:21:af:e5:a8:f2:47:93:5e:36:66:21:7d:84:c7:b2:
-         2c:70:31:71:67:88:c4:a9:45:c1:20:1b:e1:47:df:75:d6:83:
-         a2:db:45:27:ca:fa:b1:11:b0:c2:33:bc:a7:2c:fb:bd:2b:06:
-         68:0d:95:4c:d4:2f:ab:2a:5b:f8:92:4e:9b:74:30:f2:8d:7c:
-         26:c7:f1:0f:0e:f7:f1:28:b6:84:90:db:ac:a0:1a:84:4c:3e:
-         0b:14:39:de:90:ca:58:2c:f8:16:a4:0e:4d:cd:ba:c5:1d:bb:
-         91:69:a6:55:83:96:20:ee:1f:33:58:8f:da:44:32:9b:84:1e:
-         99:d3:74:60:c9:10:67:5c:a9:03:11:74:e3:82:85:99:4c:aa:
-         4e:3d:ee:ac:91:7c:e8:b9:b1:64:08:45:48:6f:34:f4:52:8a:
-         68:f9:80:6b:5b:b2:af:83:cb:fc:77:fd:9f:d0:aa:69:3e:bd:
-         f7:ca:05:17:f8:f4:39:d3:58:9a:04:81:43:a8:b3:66:90:9e:
-         b6:27:b3:1c:25:ad:8f:8c:c6:45:a4:f6:02:60:3a:0b:5e:6f:
-         6b:e6:1b:3f
+         98:4b:03:9b:ef:b9:8b:47:81:42:9c:5b:a0:49:54:2e:e1:95:
+         51:87:9c:5c:83:b1:3c:ab:21:29:7e:e0:de:11:92:ad:75:5e:
+         9d:e2:51:70:0e:95:e3:68:3f:2e:ad:69:50:31:57:6b:6d:7b:
+         6c:d2:c5:4b:e5:a7:a1:20:ba:bf:1a:8e:86:47:94:72:35:34:
+         07:5f:1a:cf:3f:13:ad:53:7f:6b:db:ef:d8:00:a2:5c:e9:5c:
+         20:47:5a:9e:f6:91:c5:9b:05:69:f3:25:05:e2:8b:dd:d8:41:
+         99:64:44:ed:74:e2:eb:f7:42:2c:b5:d0:f1:ac:64:c0:f4:87:
+         e9:3e:51:52:41:a3:c2:4e:58:c2:ee:fe:b4:25:37:b9:3d:c2:
+         f0:cf:c0:90:7f:f6:02:b2:38:88:92:2a:e0:d4:db:87:5c:b2:
+         02:a6:60:b4:da:ab:53:d2:b2:7d:64:d5:d3:b6:35:66:96:f0:
+         ec:fb:9c:8d:35:40:e1:4a:7e:52:98:1f:1b:a2:e3:e4:35:70:
+         ec:33:ad:e8:a4:ed:a4:26:7d:07:a5:03:92:ac:11:81:4f:0f:
+         b3:c7:97:7f:29:d8:09:d1:28:11:f6:8d:9a:e0:5f:26:b9:7f:
+         74:77:e7:74:b1:5b:0f:7c:ae:13:d1:75:bc:ad:49:51:05:39:
+         06:53:6d:5c
 -----BEGIN CERTIFICATE-----
 MIIC8jCCAdqgAwIBAgICEAMwDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwERSBD
-QTAeFw0xNjEwMDQxODUzMjRaFw0yNjEwMDIxODUzMjRaMBgxFjAUBgNVBAMMDUNs
-aWVudCBDZXJ0IEYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpuWFP
-Uv5kNFNnR9hYIiOCl2/Qguf3Cz3bThUVON/eNT7rrBmb2I3b6PrbL/ryIEWS3/XT
-tioDayjejSRLqjsjO34RCD6jlm+8czd9VJH8gZ6Mdu3V9uT2juhuVuKQ61Gl85DY
-Rdn6HZEBITphMTrqWsTpGu4A5pZiygunN6kcOU4SPq2r7bgshqVyTMo5A01h/Cm4
-vNsyiZUKYhoo1o5t6wYzmluP6HPhLx6EIfsLOCexg6DH/u15zKtXpc9bs4QMubga
-jJAiWfG+TUYMhWN7pxpJb47OovrlKWQDAtxo33m2a5siB1mvof+6nOZd1GHeQIEu
-ApYCqlQk1LPEGOP/AgMBAAGjTzBNMEsGA1UdEQREMEKBE3NhbnRlc3RAZXhhbXBs
+QTAeFw0xNjEyMDkyMDE4NTdaFw0yNjEyMDcyMDE4NTdaMBgxFjAUBgNVBAMMDUNs
+aWVudCBDZXJ0IEYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzXDK7
+wEgoN5tFq3ig6nITJl1G7nHEJJztqLaBNddyugquqU4gYRIi4ABngHC+rO8DstSw
+OvzFq4V7BEthhXoXbEM2ZwsZfHS4Zekc/fDfQrwM/Ql+T304wFJx5SsZgIKqacI2
+a7ctB/R0Yr+OkO1HGmQkrEy40irQnYYIwRiePt5PElxkpCuGQxKBZwyMVuQWRjwp
+z04Y6k9mX7TWc18ek63fyQZlzNxCuumGQgihq6X8ItMjV6DabIDexfmcxRFlnLLf
+89bIvaqvQGbtzl8ERhfmkupkyLPkIMvgRAkVH3zk4AfNIny9oAZlNdQ+HAdhjwFT
+IiWFk3VzQsfBwBKfAgMBAAGjTzBNMEsGA1UdEQREMEKBE3NhbnRlc3RAZXhhbXBs
 ZS5jb22gKwYKKwYBBAGCNxQCA6AdDBtzYW50ZXN0QGFkLmNvcnAuZXhhbXBsZS5j
-b20wDQYJKoZIhvcNAQELBQADggEBAF/YmXER0R+ufkr6hf/2GGDgw+iMjXtRue3q
-Jugr/9hcHpjLxqXo7yGv5ajyR5NeNmYhfYTHsixwMXFniMSpRcEgG+FH33XWg6Lb
-RSfK+rERsMIzvKcs+70rBmgNlUzUL6sqW/iSTpt0MPKNfCbH8Q8O9/EotoSQ26yg
-GoRMPgsUOd6Qylgs+BakDk3NusUdu5FpplWDliDuHzNYj9pEMpuEHpnTdGDJEGdc
-qQMRdOOChZlMqk497qyRfOi5sWQIRUhvNPRSimj5gGtbsq+Dy/x3/Z/Qqmk+vffK
-BRf49DnTWJoEgUOos2aQnrYnsxwlrY+MxkWk9gJgOgteb2vmGz8=
+b20wDQYJKoZIhvcNAQELBQADggEBAJhLA5vvuYtHgUKcW6BJVC7hlVGHnFyDsTyr
+ISl+4N4Rkq11Xp3iUXAOleNoPy6taVAxV2tte2zSxUvlp6Egur8ajoZHlHI1NAdf
+Gs8/E61Tf2vb79gAolzpXCBHWp72kcWbBWnzJQXii93YQZlkRO104uv3Qiy10PGs
+ZMD0h+k+UVJBo8JOWMLu/rQlN7k9wvDPwJB/9gKyOIiSKuDU24dcsgKmYLTaq1PS
+sn1k1dO2NWaW8Oz7nI01QOFKflKYHxui4+Q1cOwzreik7aQmfQelA5KsEYFPD7PH
+l38p2AnRKBH2jZrgXya5f3R353SxWw98rhPRdbytSVEFOQZTbVw=
 -----END CERTIFICATE-----
diff --git a/net/data/ssl/certificates/client_3.pk8 b/net/data/ssl/certificates/client_3.pk8
index 68f019a..2ffcdb2 100644
--- a/net/data/ssl/certificates/client_3.pk8
+++ b/net/data/ssl/certificates/client_3.pk8
Binary files differ
diff --git a/net/data/ssl/certificates/client_3_ca.pem b/net/data/ssl/certificates/client_3_ca.pem
index dd58ffa7..78080961 100644
--- a/net/data/ssl/certificates/client_3_ca.pem
+++ b/net/data/ssl/certificates/client_3_ca.pem
@@ -5,31 +5,31 @@
     Signature Algorithm: sha256WithRSAEncryption
         Issuer: CN=C Root CA
         Validity
-            Not Before: Oct  4 18:53:24 2016 GMT
-            Not After : Oct  2 18:53:24 2026 GMT
+            Not Before: Dec  9 20:18:57 2016 GMT
+            Not After : Dec  7 20:18:57 2026 GMT
         Subject: CN=E CA
         Subject Public Key Info:
             Public Key Algorithm: rsaEncryption
                 Public-Key: (2048 bit)
                 Modulus:
-                    00:a2:7e:a3:fd:c1:d7:78:cd:57:ac:67:54:37:69:
-                    fb:72:6f:1d:8f:d0:47:0f:11:14:ab:42:d8:3d:6a:
-                    34:2b:d6:38:07:df:16:1d:c6:62:eb:d7:12:e1:86:
-                    83:f2:dd:8f:97:09:94:8f:1b:ff:3b:84:9b:48:e5:
-                    0d:43:6b:ae:bb:75:88:1c:c6:3a:7f:d8:12:d9:7c:
-                    12:18:6d:e2:f0:88:d4:3e:5a:93:b3:af:c1:79:a1:
-                    b6:a3:f7:56:46:21:e6:7d:6e:36:ea:ba:4b:52:f7:
-                    a9:45:0b:83:09:2c:09:22:8a:67:5a:8f:88:60:b0:
-                    11:07:25:9b:c2:6a:3c:63:4c:0e:69:45:ce:9d:ba:
-                    c9:d4:01:fb:78:56:38:08:8f:e5:d6:ff:ac:e4:04:
-                    fa:26:cf:d2:05:33:57:a3:8e:80:c0:b6:40:d5:d3:
-                    ca:85:17:30:b2:24:f4:19:af:c5:48:a4:ed:c0:49:
-                    c1:a4:b7:89:29:ba:e5:2d:37:78:1c:d6:3e:9b:03:
-                    fa:bc:7b:e2:76:a6:70:f3:1b:9d:b2:4b:fc:72:7b:
-                    77:89:50:bb:88:2f:b5:b6:a2:c7:33:27:b7:d1:1a:
-                    7c:d4:58:e3:5e:88:ca:f8:49:c3:cd:cc:0f:93:4b:
-                    3c:fd:75:c3:7b:6f:bf:d3:db:ba:2e:31:7b:a7:a5:
-                    42:c5
+                    00:c3:39:c3:5a:8e:ff:f2:1d:cc:26:91:5d:15:9e:
+                    ca:e0:fb:cf:99:5f:13:3d:c6:37:59:8b:ce:cc:76:
+                    0e:1c:9f:b6:49:5b:09:97:63:9d:e1:00:74:44:fb:
+                    2f:53:f3:d5:03:92:77:97:53:74:7e:d2:da:d3:a3:
+                    f4:c1:91:6a:83:ff:89:fe:73:46:56:ca:6d:51:0d:
+                    57:16:3d:3e:e8:fc:00:d9:4a:7a:7d:93:84:06:12:
+                    c5:ff:31:b3:a6:eb:96:18:71:b8:56:5c:2f:ab:78:
+                    e2:53:dd:15:d8:65:c8:f6:96:14:dc:15:cf:2a:39:
+                    ed:e1:08:1b:84:29:c7:1c:78:67:c8:e0:72:58:4e:
+                    33:7f:cb:ef:71:82:db:45:1d:7c:0c:d0:f5:4c:af:
+                    85:6b:14:61:50:87:34:42:fe:45:a3:3c:a3:53:57:
+                    1d:ac:11:c8:cf:2f:5e:cb:78:87:39:a1:41:3f:69:
+                    21:5c:1e:19:02:a3:6c:91:d3:1b:4e:50:fc:a4:b1:
+                    03:87:c0:58:b1:fe:cd:58:5e:53:ed:c9:d6:5d:9e:
+                    a3:fb:0d:e0:a0:8e:3d:c9:9e:9e:83:07:61:c7:30:
+                    5a:ca:29:93:04:af:5e:f3:57:2e:c2:d8:c8:ae:7f:
+                    5c:a4:27:fa:cd:55:a2:fd:89:d2:0b:87:24:6b:7b:
+                    fb:19
                 Exponent: 65537 (0x10001)
         X509v3 extensions:
             X509v3 Basic Constraints: critical
@@ -37,35 +37,35 @@
             X509v3 Key Usage: critical
                 Certificate Sign, CRL Sign
     Signature Algorithm: sha256WithRSAEncryption
-         92:8b:93:94:03:04:91:3f:4d:8b:f3:90:53:ee:73:b5:33:c7:
-         61:ea:0f:a5:59:9b:f0:0d:4f:7d:48:0d:5a:58:e7:1f:68:f6:
-         d6:58:75:33:a5:d2:b7:65:6a:28:40:bc:0e:1e:78:ee:9a:13:
-         3c:b0:8b:8f:98:72:86:50:3a:a3:bf:6d:f0:21:95:a8:73:d0:
-         dd:e5:0e:25:b1:62:76:65:69:1f:ee:26:82:ab:be:a4:a8:30:
-         a7:41:34:07:57:2f:8b:ab:25:af:cb:23:a5:79:cf:b2:a2:17:
-         02:a7:aa:50:92:6e:0d:9b:ff:c9:22:38:b4:0f:47:94:d2:80:
-         7f:92:30:00:ec:5b:22:e2:a6:71:5e:e8:8f:0d:2f:38:2c:29:
-         47:6a:7f:20:0a:e2:42:cb:b7:6e:2b:29:0f:03:55:94:84:5f:
-         e7:47:bf:ae:75:88:05:4e:42:ac:78:57:9d:9c:e2:77:d2:17:
-         42:55:ba:f8:77:ee:61:d6:e8:ec:aa:e0:7a:a6:65:c6:35:80:
-         08:3d:39:a6:70:8c:9e:6d:7a:ee:e7:cf:36:46:98:00:c8:7b:
-         b8:84:7f:9d:9f:bd:31:4f:99:25:6e:76:9a:5d:46:3e:40:70:
-         c6:a8:03:f3:98:9c:be:fb:f6:ad:c2:8d:e3:f9:7d:93:3a:78:
-         da:b3:d7:dc
+         67:d4:6c:cf:cd:54:81:67:2a:c2:c4:66:c7:76:9c:b0:8b:6b:
+         ef:b8:ae:a9:b3:d6:f8:47:91:d5:97:0b:bd:1a:87:21:8c:ce:
+         be:0c:80:d5:a5:25:0d:0a:c7:ed:be:cb:8c:6d:08:e8:de:a5:
+         33:89:e6:87:df:2b:f4:54:b3:c2:94:15:0d:36:5e:1a:aa:c0:
+         b0:03:3c:24:c6:a1:81:91:ca:fe:db:0f:59:1b:d6:4e:48:0b:
+         52:d3:e7:07:d7:b1:ca:b2:22:e4:d4:37:a4:3c:87:3c:0a:11:
+         a6:10:2a:ed:86:2a:bb:db:10:7e:f3:a5:fc:10:ab:80:5b:07:
+         58:7c:22:76:3e:9b:9c:72:79:0d:dc:85:f8:e7:c2:0f:17:aa:
+         01:dd:8e:24:27:77:4e:23:03:da:88:e0:df:e6:ca:b4:84:56:
+         a1:dc:9f:e0:93:94:97:d2:98:cd:32:6d:73:84:f9:3e:4c:96:
+         b3:51:07:b8:9f:66:32:d1:ac:53:0e:17:a9:6f:29:d1:7b:73:
+         b3:55:9b:cc:8f:8b:e5:49:fd:fd:f2:30:d6:d0:f7:03:06:12:
+         e3:66:2d:0d:a1:da:28:04:04:29:b8:40:6e:0e:6f:31:48:cb:
+         54:f7:e2:89:22:d8:05:e0:f5:7e:48:b3:96:ff:6b:ef:e7:fe:
+         71:1d:0b:77
 -----BEGIN CERTIFICATE-----
 MIICwjCCAaqgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwFDESMBAGA1UEAwwJQyBS
-b290IENBMB4XDTE2MTAwNDE4NTMyNFoXDTI2MTAwMjE4NTMyNFowDzENMAsGA1UE
-AwwERSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKJ+o/3B13jN
-V6xnVDdp+3JvHY/QRw8RFKtC2D1qNCvWOAffFh3GYuvXEuGGg/Ldj5cJlI8b/zuE
-m0jlDUNrrrt1iBzGOn/YEtl8Ehht4vCI1D5ak7OvwXmhtqP3VkYh5n1uNuq6S1L3
-qUULgwksCSKKZ1qPiGCwEQclm8JqPGNMDmlFzp26ydQB+3hWOAiP5db/rOQE+ibP
-0gUzV6OOgMC2QNXTyoUXMLIk9BmvxUik7cBJwaS3iSm65S03eBzWPpsD+rx74nam
-cPMbnbJL/HJ7d4lQu4gvtbaixzMnt9EafNRY416IyvhJw83MD5NLPP11w3tvv9Pb
-ui4xe6elQsUCAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
-AQYwDQYJKoZIhvcNAQELBQADggEBAJKLk5QDBJE/TYvzkFPuc7Uzx2HqD6VZm/AN
-T31IDVpY5x9o9tZYdTOl0rdlaihAvA4eeO6aEzywi4+YcoZQOqO/bfAhlahz0N3l
-DiWxYnZlaR/uJoKrvqSoMKdBNAdXL4urJa/LI6V5z7KiFwKnqlCSbg2b/8kiOLQP
-R5TSgH+SMADsWyLipnFe6I8NLzgsKUdqfyAK4kLLt24rKQ8DVZSEX+dHv651iAVO
-Qqx4V52c4nfSF0JVuvh37mHW6Oyq4HqmZcY1gAg9OaZwjJ5teu7nzzZGmADIe7iE
-f52fvTFPmSVudppdRj5AcMaoA/OYnL779q3CjeP5fZM6eNqz19w=
+b290IENBMB4XDTE2MTIwOTIwMTg1N1oXDTI2MTIwNzIwMTg1N1owDzENMAsGA1UE
+AwwERSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMM5w1qO//Id
+zCaRXRWeyuD7z5lfEz3GN1mLzsx2DhyftklbCZdjneEAdET7L1Pz1QOSd5dTdH7S
+2tOj9MGRaoP/if5zRlbKbVENVxY9Puj8ANlKen2ThAYSxf8xs6brlhhxuFZcL6t4
+4lPdFdhlyPaWFNwVzyo57eEIG4Qpxxx4Z8jgclhOM3/L73GC20UdfAzQ9UyvhWsU
+YVCHNEL+RaM8o1NXHawRyM8vXst4hzmhQT9pIVweGQKjbJHTG05Q/KSxA4fAWLH+
+zVheU+3J1l2eo/sN4KCOPcmenoMHYccwWsopkwSvXvNXLsLYyK5/XKQn+s1Vov2J
+0guHJGt7+xkCAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQELBQADggEBAGfUbM/NVIFnKsLEZsd2nLCLa++4rqmz1vhH
+kdWXC70ahyGMzr4MgNWlJQ0Kx+2+y4xtCOjepTOJ5offK/RUs8KUFQ02XhqqwLAD
+PCTGoYGRyv7bD1kb1k5IC1LT5wfXscqyIuTUN6Q8hzwKEaYQKu2GKrvbEH7zpfwQ
+q4BbB1h8InY+m5xyeQ3chfjnwg8XqgHdjiQnd04jA9qI4N/myrSEVqHcn+CTlJfS
+mM0ybXOE+T5MlrNRB7ifZjLRrFMOF6lvKdF7c7NVm8yPi+VJ/f3yMNbQ9wMGEuNm
+LQ2h2igEBCm4QG4ObzFIy1T34oki2AXg9X5Is5b/a+/n/nEdC3c=
 -----END CERTIFICATE-----
diff --git a/net/data/ssl/certificates/client_4.key b/net/data/ssl/certificates/client_4.key
index b1e7e0f..43175e9 100644
--- a/net/data/ssl/certificates/client_4.key
+++ b/net/data/ssl/certificates/client_4.key
@@ -1,5 +1,5 @@
 -----BEGIN EC PRIVATE KEY-----
-MHcCAQEEILP75xbRvuB3x6CmLmO6dnAz4SzWM52MjX/ENrMfZWSEoAoGCCqGSM49
-AwEHoUQDQgAEeS7h2cVpnREfhVilcTyRzlg4kE1IhGT3MUl1BkvR5e1EgvkLapKA
-8lLte3NLOoH/gPKnhLDPmN5N2uTCEZhpzw==
+MHcCAQEEIMivPU8D2DOgGS1XWJ0SHOybwHGLYceOy0di/O3NTyfooAoGCCqGSM49
+AwEHoUQDQgAEicT32YPEOZz49vy8i2ZucO1QMh1i5zJMBmKPOCgzY1l9FmLhv61t
+3zRtxNZRllR1HFiAOIOIVcadhrfDZqF5Zw==
 -----END EC PRIVATE KEY-----
diff --git a/net/data/ssl/certificates/client_4.pem b/net/data/ssl/certificates/client_4.pem
index 3eeca24..914b453 100644
--- a/net/data/ssl/certificates/client_4.pem
+++ b/net/data/ssl/certificates/client_4.pem
@@ -5,18 +5,18 @@
     Signature Algorithm: sha256WithRSAEncryption
         Issuer: CN=E CA
         Validity
-            Not Before: Oct  4 18:53:24 2016 GMT
-            Not After : Oct  2 18:53:24 2026 GMT
+            Not Before: Dec  9 20:18:57 2016 GMT
+            Not After : Dec  7 20:18:57 2026 GMT
         Subject: CN=Client Cert G
         Subject Public Key Info:
             Public Key Algorithm: id-ecPublicKey
                 Public-Key: (256 bit)
                 pub: 
-                    04:79:2e:e1:d9:c5:69:9d:11:1f:85:58:a5:71:3c:
-                    91:ce:58:38:90:4d:48:84:64:f7:31:49:75:06:4b:
-                    d1:e5:ed:44:82:f9:0b:6a:92:80:f2:52:ed:7b:73:
-                    4b:3a:81:ff:80:f2:a7:84:b0:cf:98:de:4d:da:e4:
-                    c2:11:98:69:cf
+                    04:89:c4:f7:d9:83:c4:39:9c:f8:f6:fc:bc:8b:66:
+                    6e:70:ed:50:32:1d:62:e7:32:4c:06:62:8f:38:28:
+                    33:63:59:7d:16:62:e1:bf:ad:6d:df:34:6d:c4:d6:
+                    51:96:54:75:1c:58:80:38:83:88:55:c6:9d:86:b7:
+                    c3:66:a1:79:67
                 ASN1 OID: prime256v1
         X509v3 extensions:
             X509v3 Basic Constraints: critical
@@ -24,31 +24,31 @@
             X509v3 Extended Key Usage: 
                 TLS Web Server Authentication, TLS Web Client Authentication
     Signature Algorithm: sha256WithRSAEncryption
-         70:44:30:40:b7:d6:5b:09:e6:81:a1:a7:80:cd:bc:12:5d:e1:
-         45:7d:fb:04:5f:5f:21:b9:e5:a9:e0:79:52:5a:50:21:11:bb:
-         8c:25:08:e1:6d:19:e3:ba:e7:69:74:db:a6:b2:41:a4:f5:39:
-         63:18:e6:bc:ce:db:d8:3f:17:e1:90:9f:62:3a:d3:52:f4:c4:
-         01:4d:db:ad:16:ad:8b:31:51:fe:82:68:fd:34:c4:58:dc:4d:
-         6b:72:74:30:98:a6:03:4b:21:dd:54:1b:ed:e0:a5:3f:a9:5e:
-         1d:e6:57:3f:13:f4:e0:dc:d0:bf:90:68:dc:e1:e7:b5:81:b4:
-         f8:d5:45:96:95:b9:cd:83:15:c8:32:a6:20:2c:fc:b5:05:42:
-         1a:7e:26:4c:a1:9a:8b:26:2b:1b:72:c7:a5:38:f3:57:4c:b4:
-         7f:8e:dc:d9:52:0a:52:ac:e5:d9:18:0b:ae:91:b9:c5:e0:13:
-         cb:15:8d:19:3b:e9:60:1b:6b:31:0a:c7:22:4a:5a:ed:49:cf:
-         72:e1:dd:93:1e:43:a8:e0:3e:02:b6:06:ee:b9:a9:d3:d9:88:
-         2d:81:f6:96:cb:13:07:a8:51:81:89:8c:6b:28:d3:0c:22:8f:
-         e9:d7:92:1d:5a:2a:d6:c0:55:6b:86:2b:a7:f9:9e:35:88:5d:
-         bb:42:eb:b8
+         43:3c:6f:e4:e7:89:a9:fe:f8:d0:d6:a0:13:94:1b:a1:98:22:
+         26:0d:e1:3b:a1:91:41:f1:5e:88:38:cb:7d:f0:55:8c:c3:df:
+         a3:99:31:71:0c:d0:1f:23:86:89:d7:ca:9f:f0:c6:bc:d2:b8:
+         0b:4e:bc:bf:63:93:4e:c4:71:65:97:c0:f2:ea:35:34:9c:d5:
+         b5:8e:15:2e:bb:0b:63:ab:f6:fd:5d:2d:22:f7:00:e6:5a:88:
+         01:6f:f8:ef:8a:be:68:1d:95:b5:c9:b2:47:be:cd:98:bd:5a:
+         ae:a2:b9:a3:53:bc:9e:87:de:40:a6:17:b5:7c:bd:4d:35:f5:
+         29:72:22:a7:ee:2a:bc:4c:e2:b0:a6:98:47:1d:93:01:f8:53:
+         ee:af:e3:3a:1f:a2:e0:36:eb:67:28:7a:39:b8:89:95:44:57:
+         08:bb:20:8d:0b:27:36:15:ce:48:11:ae:32:07:ef:44:12:e5:
+         97:2e:92:56:c4:d6:93:0f:41:25:38:e5:52:0e:c3:f3:cc:9d:
+         de:b0:1d:4e:e3:51:79:63:0f:4c:58:ea:7c:e7:7a:ac:a8:f3:
+         c4:45:16:34:77:ba:6b:a7:49:9c:aa:62:d1:dd:81:6b:55:08:
+         38:39:11:23:a0:ec:50:ff:58:ca:22:d3:29:c8:2e:bc:35:62:
+         9b:cd:56:fb
 -----BEGIN CERTIFICATE-----
 MIICBjCB76ADAgECAgIQBDANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARFIENB
-MB4XDTE2MTAwNDE4NTMyNFoXDTI2MTAwMjE4NTMyNFowGDEWMBQGA1UEAwwNQ2xp
-ZW50IENlcnQgRzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABHku4dnFaZ0RH4VY
-pXE8kc5YOJBNSIRk9zFJdQZL0eXtRIL5C2qSgPJS7XtzSzqB/4Dyp4Swz5jeTdrk
-whGYac+jLzAtMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG
-AQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQBwRDBAt9ZbCeaBoaeAzbwSXeFFffsE
-X18hueWp4HlSWlAhEbuMJQjhbRnjuudpdNumskGk9TljGOa8ztvYPxfhkJ9iOtNS
-9MQBTdutFq2LMVH+gmj9NMRY3E1rcnQwmKYDSyHdVBvt4KU/qV4d5lc/E/Tg3NC/
-kGjc4ee1gbT41UWWlbnNgxXIMqYgLPy1BUIafiZMoZqLJisbcselOPNXTLR/jtzZ
-UgpSrOXZGAuukbnF4BPLFY0ZO+lgG2sxCsciSlrtSc9y4d2THkOo4D4CtgbuuanT
-2YgtgfaWyxMHqFGBiYxrKNMMIo/p15IdWirWwFVrhiun+Z41iF27Quu4
+MB4XDTE2MTIwOTIwMTg1N1oXDTI2MTIwNzIwMTg1N1owGDEWMBQGA1UEAwwNQ2xp
+ZW50IENlcnQgRzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABInE99mDxDmc+Pb8
+vItmbnDtUDIdYucyTAZijzgoM2NZfRZi4b+tbd80bcTWUZZUdRxYgDiDiFXGnYa3
+w2aheWejLzAtMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG
+AQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQBDPG/k54mp/vjQ1qATlBuhmCImDeE7
+oZFB8V6IOMt98FWMw9+jmTFxDNAfI4aJ18qf8Ma80rgLTry/Y5NOxHFll8Dy6jU0
+nNW1jhUuuwtjq/b9XS0i9wDmWogBb/jvir5oHZW1ybJHvs2YvVquormjU7yeh95A
+phe1fL1NNfUpciKn7iq8TOKwpphHHZMB+FPur+M6H6LgNutnKHo5uImVRFcIuyCN
+Cyc2Fc5IEa4yB+9EEuWXLpJWxNaTD0ElOOVSDsPzzJ3esB1O41F5Yw9MWOp853qs
+qPPERRY0d7prp0mcqmLR3YFrVQg4OREjoOxQ/1jKItMpyC68NWKbzVb7
 -----END CERTIFICATE-----
diff --git a/net/data/ssl/certificates/client_4.pk8 b/net/data/ssl/certificates/client_4.pk8
index 20ea5cfd..5f5f1580 100644
--- a/net/data/ssl/certificates/client_4.pk8
+++ b/net/data/ssl/certificates/client_4.pk8
Binary files differ
diff --git a/net/data/ssl/certificates/client_4_ca.pem b/net/data/ssl/certificates/client_4_ca.pem
index dd58ffa7..78080961 100644
--- a/net/data/ssl/certificates/client_4_ca.pem
+++ b/net/data/ssl/certificates/client_4_ca.pem
@@ -5,31 +5,31 @@
     Signature Algorithm: sha256WithRSAEncryption
         Issuer: CN=C Root CA
         Validity
-            Not Before: Oct  4 18:53:24 2016 GMT
-            Not After : Oct  2 18:53:24 2026 GMT
+            Not Before: Dec  9 20:18:57 2016 GMT
+            Not After : Dec  7 20:18:57 2026 GMT
         Subject: CN=E CA
         Subject Public Key Info:
             Public Key Algorithm: rsaEncryption
                 Public-Key: (2048 bit)
                 Modulus:
-                    00:a2:7e:a3:fd:c1:d7:78:cd:57:ac:67:54:37:69:
-                    fb:72:6f:1d:8f:d0:47:0f:11:14:ab:42:d8:3d:6a:
-                    34:2b:d6:38:07:df:16:1d:c6:62:eb:d7:12:e1:86:
-                    83:f2:dd:8f:97:09:94:8f:1b:ff:3b:84:9b:48:e5:
-                    0d:43:6b:ae:bb:75:88:1c:c6:3a:7f:d8:12:d9:7c:
-                    12:18:6d:e2:f0:88:d4:3e:5a:93:b3:af:c1:79:a1:
-                    b6:a3:f7:56:46:21:e6:7d:6e:36:ea:ba:4b:52:f7:
-                    a9:45:0b:83:09:2c:09:22:8a:67:5a:8f:88:60:b0:
-                    11:07:25:9b:c2:6a:3c:63:4c:0e:69:45:ce:9d:ba:
-                    c9:d4:01:fb:78:56:38:08:8f:e5:d6:ff:ac:e4:04:
-                    fa:26:cf:d2:05:33:57:a3:8e:80:c0:b6:40:d5:d3:
-                    ca:85:17:30:b2:24:f4:19:af:c5:48:a4:ed:c0:49:
-                    c1:a4:b7:89:29:ba:e5:2d:37:78:1c:d6:3e:9b:03:
-                    fa:bc:7b:e2:76:a6:70:f3:1b:9d:b2:4b:fc:72:7b:
-                    77:89:50:bb:88:2f:b5:b6:a2:c7:33:27:b7:d1:1a:
-                    7c:d4:58:e3:5e:88:ca:f8:49:c3:cd:cc:0f:93:4b:
-                    3c:fd:75:c3:7b:6f:bf:d3:db:ba:2e:31:7b:a7:a5:
-                    42:c5
+                    00:c3:39:c3:5a:8e:ff:f2:1d:cc:26:91:5d:15:9e:
+                    ca:e0:fb:cf:99:5f:13:3d:c6:37:59:8b:ce:cc:76:
+                    0e:1c:9f:b6:49:5b:09:97:63:9d:e1:00:74:44:fb:
+                    2f:53:f3:d5:03:92:77:97:53:74:7e:d2:da:d3:a3:
+                    f4:c1:91:6a:83:ff:89:fe:73:46:56:ca:6d:51:0d:
+                    57:16:3d:3e:e8:fc:00:d9:4a:7a:7d:93:84:06:12:
+                    c5:ff:31:b3:a6:eb:96:18:71:b8:56:5c:2f:ab:78:
+                    e2:53:dd:15:d8:65:c8:f6:96:14:dc:15:cf:2a:39:
+                    ed:e1:08:1b:84:29:c7:1c:78:67:c8:e0:72:58:4e:
+                    33:7f:cb:ef:71:82:db:45:1d:7c:0c:d0:f5:4c:af:
+                    85:6b:14:61:50:87:34:42:fe:45:a3:3c:a3:53:57:
+                    1d:ac:11:c8:cf:2f:5e:cb:78:87:39:a1:41:3f:69:
+                    21:5c:1e:19:02:a3:6c:91:d3:1b:4e:50:fc:a4:b1:
+                    03:87:c0:58:b1:fe:cd:58:5e:53:ed:c9:d6:5d:9e:
+                    a3:fb:0d:e0:a0:8e:3d:c9:9e:9e:83:07:61:c7:30:
+                    5a:ca:29:93:04:af:5e:f3:57:2e:c2:d8:c8:ae:7f:
+                    5c:a4:27:fa:cd:55:a2:fd:89:d2:0b:87:24:6b:7b:
+                    fb:19
                 Exponent: 65537 (0x10001)
         X509v3 extensions:
             X509v3 Basic Constraints: critical
@@ -37,35 +37,35 @@
             X509v3 Key Usage: critical
                 Certificate Sign, CRL Sign
     Signature Algorithm: sha256WithRSAEncryption
-         92:8b:93:94:03:04:91:3f:4d:8b:f3:90:53:ee:73:b5:33:c7:
-         61:ea:0f:a5:59:9b:f0:0d:4f:7d:48:0d:5a:58:e7:1f:68:f6:
-         d6:58:75:33:a5:d2:b7:65:6a:28:40:bc:0e:1e:78:ee:9a:13:
-         3c:b0:8b:8f:98:72:86:50:3a:a3:bf:6d:f0:21:95:a8:73:d0:
-         dd:e5:0e:25:b1:62:76:65:69:1f:ee:26:82:ab:be:a4:a8:30:
-         a7:41:34:07:57:2f:8b:ab:25:af:cb:23:a5:79:cf:b2:a2:17:
-         02:a7:aa:50:92:6e:0d:9b:ff:c9:22:38:b4:0f:47:94:d2:80:
-         7f:92:30:00:ec:5b:22:e2:a6:71:5e:e8:8f:0d:2f:38:2c:29:
-         47:6a:7f:20:0a:e2:42:cb:b7:6e:2b:29:0f:03:55:94:84:5f:
-         e7:47:bf:ae:75:88:05:4e:42:ac:78:57:9d:9c:e2:77:d2:17:
-         42:55:ba:f8:77:ee:61:d6:e8:ec:aa:e0:7a:a6:65:c6:35:80:
-         08:3d:39:a6:70:8c:9e:6d:7a:ee:e7:cf:36:46:98:00:c8:7b:
-         b8:84:7f:9d:9f:bd:31:4f:99:25:6e:76:9a:5d:46:3e:40:70:
-         c6:a8:03:f3:98:9c:be:fb:f6:ad:c2:8d:e3:f9:7d:93:3a:78:
-         da:b3:d7:dc
+         67:d4:6c:cf:cd:54:81:67:2a:c2:c4:66:c7:76:9c:b0:8b:6b:
+         ef:b8:ae:a9:b3:d6:f8:47:91:d5:97:0b:bd:1a:87:21:8c:ce:
+         be:0c:80:d5:a5:25:0d:0a:c7:ed:be:cb:8c:6d:08:e8:de:a5:
+         33:89:e6:87:df:2b:f4:54:b3:c2:94:15:0d:36:5e:1a:aa:c0:
+         b0:03:3c:24:c6:a1:81:91:ca:fe:db:0f:59:1b:d6:4e:48:0b:
+         52:d3:e7:07:d7:b1:ca:b2:22:e4:d4:37:a4:3c:87:3c:0a:11:
+         a6:10:2a:ed:86:2a:bb:db:10:7e:f3:a5:fc:10:ab:80:5b:07:
+         58:7c:22:76:3e:9b:9c:72:79:0d:dc:85:f8:e7:c2:0f:17:aa:
+         01:dd:8e:24:27:77:4e:23:03:da:88:e0:df:e6:ca:b4:84:56:
+         a1:dc:9f:e0:93:94:97:d2:98:cd:32:6d:73:84:f9:3e:4c:96:
+         b3:51:07:b8:9f:66:32:d1:ac:53:0e:17:a9:6f:29:d1:7b:73:
+         b3:55:9b:cc:8f:8b:e5:49:fd:fd:f2:30:d6:d0:f7:03:06:12:
+         e3:66:2d:0d:a1:da:28:04:04:29:b8:40:6e:0e:6f:31:48:cb:
+         54:f7:e2:89:22:d8:05:e0:f5:7e:48:b3:96:ff:6b:ef:e7:fe:
+         71:1d:0b:77
 -----BEGIN CERTIFICATE-----
 MIICwjCCAaqgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwFDESMBAGA1UEAwwJQyBS
-b290IENBMB4XDTE2MTAwNDE4NTMyNFoXDTI2MTAwMjE4NTMyNFowDzENMAsGA1UE
-AwwERSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKJ+o/3B13jN
-V6xnVDdp+3JvHY/QRw8RFKtC2D1qNCvWOAffFh3GYuvXEuGGg/Ldj5cJlI8b/zuE
-m0jlDUNrrrt1iBzGOn/YEtl8Ehht4vCI1D5ak7OvwXmhtqP3VkYh5n1uNuq6S1L3
-qUULgwksCSKKZ1qPiGCwEQclm8JqPGNMDmlFzp26ydQB+3hWOAiP5db/rOQE+ibP
-0gUzV6OOgMC2QNXTyoUXMLIk9BmvxUik7cBJwaS3iSm65S03eBzWPpsD+rx74nam
-cPMbnbJL/HJ7d4lQu4gvtbaixzMnt9EafNRY416IyvhJw83MD5NLPP11w3tvv9Pb
-ui4xe6elQsUCAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
-AQYwDQYJKoZIhvcNAQELBQADggEBAJKLk5QDBJE/TYvzkFPuc7Uzx2HqD6VZm/AN
-T31IDVpY5x9o9tZYdTOl0rdlaihAvA4eeO6aEzywi4+YcoZQOqO/bfAhlahz0N3l
-DiWxYnZlaR/uJoKrvqSoMKdBNAdXL4urJa/LI6V5z7KiFwKnqlCSbg2b/8kiOLQP
-R5TSgH+SMADsWyLipnFe6I8NLzgsKUdqfyAK4kLLt24rKQ8DVZSEX+dHv651iAVO
-Qqx4V52c4nfSF0JVuvh37mHW6Oyq4HqmZcY1gAg9OaZwjJ5teu7nzzZGmADIe7iE
-f52fvTFPmSVudppdRj5AcMaoA/OYnL779q3CjeP5fZM6eNqz19w=
+b290IENBMB4XDTE2MTIwOTIwMTg1N1oXDTI2MTIwNzIwMTg1N1owDzENMAsGA1UE
+AwwERSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMM5w1qO//Id
+zCaRXRWeyuD7z5lfEz3GN1mLzsx2DhyftklbCZdjneEAdET7L1Pz1QOSd5dTdH7S
+2tOj9MGRaoP/if5zRlbKbVENVxY9Puj8ANlKen2ThAYSxf8xs6brlhhxuFZcL6t4
+4lPdFdhlyPaWFNwVzyo57eEIG4Qpxxx4Z8jgclhOM3/L73GC20UdfAzQ9UyvhWsU
+YVCHNEL+RaM8o1NXHawRyM8vXst4hzmhQT9pIVweGQKjbJHTG05Q/KSxA4fAWLH+
+zVheU+3J1l2eo/sN4KCOPcmenoMHYccwWsopkwSvXvNXLsLYyK5/XKQn+s1Vov2J
+0guHJGt7+xkCAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQELBQADggEBAGfUbM/NVIFnKsLEZsd2nLCLa++4rqmz1vhH
+kdWXC70ahyGMzr4MgNWlJQ0Kx+2+y4xtCOjepTOJ5offK/RUs8KUFQ02XhqqwLAD
+PCTGoYGRyv7bD1kb1k5IC1LT5wfXscqyIuTUN6Q8hzwKEaYQKu2GKrvbEH7zpfwQ
+q4BbB1h8InY+m5xyeQ3chfjnwg8XqgHdjiQnd04jA9qI4N/myrSEVqHcn+CTlJfS
+mM0ybXOE+T5MlrNRB7ifZjLRrFMOF6lvKdF7c7NVm8yPi+VJ/f3yMNbQ9wMGEuNm
+LQ2h2igEBCm4QG4ObzFIy1T34oki2AXg9X5Is5b/a+/n/nEdC3c=
 -----END CERTIFICATE-----
diff --git a/net/data/ssl/certificates/client_5.key b/net/data/ssl/certificates/client_5.key
new file mode 100644
index 0000000..ab74e24
--- /dev/null
+++ b/net/data/ssl/certificates/client_5.key
@@ -0,0 +1,6 @@
+-----BEGIN EC PRIVATE KEY-----
+MIGkAgEBBDDIPJAB+fFVxe/nIqgAGt9Pff2OF9Ts6WOBW3RZbf5o3SZiuS1fhUh1
+ppZfdaRmjEygBwYFK4EEACKhZANiAARMBdRlPc2YnctgdjXBkdxS79SBGI4WBsRz
+jiYMjMkPGDVdN/kID0Gi5hkwXTZ6yhRmbqf7NdNsC5f2nH74BTfoqn//Aj0SroiI
+OalVGt2S2NW6ea690MvYnA/AM2B3L/Y=
+-----END EC PRIVATE KEY-----
diff --git a/net/data/ssl/certificates/client_5.pem b/net/data/ssl/certificates/client_5.pem
new file mode 100644
index 0000000..e984048
--- /dev/null
+++ b/net/data/ssl/certificates/client_5.pem
@@ -0,0 +1,57 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 4101 (0x1005)
+    Signature Algorithm: sha256WithRSAEncryption
+        Issuer: CN=E CA
+        Validity
+            Not Before: Dec  9 20:18:57 2016 GMT
+            Not After : Dec  7 20:18:57 2026 GMT
+        Subject: CN=Client Cert H
+        Subject Public Key Info:
+            Public Key Algorithm: id-ecPublicKey
+                Public-Key: (384 bit)
+                pub: 
+                    04:4c:05:d4:65:3d:cd:98:9d:cb:60:76:35:c1:91:
+                    dc:52:ef:d4:81:18:8e:16:06:c4:73:8e:26:0c:8c:
+                    c9:0f:18:35:5d:37:f9:08:0f:41:a2:e6:19:30:5d:
+                    36:7a:ca:14:66:6e:a7:fb:35:d3:6c:0b:97:f6:9c:
+                    7e:f8:05:37:e8:aa:7f:ff:02:3d:12:ae:88:88:39:
+                    a9:55:1a:dd:92:d8:d5:ba:79:ae:bd:d0:cb:d8:9c:
+                    0f:c0:33:60:77:2f:f6
+                ASN1 OID: secp384r1
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Extended Key Usage: 
+                TLS Web Server Authentication, TLS Web Client Authentication
+    Signature Algorithm: sha256WithRSAEncryption
+         b2:37:fc:b9:0c:90:27:fc:e3:3e:a7:6f:c6:94:95:2c:61:37:
+         46:25:64:55:ae:61:fe:00:58:0e:64:5f:9a:5b:bc:3a:b7:52:
+         e1:42:9a:8a:05:c2:b6:1d:cc:d7:47:a8:88:d5:78:1f:74:08:
+         db:52:e1:00:3c:aa:7c:80:73:b1:91:f9:75:6e:d3:53:28:ef:
+         af:5a:b7:1d:3e:38:a8:b8:1b:48:ed:20:18:a8:4a:de:60:97:
+         bb:3f:b6:b8:cc:d5:5b:bf:1c:97:06:d1:9a:25:b8:85:1c:36:
+         26:02:e0:78:47:e0:f5:07:a4:0a:6a:55:14:39:51:d6:f3:f2:
+         b9:d4:44:9d:78:c4:45:e5:39:6f:71:0e:bd:2a:7b:71:9e:c4:
+         12:f2:52:f0:ed:6a:78:47:48:df:ea:a0:44:eb:ce:f6:5c:50:
+         53:47:3d:a6:db:ca:ad:a7:62:d8:6d:06:56:9f:e2:1b:72:08:
+         b3:4a:cb:2d:e9:4a:62:9e:c1:7e:5e:bd:ce:08:2f:82:bd:2f:
+         6e:8b:55:e2:43:01:e6:30:40:b7:67:3c:0d:96:e1:9a:33:bd:
+         b8:c2:88:03:f5:87:68:4d:6d:49:7f:8e:94:f3:6a:41:2f:31:
+         19:b6:0d:33:61:24:41:33:16:d4:5b:ad:98:8e:05:f7:9c:a1:
+         13:dd:5f:7d
+-----BEGIN CERTIFICATE-----
+MIICJDCCAQygAwIBAgICEAUwDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwERSBD
+QTAeFw0xNjEyMDkyMDE4NTdaFw0yNjEyMDcyMDE4NTdaMBgxFjAUBgNVBAMMDUNs
+aWVudCBDZXJ0IEgwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARMBdRlPc2YnctgdjXB
+kdxS79SBGI4WBsRzjiYMjMkPGDVdN/kID0Gi5hkwXTZ6yhRmbqf7NdNsC5f2nH74
+BTfoqn//Aj0SroiIOalVGt2S2NW6ea690MvYnA/AM2B3L/ajLzAtMAwGA1UdEwEB
+/wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEB
+CwUAA4IBAQCyN/y5DJAn/OM+p2/GlJUsYTdGJWRVrmH+AFgOZF+aW7w6t1LhQpqK
+BcK2HczXR6iI1XgfdAjbUuEAPKp8gHOxkfl1btNTKO+vWrcdPjiouBtI7SAYqEre
+YJe7P7a4zNVbvxyXBtGaJbiFHDYmAuB4R+D1B6QKalUUOVHW8/K51ESdeMRF5Tlv
+cQ69KntxnsQS8lLw7Wp4R0jf6qBE6872XFBTRz2m28qtp2LYbQZWn+IbcgizSsst
+6UpinsF+Xr3OCC+CvS9ui1XiQwHmMEC3ZzwNluGaM724wogD9YdoTW1Jf46U82pB
+LzEZtg0zYSRBMxbUW62YjgX3nKET3V99
+-----END CERTIFICATE-----
diff --git a/net/data/ssl/certificates/client_5.pk8 b/net/data/ssl/certificates/client_5.pk8
new file mode 100644
index 0000000..26da499
--- /dev/null
+++ b/net/data/ssl/certificates/client_5.pk8
Binary files differ
diff --git a/net/data/ssl/certificates/client_5_ca.pem b/net/data/ssl/certificates/client_5_ca.pem
new file mode 100644
index 0000000..78080961
--- /dev/null
+++ b/net/data/ssl/certificates/client_5_ca.pem
@@ -0,0 +1,71 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 4098 (0x1002)
+    Signature Algorithm: sha256WithRSAEncryption
+        Issuer: CN=C Root CA
+        Validity
+            Not Before: Dec  9 20:18:57 2016 GMT
+            Not After : Dec  7 20:18:57 2026 GMT
+        Subject: CN=E CA
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:c3:39:c3:5a:8e:ff:f2:1d:cc:26:91:5d:15:9e:
+                    ca:e0:fb:cf:99:5f:13:3d:c6:37:59:8b:ce:cc:76:
+                    0e:1c:9f:b6:49:5b:09:97:63:9d:e1:00:74:44:fb:
+                    2f:53:f3:d5:03:92:77:97:53:74:7e:d2:da:d3:a3:
+                    f4:c1:91:6a:83:ff:89:fe:73:46:56:ca:6d:51:0d:
+                    57:16:3d:3e:e8:fc:00:d9:4a:7a:7d:93:84:06:12:
+                    c5:ff:31:b3:a6:eb:96:18:71:b8:56:5c:2f:ab:78:
+                    e2:53:dd:15:d8:65:c8:f6:96:14:dc:15:cf:2a:39:
+                    ed:e1:08:1b:84:29:c7:1c:78:67:c8:e0:72:58:4e:
+                    33:7f:cb:ef:71:82:db:45:1d:7c:0c:d0:f5:4c:af:
+                    85:6b:14:61:50:87:34:42:fe:45:a3:3c:a3:53:57:
+                    1d:ac:11:c8:cf:2f:5e:cb:78:87:39:a1:41:3f:69:
+                    21:5c:1e:19:02:a3:6c:91:d3:1b:4e:50:fc:a4:b1:
+                    03:87:c0:58:b1:fe:cd:58:5e:53:ed:c9:d6:5d:9e:
+                    a3:fb:0d:e0:a0:8e:3d:c9:9e:9e:83:07:61:c7:30:
+                    5a:ca:29:93:04:af:5e:f3:57:2e:c2:d8:c8:ae:7f:
+                    5c:a4:27:fa:cd:55:a2:fd:89:d2:0b:87:24:6b:7b:
+                    fb:19
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+    Signature Algorithm: sha256WithRSAEncryption
+         67:d4:6c:cf:cd:54:81:67:2a:c2:c4:66:c7:76:9c:b0:8b:6b:
+         ef:b8:ae:a9:b3:d6:f8:47:91:d5:97:0b:bd:1a:87:21:8c:ce:
+         be:0c:80:d5:a5:25:0d:0a:c7:ed:be:cb:8c:6d:08:e8:de:a5:
+         33:89:e6:87:df:2b:f4:54:b3:c2:94:15:0d:36:5e:1a:aa:c0:
+         b0:03:3c:24:c6:a1:81:91:ca:fe:db:0f:59:1b:d6:4e:48:0b:
+         52:d3:e7:07:d7:b1:ca:b2:22:e4:d4:37:a4:3c:87:3c:0a:11:
+         a6:10:2a:ed:86:2a:bb:db:10:7e:f3:a5:fc:10:ab:80:5b:07:
+         58:7c:22:76:3e:9b:9c:72:79:0d:dc:85:f8:e7:c2:0f:17:aa:
+         01:dd:8e:24:27:77:4e:23:03:da:88:e0:df:e6:ca:b4:84:56:
+         a1:dc:9f:e0:93:94:97:d2:98:cd:32:6d:73:84:f9:3e:4c:96:
+         b3:51:07:b8:9f:66:32:d1:ac:53:0e:17:a9:6f:29:d1:7b:73:
+         b3:55:9b:cc:8f:8b:e5:49:fd:fd:f2:30:d6:d0:f7:03:06:12:
+         e3:66:2d:0d:a1:da:28:04:04:29:b8:40:6e:0e:6f:31:48:cb:
+         54:f7:e2:89:22:d8:05:e0:f5:7e:48:b3:96:ff:6b:ef:e7:fe:
+         71:1d:0b:77
+-----BEGIN CERTIFICATE-----
+MIICwjCCAaqgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwFDESMBAGA1UEAwwJQyBS
+b290IENBMB4XDTE2MTIwOTIwMTg1N1oXDTI2MTIwNzIwMTg1N1owDzENMAsGA1UE
+AwwERSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMM5w1qO//Id
+zCaRXRWeyuD7z5lfEz3GN1mLzsx2DhyftklbCZdjneEAdET7L1Pz1QOSd5dTdH7S
+2tOj9MGRaoP/if5zRlbKbVENVxY9Puj8ANlKen2ThAYSxf8xs6brlhhxuFZcL6t4
+4lPdFdhlyPaWFNwVzyo57eEIG4Qpxxx4Z8jgclhOM3/L73GC20UdfAzQ9UyvhWsU
+YVCHNEL+RaM8o1NXHawRyM8vXst4hzmhQT9pIVweGQKjbJHTG05Q/KSxA4fAWLH+
+zVheU+3J1l2eo/sN4KCOPcmenoMHYccwWsopkwSvXvNXLsLYyK5/XKQn+s1Vov2J
+0guHJGt7+xkCAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQELBQADggEBAGfUbM/NVIFnKsLEZsd2nLCLa++4rqmz1vhH
+kdWXC70ahyGMzr4MgNWlJQ0Kx+2+y4xtCOjepTOJ5offK/RUs8KUFQ02XhqqwLAD
+PCTGoYGRyv7bD1kb1k5IC1LT5wfXscqyIuTUN6Q8hzwKEaYQKu2GKrvbEH7zpfwQ
+q4BbB1h8InY+m5xyeQ3chfjnwg8XqgHdjiQnd04jA9qI4N/myrSEVqHcn+CTlJfS
+mM0ybXOE+T5MlrNRB7ifZjLRrFMOF6lvKdF7c7NVm8yPi+VJ/f3yMNbQ9wMGEuNm
+LQ2h2igEBCm4QG4ObzFIy1T34oki2AXg9X5Is5b/a+/n/nEdC3c=
+-----END CERTIFICATE-----
diff --git a/net/data/ssl/certificates/client_6.key b/net/data/ssl/certificates/client_6.key
new file mode 100644
index 0000000..289c2d7
--- /dev/null
+++ b/net/data/ssl/certificates/client_6.key
@@ -0,0 +1,7 @@
+-----BEGIN EC PRIVATE KEY-----
+MIHcAgEBBEIBp33i9oT0DV1aUcOE8av0Nt6ZCvsoVPPP/4kpU6T6d7wgLNwLK3uG
+vGCZX5AbdL1VvLA1rvfodqYug3pRnH0wSyigBwYFK4EEACOhgYkDgYYABACtf0oy
+HoxXTu/joG5I2fTeeYe6ZCEKlz2D5cMckF4bIkjRpue12TMhzs7FYp0cg+My3bxO
+A87t7os/vXJ3SZxGCwBFIQJc/vMSz7eOlaYHWXYY+vuD4Ab/j34lv1U+6LjtinWo
+I2WAbq/rxzSku9/NnLtKATbz3YgnYyzCEsmxQHfiKg==
+-----END EC PRIVATE KEY-----
diff --git a/net/data/ssl/certificates/client_6.pem b/net/data/ssl/certificates/client_6.pem
new file mode 100644
index 0000000..f90a4ca8
--- /dev/null
+++ b/net/data/ssl/certificates/client_6.pem
@@ -0,0 +1,60 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 4102 (0x1006)
+    Signature Algorithm: sha256WithRSAEncryption
+        Issuer: CN=E CA
+        Validity
+            Not Before: Dec  9 20:18:57 2016 GMT
+            Not After : Dec  7 20:18:57 2026 GMT
+        Subject: CN=Client Cert I
+        Subject Public Key Info:
+            Public Key Algorithm: id-ecPublicKey
+                Public-Key: (521 bit)
+                pub: 
+                    04:00:ad:7f:4a:32:1e:8c:57:4e:ef:e3:a0:6e:48:
+                    d9:f4:de:79:87:ba:64:21:0a:97:3d:83:e5:c3:1c:
+                    90:5e:1b:22:48:d1:a6:e7:b5:d9:33:21:ce:ce:c5:
+                    62:9d:1c:83:e3:32:dd:bc:4e:03:ce:ed:ee:8b:3f:
+                    bd:72:77:49:9c:46:0b:00:45:21:02:5c:fe:f3:12:
+                    cf:b7:8e:95:a6:07:59:76:18:fa:fb:83:e0:06:ff:
+                    8f:7e:25:bf:55:3e:e8:b8:ed:8a:75:a8:23:65:80:
+                    6e:af:eb:c7:34:a4:bb:df:cd:9c:bb:4a:01:36:f3:
+                    dd:88:27:63:2c:c2:12:c9:b1:40:77:e2:2a
+                ASN1 OID: secp521r1
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Extended Key Usage: 
+                TLS Web Server Authentication, TLS Web Client Authentication
+    Signature Algorithm: sha256WithRSAEncryption
+         8d:7b:44:61:33:92:ef:73:17:b7:b1:95:d8:f3:87:02:36:1c:
+         f7:d1:00:0d:2b:59:88:80:31:93:0b:ef:e8:c0:19:c6:bb:89:
+         26:3a:6e:47:90:0b:b2:99:d5:46:19:c4:cb:61:eb:51:6e:74:
+         f7:d0:87:4f:3b:08:fe:5a:48:a3:23:cc:b4:5d:a4:b6:0c:78:
+         f1:b2:f0:36:71:d7:c6:a7:e1:80:59:a6:67:b4:2a:ea:b5:1b:
+         9f:a2:bb:4d:01:36:e3:58:ed:19:bd:e6:b4:8e:d7:3c:b7:cc:
+         95:76:8b:e9:ec:78:c0:de:1b:09:04:d7:44:6c:2c:3c:c3:0e:
+         39:dc:be:3b:eb:ec:7d:b5:b9:3e:e6:eb:c0:ef:15:af:ca:96:
+         1d:f0:9e:ba:27:41:a2:7c:66:67:7d:37:65:0c:66:b7:aa:1b:
+         e8:88:55:f1:50:54:b9:36:e3:84:9c:27:a9:fa:8c:06:06:ce:
+         02:63:85:a6:70:dd:fc:78:1f:26:1f:13:01:aa:8d:34:54:80:
+         23:28:84:bf:90:a4:1a:61:e7:83:90:93:b7:0b:13:1d:c5:78:
+         7b:74:eb:5d:18:f1:b2:dd:6c:23:10:bc:80:1c:14:38:e6:76:
+         d5:78:b9:3a:0a:57:38:bd:fe:45:b0:68:a3:8c:1e:ae:25:84:
+         2f:dc:7a:b2
+-----BEGIN CERTIFICATE-----
+MIICSjCCATKgAwIBAgICEAYwDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwERSBD
+QTAeFw0xNjEyMDkyMDE4NTdaFw0yNjEyMDcyMDE4NTdaMBgxFjAUBgNVBAMMDUNs
+aWVudCBDZXJ0IEkwgZswEAYHKoZIzj0CAQYFK4EEACMDgYYABACtf0oyHoxXTu/j
+oG5I2fTeeYe6ZCEKlz2D5cMckF4bIkjRpue12TMhzs7FYp0cg+My3bxOA87t7os/
+vXJ3SZxGCwBFIQJc/vMSz7eOlaYHWXYY+vuD4Ab/j34lv1U+6LjtinWoI2WAbq/r
+xzSku9/NnLtKATbz3YgnYyzCEsmxQHfiKqMvMC0wDAYDVR0TAQH/BAIwADAdBgNV
+HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAI17
+RGEzku9zF7exldjzhwI2HPfRAA0rWYiAMZML7+jAGca7iSY6bkeQC7KZ1UYZxMth
+61FudPfQh087CP5aSKMjzLRdpLYMePGy8DZx18an4YBZpme0Kuq1G5+iu00BNuNY
+7Rm95rSO1zy3zJV2i+nseMDeGwkE10RsLDzDDjncvjvr7H21uT7m68DvFa/Klh3w
+nronQaJ8Zmd9N2UMZreqG+iIVfFQVLk244ScJ6n6jAYGzgJjhaZw3fx4HyYfEwGq
+jTRUgCMohL+QpBph54OQk7cLEx3FeHt0610Y8bLdbCMQvIAcFDjmdtV4uToKVzi9
+/kWwaKOMHq4lhC/cerI=
+-----END CERTIFICATE-----
diff --git a/net/data/ssl/certificates/client_6.pk8 b/net/data/ssl/certificates/client_6.pk8
new file mode 100644
index 0000000..62c42f4
--- /dev/null
+++ b/net/data/ssl/certificates/client_6.pk8
Binary files differ
diff --git a/net/data/ssl/certificates/client_6_ca.pem b/net/data/ssl/certificates/client_6_ca.pem
new file mode 100644
index 0000000..78080961
--- /dev/null
+++ b/net/data/ssl/certificates/client_6_ca.pem
@@ -0,0 +1,71 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 4098 (0x1002)
+    Signature Algorithm: sha256WithRSAEncryption
+        Issuer: CN=C Root CA
+        Validity
+            Not Before: Dec  9 20:18:57 2016 GMT
+            Not After : Dec  7 20:18:57 2026 GMT
+        Subject: CN=E CA
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:c3:39:c3:5a:8e:ff:f2:1d:cc:26:91:5d:15:9e:
+                    ca:e0:fb:cf:99:5f:13:3d:c6:37:59:8b:ce:cc:76:
+                    0e:1c:9f:b6:49:5b:09:97:63:9d:e1:00:74:44:fb:
+                    2f:53:f3:d5:03:92:77:97:53:74:7e:d2:da:d3:a3:
+                    f4:c1:91:6a:83:ff:89:fe:73:46:56:ca:6d:51:0d:
+                    57:16:3d:3e:e8:fc:00:d9:4a:7a:7d:93:84:06:12:
+                    c5:ff:31:b3:a6:eb:96:18:71:b8:56:5c:2f:ab:78:
+                    e2:53:dd:15:d8:65:c8:f6:96:14:dc:15:cf:2a:39:
+                    ed:e1:08:1b:84:29:c7:1c:78:67:c8:e0:72:58:4e:
+                    33:7f:cb:ef:71:82:db:45:1d:7c:0c:d0:f5:4c:af:
+                    85:6b:14:61:50:87:34:42:fe:45:a3:3c:a3:53:57:
+                    1d:ac:11:c8:cf:2f:5e:cb:78:87:39:a1:41:3f:69:
+                    21:5c:1e:19:02:a3:6c:91:d3:1b:4e:50:fc:a4:b1:
+                    03:87:c0:58:b1:fe:cd:58:5e:53:ed:c9:d6:5d:9e:
+                    a3:fb:0d:e0:a0:8e:3d:c9:9e:9e:83:07:61:c7:30:
+                    5a:ca:29:93:04:af:5e:f3:57:2e:c2:d8:c8:ae:7f:
+                    5c:a4:27:fa:cd:55:a2:fd:89:d2:0b:87:24:6b:7b:
+                    fb:19
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+    Signature Algorithm: sha256WithRSAEncryption
+         67:d4:6c:cf:cd:54:81:67:2a:c2:c4:66:c7:76:9c:b0:8b:6b:
+         ef:b8:ae:a9:b3:d6:f8:47:91:d5:97:0b:bd:1a:87:21:8c:ce:
+         be:0c:80:d5:a5:25:0d:0a:c7:ed:be:cb:8c:6d:08:e8:de:a5:
+         33:89:e6:87:df:2b:f4:54:b3:c2:94:15:0d:36:5e:1a:aa:c0:
+         b0:03:3c:24:c6:a1:81:91:ca:fe:db:0f:59:1b:d6:4e:48:0b:
+         52:d3:e7:07:d7:b1:ca:b2:22:e4:d4:37:a4:3c:87:3c:0a:11:
+         a6:10:2a:ed:86:2a:bb:db:10:7e:f3:a5:fc:10:ab:80:5b:07:
+         58:7c:22:76:3e:9b:9c:72:79:0d:dc:85:f8:e7:c2:0f:17:aa:
+         01:dd:8e:24:27:77:4e:23:03:da:88:e0:df:e6:ca:b4:84:56:
+         a1:dc:9f:e0:93:94:97:d2:98:cd:32:6d:73:84:f9:3e:4c:96:
+         b3:51:07:b8:9f:66:32:d1:ac:53:0e:17:a9:6f:29:d1:7b:73:
+         b3:55:9b:cc:8f:8b:e5:49:fd:fd:f2:30:d6:d0:f7:03:06:12:
+         e3:66:2d:0d:a1:da:28:04:04:29:b8:40:6e:0e:6f:31:48:cb:
+         54:f7:e2:89:22:d8:05:e0:f5:7e:48:b3:96:ff:6b:ef:e7:fe:
+         71:1d:0b:77
+-----BEGIN CERTIFICATE-----
+MIICwjCCAaqgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwFDESMBAGA1UEAwwJQyBS
+b290IENBMB4XDTE2MTIwOTIwMTg1N1oXDTI2MTIwNzIwMTg1N1owDzENMAsGA1UE
+AwwERSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMM5w1qO//Id
+zCaRXRWeyuD7z5lfEz3GN1mLzsx2DhyftklbCZdjneEAdET7L1Pz1QOSd5dTdH7S
+2tOj9MGRaoP/if5zRlbKbVENVxY9Puj8ANlKen2ThAYSxf8xs6brlhhxuFZcL6t4
+4lPdFdhlyPaWFNwVzyo57eEIG4Qpxxx4Z8jgclhOM3/L73GC20UdfAzQ9UyvhWsU
+YVCHNEL+RaM8o1NXHawRyM8vXst4hzmhQT9pIVweGQKjbJHTG05Q/KSxA4fAWLH+
+zVheU+3J1l2eo/sN4KCOPcmenoMHYccwWsopkwSvXvNXLsLYyK5/XKQn+s1Vov2J
+0guHJGt7+xkCAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQELBQADggEBAGfUbM/NVIFnKsLEZsd2nLCLa++4rqmz1vhH
+kdWXC70ahyGMzr4MgNWlJQ0Kx+2+y4xtCOjepTOJ5offK/RUs8KUFQ02XhqqwLAD
+PCTGoYGRyv7bD1kb1k5IC1LT5wfXscqyIuTUN6Q8hzwKEaYQKu2GKrvbEH7zpfwQ
+q4BbB1h8InY+m5xyeQ3chfjnwg8XqgHdjiQnd04jA9qI4N/myrSEVqHcn+CTlJfS
+mM0ybXOE+T5MlrNRB7ifZjLRrFMOF6lvKdF7c7NVm8yPi+VJ/f3yMNbQ9wMGEuNm
+LQ2h2igEBCm4QG4ObzFIy1T34oki2AXg9X5Is5b/a+/n/nEdC3c=
+-----END CERTIFICATE-----
diff --git a/net/data/ssl/certificates/client_root_ca.pem b/net/data/ssl/certificates/client_root_ca.pem
index b4048103..cb41907 100644
--- a/net/data/ssl/certificates/client_root_ca.pem
+++ b/net/data/ssl/certificates/client_root_ca.pem
@@ -1,18 +1,18 @@
 -----BEGIN CERTIFICATE-----
-MIICzjCCAbagAwIBAgIJAO+K/Ai3YiytMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV
-BAMMCUMgUm9vdCBDQTAeFw0xNjEwMDQxODUzMjRaFw0yNjEwMDIxODUzMjRaMBQx
+MIICzjCCAbagAwIBAgIJAOlWtiy6ZPwFMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV
+BAMMCUMgUm9vdCBDQTAeFw0xNjEyMDkyMDE4NTdaFw0yNjEyMDcyMDE4NTdaMBQx
 EjAQBgNVBAMMCUMgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
-ggEBALKU+gX11E3vQ6CHy5bNfePr5uiJMHX+P97/I8y8DCk117+0gGxlO4adwImE
-dgA6jFmMcphJU+BPfi1eDwO2WHQVa31NALMy3CbEzv4qV1gqTAfNJdICKZk7S87E
-GbZUBauHe8q443UwD3c+R49XTsGvUSoMjh3N7K0/kNeoLi4RLW6WOZvJh954Rj+I
-EHmCibJENDfzdYWfQtLZJEYrzJv01ZdWcigvOR7qQqLdX6f2WTBaWpjgSnP5QzO/
-8gkX+rVRRUpbD/lMNdXqO9AoBcSG07tWMx1MDRnDG8SzrCQ4sScSbcPnHQDEbdDv
-suCnGXzSerruQXCqVwcCHIEHRSMCAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAO
-BgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAHL9wuInYSfItXwoO2jG
-W08CPjcPMN1Q7yulKFtND6jU4cWB/m2xQmpMjhrahrF1hYwwiOXfwB+bxHOoekmK
-Uf+WmsiFXUQ5q9IeBMnxrrKOqZ9X2S+WaTi9GosJ52IEX4JJT7w3JDEcNTh3h66g
-FHB9cXao0EDx5fkEvSCKhcSy+tWjWzUB+GszG3ApCe0ZxbcehUSRSZTcLYvlNlXF
-NMNvEH5C1BVzCQWAZlgT4gp4miEPCFTc4Vr90pgDzJ3eFWu4V0s6snyDOip0PD9A
-N6wOvSix25wUYni46xGHFc9ZZn3x35HdhW9+IMAgJI14hMsoIHQwAgzqF4neRYvY
-RT4=
+ggEBAMA+ZigXbDXCxJ4JCLXzWo/3dzVU/lQgToMmzXMAN7YLkYrpMHSh0+YgrtOv
+XA70wFaLPa6SYGqr9OU2FqTlob43GQU9uNmIOi/SNmz3WRudoJgqbYK0Gv4qRarR
+wrNqpPWgQXxP3T/slF7UVV0JRFWcscXPIxVIOQ64qGTtMpzjYP21g0V8e6pz30U9
+/9iil7FdSVIpjKc2RN42QGi2URIe2hYOIgCMADO/m5eUMVVX3wJ+ka4X619uTFrg
+BEexVhIMu5ZPwEXcyUBxebLzJqx+JTwe2P2/20UMGQBSqT9xsXcuW8Y3+5q7Vl0j
+7F5u9pE2PAZiVuDLWE3TXFSwVd8CAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAO
+BgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAJE45oY5GAmSefzxBKI2
+mVfZj7TlUG/KQ1W7RrsoDeYb93PTA/S4XM56wQhT8vdz3imED83EZ1hoDFourhAV
+hNVCSSHBJ/Bgtj3Yt6bUZdx0dSK5PbnvfTYAnRxzx0o8d4pRXb0G225BT3kYNIOK
+E1M24xmnjP3OoeyqWzP7uyU7vxfA4oCloNgeMWMJ9zdfgRX8Qnj6XRHVuhMXdofn
+7vB9dpsbJI5ozXaFYuXMKZ8g97M1vUzWTQsbUWc/L3YaO+UZOQXg1gLHhZmwn9MC
+xZSldz7Z4QIDV+U03cJUKL5O4hQcMgrtug2d75vxMKVjETKkvqbzs56h62YmhEyw
+3Gg=
 -----END CERTIFICATE-----
diff --git a/net/data/ssl/scripts/generate-client-certificates.sh b/net/data/ssl/scripts/generate-client-certificates.sh
index e7c8c01..5e584b2 100755
--- a/net/data/ssl/scripts/generate-client-certificates.sh
+++ b/net/data/ssl/scripts/generate-client-certificates.sh
@@ -14,6 +14,8 @@
 #   2. D (end-entity) -> E -> C (self-signed root)
 #   3. F (end-entity) -> E -> C (self-signed root)
 #   4. G (end-entity, P-256) -> E -> C (self-signed root)
+#   5. H (end-entity, P-384) -> E -> C (self-signed root)
+#   6. I (end-entity, P-521) -> E -> C (self-signed root)
 #
 # In which the certificates all have distinct keypairs. The client
 # certificates share the same root, but are issued by different
@@ -45,6 +47,8 @@
 done
 
 try openssl ecparam -name prime256v1 -genkey -noout -out out/G.key
+try openssl ecparam -name secp384r1 -genkey -noout -out out/H.key
+try openssl ecparam -name secp521r1 -genkey -noout -out out/I.key
 
 echo Generate the C CSR
 COMMON_NAME="C Root CA" \
@@ -108,7 +112,7 @@
     -config client-certs.cnf
 
 echo Generate the leaf certs
-for id in A D F G
+for id in A D F G H I
 do
   COMMON_NAME="Client Cert $id" \
   ID=$id \
@@ -169,12 +173,36 @@
     -out out/G.pem \
     -config client-certs.cnf
 
+echo E signs H
+COMMON_NAME="E CA" \
+  CA_DIR=out \
+  ID=E \
+  try openssl ca \
+    -batch \
+    -extensions user_cert \
+    -in out/H.csr \
+    -out out/H.pem \
+    -config client-certs.cnf
+
+echo E signs I
+COMMON_NAME="E CA" \
+  CA_DIR=out \
+  ID=E \
+  try openssl ca \
+    -batch \
+    -extensions user_cert \
+    -in out/I.csr \
+    -out out/I.pem \
+    -config client-certs.cnf
+
 echo Package the client certs and private keys into PKCS12 files
 # This is done for easily importing all of the certs needed for clients.
 try /bin/sh -c "cat out/A.pem out/A.key out/B.pem out/C.pem > out/A-chain.pem"
 try /bin/sh -c "cat out/D.pem out/D.key out/E.pem out/C.pem > out/D-chain.pem"
 try /bin/sh -c "cat out/F.pem out/F.key out/E.pem out/C.pem > out/F-chain.pem"
 try /bin/sh -c "cat out/G.pem out/G.key out/E.pem out/C.pem > out/G-chain.pem"
+try /bin/sh -c "cat out/H.pem out/H.key out/E.pem out/C.pem > out/H-chain.pem"
+try /bin/sh -c "cat out/I.pem out/I.key out/E.pem out/C.pem > out/I-chain.pem"
 
 try openssl pkcs12 \
   -in out/A-chain.pem \
@@ -200,6 +228,18 @@
   -export \
   -passout pass:chrome
 
+try openssl pkcs12 \
+  -in out/H-chain.pem \
+  -out client_5.p12 \
+  -export \
+  -passout pass:chrome
+
+try openssl pkcs12 \
+  -in out/I-chain.pem \
+  -out client_6.p12 \
+  -export \
+  -passout pass:chrome
+
 echo Package the client certs for unit tests
 try cp out/A.pem ../certificates/client_1.pem
 try cp out/A.key ../certificates/client_1.key
@@ -221,4 +261,14 @@
 try cp out/G.pk8 ../certificates/client_4.pk8
 try cp out/E.pem ../certificates/client_4_ca.pem
 
+try cp out/H.pem ../certificates/client_5.pem
+try cp out/H.key ../certificates/client_5.key
+try cp out/H.pk8 ../certificates/client_5.pk8
+try cp out/E.pem ../certificates/client_5_ca.pem
+
+try cp out/I.pem ../certificates/client_6.pem
+try cp out/I.key ../certificates/client_6.key
+try cp out/I.pk8 ../certificates/client_6.pk8
+try cp out/E.pem ../certificates/client_6_ca.pem
+
 try cp out/C.pem ../certificates/client_root_ca.pem
diff --git a/net/docs/crash-course-in-net-internals.md b/net/docs/crash-course-in-net-internals.md
index 008a5755..9187f85 100644
--- a/net/docs/crash-course-in-net-internals.md
+++ b/net/docs/crash-course-in-net-internals.md
@@ -14,77 +14,138 @@
 For this reason, it lacks knowledge of tabs, navigation, frames, resource types,
 etc.
 
-The top level network stack object is the URLRequestContext.  The Events View
+The leftmost column presents a list of views.  Most debugging is done with the
+Events view, which will be all this document covers.
+
+The top level network stack object is the URLRequestContext.  The Events view
 has information for all Chrome URLRequestContexts that are hooked up to the
-single, global, ChromeNetLog object.  This includes both incognito and non-
-incognito profiles, among other things.  The Events view only shows events for
-the period that net-internals was open and running, and is incrementally updated
-as events occur.  The code attempts to add a top level event for URLRequests
-that were active when the tab was opened, to help debug hung requests, but
-that's best-effort only, and only includes requests for the current profile and
-the system URLRequestContext.
+single, global, ChromeNetLog object.  This includes both incognito and
+non-incognito profiles, among other things.  The Events view only shows events
+for the period that net-internals was open and running, and is incrementally
+updated as events occur.  The code attempts to add a top level event for
+URLRequests that were active when the about:net-internals tab was opened, to
+help debug hung requests, but that's best-effort only, and only includes
+requests for the current profile and the system URLRequestContext.
 
 The other views are all snapshots of the current state of the main
 URLRequestContext's components, and are updated on a 5 second timer.  These will
-show objects that were created before about:net-internals was opened.  Most
-debugging is done with the Events view (which will be all this document
-covers), but it's good to be aware of this distinction.
+show objects that were created before about:net-internals was opened.
 
 # Events vs Sources
 
-The Event View shows events logged by the NetLog.  The NetLog model is that
+The Events view shows events logged by the NetLog.  The NetLog model is that
 long-lived network stack objects, called sources, emit events over their
-lifetime.  When looking at the code, a "NetLogWithSource" object contains a source
-ID, and a pointer to the NetLog the source emits events to.  Some events have a
-beginning and end point (during which other subevents may occur), and some only
-occur at a single point in time.  Generally only one event can be occuring for a
-source at a time.  If there can be multiple events doing completely independent
-thing, the code often uses new sources to represent the parallelism.
+lifetime.  A NetLogWithSource object contains a source ID, a NetLogSourceType,
+and a pointer to the NetLog the source emits events to.
+
+The Events view has a list of sources in a column adjacent to the list of views.
+Sources that include an event with a net_error parameter with negative value
+(that is, some kind of ERR_) are shown with red background.  Sources whose
+opening event has not ended yet are shown with white background.  Other events
+have green background.  The search queries corresponding to the first two kinds
+are `is:error` and `is:active`.
+
+When one or more sources are selected, corresponding events show up in another
+column to the right, sorted by source, and by time within each source.  There
+are two time values: t is measured from some reference point common to all
+sources, and st is measured from the first event for each source.  Time is
+displayed in milliseconds.
+
+Since the network stack is asynchronous, events from different sources will
+often be interlaced in time, but Events view does not feature showing events from
+different sources ordered by time.  Large time gaps in the event list of a
+single source usually mean that time is spent in the context of another source.
+
+Some events come in pairs: a beginning and end event, between which other events
+may occur.  They are shown with + and - prefixes, respectively.  The begin event
+has a dt value which shows the duration.  If the end event was captured, then
+duration is calculated as the time difference between the begin and the end
+events.  Otherwise the time elapsed from the begin event until capturing
+was stopped is displayed (a lower bound for actual duration), followed by a +
+sign (for example, "dt=120+").
+
+If there are no other events in between the begin and end, and the end event has
+no parameters, then they are collapsed in a single line without a sign prefix.
+
+Some other events only occur at a single point in time, and will not have either
+a sign prefix, or a dt duration value.
+
+Generally only one event can be occuring for a source at a time.  If there can
+be multiple events doing completely independent things, the code often uses new
+sources to represent the parallelism.
+
+Most, but not all events correspond to a source.  Exceptions are global events,
+which have no source, and show up as individual entries in the source list.
+Examples of global events include NETWORK_CHANGED, DNS_CONFIG_CHANGED, and
+PROXY_CONFIG_CHANGED.
+
+# Common source types
 
 "Sources" correspond to certain net objects, however, multiple layers of net/
 will often log to a single source.  Here are the main source types and what they
-include (Excluding HTTP2 [SPDY]/QUIC):
+include (excluding HTTP2 [SPDY]/QUIC):
 
 * URL_REQUEST:  This corresponds to the URLRequest object.  It includes events
 from all the URLRequestJobs, HttpCache::Transactions, NetworkTransactions,
 HttpStreamFactoryImpl::Requests, HttpStream implementations, and
 HttpStreamParsers used to service a response.  If the URL_REQUEST follows HTTP
 redirects, it will include each redirect.  This is a lot of stuff, but generally
-only object is doing work at a time.  This event source includes the full URL
-and generally includes the request / response headers (Except when the cache
+only one object is doing work at a time.  This event source includes the full
+URL and generally includes the request / response headers (except when the cache
 handles the response).
 
-* HTTP_STREAM_JOB:  This corresponds to HttpStreamFactoryImpl::Job (Note that
+* HTTP_STREAM_JOB:  This corresponds to HttpStreamFactoryImpl::Job (note that
 one Request can have multiple Jobs).  It also includes its proxy and DNS
-lookups.  HTTP_STREAM_JOB log events are separate from URL_REQUEST because
-two stream jobs may be created and races against each other, in some cases -
-one for one for QUIC, and one for HTTP.  One of the final events of this source
-indicates how an HttpStream was created (Reusing an existing SOCKET /
-HTTP2_SESSION / QUIC_SESSION, or creating a new one).
+lookups.  HTTP_STREAM_JOB log events are separate from URL_REQUEST because two
+stream jobs may be created and races against each other, in some cases -- one
+for QUIC, and one for HTTP.
+
+    One of the final events of this source, before the
+    HTTP_STREAM_JOB_BOUND_TO_REQUEST event, indicates how an HttpStream was
+    created:
+
+    + A SOCKET_POOL_BOUND_TO_CONNECT_JOB event means that a new TCP socket was
+    created, whereas a SOCKET_POOL_REUSED_AN_EXISTING_SOCKET event indicates that
+    an existing TCP socket was reused for a non-HTTP/2 request.
+
+    + An HTTP2_SESSION_POOL_IMPORTED_SESSION_FROM_SOCKET event indicates that a
+    new HTTP/2 session was opened by this Job.
+
+    + An HTTP2_SESSION_POOL_FOUND_EXISTING_SESSION event indicates that the request
+    was served on a preexisting HTTP/2 session.
+
+    + An HTTP2_SESSION_POOL_FOUND_EXISTING_SESSION_FROM_IP_POOL event means that
+    the request was pooled to a preexisting HTTP/2 session which had a different
+    SpdySessionKey, but DNS resolution resulted in the same IP, and the
+    certificate matches.
+
+    + There are currently no events logged for opening new QUIC sessions or
+    reusing existing ones.
 
 * \*_CONNECT_JOB:  This corresponds to the ConnectJob subclasses that each socket
-pool uses.  A successful CONNECT_JOB return a SOCKET.  The events here vary a
+pool uses.  A successful CONNECT_JOB returns a SOCKET.  The events here vary a
 lot by job type.  Their main event is generally either to create a socket, or
-request a socket from another socket pool (Which creates another CONNECT_JOB)
-and then do some extra work on top of that - like establish an SSL connection on
+request a socket from another socket pool (which creates another CONNECT_JOB)
+and then do some extra work on top of that -- like establish an SSL connection on
 top of a TCP connection.
 
 * SOCKET:  These correspond to TCPSockets, but may also have other classes
-layered on top of them (Like an SSLClientSocket).  This is a bit different from
+layered on top of them (like an SSLClientSocket).  This is a bit different from
 the other classes, where the name corresponds to the topmost class, instead of
 the bottommost one.  This is largely an artifact of the fact the socket is
-created first, and then SSL (Or a proxy connection) is layered on top of it.
+created first, and then SSL (or a proxy connection) is layered on top of it.
 SOCKETs may be reused between multiple requests, and a request may end up
 getting a socket created for another request.
 
-* HOST_RESOLVER_IMPL_JOB:  These correspond to HostResolverImpl::Job.  The
+* HOST_RESOLVER_IMPL_JOB:  These correspond to HostResolverImpl::Job.  They
 include information about how long the lookup was queued, each DNS request that
-was attempted (With the platform or built-in resolver) and all the other sources
+was attempted (with the platform or built-in resolver) and all the other sources
 that are waiting on the job.
 
-When one source depends on another, the code generally logs an event with
-"source_dependency" value to both sources, which lets you jump between the two
-related events.
+When one source depends on another, the code generally logs an event at both
+sources with a `source_dependency` value pointing to the other source.  These
+are clickable in the UI, adding the referred source to the list of selected
+sources.
 
 # Debugging
 
@@ -96,9 +157,9 @@
 about the actual problem.  There are two filters in net-internals that can help
 in a lot of cases:
 
-* "type:URL_REQUEST is:error" will restrict the list to URL_REQUEST object with
-an error of some sort (red background).  Cache errors are often non-fatal, so
-you should generally ignore those, and look for a more interesting one.
+* "type:URL_REQUEST is:error" will restrict the source list to URL_REQUEST
+objects with an error of some sort.  Cache errors are often non-fatal, so you
+should generally ignore those, and look for a more interesting one.
 
 * "type:URL_REQUEST sort:duration" will show the longest-lived requests first.
 This is often useful in finding hung or slow requests.
@@ -107,14 +168,11 @@
 about:net-internals.
 
 Once you locate the problematic request, the next is to figure out where the
-problem is - it's often one of the last events, though it could also be related
-to response or request headers.  You can use "source_dependency" links to drill
-down into other related sources, or up from layers below URL_REQUEST.
-
-You can use the name of an event to search for the code responsible for that
-event, and try to deduce what went wrong before/after a particular event.  Note
-that the event names used in net-internals are not the entire string names, so
-you should not do an entire string match.
+problem is -- it's often one of the last events, though it could also be related
+to response or request headers.  You can use `source_dependency` links to
+navigate between related sources.  You can use the name of an event to search
+for the code responsible for that event, and try to deduce what went wrong
+before/after a particular event.
 
 Some things to look for while debugging:
 
@@ -122,8 +180,7 @@
 
 * Changing networks and entering / exiting suspend mode can have all sorts of
 fun and exciting effects on underway network activity.  Network changes log a
-top level NETWORK_CHANGED event with no source - the event itself is treated as
-its own source.  Suspend events are currently not logged.
+top level NETWORK_CHANGED event.  Suspend events are currently not logged.
 
 * URL_REQUEST_DELEGATE / DELEGATE_INFO events mean a URL_REQUEST is blocked on a
 URLRequest::Delegate or the NetworkDelegate, which are implemented outside the
@@ -136,7 +193,8 @@
 
 * Sockets are often reused between requests.  If a request is on a stale
 (reused) socket, what was the previous request that used the socket, how long
-ago was it made?
+ago was it made?  (Look at SOCKET_IN_USE events, and the HTTP_STREAM_JOBS they
+point to via the `source_dependency` value.)
 
 * SSL negotation is a process fraught with peril, particularly with broken
 proxies.  These will generally stall or fail in the SSL_CONNECT phase at the
@@ -146,15 +204,15 @@
 issued by the media and PDF code.
 
 * Late binding:  HTTP_STREAM_JOBs are not associated with any CONNECT_JOB until
-a CONNECT_JOB actually connects.  This is so the highest priority pending job
-gets the first available socket (Which may be a new socket, or an old one that's
-freed up).  For this reason, it can be a little tricky to relate hung
-HTTP_STREAM_JOBs to CONNECT_JOBs.
+a CONNECT_JOB actually connects.  This is so the highest priority pending
+HTTP_STREAM_JOB gets the first available socket (which may be a new socket, or
+an old one that's freed up).  For this reason, it can be a little tricky to
+relate hung HTTP_STREAM_JOBs to CONNECT_JOBs.
 
 * Each CONNECT_JOB belongs to a "group", which has a limit of 6 connections.  If
-all CONNECT_JOBs beling to a group (The CONNECT_JOB's description field) are
+all CONNECT_JOBs belonging to a group (the CONNECT_JOB's description field) are
 stalled waiting on an available socket, the group probably has 6 sockets that
-that are hung - either hung trying to connect, or used by stalled requests and
+that are hung -- either hung trying to connect, or used by stalled requests and
 thus outside the socket pool's control.
 
 * There's a limit on number of DNS resolutions that can be started at once.  If
diff --git a/net/http/http_server_properties_manager.cc b/net/http/http_server_properties_manager.cc
index 6f1b8a6a..0c4d2fe 100644
--- a/net/http/http_server_properties_manager.cc
+++ b/net/http/http_server_properties_manager.cc
@@ -100,7 +100,7 @@
   http_server_properties_impl_.reset(new HttpServerPropertiesImpl());
 
   network_prefs_update_timer_.reset(new base::OneShotTimer);
-
+  network_prefs_update_timer_->SetTaskRunner(network_task_runner_);
   pref_task_runner_->PostTask(
       FROM_HERE,
       base::Bind(&HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread,
diff --git a/net/http/http_server_properties_manager_unittest.cc b/net/http/http_server_properties_manager_unittest.cc
index 97b5a24..c88b296 100644
--- a/net/http/http_server_properties_manager_unittest.cc
+++ b/net/http/http_server_properties_manager_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
+#include "base/test/test_mock_time_task_runner.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
@@ -29,6 +30,7 @@
 namespace {
 
 using base::StringPrintf;
+using base::TestMockTimeTaskRunner;
 using ::testing::_;
 using ::testing::Invoke;
 using ::testing::Mock;
@@ -149,14 +151,16 @@
 
 class HttpServerPropertiesManagerTest : public testing::TestWithParam<int> {
  protected:
-  HttpServerPropertiesManagerTest() {}
+  HttpServerPropertiesManagerTest()
+      : net_test_task_runner_(new TestMockTimeTaskRunner()) {}
 
   void SetUp() override {
     one_day_from_now_ = base::Time::Now() + base::TimeDelta::FromDays(1);
     pref_delegate_ = new MockPrefDelegate;
     http_server_props_manager_.reset(
         new StrictMock<TestingHttpServerPropertiesManager>(
-            pref_delegate_, base::ThreadTaskRunnerHandle::Get()));
+            pref_delegate_, net_test_task_runner_));
+
     ExpectCacheUpdate();
     base::RunLoop().RunUntilIdle();
   }
@@ -218,6 +222,7 @@
   std::unique_ptr<TestingHttpServerPropertiesManager>
       http_server_props_manager_;
   base::Time one_day_from_now_;
+  scoped_refptr<TestMockTimeTaskRunner> net_test_task_runner_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(HttpServerPropertiesManagerTest);
@@ -357,6 +362,8 @@
   pref_delegate_->SetPrefs(http_server_properties_dict);
 
   base::RunLoop().RunUntilIdle();
+  net_test_task_runner_->FastForwardUntilNoTasksRemain();
+
   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
 
   // Verify SupportsSpdy.
@@ -447,7 +454,7 @@
 
 TEST_P(HttpServerPropertiesManagerTest, BadCachedHostPortPair) {
   ExpectCacheUpdate();
-  // The prefs are automaticalls updated in the case corruption is detected.
+  // The prefs are automatically updated in the case corruption is detected.
   ExpectPrefsUpdate();
   ExpectScheduleUpdatePrefsOnNetworkThread();
 
@@ -509,6 +516,8 @@
   pref_delegate_->SetPrefs(http_server_properties_dict);
 
   base::RunLoop().RunUntilIdle();
+  net_test_task_runner_->FastForwardUntilNoTasksRemain();
+
   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
 
   // Verify that nothing is set.
@@ -528,7 +537,7 @@
 
 TEST_P(HttpServerPropertiesManagerTest, BadCachedAltProtocolPort) {
   ExpectCacheUpdate();
-  // The prefs are automaticalls updated in the case corruption is detected.
+  // The prefs are automatically updated in the case corruption is detected.
   ExpectPrefsUpdate();
   ExpectScheduleUpdatePrefsOnNetworkThread();
 
@@ -573,6 +582,8 @@
   pref_delegate_->SetPrefs(http_server_properties_dict);
 
   base::RunLoop().RunUntilIdle();
+  net_test_task_runner_->FastForwardUntilNoTasksRemain();
+
   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
 
   // Verify alternative service is not set.
@@ -597,6 +608,7 @@
 
   // Run the task.
   base::RunLoop().RunUntilIdle();
+  net_test_task_runner_->FastForwardUntilNoTasksRemain();
 
   EXPECT_TRUE(http_server_props_manager_->SupportsRequestPriority(spdy_server));
   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
@@ -618,6 +630,8 @@
 
   // Run the task.
   base::RunLoop().RunUntilIdle();
+  net_test_task_runner_->FastForwardUntilNoTasksRemain();
+
   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
 
   AlternativeServiceVector alternative_service_vector =
@@ -649,6 +663,8 @@
 
   // Run the task.
   base::RunLoop().RunUntilIdle();
+  net_test_task_runner_->FastForwardUntilNoTasksRemain();
+
   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
 
   AlternativeServiceVector alternative_service_vector =
@@ -712,6 +728,8 @@
 
   // Run the task.
   base::RunLoop().RunUntilIdle();
+  net_test_task_runner_->FastForwardUntilNoTasksRemain();
+
   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
 
   EXPECT_FALSE(http_server_props_manager_->IsAlternativeServiceBroken(
@@ -734,6 +752,8 @@
 
   // Run the task.
   base::RunLoop().RunUntilIdle();
+  net_test_task_runner_->FastForwardUntilNoTasksRemain();
+
   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
 
   EXPECT_TRUE(http_server_props_manager_->GetSupportsQuic(&address));
@@ -756,6 +776,8 @@
 
   // Run the task.
   base::RunLoop().RunUntilIdle();
+  net_test_task_runner_->FastForwardUntilNoTasksRemain();
+
   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
 
   const ServerNetworkStats* stats2 =
@@ -779,6 +801,8 @@
 
   // Run the task.
   base::RunLoop().RunUntilIdle();
+  net_test_task_runner_->FastForwardUntilNoTasksRemain();
+
   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
 
   EXPECT_EQ(quic_server_info1, *http_server_props_manager_->GetQuicServerInfo(
@@ -807,6 +831,7 @@
 
   // Run the task.
   base::RunLoop().RunUntilIdle();
+  net_test_task_runner_->FastForwardUntilNoTasksRemain();
 
   EXPECT_TRUE(http_server_props_manager_->SupportsRequestPriority(spdy_server));
   EXPECT_TRUE(HasAlternativeService(spdy_server));
@@ -912,6 +937,8 @@
   pref_delegate_->SetPrefs(http_server_properties_dict);
 
   base::RunLoop().RunUntilIdle();
+  net_test_task_runner_->FastForwardUntilNoTasksRemain();
+
   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
 
   // Verify alternative service.
@@ -983,6 +1010,8 @@
   ExpectPrefsUpdate();
   ExpectCacheUpdate();
   http_server_props_manager_->ScheduleUpdateCacheOnPrefThread();
+
+  net_test_task_runner_->FastForwardUntilNoTasksRemain();
   base::RunLoop().RunUntilIdle();
 
   // Verify preferences.
@@ -1114,6 +1143,8 @@
   ExpectPrefsUpdate();
   ExpectCacheUpdate();
   http_server_props_manager_->ScheduleUpdateCacheOnPrefThread();
+
+  net_test_task_runner_->FastForwardUntilNoTasksRemain();
   base::RunLoop().RunUntilIdle();
 
   const base::DictionaryValue& pref_dict =
@@ -1241,7 +1272,9 @@
   // Shutdown comes before the task is executed.
   http_server_props_manager_->ShutdownOnPrefThread();
   // Run the task after shutdown, but before deletion.
+  net_test_task_runner_->FastForwardUntilNoTasksRemain();
   base::RunLoop().RunUntilIdle();
+
   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
   http_server_props_manager_.reset();
   base::RunLoop().RunUntilIdle();
diff --git a/net/net.gypi b/net/net.gypi
index 79e7e02..cb983a25 100644
--- a/net/net.gypi
+++ b/net/net.gypi
@@ -2400,6 +2400,14 @@
       'data/ssl/certificates/client_4.pem',
       'data/ssl/certificates/client_4.pk8',
       'data/ssl/certificates/client_4_ca.pem',
+      'data/ssl/certificates/client_5.key',
+      'data/ssl/certificates/client_5.pem',
+      'data/ssl/certificates/client_5.pk8',
+      'data/ssl/certificates/client_5_ca.pem',
+      'data/ssl/certificates/client_6.key',
+      'data/ssl/certificates/client_6.pem',
+      'data/ssl/certificates/client_6.pk8',
+      'data/ssl/certificates/client_6_ca.pem',
       'data/ssl/certificates/client_root_ca.pem',
       'data/ssl/certificates/comodo.chain.pem',
       'data/ssl/certificates/crit-codeSigning-chain.pem',
diff --git a/net/quic/core/congestion_control/bbr_sender.cc b/net/quic/core/congestion_control/bbr_sender.cc
index f3042847a..3145d03 100644
--- a/net/quic/core/congestion_control/bbr_sender.cc
+++ b/net/quic/core/congestion_control/bbr_sender.cc
@@ -64,14 +64,12 @@
 
 BbrSender::DebugState::DebugState(const DebugState& state) = default;
 
-BbrSender::BbrSender(const QuicClock* clock,
-                     const RttStats* rtt_stats,
+BbrSender::BbrSender(const RttStats* rtt_stats,
                      const QuicUnackedPacketMap* unacked_packets,
                      QuicPacketCount initial_tcp_congestion_window,
                      QuicPacketCount max_tcp_congestion_window,
                      QuicRandom* random)
-    : clock_(clock),
-      rtt_stats_(rtt_stats),
+    : rtt_stats_(rtt_stats),
       unacked_packets_(unacked_packets),
       random_(random),
       mode_(STARTUP),
diff --git a/net/quic/core/congestion_control/bbr_sender.h b/net/quic/core/congestion_control/bbr_sender.h
index 152d5ec9..ac32949 100644
--- a/net/quic/core/congestion_control/bbr_sender.h
+++ b/net/quic/core/congestion_control/bbr_sender.h
@@ -89,8 +89,7 @@
     bool last_sample_is_app_limited;
   };
 
-  BbrSender(const QuicClock* clock,
-            const RttStats* rtt_stats,
+  BbrSender(const RttStats* rtt_stats,
             const QuicUnackedPacketMap* unacked_packets,
             QuicPacketCount initial_tcp_congestion_window,
             QuicPacketCount max_tcp_congestion_window,
@@ -190,7 +189,6 @@
   // recovery.
   void CalculateRecoveryWindow(QuicByteCount bytes_acked);
 
-  const QuicClock* clock_;
   const RttStats* rtt_stats_;
   const QuicUnackedPacketMap* unacked_packets_;
   QuicRandom* random_;
diff --git a/net/quic/core/congestion_control/bbr_sender_test.cc b/net/quic/core/congestion_control/bbr_sender_test.cc
index c02fb71..0079d49 100644
--- a/net/quic/core/congestion_control/bbr_sender_test.cc
+++ b/net/quic/core/congestion_control/bbr_sender_test.cc
@@ -81,7 +81,7 @@
     FLAGS_quic_bbr_faster_startup = true;
 
     rtt_stats_ = bbr_sender_.connection()->sent_packet_manager().GetRttStats();
-    sender_ = new BbrSender(simulator_.GetClock(), rtt_stats_,
+    sender_ = new BbrSender(rtt_stats_,
                             QuicSentPacketManagerPeer::GetUnackedPacketMap(
                                 QuicConnectionPeer::GetSentPacketManager(
                                     bbr_sender_.connection(), kDefaultPathId)),
diff --git a/net/quic/core/congestion_control/cubic.cc b/net/quic/core/congestion_control/cubic.cc
index f0a1871..f93f91cc 100644
--- a/net/quic/core/congestion_control/cubic.cc
+++ b/net/quic/core/congestion_control/cubic.cc
@@ -41,7 +41,8 @@
       epoch_(QuicTime::Zero()),
       app_limited_start_time_(QuicTime::Zero()),
       last_update_time_(QuicTime::Zero()),
-      fix_convex_mode_(false) {
+      fix_convex_mode_(false),
+      fix_beta_last_max_(false) {
   Reset();
 }
 
@@ -65,6 +66,16 @@
   return (num_connections_ - 1 + kBeta) / num_connections_;
 }
 
+float Cubic::BetaLastMax() const {
+  // BetaLastMax is the additional backoff factor after loss for our
+  // N-connection emulation, which emulates the additional backoff of
+  // an ensemble of N TCP-Reno connections on a single loss event. The
+  // effective multiplier is computed as:
+  return fix_beta_last_max_
+             ? (num_connections_ - 1 + kBetaLastMax) / num_connections_
+             : kBetaLastMax;
+}
+
 void Cubic::Reset() {
   epoch_ = QuicTime::Zero();  // Reset time.
   app_limited_start_time_ = QuicTime::Zero();
@@ -77,7 +88,6 @@
   origin_point_congestion_window_ = 0;
   time_to_origin_point_ = 0;
   last_target_congestion_window_ = 0;
-  fix_convex_mode_ = false;
 }
 
 void Cubic::OnApplicationLimited() {
@@ -90,13 +100,17 @@
   fix_convex_mode_ = fix_convex_mode;
 }
 
+void Cubic::SetFixBetaLastMax(bool fix_beta_last_max) {
+  fix_beta_last_max_ = fix_beta_last_max;
+}
+
 QuicPacketCount Cubic::CongestionWindowAfterPacketLoss(
     QuicPacketCount current_congestion_window) {
   if (current_congestion_window < last_max_congestion_window_) {
     // We never reached the old max, so assume we are competing with another
     // flow. Use our extra back off factor to allow the other flow to go up.
     last_max_congestion_window_ =
-        static_cast<int>(kBetaLastMax * current_congestion_window);
+        static_cast<int>(BetaLastMax() * current_congestion_window);
   } else {
     last_max_congestion_window_ = current_congestion_window;
   }
@@ -106,10 +120,12 @@
 
 QuicPacketCount Cubic::CongestionWindowAfterAck(
     QuicPacketCount current_congestion_window,
-    QuicTime::Delta delay_min) {
+    QuicTime::Delta delay_min,
+    QuicTime event_time) {
   acked_packets_count_ += 1;  // Packets acked.
   epoch_packets_count_ += 1;
-  QuicTime current_time = clock_->ApproximateNow();
+  QuicTime current_time =
+      FLAGS_quic_use_event_time ? event_time : clock_->ApproximateNow();
 
   // Cubic is "independent" of RTT, the update is limited by the time elapsed.
   if (last_congestion_window_ == current_congestion_window &&
diff --git a/net/quic/core/congestion_control/cubic.h b/net/quic/core/congestion_control/cubic.h
index e3a44be2..8c1afb3 100644
--- a/net/quic/core/congestion_control/cubic.h
+++ b/net/quic/core/congestion_control/cubic.h
@@ -19,6 +19,10 @@
 
 namespace net {
 
+namespace test {
+class CubicTest;
+}  // namespace test
+
 class QUIC_EXPORT_PRIVATE Cubic {
  public:
   explicit Cubic(const QuicClock* clock);
@@ -38,7 +42,8 @@
   // window follows a cubic function that depends on the time passed
   // since last packet loss.
   QuicPacketCount CongestionWindowAfterAck(QuicPacketCount current,
-                                           QuicTime::Delta delay_min);
+                                           QuicTime::Delta delay_min,
+                                           QuicTime event_time);
 
   // Call on ack arrival when sender is unable to use the available congestion
   // window. Resets Cubic state during quiescence.
@@ -49,15 +54,27 @@
   // TODO(jokulik):  Remove once the fix is enabled by default.
   void SetFixConvexMode(bool fix_convex_mode);
 
+  // If true, enable the fix for scaling BetaLastMax for n-nonnection
+  // emulation.  See b/33272010 for more information about the bug.
+  // TODO(jokulik):  Remove once the fix is enabled by default.
+  void SetFixBetaLastMax(bool fix_bet_last_max);
+
  private:
+  friend class test::CubicTest;
+
   static const QuicTime::Delta MaxCubicTimeInterval() {
     return QuicTime::Delta::FromMilliseconds(30);
   }
 
-  // Compute the TCP Cubic alpha and beta based on the current number of
-  // connections.
+  // Compute the TCP Cubic alpha, beta, and beta-last-max based on the
+  // current number of connections.
   float Alpha() const;
   float Beta() const;
+  float BetaLastMax() const;
+
+  QuicByteCount last_max_congestion_window() const {
+    return last_max_congestion_window_;
+  }
 
   const QuicClock* clock_;
 
@@ -106,6 +123,10 @@
   // TODO(jokulik):  Remove once the cubic convex experiment is done.
   bool fix_convex_mode_;
 
+  // Fix beta last max for n-connection-emulation.
+  // TODO(jokulik):  Remove once the corresponding experiment is done.
+  bool fix_beta_last_max_;
+
   DISALLOW_COPY_AND_ASSIGN(Cubic);
 };
 
diff --git a/net/quic/core/congestion_control/cubic_bytes.cc b/net/quic/core/congestion_control/cubic_bytes.cc
index 7abe9209..d546afc 100644
--- a/net/quic/core/congestion_control/cubic_bytes.cc
+++ b/net/quic/core/congestion_control/cubic_bytes.cc
@@ -41,7 +41,9 @@
       num_connections_(kDefaultNumConnections),
       epoch_(QuicTime::Zero()),
       last_update_time_(QuicTime::Zero()),
-      fix_convex_mode_(false) {
+      fix_convex_mode_(false),
+      fix_cubic_quantization_(false),
+      fix_beta_last_max_(false) {
   Reset();
 }
 
@@ -65,6 +67,16 @@
   return (num_connections_ - 1 + kBeta) / num_connections_;
 }
 
+float CubicBytes::BetaLastMax() const {
+  // BetaLastMax is the additional backoff factor after loss for our
+  // N-connection emulation, which emulates the additional backoff of
+  // an ensemble of N TCP-Reno connections on a single loss event. The
+  // effective multiplier is computed as:
+  return fix_beta_last_max_
+             ? (num_connections_ - 1 + kBetaLastMax) / num_connections_
+             : kBetaLastMax;
+}
+
 void CubicBytes::Reset() {
   epoch_ = QuicTime::Zero();             // Reset time.
   last_update_time_ = QuicTime::Zero();  // Reset time.
@@ -82,6 +94,14 @@
   fix_convex_mode_ = fix_convex_mode;
 }
 
+void CubicBytes::SetFixCubicQuantization(bool fix_cubic_quantization) {
+  fix_cubic_quantization_ = fix_cubic_quantization;
+}
+
+void CubicBytes::SetFixBetaLastMax(bool fix_beta_last_max) {
+  fix_beta_last_max_ = fix_beta_last_max;
+}
+
 void CubicBytes::OnApplicationLimited() {
   // When sender is not using the available congestion window, the window does
   // not grow. But to be RTT-independent, Cubic assumes that the sender has been
@@ -96,11 +116,18 @@
 
 QuicByteCount CubicBytes::CongestionWindowAfterPacketLoss(
     QuicByteCount current_congestion_window) {
-  if (current_congestion_window < last_max_congestion_window_) {
-    // We never reached the old max, so assume we are competing with another
-    // flow. Use our extra back off factor to allow the other flow to go up.
+  // Since bytes-mode Reno mode slightly under-estimates the cwnd, we
+  // may never reach precisely the last cwnd over the course of an
+  // RTT.  Do not interpret a slight under-estimation as competing traffic.
+  const QuicByteCount last_window_delta =
+      fix_beta_last_max_ ? kDefaultTCPMSS : 0;
+  if (current_congestion_window + last_window_delta <
+      last_max_congestion_window_) {
+    // We never reached the old max, so assume we are competing with
+    // another flow. Use our extra back off factor to allow the other
+    // flow to go up.
     last_max_congestion_window_ =
-        static_cast<int>(kBetaLastMax * current_congestion_window);
+        static_cast<int>(BetaLastMax() * current_congestion_window);
   } else {
     last_max_congestion_window_ = current_congestion_window;
   }
@@ -111,9 +138,11 @@
 QuicByteCount CubicBytes::CongestionWindowAfterAck(
     QuicByteCount acked_bytes,
     QuicByteCount current_congestion_window,
-    QuicTime::Delta delay_min) {
+    QuicTime::Delta delay_min,
+    QuicTime event_time) {
   acked_bytes_count_ += acked_bytes;
-  QuicTime current_time = clock_->ApproximateNow();
+  QuicTime current_time =
+      FLAGS_quic_use_event_time ? event_time : clock_->ApproximateNow();
 
   // Cubic is "independent" of RTT, the update is limited by the time elapsed.
   if (last_congestion_window_ == current_congestion_window &&
@@ -158,8 +187,13 @@
     offset = positive_offset;
   }
   QuicByteCount delta_congestion_window =
-      ((kCubeCongestionWindowScale * offset * offset * offset) >> kCubeScale) *
-      kDefaultTCPMSS;
+      fix_cubic_quantization_
+          ? (kCubeCongestionWindowScale * offset * offset * offset *
+             kDefaultTCPMSS) >>
+                kCubeScale
+          : ((kCubeCongestionWindowScale * offset * offset * offset) >>
+             kCubeScale) *
+                kDefaultTCPMSS;
 
   const bool add_delta = elapsed_time > time_to_origin_point_;
   DCHECK(add_delta ||
diff --git a/net/quic/core/congestion_control/cubic_bytes.h b/net/quic/core/congestion_control/cubic_bytes.h
index 481b012..c205cef05 100644
--- a/net/quic/core/congestion_control/cubic_bytes.h
+++ b/net/quic/core/congestion_control/cubic_bytes.h
@@ -19,6 +19,10 @@
 
 namespace net {
 
+namespace test {
+class CubicBytesTest;
+}  // namespace test
+
 class QUIC_EXPORT_PRIVATE CubicBytes {
  public:
   explicit CubicBytes(const QuicClock* clock);
@@ -39,23 +43,44 @@
   // loss.
   QuicByteCount CongestionWindowAfterAck(QuicByteCount acked_bytes,
                                          QuicByteCount current,
-                                         QuicTime::Delta delay_min);
+                                         QuicTime::Delta delay_min,
+                                         QuicTime event_time);
 
   // Call on ack arrival when sender is unable to use the available congestion
   // window. Resets Cubic state during quiescence.
   void OnApplicationLimited();
 
+  // If true, enable the fix for the convex-mode signing bug.  See
+  // b/32170105 for more information about the bug.
+  // TODO(jokulik):  Remove once the fix is enabled by default.
   void SetFixConvexMode(bool fix_convex_mode);
 
+  // If true, fix CubicBytes quantization bug.  See b/33273459 for
+  // more information about the bug.
+  // TODO(jokulik): Remove once the fix is enabled by default.
+  void SetFixCubicQuantization(bool fix_cubic_quantization);
+
+  // If true, enable the fix for scaling BetaLastMax for n-nonnection
+  // emulation.  See b/33272010 for more information about the bug.
+  // TODO(jokulik):  Remove once the fix is enabled by default.
+  void SetFixBetaLastMax(bool fix_beta_last_max);
+
  private:
+  friend class test::CubicBytesTest;
+
   static const QuicTime::Delta MaxCubicTimeInterval() {
     return QuicTime::Delta::FromMilliseconds(30);
   }
 
-  // Compute the TCP Cubic alpha and beta based on the current number of
-  // connections.
+  // Compute the TCP Cubic alpha, beta, and beta-last-max based on the
+  // current number of connections.
   float Alpha() const;
   float Beta() const;
+  float BetaLastMax() const;
+
+  QuicByteCount last_max_congestion_window() const {
+    return last_max_congestion_window_;
+  }
 
   const QuicClock* clock_;
 
@@ -95,6 +120,14 @@
   // TODO(jokulik):  Remove once the cubic convex experiment is done.
   bool fix_convex_mode_;
 
+  // Fix for quantization in cubic mode.
+  // TODO(jokulik):  Remove once the experiment is done.
+  bool fix_cubic_quantization_;
+
+  // Fix beta last max for n-connection-emulation.
+  // TODO(jokulik):  Remove once the corresponding experiment is done.
+  bool fix_beta_last_max_;
+
   DISALLOW_COPY_AND_ASSIGN(CubicBytes);
 };
 
diff --git a/net/quic/core/congestion_control/cubic_bytes_test.cc b/net/quic/core/congestion_control/cubic_bytes_test.cc
index 0ee3b43c..80f6b57 100644
--- a/net/quic/core/congestion_control/cubic_bytes_test.cc
+++ b/net/quic/core/congestion_control/cubic_bytes_test.cc
@@ -14,20 +14,24 @@
 namespace net {
 namespace test {
 
-const float kBeta = 0.7f;  // Default Cubic backoff factor.
+const float kBeta = 0.7f;          // Default Cubic backoff factor.
+const float kBetaLastMax = 0.85f;  // Default Cubic backoff factor.
 const uint32_t kNumConnections = 2;
 const float kNConnectionBeta = (kNumConnections - 1 + kBeta) / kNumConnections;
+const float kNConnectionBetaLastMax =
+    (kNumConnections - 1 + kBetaLastMax) / kNumConnections;
 const float kNConnectionAlpha = 3 * kNumConnections * kNumConnections *
                                 (1 - kNConnectionBeta) / (1 + kNConnectionBeta);
 
-class CubicBytesTest : public ::testing::TestWithParam<bool> {
+class CubicBytesTest : public ::testing::Test {
  protected:
   CubicBytesTest()
       : one_ms_(QuicTime::Delta::FromMilliseconds(1)),
         hundred_ms_(QuicTime::Delta::FromMilliseconds(100)),
-        cubic_(&clock_),
-        fix_convex_mode_(GetParam()) {
-    cubic_.SetFixConvexMode(fix_convex_mode_);
+        cubic_(&clock_) {
+    cubic_.SetFixConvexMode(FLAGS_quic_fix_cubic_convex_mode);
+    cubic_.SetFixCubicQuantization(FLAGS_quic_fix_cubic_bytes_quantization);
+    cubic_.SetFixBetaLastMax(FLAGS_quic_fix_beta_last_max);
   }
 
   QuicByteCount RenoCwndInBytes(QuicByteCount current_cwnd) {
@@ -43,30 +47,34 @@
   }
 
   QuicByteCount CubicConvexCwndInBytes(QuicByteCount initial_cwnd,
-                                       int64_t rtt_ms,
-                                       int64_t elapsed_time_ms) {
-    const int64_t offset = ((elapsed_time_ms + rtt_ms) << 10) / 1000;
+                                       QuicTime::Delta rtt,
+                                       QuicTime::Delta elapsed_time) {
+    const int64_t offset =
+        ((elapsed_time + rtt).ToMicroseconds() << 10) / 1000000;
     const QuicByteCount delta_congestion_window =
-        ((410 * offset * offset * offset) >> 40) * kDefaultTCPMSS;
+        FLAGS_quic_fix_cubic_bytes_quantization
+            ? ((410 * offset * offset * offset) * kDefaultTCPMSS >> 40)
+            : ((410 * offset * offset * offset) >> 40) * kDefaultTCPMSS;
     const QuicByteCount cubic_cwnd = initial_cwnd + delta_congestion_window;
     return cubic_cwnd;
   }
 
+  QuicByteCount LastMaxCongestionWindow() {
+    return cubic_.last_max_congestion_window();
+  }
+
   const QuicTime::Delta one_ms_;
   const QuicTime::Delta hundred_ms_;
   MockClock clock_;
   CubicBytes cubic_;
-  bool fix_convex_mode_;
 };
 
-INSTANTIATE_TEST_CASE_P(CubicBytesTests, CubicBytesTest, testing::Bool());
-
 // TODO(jokulik): The original "AboveOrigin" test, below, is very
 // loose.  It's nearly impossible to make the test tighter without
 // deploying the fix for convex mode.  Once cubic convex is deployed,
 // replace "AboveOrigin" with this test.
-TEST_P(CubicBytesTest, AboveOriginWithTighterBounds) {
-  if (!fix_convex_mode_) {
+TEST_F(CubicBytesTest, AboveOriginWithTighterBounds) {
+  if (!FLAGS_quic_fix_cubic_convex_mode) {
     // Without convex mode fixed, the behavior of the algorithm is so
     // far from expected, there's no point in doing a tighter test.
     return;
@@ -81,16 +89,21 @@
   clock_.AdvanceTime(one_ms_);
   const QuicTime initial_time = clock_.ApproximateNow();
   const QuicByteCount expected_first_cwnd = RenoCwndInBytes(current_cwnd);
-  current_cwnd =
-      cubic_.CongestionWindowAfterAck(kDefaultTCPMSS, current_cwnd, rtt_min);
+  current_cwnd = cubic_.CongestionWindowAfterAck(kDefaultTCPMSS, current_cwnd,
+                                                 rtt_min, initial_time);
   ASSERT_EQ(expected_first_cwnd, current_cwnd);
 
   // Normal TCP phase.
   // The maximum number of expected Reno RTTs is calculated by
   // finding the point where the cubic curve and the reno curve meet.
   const int max_reno_rtts =
-      std::sqrt(kNConnectionAlpha / (.4 * rtt_min_s * rtt_min_s * rtt_min_s)) -
-      1;
+      FLAGS_quic_fix_cubic_bytes_quantization
+          ? std::sqrt(kNConnectionAlpha /
+                      (.4 * rtt_min_s * rtt_min_s * rtt_min_s)) -
+                2
+          : std::sqrt(kNConnectionAlpha /
+                      (.4 * rtt_min_s * rtt_min_s * rtt_min_s)) -
+                1;
   for (int i = 0; i < max_reno_rtts; ++i) {
     // Alternatively, we expect it to increase by one, every time we
     // receive current_cwnd/Alpha acks back.  (This is another way of
@@ -102,8 +115,8 @@
     for (QuicPacketCount n = 0; n < num_acks_this_epoch; ++n) {
       // Call once per ACK.
       const QuicByteCount expected_next_cwnd = RenoCwndInBytes(current_cwnd);
-      current_cwnd = cubic_.CongestionWindowAfterAck(kDefaultTCPMSS,
-                                                     current_cwnd, rtt_min);
+      current_cwnd = cubic_.CongestionWindowAfterAck(
+          kDefaultTCPMSS, current_cwnd, rtt_min, clock_.ApproximateNow());
       ASSERT_EQ(expected_next_cwnd, current_cwnd);
     }
     // Our byte-wise Reno implementation is an estimate.  We expect
@@ -116,56 +129,65 @@
     clock_.AdvanceTime(hundred_ms_);
   }
 
-  // Because our byte-wise Reno under-estimates the cwnd, we switch to
-  // conservative increases for a few acks before switching to true
-  // cubic increases.
-  for (int i = 0; i < 3; ++i) {
-    const QuicByteCount next_expected_cwnd =
-        ConservativeCwndInBytes(current_cwnd);
-    current_cwnd =
-        cubic_.CongestionWindowAfterAck(kDefaultTCPMSS, current_cwnd, rtt_min);
-    ASSERT_EQ(next_expected_cwnd, current_cwnd);
+  if (!FLAGS_quic_fix_cubic_bytes_quantization) {
+    // Because our byte-wise Reno under-estimates the cwnd, we switch to
+    // conservative increases for a few acks before switching to true
+    // cubic increases.
+    for (int i = 0; i < 3; ++i) {
+      const QuicByteCount next_expected_cwnd =
+          ConservativeCwndInBytes(current_cwnd);
+      current_cwnd = cubic_.CongestionWindowAfterAck(
+          kDefaultTCPMSS, current_cwnd, rtt_min, clock_.ApproximateNow());
+      ASSERT_EQ(next_expected_cwnd, current_cwnd);
+    }
   }
 
   for (int i = 0; i < 54; ++i) {
     const uint64_t max_acks_this_epoch = current_cwnd / kDefaultTCPMSS;
-    const int elapsed_time_ms =
-        (clock_.ApproximateNow() - initial_time).ToMilliseconds();
     const QuicByteCount expected_cwnd = CubicConvexCwndInBytes(
-        initial_cwnd, rtt_min.ToMilliseconds(), elapsed_time_ms);
-    current_cwnd =
-        cubic_.CongestionWindowAfterAck(kDefaultTCPMSS, current_cwnd, rtt_min);
+        initial_cwnd, rtt_min, (clock_.ApproximateNow() - initial_time));
+    current_cwnd = cubic_.CongestionWindowAfterAck(
+        kDefaultTCPMSS, current_cwnd, rtt_min, clock_.ApproximateNow());
     ASSERT_EQ(expected_cwnd, current_cwnd);
 
     for (QuicPacketCount n = 1; n < max_acks_this_epoch; ++n) {
       // Call once per ACK.
       ASSERT_EQ(current_cwnd, cubic_.CongestionWindowAfterAck(
-                                  kDefaultTCPMSS, current_cwnd, rtt_min));
+                                  kDefaultTCPMSS, current_cwnd, rtt_min,
+                                  clock_.ApproximateNow()));
     }
     clock_.AdvanceTime(hundred_ms_);
   }
-  const int elapsed_time_ms =
-      (clock_.ApproximateNow() - initial_time).ToMilliseconds();
   const QuicByteCount expected_cwnd = CubicConvexCwndInBytes(
-      initial_cwnd, rtt_min.ToMilliseconds(), elapsed_time_ms);
-  current_cwnd =
-      cubic_.CongestionWindowAfterAck(kDefaultTCPMSS, current_cwnd, rtt_min);
+      initial_cwnd, rtt_min, (clock_.ApproximateNow() - initial_time));
+  current_cwnd = cubic_.CongestionWindowAfterAck(
+      kDefaultTCPMSS, current_cwnd, rtt_min, clock_.ApproximateNow());
   ASSERT_EQ(expected_cwnd, current_cwnd);
 }
 
-TEST_P(CubicBytesTest, AboveOrigin) {
+TEST_F(CubicBytesTest, AboveOrigin) {
+  if (!FLAGS_quic_fix_cubic_convex_mode &&
+      FLAGS_quic_fix_cubic_bytes_quantization) {
+    // Without convex mode fixed, the behavior of the algorithm does
+    // not fit the exact pattern of this test.
+    // TODO(jokulik): Once the convex mode fix becomes default, this
+    // test can be replaced with the better AboveOriginTighterBounds
+    // test.
+    return;
+  }
   // Convex growth.
   const QuicTime::Delta rtt_min = hundred_ms_;
   QuicByteCount current_cwnd = 10 * kDefaultTCPMSS;
   // Without the signed-integer, cubic-convex fix, we start out in the
   // wrong mode.
-  QuicPacketCount expected_cwnd = fix_convex_mode_
+  QuicPacketCount expected_cwnd = FLAGS_quic_fix_cubic_convex_mode
                                       ? RenoCwndInBytes(current_cwnd)
                                       : ConservativeCwndInBytes(current_cwnd);
   // Initialize the state.
   clock_.AdvanceTime(one_ms_);
-  ASSERT_EQ(expected_cwnd, cubic_.CongestionWindowAfterAck(
-                               kDefaultTCPMSS, current_cwnd, rtt_min));
+  ASSERT_EQ(expected_cwnd,
+            cubic_.CongestionWindowAfterAck(kDefaultTCPMSS, current_cwnd,
+                                            rtt_min, clock_.ApproximateNow()));
   current_cwnd = expected_cwnd;
   const QuicPacketCount initial_cwnd = expected_cwnd;
   // Normal TCP phase.
@@ -174,13 +196,14 @@
          n < current_cwnd / kDefaultTCPMSS / kNConnectionAlpha; ++n) {
       // Call once per ACK.
       ASSERT_NEAR(current_cwnd, cubic_.CongestionWindowAfterAck(
-                                    kDefaultTCPMSS, current_cwnd, rtt_min),
+                                    kDefaultTCPMSS, current_cwnd, rtt_min,
+                                    clock_.ApproximateNow()),
                   kDefaultTCPMSS);
     }
     clock_.AdvanceTime(hundred_ms_);
-    current_cwnd =
-        cubic_.CongestionWindowAfterAck(kDefaultTCPMSS, current_cwnd, rtt_min);
-    if (fix_convex_mode_) {
+    current_cwnd = cubic_.CongestionWindowAfterAck(
+        kDefaultTCPMSS, current_cwnd, rtt_min, clock_.ApproximateNow());
+    if (FLAGS_quic_fix_cubic_convex_mode) {
       // When we fix convex mode and the uint64 arithmetic, we
       // increase the expected_cwnd only after after the first 100ms,
       // rather than after the initial 1ms.
@@ -196,12 +219,13 @@
     for (QuicPacketCount n = 1; n < current_cwnd / kDefaultTCPMSS; ++n) {
       // Call once per ACK.
       ASSERT_NEAR(current_cwnd, cubic_.CongestionWindowAfterAck(
-                                    kDefaultTCPMSS, current_cwnd, rtt_min),
+                                    kDefaultTCPMSS, current_cwnd, rtt_min,
+                                    clock_.ApproximateNow()),
                   kDefaultTCPMSS);
     }
     clock_.AdvanceTime(hundred_ms_);
-    current_cwnd =
-        cubic_.CongestionWindowAfterAck(kDefaultTCPMSS, current_cwnd, rtt_min);
+    current_cwnd = cubic_.CongestionWindowAfterAck(
+        kDefaultTCPMSS, current_cwnd, rtt_min, clock_.ApproximateNow());
   }
   // Total time elapsed so far; add min_rtt (0.1s) here as well.
   float elapsed_time_s = 10.0f + 0.1f;
@@ -210,57 +234,160 @@
       initial_cwnd / kDefaultTCPMSS +
       (elapsed_time_s * elapsed_time_s * elapsed_time_s * 410) / 1024;
   // Without the convex mode fix, the result is off by one.
-  if (!fix_convex_mode_) {
+  if (!FLAGS_quic_fix_cubic_convex_mode) {
     ++expected_cwnd;
   }
   EXPECT_EQ(expected_cwnd, current_cwnd / kDefaultTCPMSS);
 }
 
-TEST_P(CubicBytesTest, LossEvents) {
+// Constructs an artificial scenario to ensure that cubic-convex
+// increases are truly fine-grained:
+//
+// - After starting the epoch, this test advances the elapsed time
+// sufficiently far that cubic will do small increases at less than
+// MaxCubicTimeInterval() intervals.
+//
+// - Sets an artificially large initial cwnd to prevent Reno from the
+// convex increases on every ack.
+TEST_F(CubicBytesTest, AboveOriginFineGrainedCubing) {
+  if (!FLAGS_quic_fix_cubic_convex_mode ||
+      !FLAGS_quic_fix_cubic_bytes_quantization) {
+    // Without these two fixes, this test cannot pass.
+    return;
+  }
+
+  // Start the test with an artificially large cwnd to prevent Reno
+  // from over-taking cubic.
+  QuicByteCount current_cwnd = 1000 * kDefaultTCPMSS;
+  const QuicByteCount initial_cwnd = current_cwnd;
+  const QuicTime::Delta rtt_min = hundred_ms_;
+  clock_.AdvanceTime(one_ms_);
+  QuicTime initial_time = clock_.ApproximateNow();
+
+  // Start the epoch and then artificially advance the time.
+  current_cwnd = cubic_.CongestionWindowAfterAck(
+      kDefaultTCPMSS, current_cwnd, rtt_min, clock_.ApproximateNow());
+  clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(600));
+  current_cwnd = cubic_.CongestionWindowAfterAck(
+      kDefaultTCPMSS, current_cwnd, rtt_min, clock_.ApproximateNow());
+
+  // We expect the algorithm to perform only non-zero, fine-grained cubic
+  // increases on every ack in this case.
+  for (int i = 0; i < 100; ++i) {
+    clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
+    const QuicByteCount expected_cwnd = CubicConvexCwndInBytes(
+        initial_cwnd, rtt_min, (clock_.ApproximateNow() - initial_time));
+    const QuicByteCount next_cwnd = cubic_.CongestionWindowAfterAck(
+        kDefaultTCPMSS, current_cwnd, rtt_min, clock_.ApproximateNow());
+    // Make sure we are performing cubic increases.
+    ASSERT_EQ(expected_cwnd, next_cwnd);
+    // Make sure that these are non-zero, less-than-packet sized
+    // increases.
+    ASSERT_GT(next_cwnd, current_cwnd);
+    const QuicByteCount cwnd_delta = next_cwnd - current_cwnd;
+    ASSERT_GT(kDefaultTCPMSS * .1, cwnd_delta);
+
+    current_cwnd = next_cwnd;
+  }
+}
+
+TEST_F(CubicBytesTest, LossEvents) {
   const QuicTime::Delta rtt_min = hundred_ms_;
   QuicByteCount current_cwnd = 422 * kDefaultTCPMSS;
   // Without the signed-integer, cubic-convex fix, we mistakenly
   // increment cwnd after only one_ms_ and a single ack.
-  QuicPacketCount expected_cwnd = fix_convex_mode_
+  QuicPacketCount expected_cwnd = FLAGS_quic_fix_cubic_convex_mode
                                       ? RenoCwndInBytes(current_cwnd)
                                       : current_cwnd + kDefaultTCPMSS / 2;
   // Initialize the state.
   clock_.AdvanceTime(one_ms_);
-  EXPECT_EQ(expected_cwnd, cubic_.CongestionWindowAfterAck(
-                               kDefaultTCPMSS, current_cwnd, rtt_min));
-  expected_cwnd = static_cast<QuicPacketCount>(current_cwnd * kNConnectionBeta);
+  EXPECT_EQ(expected_cwnd,
+            cubic_.CongestionWindowAfterAck(kDefaultTCPMSS, current_cwnd,
+                                            rtt_min, clock_.ApproximateNow()));
+
+  // On the first loss, the last max congestion window is set to the
+  // congestion window before the loss.
+  QuicByteCount pre_loss_cwnd = current_cwnd;
+  ASSERT_EQ(0u, LastMaxCongestionWindow());
+  expected_cwnd = static_cast<QuicByteCount>(current_cwnd * kNConnectionBeta);
   EXPECT_EQ(expected_cwnd,
             cubic_.CongestionWindowAfterPacketLoss(current_cwnd));
-  expected_cwnd = static_cast<QuicPacketCount>(current_cwnd * kNConnectionBeta);
+  ASSERT_EQ(pre_loss_cwnd, LastMaxCongestionWindow());
+  current_cwnd = expected_cwnd;
+
+  // On the second loss, the current congestion window has not yet
+  // reached the last max congestion window.  The last max congestion
+  // window will be reduced by an additional backoff factor to allow
+  // for competition.
+  pre_loss_cwnd = current_cwnd;
+  expected_cwnd = static_cast<QuicByteCount>(current_cwnd * kNConnectionBeta);
+  ASSERT_EQ(expected_cwnd,
+            cubic_.CongestionWindowAfterPacketLoss(current_cwnd));
+  current_cwnd = expected_cwnd;
+  EXPECT_GT(pre_loss_cwnd, LastMaxCongestionWindow());
+  QuicByteCount expected_last_max =
+      FLAGS_quic_fix_beta_last_max
+          ? static_cast<QuicByteCount>(pre_loss_cwnd * kNConnectionBetaLastMax)
+          : static_cast<QuicByteCount>(pre_loss_cwnd * kBetaLastMax);
+  EXPECT_EQ(expected_last_max, LastMaxCongestionWindow());
+  if (FLAGS_quic_fix_beta_last_max) {
+    EXPECT_LT(expected_cwnd, LastMaxCongestionWindow());
+  } else {
+    // If we don't scale kLastBetaMax, the current window is exactly
+    // equal to the last max congestion window, which would cause us
+    // to land above the origin on the next increase.
+    EXPECT_EQ(expected_cwnd, LastMaxCongestionWindow());
+  }
+  // Simulate an increase, and check that we are below the origin.
+  current_cwnd = cubic_.CongestionWindowAfterAck(
+      kDefaultTCPMSS, current_cwnd, rtt_min, clock_.ApproximateNow());
+  if (FLAGS_quic_fix_beta_last_max) {
+    EXPECT_GT(LastMaxCongestionWindow(), current_cwnd);
+  } else {
+    // Without the bug fix, we will be at or above the origin.
+    EXPECT_LE(LastMaxCongestionWindow(), current_cwnd);
+  }
+
+  // On the final loss, simulate the condition where the congestion
+  // window had a chance to grow nearly to the last congestion window.
+  current_cwnd = LastMaxCongestionWindow() - 1;
+  pre_loss_cwnd = current_cwnd;
+  expected_cwnd = static_cast<QuicByteCount>(current_cwnd * kNConnectionBeta);
   EXPECT_EQ(expected_cwnd,
             cubic_.CongestionWindowAfterPacketLoss(current_cwnd));
+  expected_last_max =
+      FLAGS_quic_fix_beta_last_max
+          ? pre_loss_cwnd
+          : static_cast<QuicByteCount>(pre_loss_cwnd * kBetaLastMax);
+  ASSERT_EQ(expected_last_max, LastMaxCongestionWindow());
 }
 
-TEST_P(CubicBytesTest, BelowOrigin) {
+TEST_F(CubicBytesTest, BelowOrigin) {
   // Concave growth.
   const QuicTime::Delta rtt_min = hundred_ms_;
   QuicByteCount current_cwnd = 422 * kDefaultTCPMSS;
   // Without the signed-integer, cubic-convex fix, we mistakenly
   // increment cwnd after only one_ms_ and a single ack.
-  QuicPacketCount expected_cwnd = fix_convex_mode_
+  QuicPacketCount expected_cwnd = FLAGS_quic_fix_cubic_convex_mode
                                       ? RenoCwndInBytes(current_cwnd)
                                       : current_cwnd + kDefaultTCPMSS / 2;
   // Initialize the state.
   clock_.AdvanceTime(one_ms_);
-  EXPECT_EQ(expected_cwnd, cubic_.CongestionWindowAfterAck(
-                               kDefaultTCPMSS, current_cwnd, rtt_min));
+  EXPECT_EQ(expected_cwnd,
+            cubic_.CongestionWindowAfterAck(kDefaultTCPMSS, current_cwnd,
+                                            rtt_min, clock_.ApproximateNow()));
   expected_cwnd = static_cast<QuicPacketCount>(current_cwnd * kNConnectionBeta);
   EXPECT_EQ(expected_cwnd,
             cubic_.CongestionWindowAfterPacketLoss(current_cwnd));
   current_cwnd = expected_cwnd;
   // First update after loss to initialize the epoch.
-  current_cwnd =
-      cubic_.CongestionWindowAfterAck(kDefaultTCPMSS, current_cwnd, rtt_min);
+  current_cwnd = cubic_.CongestionWindowAfterAck(
+      kDefaultTCPMSS, current_cwnd, rtt_min, clock_.ApproximateNow());
   // Cubic phase.
   for (int i = 0; i < 40; ++i) {
     clock_.AdvanceTime(hundred_ms_);
-    current_cwnd =
-        cubic_.CongestionWindowAfterAck(kDefaultTCPMSS, current_cwnd, rtt_min);
+    current_cwnd = cubic_.CongestionWindowAfterAck(
+        kDefaultTCPMSS, current_cwnd, rtt_min, clock_.ApproximateNow());
   }
   expected_cwnd = 553632;
   EXPECT_EQ(expected_cwnd, current_cwnd);
diff --git a/net/quic/core/congestion_control/cubic_test.cc b/net/quic/core/congestion_control/cubic_test.cc
index c9342c0..7020b48 100644
--- a/net/quic/core/congestion_control/cubic_test.cc
+++ b/net/quic/core/congestion_control/cubic_test.cc
@@ -7,15 +7,19 @@
 #include <cstdint>
 
 #include "base/logging.h"
+#include "net/quic/core/quic_flags.h"
 #include "net/quic/test_tools/mock_clock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace net {
 namespace test {
 
-const float kBeta = 0.7f;  // Default Cubic backoff factor.
+const float kBeta = 0.7f;          // Default Cubic backoff factor.
+const float kBetaLastMax = 0.85f;  // Default Cubic backoff factor.
 const uint32_t kNumConnections = 2;
 const float kNConnectionBeta = (kNumConnections - 1 + kBeta) / kNumConnections;
+const float kNConnectionBetaLastMax =
+    (kNumConnections - 1 + kBetaLastMax) / kNumConnections;
 const float kNConnectionAlpha = 3 * kNumConnections * kNumConnections *
                                 (1 - kNConnectionBeta) / (1 + kNConnectionBeta);
 
@@ -29,7 +33,13 @@
         cubic_(&clock_) {
     fix_convex_mode_ = GetParam();
     cubic_.SetFixConvexMode(fix_convex_mode_);
+    cubic_.SetFixBetaLastMax(FLAGS_quic_fix_beta_last_max);
   }
+
+  QuicByteCount LastMaxCongestionWindow() {
+    return cubic_.last_max_congestion_window();
+  }
+
   const QuicTime::Delta one_ms_;
   const QuicTime::Delta hundred_ms_;
   MockClock clock_;
@@ -51,7 +61,8 @@
   // Initialize the state.
   clock_.AdvanceTime(one_ms_);
   const QuicTime initial_time = clock_.ApproximateNow();
-  current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min);
+  current_cwnd =
+      cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min, initial_time);
   ASSERT_EQ(expected_cwnd, current_cwnd);
   const QuicPacketCount initial_cwnd = current_cwnd;
   // Normal TCP phase.
@@ -64,12 +75,13 @@
     const QuicByteCount max_per_ack_cwnd = current_cwnd;
     for (QuicPacketCount n = 1; n < max_per_ack_cwnd / kNConnectionAlpha; ++n) {
       // Call once per ACK.
-      const QuicByteCount next_cwnd =
-          cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min);
+      const QuicByteCount next_cwnd = cubic_.CongestionWindowAfterAck(
+          current_cwnd, rtt_min, clock_.ApproximateNow());
       ASSERT_EQ(current_cwnd, next_cwnd);
     }
     clock_.AdvanceTime(hundred_ms_);
-    current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min);
+    current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min,
+                                                   clock_.ApproximateNow());
     if (fix_convex_mode_) {
       // When we fix convex mode and the uint64 arithmetic, we
       // increase the expected_cwnd only after after the first 100ms,
@@ -86,10 +98,12 @@
     for (QuicPacketCount n = 1; n < current_cwnd; ++n) {
       // Call once per ACK.
       ASSERT_EQ(current_cwnd,
-                cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min));
+                cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min,
+                                                clock_.ApproximateNow()));
     }
     clock_.AdvanceTime(hundred_ms_);
-    current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min);
+    current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min,
+                                                   clock_.ApproximateNow());
   }
   // Total time elapsed so far; add min_rtt (0.1s) here as well.
   const float elapsed_time_ms =
@@ -112,14 +126,61 @@
       fix_convex_mode_ ? current_cwnd : current_cwnd + 1;
   // Initialize the state.
   clock_.AdvanceTime(one_ms_);
+  EXPECT_EQ(expected_cwnd, cubic_.CongestionWindowAfterAck(
+                               current_cwnd, rtt_min, clock_.ApproximateNow()));
+
+  // On the first loss, the last max congestion window is set to the
+  // congestion window before the loss.
+  QuicByteCount pre_loss_cwnd = current_cwnd;
+  expected_cwnd = static_cast<QuicPacketCount>(current_cwnd * kNConnectionBeta);
+  ASSERT_EQ(0u, LastMaxCongestionWindow());
   EXPECT_EQ(expected_cwnd,
-            cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min));
+            cubic_.CongestionWindowAfterPacketLoss(current_cwnd));
+  ASSERT_EQ(pre_loss_cwnd, LastMaxCongestionWindow());
+  current_cwnd = expected_cwnd;
+
+  // On the second loss, the current congestion window is
+  // significantly lower than the last max congestion window.  The
+  // last max congestion window will be reduced by an additional
+  // backoff factor to allow for competition.
+  pre_loss_cwnd = current_cwnd;
+  expected_cwnd = static_cast<QuicPacketCount>(current_cwnd * kNConnectionBeta);
+  ASSERT_EQ(expected_cwnd,
+            cubic_.CongestionWindowAfterPacketLoss(current_cwnd));
+  current_cwnd = expected_cwnd;
+  EXPECT_GT(pre_loss_cwnd, LastMaxCongestionWindow());
+  QuicByteCount expected_last_max =
+      FLAGS_quic_fix_beta_last_max
+          ? static_cast<QuicPacketCount>(pre_loss_cwnd *
+                                         kNConnectionBetaLastMax)
+          : static_cast<QuicPacketCount>(pre_loss_cwnd * kBetaLastMax);
+  EXPECT_EQ(expected_last_max, LastMaxCongestionWindow());
+  if (FLAGS_quic_fix_beta_last_max) {
+    EXPECT_LT(expected_cwnd, LastMaxCongestionWindow());
+  } else {
+    // If we don't scale kLastBetaMax, the current window is exactly
+    // equal to the last max congestion window, which would cause us
+    // to land above the origin on the next increase.
+    EXPECT_EQ(expected_cwnd, LastMaxCongestionWindow());
+  }
+  // Simulate an increase, and check that we are below the origin.
+  current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min,
+                                                 clock_.ApproximateNow());
+  if (FLAGS_quic_fix_beta_last_max) {
+    EXPECT_GT(LastMaxCongestionWindow(), current_cwnd);
+  } else {
+    // Without the bug fix, we will be at or above the origin.
+    EXPECT_LE(LastMaxCongestionWindow(), current_cwnd);
+  }
+
+  // On the final loss, simulate the condition where the congestion
+  // window had a chance to grow back to the last congestion window.
+  current_cwnd = LastMaxCongestionWindow();
+  pre_loss_cwnd = current_cwnd;
   expected_cwnd = static_cast<QuicPacketCount>(current_cwnd * kNConnectionBeta);
   EXPECT_EQ(expected_cwnd,
             cubic_.CongestionWindowAfterPacketLoss(current_cwnd));
-  expected_cwnd = static_cast<QuicPacketCount>(current_cwnd * kNConnectionBeta);
-  EXPECT_EQ(expected_cwnd,
-            cubic_.CongestionWindowAfterPacketLoss(current_cwnd));
+  ASSERT_EQ(pre_loss_cwnd, LastMaxCongestionWindow());
 }
 
 TEST_P(CubicTest, BelowOrigin) {
@@ -132,18 +193,20 @@
       fix_convex_mode_ ? current_cwnd : current_cwnd + 1;
   // Initialize the state.
   clock_.AdvanceTime(one_ms_);
-  EXPECT_EQ(expected_cwnd,
-            cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min));
+  EXPECT_EQ(expected_cwnd, cubic_.CongestionWindowAfterAck(
+                               current_cwnd, rtt_min, clock_.ApproximateNow()));
   expected_cwnd = static_cast<QuicPacketCount>(current_cwnd * kNConnectionBeta);
   EXPECT_EQ(expected_cwnd,
             cubic_.CongestionWindowAfterPacketLoss(current_cwnd));
   current_cwnd = expected_cwnd;
   // First update after loss to initialize the epoch.
-  current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min);
+  current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min,
+                                                 clock_.ApproximateNow());
   // Cubic phase.
   for (int i = 0; i < 40; ++i) {
     clock_.AdvanceTime(hundred_ms_);
-    current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min);
+    current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min,
+                                                   clock_.ApproximateNow());
   }
   expected_cwnd = 399;
   EXPECT_EQ(expected_cwnd, current_cwnd);
diff --git a/net/quic/core/congestion_control/send_algorithm_interface.cc b/net/quic/core/congestion_control/send_algorithm_interface.cc
index bc44de0..badfd2b1 100644
--- a/net/quic/core/congestion_control/send_algorithm_interface.cc
+++ b/net/quic/core/congestion_control/send_algorithm_interface.cc
@@ -28,7 +28,7 @@
   switch (congestion_control_type) {
     case kBBR:
       if (FLAGS_quic_allow_new_bbr) {
-        return new BbrSender(clock, rtt_stats, unacked_packets,
+        return new BbrSender(rtt_stats, unacked_packets,
                              initial_congestion_window, max_congestion_window,
                              random);
       }
diff --git a/net/quic/core/congestion_control/send_algorithm_test.cc b/net/quic/core/congestion_control/send_algorithm_test.cc
index 75bacfb..c5e5324 100644
--- a/net/quic/core/congestion_control/send_algorithm_test.cc
+++ b/net/quic/core/congestion_control/send_algorithm_test.cc
@@ -60,7 +60,7 @@
 const QuicBandwidth kTestLinkWiredBandwidth =
     QuicBandwidth::FromKBitsPerSecond(4000);
 const QuicTime::Delta kTestLinkWiredPropagationDelay =
-    QuicTime::Delta::FromMilliseconds(30);
+    QuicTime::Delta::FromMilliseconds(50);
 const QuicTime::Delta kTestWiredTransferTime =
     kTestLinkWiredBandwidth.TransferTime(kMaxPacketSize) +
     kLocalLinkBandwidth.TransferTime(kMaxPacketSize);
@@ -77,7 +77,7 @@
 const QuicBandwidth kTestLinkLowBdpBandwidth =
     QuicBandwidth::FromKBitsPerSecond(200);
 const QuicTime::Delta kTestLinkLowBdpPropagationDelay =
-    QuicTime::Delta::FromMilliseconds(30);
+    QuicTime::Delta::FromMilliseconds(50);
 const QuicByteCount kTestPolicerQueue = kMaxPacketSize;
 
 // Satellite network settings.  In a satellite network, the bottleneck
@@ -168,13 +168,7 @@
         GetParam().congestion_control_type, &random_, &stats_,
         kInitialCongestionWindowPackets);
 
-    if (FLAGS_quic_fix_cubic_convex_mode) {
-      QuicConfig client_config;
-      QuicTagVector options;
-      options.push_back(kCCVX);
-      client_config.SetInitialReceivedConnectionOptions(options);
-      sender_->SetFromConfig(client_config, Perspective::IS_SERVER);
-    }
+    SetExperimentalOptionsInServerConfig();
 
     QuicConnectionPeer::SetSendAlgorithm(quic_sender_.connection(),
                                          kDefaultPathId, sender_);
@@ -187,6 +181,30 @@
     VLOG(1) << "SendAlgorithmTest simulator set up.  Seed: " << seed;
   }
 
+  // Sets experimental options in the server config, as if they had
+  // been sent by the client.
+  void SetExperimentalOptionsInServerConfig() {
+    QuicConfig client_config;
+    QuicTagVector options;
+    if (FLAGS_quic_fix_cubic_convex_mode) {
+      options.push_back(kCCVX);
+    }
+    if (FLAGS_quic_fix_cubic_convex_mode &&
+        FLAGS_quic_fix_cubic_bytes_quantization) {
+      options.push_back(kCCVX);
+      options.push_back(kCBQT);
+    }
+
+    if (FLAGS_quic_fix_beta_last_max) {
+      options.push_back(kBLMX);
+    }
+
+    if (!options.empty()) {
+      client_config.SetInitialReceivedConnectionOptions(options);
+      sender_->SetFromConfig(client_config, Perspective::IS_SERVER);
+    }
+  }
+
   // Creates a simulated network, with default settings between the
   // sender and the switch and the given settings from the switch to
   // the receiver.
@@ -246,8 +264,12 @@
   }
 
   void PrintTransferStats() {
+    const QuicConnectionStats& stats = quic_sender_.connection()->GetStats();
     VLOG(1) << "Summary for scenario " << GetParam();
-    VLOG(1) << "Sender stats is " << quic_sender_.connection()->GetStats();
+    VLOG(1) << "Sender stats is " << stats;
+    const double rtx_rate =
+        static_cast<double>(stats.bytes_retransmitted) / stats.bytes_sent;
+    VLOG(1) << "Retransmit rate (num_rtx/num_total_sent): " << rtx_rate;
     VLOG(1) << "Connection elapsed time: "
             << (clock_->Now() - QuicSenderStartTime()).ToMilliseconds()
             << " (ms)";
diff --git a/net/quic/core/congestion_control/tcp_cubic_sender_base.cc b/net/quic/core/congestion_control/tcp_cubic_sender_base.cc
index 069bb16..c8d8930 100644
--- a/net/quic/core/congestion_control/tcp_cubic_sender_base.cc
+++ b/net/quic/core/congestion_control/tcp_cubic_sender_base.cc
@@ -123,7 +123,7 @@
 void TcpCubicSenderBase::OnCongestionEvent(
     bool rtt_updated,
     QuicByteCount prior_in_flight,
-    QuicTime /*event_time*/,
+    QuicTime event_time,
     const CongestionVector& acked_packets,
     const CongestionVector& lost_packets) {
   if (rtt_updated && InSlowStart() &&
@@ -138,13 +138,14 @@
   }
   for (CongestionVector::const_iterator it = acked_packets.begin();
        it != acked_packets.end(); ++it) {
-    OnPacketAcked(it->first, it->second, prior_in_flight);
+    OnPacketAcked(it->first, it->second, prior_in_flight, event_time);
   }
 }
 
 void TcpCubicSenderBase::OnPacketAcked(QuicPacketNumber acked_packet_number,
                                        QuicByteCount acked_bytes,
-                                       QuicByteCount prior_in_flight) {
+                                       QuicByteCount prior_in_flight,
+                                       QuicTime event_time) {
   largest_acked_packet_number_ =
       std::max(acked_packet_number, largest_acked_packet_number_);
   if (InRecovery()) {
@@ -154,7 +155,8 @@
     }
     return;
   }
-  MaybeIncreaseCwnd(acked_packet_number, acked_bytes, prior_in_flight);
+  MaybeIncreaseCwnd(acked_packet_number, acked_bytes, prior_in_flight,
+                    event_time);
   if (InSlowStart()) {
     hybrid_slow_start_.OnPacketAcked(acked_packet_number);
   }
diff --git a/net/quic/core/congestion_control/tcp_cubic_sender_base.h b/net/quic/core/congestion_control/tcp_cubic_sender_base.h
index f04eb74..a4ac1e57 100644
--- a/net/quic/core/congestion_control/tcp_cubic_sender_base.h
+++ b/net/quic/core/congestion_control/tcp_cubic_sender_base.h
@@ -95,7 +95,8 @@
   // window.
   virtual void MaybeIncreaseCwnd(QuicPacketNumber acked_packet_number,
                                  QuicByteCount acked_bytes,
-                                 QuicByteCount prior_in_flight) = 0;
+                                 QuicByteCount prior_in_flight,
+                                 QuicTime event_time) = 0;
 
   // Called when a retransmission has occured which resulted in packets
   // being retransmitted.
@@ -112,7 +113,8 @@
   // TODO(ianswett): Remove these and migrate to OnCongestionEvent.
   void OnPacketAcked(QuicPacketNumber acked_packet_number,
                      QuicByteCount acked_bytes,
-                     QuicByteCount prior_in_flight);
+                     QuicByteCount prior_in_flight,
+                     QuicTime event_time);
 
  protected:
   // TODO(rch): Make these private and clean up subclass access to them.
diff --git a/net/quic/core/congestion_control/tcp_cubic_sender_bytes.cc b/net/quic/core/congestion_control/tcp_cubic_sender_bytes.cc
index dab758a..8499143 100644
--- a/net/quic/core/congestion_control/tcp_cubic_sender_bytes.cc
+++ b/net/quic/core/congestion_control/tcp_cubic_sender_bytes.cc
@@ -52,6 +52,15 @@
       ContainsQuicTag(config.ReceivedConnectionOptions(), kCCVX)) {
     cubic_.SetFixConvexMode(true);
   }
+  if (FLAGS_quic_fix_cubic_bytes_quantization &&
+      config.HasReceivedConnectionOptions() &&
+      ContainsQuicTag(config.ReceivedConnectionOptions(), kCBQT)) {
+    cubic_.SetFixCubicQuantization(true);
+  }
+  if (FLAGS_quic_fix_beta_last_max && config.HasReceivedConnectionOptions() &&
+      ContainsQuicTag(config.ReceivedConnectionOptions(), kBLMX)) {
+    cubic_.SetFixBetaLastMax(true);
+  }
 }
 
 void TcpCubicSenderBytes::SetCongestionWindowFromBandwidthAndRtt(
@@ -152,7 +161,8 @@
 void TcpCubicSenderBytes::MaybeIncreaseCwnd(
     QuicPacketNumber acked_packet_number,
     QuicByteCount acked_bytes,
-    QuicByteCount prior_in_flight) {
+    QuicByteCount prior_in_flight,
+    QuicTime event_time) {
   QUIC_BUG_IF(InRecovery()) << "Never increase the CWND during recovery.";
   // Do not increase the congestion window unless the sender is close to using
   // the current window.
@@ -186,10 +196,10 @@
              << " slowstart threshold: " << slowstart_threshold_
              << " congestion window count: " << num_acked_packets_;
   } else {
-    congestion_window_ =
-        std::min(max_congestion_window_,
-                 cubic_.CongestionWindowAfterAck(
-                     acked_bytes, congestion_window_, rtt_stats_->min_rtt()));
+    congestion_window_ = std::min(
+        max_congestion_window_,
+        cubic_.CongestionWindowAfterAck(acked_bytes, congestion_window_,
+                                        rtt_stats_->min_rtt(), event_time));
     DVLOG(1) << "Cubic; congestion window: " << congestion_window_
              << " slowstart threshold: " << slowstart_threshold_;
   }
diff --git a/net/quic/core/congestion_control/tcp_cubic_sender_bytes.h b/net/quic/core/congestion_control/tcp_cubic_sender_bytes.h
index 7813b2b..d49543f 100644
--- a/net/quic/core/congestion_control/tcp_cubic_sender_bytes.h
+++ b/net/quic/core/congestion_control/tcp_cubic_sender_bytes.h
@@ -63,7 +63,8 @@
                     QuicByteCount prior_in_flight) override;
   void MaybeIncreaseCwnd(QuicPacketNumber acked_packet_number,
                          QuicByteCount acked_bytes,
-                         QuicByteCount prior_in_flight) override;
+                         QuicByteCount prior_in_flight,
+                         QuicTime event_time) override;
   void HandleRetransmissionTimeout() override;
 
  private:
diff --git a/net/quic/core/congestion_control/tcp_cubic_sender_packets.cc b/net/quic/core/congestion_control/tcp_cubic_sender_packets.cc
index aa99b9bf..7089a5b 100644
--- a/net/quic/core/congestion_control/tcp_cubic_sender_packets.cc
+++ b/net/quic/core/congestion_control/tcp_cubic_sender_packets.cc
@@ -49,6 +49,10 @@
       ContainsQuicTag(config.ReceivedConnectionOptions(), kCCVX)) {
     cubic_.SetFixConvexMode(true);
   }
+  if (FLAGS_quic_fix_beta_last_max && config.HasReceivedConnectionOptions() &&
+      ContainsQuicTag(config.ReceivedConnectionOptions(), kBLMX)) {
+    cubic_.SetFixBetaLastMax(true);
+  }
 }
 
 void TcpCubicSenderPackets::SetCongestionWindowFromBandwidthAndRtt(
@@ -154,7 +158,8 @@
 void TcpCubicSenderPackets::MaybeIncreaseCwnd(
     QuicPacketNumber acked_packet_number,
     QuicByteCount /*acked_bytes*/,
-    QuicByteCount prior_in_flight) {
+    QuicByteCount prior_in_flight,
+    QuicTime event_time) {
   QUIC_BUG_IF(InRecovery()) << "Never increase the CWND during recovery.";
   // Do not increase the congestion window unless the sender is close to using
   // the current window.
@@ -189,8 +194,8 @@
   } else {
     congestion_window_ =
         std::min(max_tcp_congestion_window_,
-                 cubic_.CongestionWindowAfterAck(congestion_window_,
-                                                 rtt_stats_->min_rtt()));
+                 cubic_.CongestionWindowAfterAck(
+                     congestion_window_, rtt_stats_->min_rtt(), event_time));
     DVLOG(1) << "Cubic; congestion window: " << congestion_window_
              << " slowstart threshold: " << slowstart_threshold_;
   }
diff --git a/net/quic/core/congestion_control/tcp_cubic_sender_packets.h b/net/quic/core/congestion_control/tcp_cubic_sender_packets.h
index ff06a1d..cf0a297 100644
--- a/net/quic/core/congestion_control/tcp_cubic_sender_packets.h
+++ b/net/quic/core/congestion_control/tcp_cubic_sender_packets.h
@@ -65,7 +65,8 @@
                     QuicByteCount prior_in_flight) override;
   void MaybeIncreaseCwnd(QuicPacketNumber acked_packet_number,
                          QuicByteCount acked_bytes,
-                         QuicByteCount prior_in_flight) override;
+                         QuicByteCount prior_in_flight,
+                         QuicTime event_time) override;
   void HandleRetransmissionTimeout() override;
 
  private:
diff --git a/net/quic/core/crypto/crypto_protocol.h b/net/quic/core/crypto/crypto_protocol.h
index 20fb1428..80b61ad0 100644
--- a/net/quic/core/crypto/crypto_protocol.h
+++ b/net/quic/core/crypto/crypto_protocol.h
@@ -69,6 +69,18 @@
                                                  // of stream flow control
                                                  // receive window to
                                                  // 128KB. (2^7 KB).
+const QuicTag kIFW8 = TAG('I', 'F', 'W', '8');   // Set initial size
+                                                 // of stream flow control
+                                                 // receive window to
+                                                 // 256KB. (2^8 KB).
+const QuicTag kIFW9 = TAG('I', 'F', 'W', '9');   // Set initial size
+                                                 // of stream flow control
+                                                 // receive window to
+                                                 // 512KB. (2^9 KB).
+const QuicTag kIFWA = TAG('I', 'F', 'W', 'a');   // Set initial size
+                                                 // of stream flow control
+                                                 // receive window to
+                                                 // 1MB. (2^0xa KB).
 const QuicTag kTBBR = TAG('T', 'B', 'B', 'R');   // Reduced Buffer Bloat TCP
 const QuicTag kRENO = TAG('R', 'E', 'N', 'O');   // Reno Congestion Control
 const QuicTag kBYTE = TAG('B', 'Y', 'T', 'E');   // TCP cubic or reno in bytes
@@ -114,6 +126,8 @@
                                                  // settings frame.
 
 const QuicTag kCCVX = TAG('C', 'C', 'V', 'X');   // Fix Cubic convex bug.
+const QuicTag kCBQT = TAG('C', 'B', 'Q', 'T');   // Fix CubicBytes quantization.
+const QuicTag kBLMX = TAG('B', 'L', 'M', 'X');   // Fix Cubic BetaLastMax bug.
 
 // Optional support of truncated Connection IDs.  If sent by a peer, the value
 // is the minimum number of bytes allowed for the connection ID sent to the
diff --git a/net/quic/core/quic_crypto_client_stream_test.cc b/net/quic/core/quic_crypto_client_stream_test.cc
index fa031bad..75dedfcb 100644
--- a/net/quic/core/quic_crypto_client_stream_test.cc
+++ b/net/quic/core/quic_crypto_client_stream_test.cc
@@ -230,7 +230,8 @@
       reinterpret_cast<char*>(scfg), arraysize(scfg));
 
   QuicStreamSequencer* sequencer = QuicStreamPeer::sequencer(stream());
-  EXPECT_NE(FLAGS_quic_release_crypto_stream_buffer,
+  EXPECT_NE(FLAGS_quic_release_crypto_stream_buffer &&
+                FLAGS_quic_reduce_sequencer_buffer_memory_life_time,  // NOLINT
             QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer));
 }
 
diff --git a/net/quic/core/quic_flags_list.h b/net/quic/core/quic_flags_list.h
index ebdba96..9bed32d 100644
--- a/net/quic/core/quic_flags_list.h
+++ b/net/quic/core/quic_flags_list.h
@@ -89,7 +89,7 @@
 
 // Use a more conservative backoff of 2x instead of 1.5x for handshake
 // retransmissions, as well as a larger minimum.
-QUIC_FLAG(bool, FLAGS_quic_conservative_handshake_retransmits, true)
+QUIC_FLAG(bool, FLAGS_quic_conservative_handshake_retransmits, false)
 
 // If true, buffer packets while parsing public headers instead of parsing down
 // if CHLO is already buffered.
@@ -101,7 +101,7 @@
 QUIC_FLAG(bool, FLAGS_quic_receive_packet_once_decrypted, false)
 
 // If true, enable the Lazy FACK style loss detection in QUIC.
-QUIC_FLAG(bool, FLAGS_quic_enable_lazy_fack, true)
+QUIC_FLAG(bool, FLAGS_quic_enable_lazy_fack, false)
 
 // If true, do not override a connection in global map if exists. Only create
 // QUIC session if it is successfully inserted to the global map. Toss the
@@ -151,3 +151,21 @@
 // If true, GFE sends SETTINGS_MAX_HEADER_LIST_SIZE to the client at the
 // beginning of a connection.
 QUIC_FLAG(bool, FLAGS_quic_send_max_header_list_size, true)
+
+// If true, fix quantization of CubicBytes while performing convex increases.
+QUIC_FLAG(bool, FLAGS_quic_fix_cubic_bytes_quantization, false)
+
+// If true, QUIC cubic code will use the event time when adjusting CWND after an
+// ACK instead of the clock\'s current approximate time.
+QUIC_FLAG(bool, FLAGS_quic_use_event_time, false)
+
+// If true, lazy allocate and early release memeory used in
+// QuicStreamSequencerBuffer to buffer incoming data.
+QUIC_FLAG(bool, FLAGS_quic_reduce_sequencer_buffer_memory_life_time, true)
+
+// If true, Makes GFE respect the connection options for initial flow control
+// window larger than 32 KB.
+QUIC_FLAG(bool, FLAGS_quic_large_ifw_options, false)
+
+// If true, fix Cubic\'s use of kBetaLastMax for n-connection emulation.
+QUIC_FLAG(bool, FLAGS_quic_fix_beta_last_max, false)
diff --git a/net/quic/core/quic_session.cc b/net/quic/core/quic_session.cc
index ced354a..4762222 100644
--- a/net/quic/core/quic_session.cc
+++ b/net/quic/core/quic_session.cc
@@ -439,6 +439,27 @@
     max_streams = config_.MaxStreamsPerConnection();
   }
   set_max_open_outgoing_streams(max_streams);
+  if (FLAGS_quic_large_ifw_options && perspective() == Perspective::IS_SERVER) {
+    if (config_.HasReceivedConnectionOptions()) {
+      // The following variations change the initial receive flow control
+      // window sizes.
+      if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFW6)) {
+        AdjustInitialFlowControlWindows(64 * 1024);
+      }
+      if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFW7)) {
+        AdjustInitialFlowControlWindows(128 * 1024);
+      }
+      if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFW8)) {
+        AdjustInitialFlowControlWindows(256 * 1024);
+      }
+      if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFW9)) {
+        AdjustInitialFlowControlWindows(512 * 1024);
+      }
+      if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFWA)) {
+        AdjustInitialFlowControlWindows(1024 * 1024);
+      }
+    }
+  }
 
   if (version <= QUIC_VERSION_34) {
     // A small number of additional incoming streams beyond the limit should be
@@ -472,6 +493,30 @@
   }
 }
 
+void QuicSession::AdjustInitialFlowControlWindows(size_t stream_window) {
+  const float session_window_multiplier =
+      config_.GetInitialStreamFlowControlWindowToSend()
+          ? static_cast<float>(
+                config_.GetInitialSessionFlowControlWindowToSend()) /
+                config_.GetInitialStreamFlowControlWindowToSend()
+          : 1.5;
+
+  DVLOG(1) << ENDPOINT << "Set stream receive window to " << stream_window;
+  config_.SetInitialStreamFlowControlWindowToSend(stream_window);
+
+  size_t session_window = session_window_multiplier * stream_window;
+  DVLOG(1) << ENDPOINT << "Set session receive window to " << session_window;
+  config_.SetInitialSessionFlowControlWindowToSend(session_window);
+  flow_controller_.UpdateReceiveWindowSize(session_window);
+  // Inform all existing streams about the new window.
+  for (auto const& kv : static_stream_map_) {
+    kv.second->flow_controller()->UpdateReceiveWindowSize(stream_window);
+  }
+  for (auto const& kv : dynamic_stream_map_) {
+    kv.second->flow_controller()->UpdateReceiveWindowSize(stream_window);
+  }
+}
+
 void QuicSession::HandleFrameOnNonexistentOutgoingStream(
     QuicStreamId stream_id) {
   DCHECK(!IsClosedStream(stream_id));
diff --git a/net/quic/core/quic_session.h b/net/quic/core/quic_session.h
index 1807a452..f3c1522a 100644
--- a/net/quic/core/quic_session.h
+++ b/net/quic/core/quic_session.h
@@ -372,6 +372,10 @@
                                  uint64_t previous_bytes_written,
                                  bool previous_fin_sent);
 
+  // Called in OnConfigNegotiated for Finch trials to measure performance of
+  // starting with larger flow control receive windows.
+  void AdjustInitialFlowControlWindows(size_t stream_window);
+
   // Keep track of highest received byte offset of locally closed streams, while
   // waiting for a definitive final highest offset from the peer.
   std::map<QuicStreamId, QuicStreamOffset>
diff --git a/net/quic/core/quic_session_test.cc b/net/quic/core/quic_session_test.cc
index 43e303a4..84fd78b 100644
--- a/net/quic/core/quic_session_test.cc
+++ b/net/quic/core/quic_session_test.cc
@@ -1096,6 +1096,18 @@
   session_.OnConfigNegotiated();
 }
 
+// Test negotiation of custom server initial flow control window.
+TEST_P(QuicSessionTestServer, CustomFlowControlWindow) {
+  FLAGS_quic_large_ifw_options = true;
+  QuicTagVector copt;
+  copt.push_back(kIFW7);
+  QuicConfigPeer::SetReceivedConnectionOptions(session_.config(), copt);
+
+  session_.OnConfigNegotiated();
+  EXPECT_EQ(192 * 1024u, QuicFlowControllerPeer::ReceiveWindowSize(
+                             session_.flow_controller()));
+}
+
 TEST_P(QuicSessionTestServer, FlowControlWithInvalidFinalOffset) {
   // Test that if we receive a stream RST with a highest byte offset that
   // violates flow control, that we close the connection.
diff --git a/net/quic/core/quic_stream_sequencer_buffer.cc b/net/quic/core/quic_stream_sequencer_buffer.cc
index 6b3ee9d9..9b866a1 100644
--- a/net/quic/core/quic_stream_sequencer_buffer.cc
+++ b/net/quic/core/quic_stream_sequencer_buffer.cc
@@ -49,7 +49,11 @@
       blocks_count_(
           ceil(static_cast<double>(max_capacity_bytes) / kBlockSizeBytes)),
       total_bytes_read_(0),
-      blocks_(nullptr),
+      reduce_sequencer_buffer_memory_life_time_(
+          FLAGS_quic_reduce_sequencer_buffer_memory_life_time),  // NOLINT
+      blocks_(reduce_sequencer_buffer_memory_life_time_
+                  ? nullptr
+                  : new BufferBlock*[blocks_count_]()),
       destruction_indicator_(123456) {
   CHECK_GT(blocks_count_, 1u)
       << "blocks_count_ = " << blocks_count_
@@ -63,7 +67,7 @@
 }
 
 void QuicStreamSequencerBuffer::Clear() {
-  if (blocks_ != nullptr) {
+  if (!reduce_sequencer_buffer_memory_life_time_ || blocks_ != nullptr) {
     for (size_t i = 0; i < blocks_count_; ++i) {
       if (blocks_[i] != nullptr) {
         RetireBlock(i);
@@ -182,7 +186,7 @@
       bytes_avail = total_bytes_read_ + max_buffer_capacity_bytes_ - offset;
     }
 
-    if (blocks_ == nullptr) {
+    if (reduce_sequencer_buffer_memory_life_time_ && blocks_ == nullptr) {
       blocks_.reset(new BufferBlock*[blocks_count_]());
       for (size_t i = 0; i < blocks_count_; ++i) {
         blocks_[i] = nullptr;
@@ -473,6 +477,10 @@
 }
 
 void QuicStreamSequencerBuffer::ReleaseWholeBuffer() {
+  if (!reduce_sequencer_buffer_memory_life_time_) {
+    // Don't release buffer if flag is off.
+    return;
+  }
   Clear();
   blocks_.reset(nullptr);
 }
diff --git a/net/quic/core/quic_stream_sequencer_buffer.h b/net/quic/core/quic_stream_sequencer_buffer.h
index f4c5545..22d2beb 100644
--- a/net/quic/core/quic_stream_sequencer_buffer.h
+++ b/net/quic/core/quic_stream_sequencer_buffer.h
@@ -168,6 +168,10 @@
   // Count how many bytes are in buffer at this moment.
   size_t BytesBuffered() const;
 
+  bool reduce_sequencer_buffer_memory_life_time() const {
+    return reduce_sequencer_buffer_memory_life_time_;
+  }
+
  private:
   friend class test::QuicStreamSequencerBufferPeer;
 
@@ -237,6 +241,10 @@
   // Contains Gaps which represents currently missing data.
   std::list<Gap> gaps_;
 
+  // If true, allocate buffer memory upon the first frame arrival and release
+  // the memory when stream is read closed.
+  bool reduce_sequencer_buffer_memory_life_time_;
+
   // An ordered, variable-length list of blocks, with the length limited
   // such that the number of blocks never exceeds blocks_count_.
   // Each list entry can hold up to kBlockSizeBytes bytes.
diff --git a/net/quic/core/quic_stream_sequencer_buffer_test.cc b/net/quic/core/quic_stream_sequencer_buffer_test.cc
index 78a11ef5..dcef21ea 100644
--- a/net/quic/core/quic_stream_sequencer_buffer_test.cc
+++ b/net/quic/core/quic_stream_sequencer_buffer_test.cc
@@ -110,7 +110,9 @@
 }
 
 TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithinBlock) {
-  EXPECT_FALSE(helper_->IsBufferAllocated());
+  if (FLAGS_quic_reduce_sequencer_buffer_memory_life_time) {  // NOLINT
+    EXPECT_FALSE(helper_->IsBufferAllocated());
+  }
   string source(1024, 'a');
   size_t written;
   clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
@@ -469,6 +471,10 @@
 
 TEST_F(QuicStreamSequencerBufferTest, ReleaseWholeBuffer) {
   // Tests that buffer is not deallocated unless ReleaseWholeBuffer() is called.
+  if (!FLAGS_quic_reduce_sequencer_buffer_memory_life_time) {  // NOLINT
+    // Won't release buffer when flag is off.
+    return;
+  }
 
   string source(100, 'b');
   clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
diff --git a/net/quic/test_tools/quic_stream_sequencer_buffer_peer.cc b/net/quic/test_tools/quic_stream_sequencer_buffer_peer.cc
index a493ed8f..bc0bf437 100644
--- a/net/quic/test_tools/quic_stream_sequencer_buffer_peer.cc
+++ b/net/quic/test_tools/quic_stream_sequencer_buffer_peer.cc
@@ -41,7 +41,8 @@
 }
 
 bool QuicStreamSequencerBufferPeer::IsBlockArrayEmpty() {
-  if (buffer_->blocks_ == nullptr) {
+  if (FLAGS_quic_reduce_sequencer_buffer_memory_life_time &&  // NOLINT
+      buffer_->blocks_ == nullptr) {
     return true;
   }
 
diff --git a/net/spdy/hpack/hpack_encoder.cc b/net/spdy/hpack/hpack_encoder.cc
index 7362bb1a..f186b6a4 100644
--- a/net/spdy/hpack/hpack_encoder.cc
+++ b/net/spdy/hpack/hpack_encoder.cc
@@ -82,7 +82,7 @@
       min_table_size_setting_received_(std::numeric_limits<size_t>::max()),
       listener_(NoOpListener),
       should_index_(DefaultPolicy),
-      allow_huffman_compression_(true),
+      enable_compression_(true),
       should_emit_table_size_(false) {}
 
 HpackEncoder::~HpackEncoder() {}
@@ -120,21 +120,6 @@
   return true;
 }
 
-bool HpackEncoder::EncodeHeaderSetWithoutCompression(
-    const SpdyHeaderBlock& header_set,
-    string* output) {
-  allow_huffman_compression_ = false;
-  MaybeEmitTableSize();
-  for (const auto& header : header_set) {
-    listener_(header.first, header.second);
-    // Note that cookies are not crumbled in this case.
-    EmitNonIndexedLiteral(header);
-  }
-  allow_huffman_compression_ = true;
-  output_stream_.TakeString(output);
-  return true;
-}
-
 void HpackEncoder::ApplyHeaderTableSizeSetting(size_t size_setting) {
   if (size_setting == header_table_.settings_size_bound()) {
     return;
@@ -153,12 +138,16 @@
   while (iter->HasNext()) {
     const auto header = iter->Next();
     listener_(header.first, header.second);
-    const HpackEntry* entry =
-        header_table_.GetByNameAndValue(header.first, header.second);
-    if (entry != nullptr) {
-      EmitIndex(entry);
-    } else if (should_index_(header.first, header.second)) {
-      EmitIndexedLiteral(header);
+    if (enable_compression_) {
+      const HpackEntry* entry =
+          header_table_.GetByNameAndValue(header.first, header.second);
+      if (entry != nullptr) {
+        EmitIndex(entry);
+      } else if (should_index_(header.first, header.second)) {
+        EmitIndexedLiteral(header);
+      } else {
+        EmitNonIndexedLiteral(header);
+      }
     } else {
       EmitNonIndexedLiteral(header);
     }
@@ -198,8 +187,7 @@
 
 void HpackEncoder::EmitString(StringPiece str) {
   size_t encoded_size =
-      (!allow_huffman_compression_ ? str.size()
-                                   : huffman_table_.EncodedSize(str));
+      enable_compression_ ? huffman_table_.EncodedSize(str) : str.size();
   if (encoded_size < str.size()) {
     output_stream_.AppendPrefix(kStringLiteralHuffmanEncoded);
     output_stream_.AppendUint32(encoded_size);
@@ -286,9 +274,7 @@
 // Iteratively encodes a SpdyHeaderBlock.
 class HpackEncoder::Encoderator : public ProgressiveEncoder {
  public:
-  Encoderator(const SpdyHeaderBlock& header_set,
-              HpackEncoder* encoder,
-              bool use_compression);
+  Encoderator(const SpdyHeaderBlock& header_set, HpackEncoder* encoder);
 
   // Encoderator is neither copyable nor movable.
   Encoderator(const Encoderator&) = delete;
@@ -307,29 +293,27 @@
   Representations pseudo_headers_;
   Representations regular_headers_;
   bool has_next_;
-  bool use_compression_;
 };
 
 HpackEncoder::Encoderator::Encoderator(const SpdyHeaderBlock& header_set,
-                                       HpackEncoder* encoder,
-                                       bool use_compression)
-    : encoder_(encoder), has_next_(true), use_compression_(use_compression) {
+                                       HpackEncoder* encoder)
+    : encoder_(encoder), has_next_(true) {
   // Separate header set into pseudo-headers and regular headers.
+  const bool use_compression = encoder_->enable_compression_;
   bool found_cookie = false;
   for (const auto& header : header_set) {
     if (!found_cookie && header.first == "cookie") {
       // Note that there can only be one "cookie" header, because header_set
       // is a map.
       found_cookie = true;
-      use_compression_ ? CookieToCrumbs(header, &regular_headers_)
-                       : GatherRepresentation(header, &regular_headers_);
+      CookieToCrumbs(header, &regular_headers_);
     } else if (!header.first.empty() &&
                header.first[0] == kPseudoHeaderPrefix) {
-      use_compression_ ? DecomposeRepresentation(header, &pseudo_headers_)
-                       : GatherRepresentation(header, &pseudo_headers_);
+      use_compression ? DecomposeRepresentation(header, &pseudo_headers_)
+                      : GatherRepresentation(header, &pseudo_headers_);
     } else {
-      use_compression_ ? DecomposeRepresentation(header, &regular_headers_)
-                       : GatherRepresentation(header, &regular_headers_);
+      use_compression ? DecomposeRepresentation(header, &regular_headers_)
+                      : GatherRepresentation(header, &regular_headers_);
     }
   }
   header_it_ = base::MakeUnique<RepresentationIterator>(pseudo_headers_,
@@ -341,13 +325,14 @@
 void HpackEncoder::Encoderator::Next(size_t max_encoded_bytes, string* output) {
   SPDY_BUG_IF(!has_next_)
       << "Encoderator::Next called with nothing left to encode.";
+  const bool use_compression = encoder_->enable_compression_;
 
   // Encode up to max_encoded_bytes of headers.
   while (header_it_->HasNext() &&
          encoder_->output_stream_.size() <= max_encoded_bytes) {
     const Representation header = header_it_->Next();
     encoder_->listener_(header.first, header.second);
-    if (use_compression_) {
+    if (use_compression) {
       const HpackEntry* entry = encoder_->header_table_.GetByNameAndValue(
           header.first, header.second);
       if (entry != nullptr) {
@@ -358,9 +343,7 @@
         encoder_->EmitNonIndexedLiteral(header);
       }
     } else {
-      encoder_->allow_huffman_compression_ = false;
       encoder_->EmitNonIndexedLiteral(header);
-      encoder_->allow_huffman_compression_ = true;
     }
   }
 
@@ -369,9 +352,8 @@
 }
 
 std::unique_ptr<HpackEncoder::ProgressiveEncoder> HpackEncoder::EncodeHeaderSet(
-    const SpdyHeaderBlock& header_set,
-    bool use_compression) {
-  return base::MakeUnique<Encoderator>(header_set, this, use_compression);
+    const SpdyHeaderBlock& header_set) {
+  return base::MakeUnique<Encoderator>(header_set, this);
 }
 
 }  // namespace net
diff --git a/net/spdy/hpack/hpack_encoder.h b/net/spdy/hpack/hpack_encoder.h
index b2778af..f2d95e3 100644
--- a/net/spdy/hpack/hpack_encoder.h
+++ b/net/spdy/hpack/hpack_encoder.h
@@ -60,12 +60,6 @@
   // whether or not the encoding was successful.
   bool EncodeHeaderSet(const SpdyHeaderBlock& header_set, std::string* output);
 
-  // Encodes the given header set into the given string. Only non-indexed
-  // literal representations are emitted, bypassing the header table. Huffman
-  // coding is also not used. Returns whether the encoding was successful.
-  bool EncodeHeaderSetWithoutCompression(const SpdyHeaderBlock& header_set,
-                                         std::string* output);
-
   class NET_EXPORT_PRIVATE ProgressiveEncoder {
    public:
     virtual ~ProgressiveEncoder() {}
@@ -81,8 +75,7 @@
   // Returns a ProgressiveEncoder which must be outlived by both the given
   // SpdyHeaderBlock and this object.
   std::unique_ptr<ProgressiveEncoder> EncodeHeaderSet(
-      const SpdyHeaderBlock& header_set,
-      bool use_compression);
+      const SpdyHeaderBlock& header_set);
 
   // Called upon a change to SETTINGS_HEADER_TABLE_SIZE. Specifically, this
   // is to be called after receiving (and sending an acknowledgement for) a
@@ -106,6 +99,8 @@
     header_table_.set_debug_visitor(std::move(visitor));
   }
 
+  void DisableCompression() { enable_compression_ = false; }
+
  private:
   friend class test::HpackEncoderPeer;
 
@@ -149,7 +144,7 @@
   size_t min_table_size_setting_received_;
   HeaderListener listener_;
   IndexingPolicy should_index_;
-  bool allow_huffman_compression_;
+  bool enable_compression_;
   bool should_emit_table_size_;
 
   DISALLOW_COPY_AND_ASSIGN(HpackEncoder);
diff --git a/net/spdy/hpack/hpack_encoder_test.cc b/net/spdy/hpack/hpack_encoder_test.cc
index fd4861c..c1db5b4c 100644
--- a/net/spdy/hpack/hpack_encoder_test.cc
+++ b/net/spdy/hpack/hpack_encoder_test.cc
@@ -9,6 +9,7 @@
 
 #include "base/rand_util.h"
 #include "net/base/arena.h"
+#include "net/spdy/hpack/hpack_huffman_table.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -41,10 +42,11 @@
 
   explicit HpackEncoderPeer(HpackEncoder* encoder) : encoder_(encoder) {}
 
+  bool compression_enabled() const { return encoder_->enable_compression_; }
   HpackHeaderTable* table() { return &encoder_->header_table_; }
   HpackHeaderTablePeer table_peer() { return HpackHeaderTablePeer(table()); }
-  void set_allow_huffman_compression(bool allow) {
-    encoder_->allow_huffman_compression_ = allow;
+  const HpackHuffmanTable& huffman_table() const {
+    return encoder_->huffman_table_;
   }
   void EmitString(StringPiece str) { encoder_->EmitString(str); }
   void TakeString(string* out) { encoder_->output_stream_.TakeString(out); }
@@ -75,23 +77,19 @@
   static bool EncodeHeaderSet(HpackEncoder* encoder,
                               const SpdyHeaderBlock& header_set,
                               string* output,
-                              bool use_compression,
                               bool use_incremental) {
     if (use_incremental) {
-      return EncodeIncremental(encoder, header_set, output, use_compression);
+      return EncodeIncremental(encoder, header_set, output);
     } else {
-      return use_compression ? encoder->EncodeHeaderSet(header_set, output)
-                             : encoder->EncodeHeaderSetWithoutCompression(
-                                   header_set, output);
+      return encoder->EncodeHeaderSet(header_set, output);
     }
   }
 
   static bool EncodeIncremental(HpackEncoder* encoder,
                                 const SpdyHeaderBlock& header_set,
-                                string* output,
-                                bool use_compression) {
+                                string* output) {
     std::unique_ptr<HpackEncoder::ProgressiveEncoder> encoderator =
-        encoder->EncodeHeaderSet(header_set, use_compression);
+        encoder->EncodeHeaderSet(header_set);
     string output_buffer;
     encoderator->Next(base::RandInt(0, 15), &output_buffer);
     while (encoderator->HasNext()) {
@@ -137,9 +135,6 @@
 
     // No further insertions may occur without evictions.
     peer_.table()->SetMaxSize(peer_.table()->size());
-
-    // Disable Huffman coding by default. Most tests don't care about it.
-    peer_.set_allow_huffman_compression(false);
   }
 
   void SaveHeaders(StringPiece name, StringPiece value) {
@@ -157,29 +152,34 @@
   void ExpectIndexedLiteral(const HpackEntry* key_entry, StringPiece value) {
     expected_.AppendPrefix(kLiteralIncrementalIndexOpcode);
     expected_.AppendUint32(IndexOf(key_entry));
-    expected_.AppendPrefix(kStringLiteralIdentityEncoded);
-    expected_.AppendUint32(value.size());
-    expected_.AppendBytes(value);
+    ExpectString(&expected_, value);
   }
   void ExpectIndexedLiteral(StringPiece name, StringPiece value) {
     expected_.AppendPrefix(kLiteralIncrementalIndexOpcode);
     expected_.AppendUint32(0);
-    expected_.AppendPrefix(kStringLiteralIdentityEncoded);
-    expected_.AppendUint32(name.size());
-    expected_.AppendBytes(name);
-    expected_.AppendPrefix(kStringLiteralIdentityEncoded);
-    expected_.AppendUint32(value.size());
-    expected_.AppendBytes(value);
+    ExpectString(&expected_, name);
+    ExpectString(&expected_, value);
   }
   void ExpectNonIndexedLiteral(StringPiece name, StringPiece value) {
     expected_.AppendPrefix(kLiteralNoIndexOpcode);
     expected_.AppendUint32(0);
-    expected_.AppendPrefix(kStringLiteralIdentityEncoded);
-    expected_.AppendUint32(name.size());
-    expected_.AppendBytes(name);
-    expected_.AppendPrefix(kStringLiteralIdentityEncoded);
-    expected_.AppendUint32(value.size());
-    expected_.AppendBytes(value);
+    ExpectString(&expected_, name);
+    ExpectString(&expected_, value);
+  }
+  void ExpectString(HpackOutputStream* stream, StringPiece str) {
+    const HpackHuffmanTable& huffman_table = peer_.huffman_table();
+    size_t encoded_size = peer_.compression_enabled()
+                              ? huffman_table.EncodedSize(str)
+                              : str.size();
+    if (encoded_size < str.size()) {
+      expected_.AppendPrefix(kStringLiteralHuffmanEncoded);
+      expected_.AppendUint32(encoded_size);
+      huffman_table.EncodeString(str, stream);
+    } else {
+      expected_.AppendPrefix(kStringLiteralIdentityEncoded);
+      expected_.AppendUint32(str.size());
+      expected_.AppendBytes(str);
+    }
   }
   void ExpectHeaderTableSizeUpdate(uint32_t size) {
     expected_.AppendPrefix(kHeaderTableSizeUpdateOpcode);
@@ -189,15 +189,7 @@
     string expected_out, actual_out;
     expected_.TakeString(&expected_out);
     EXPECT_TRUE(test::HpackEncoderPeer::EncodeHeaderSet(
-        &encoder_, header_set, &actual_out, true, use_incremental_));
-    EXPECT_EQ(expected_out, actual_out);
-  }
-  void CompareWithExpectedEncodingWithoutCompression(
-      const SpdyHeaderBlock& header_set) {
-    string expected_out, actual_out;
-    expected_.TakeString(&expected_out);
-    EXPECT_TRUE(test::HpackEncoderPeer::EncodeHeaderSet(
-        &encoder_, header_set, &actual_out, false, use_incremental_));
+        &encoder_, header_set, &actual_out, use_incremental_));
     EXPECT_EQ(expected_out, actual_out);
   }
   size_t IndexOf(const HpackEntry* entry) {
@@ -317,8 +309,6 @@
 }
 
 TEST_P(HpackEncoderTest, StringsDynamicallySelectHuffmanCoding) {
-  peer_.set_allow_huffman_compression(true);
-
   // Compactable string. Uses Huffman coding.
   peer_.EmitString("feedbeef");
   expected_.AppendPrefix(kStringLiteralHuffmanEncoded);
@@ -341,12 +331,11 @@
   encoder_.SetHeaderListener([this](StringPiece name, StringPiece value) {
     this->SaveHeaders(name, value);
   });
-
-  // Implementation should internally disable.
-  peer_.set_allow_huffman_compression(true);
+  encoder_.DisableCompression();
 
   ExpectNonIndexedLiteral(":path", "/index.html");
-  ExpectNonIndexedLiteral("cookie", "foo=bar; baz=bing");
+  ExpectNonIndexedLiteral("cookie", "foo=bar");
+  ExpectNonIndexedLiteral("cookie", "baz=bing");
   ExpectNonIndexedLiteral("hello", "goodbye");
 
   SpdyHeaderBlock headers;
@@ -354,12 +343,12 @@
   headers["cookie"] = "foo=bar; baz=bing";
   headers["hello"] = "goodbye";
 
-  CompareWithExpectedEncodingWithoutCompression(headers);
+  CompareWithExpectedEncoding(headers);
 
-  EXPECT_THAT(headers_observed_,
-              ElementsAre(Pair(":path", "/index.html"),
-                          Pair("cookie", "foo=bar; baz=bing"),
-                          Pair("hello", "goodbye")));
+  EXPECT_THAT(
+      headers_observed_,
+      ElementsAre(Pair(":path", "/index.html"), Pair("cookie", "foo=bar"),
+                  Pair("cookie", "baz=bing"), Pair("hello", "goodbye")));
 }
 
 TEST_P(HpackEncoderTest, MultipleEncodingPasses) {
diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc
index 5d724f84..9f5140d 100644
--- a/net/spdy/spdy_framer.cc
+++ b/net/spdy/spdy_framer.cc
@@ -1783,8 +1783,8 @@
       debug_total_size_(0),
       is_first_frame_(true),
       has_next_frame_(true) {
-  encoder_ = framer_->GetHpackEncoder()->EncodeHeaderSet(
-      headers_ir_->header_block(), framer_->compression_enabled());
+  encoder_ =
+      framer_->GetHpackEncoder()->EncodeHeaderSet(headers_ir_->header_block());
 }
 
 SpdyFramer::SpdyHeaderFrameIterator::~SpdyHeaderFrameIterator() {}
@@ -2006,12 +2006,7 @@
   }
 
   string hpack_encoding;
-  if (compression_enabled()) {
-    GetHpackEncoder()->EncodeHeaderSet(headers.header_block(), &hpack_encoding);
-  } else {
-    GetHpackEncoder()->EncodeHeaderSetWithoutCompression(headers.header_block(),
-                                                         &hpack_encoding);
-  }
+  GetHpackEncoder()->EncodeHeaderSet(headers.header_block(), &hpack_encoding);
   size += hpack_encoding.size();
   if (size > kMaxControlFrameSize) {
     size += GetNumberRequiredContinuationFrames(size) *
@@ -2083,13 +2078,8 @@
   }
 
   string hpack_encoding;
-  if (compression_enabled()) {
-    GetHpackEncoder()->EncodeHeaderSet(push_promise.header_block(),
-                                       &hpack_encoding);
-  } else {
-    GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
-        push_promise.header_block(), &hpack_encoding);
-  }
+  GetHpackEncoder()->EncodeHeaderSet(push_promise.header_block(),
+                                     &hpack_encoding);
   size += hpack_encoding.size();
   if (size > kMaxControlFrameSize) {
     size += GetNumberRequiredContinuationFrames(size) *
@@ -2367,6 +2357,9 @@
 HpackEncoder* SpdyFramer::GetHpackEncoder() {
   if (hpack_encoder_.get() == nullptr) {
     hpack_encoder_.reset(new HpackEncoder(ObtainHpackHuffmanTable()));
+    if (!compression_enabled()) {
+      hpack_encoder_->DisableCompression();
+    }
   }
   return hpack_encoder_.get();
 }
diff --git a/net/spdy/spdy_framer_test.cc b/net/spdy/spdy_framer_test.cc
index 470707d..4b0333b 100644
--- a/net/spdy/spdy_framer_test.cc
+++ b/net/spdy/spdy_framer_test.cc
@@ -1175,7 +1175,8 @@
   header_set["name"] = value;
   string buffer;
   HpackEncoder encoder(ObtainHpackHuffmanTable());
-  encoder.EncodeHeaderSetWithoutCompression(header_set, &buffer);
+  encoder.DisableCompression();
+  encoder.EncodeHeaderSet(header_set, &buffer);
   frame.WriteBytes(&buffer[0], buffer.size());
   // write the length
   frame.RewriteLength(framer);
@@ -2343,7 +2344,8 @@
   header_block["foo"] = "bar";
   auto buffer = base::MakeUnique<string>();
   HpackEncoder encoder(ObtainHpackHuffmanTable());
-  encoder.EncodeHeaderSetWithoutCompression(header_block, buffer.get());
+  encoder.DisableCompression();
+  encoder.EncodeHeaderSet(header_block, buffer.get());
 
   SpdyContinuationIR continuation(42);
   continuation.take_encoding(std::move(buffer));
diff --git a/net/spdy/spdy_protocol.h b/net/spdy/spdy_protocol.h
index f71d6b2c..bbd959a 100644
--- a/net/spdy/spdy_protocol.h
+++ b/net/spdy/spdy_protocol.h
@@ -38,6 +38,9 @@
 // flow control).
 const SpdyStreamId kSessionFlowControlStreamId = 0;
 
+// Max stream id.
+const SpdyStreamId kMaxStreamId = 0x7fffffff;
+
 // The maximum possible frame payload size allowed by the spec.
 const uint32_t kSpdyMaxFrameSizeLimit = (1 << 24) - 1;
 
diff --git a/net/ssl/ssl_client_session_cache.cc b/net/ssl/ssl_client_session_cache.cc
index 5fd3c48..19b9d55 100644
--- a/net/ssl/ssl_client_session_cache.cc
+++ b/net/ssl/ssl_client_session_cache.cc
@@ -98,31 +98,30 @@
     return;
   cache_dump = pmd->CreateAllocatorDump(absolute_name);
   base::AutoLock lock(lock_);
+  int total_serialized_cert_size = 0;
+  int total_cert_count = 0;
   for (const auto& pair : cache_) {
     auto entry = pair.second.get();
     auto cert_chain = entry->x509_chain;
     size_t cert_count = sk_X509_num(cert_chain);
-    base::trace_event::MemoryAllocatorDump* entry_dump =
-        pmd->CreateAllocatorDump(
-            base::StringPrintf("%s/entry_%p", absolute_name.c_str(), entry));
-    int cert_size = 0;
+    total_cert_count += cert_count;
     for (size_t i = 0; i < cert_count; ++i) {
       X509* cert = sk_X509_value(cert_chain, i);
-      cert_size += i2d_X509(cert, nullptr);
+      total_serialized_cert_size += i2d_X509(cert, nullptr);
     }
-    // This measures the lower bound of the serialized certificate. It doesn't
-    // measure the actual memory used, which is 4x this amount (see
-    // crbug.com/671420 for more details).
-    entry_dump->AddScalar("cert_size",
-                          base::trace_event::MemoryAllocatorDump::kUnitsBytes,
-                          cert_size);
-    entry_dump->AddScalar("serialized_cert_count",
-                          base::trace_event::MemoryAllocatorDump::kUnitsObjects,
-                          cert_count);
-    entry_dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
-                          base::trace_event::MemoryAllocatorDump::kUnitsBytes,
-                          cert_size);
   }
+  // This measures the lower bound of the serialized certificate. It doesn't
+  // measure the actual memory used, which is 4x this amount (see
+  // crbug.com/671420 for more details).
+  cache_dump->AddScalar("serialized_cert_size",
+                        base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+                        total_serialized_cert_size);
+  cache_dump->AddScalar("cert_count",
+                        base::trace_event::MemoryAllocatorDump::kUnitsObjects,
+                        total_cert_count);
+  cache_dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+                        base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+                        total_serialized_cert_size);
 }
 
 void SSLClientSessionCache::FlushExpiredSessions() {
diff --git a/net/ssl/ssl_client_session_cache_unittest.cc b/net/ssl/ssl_client_session_cache_unittest.cc
index 2f14ae86..c9cf6f28c 100644
--- a/net/ssl/ssl_client_session_cache_unittest.cc
+++ b/net/ssl/ssl_client_session_cache_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/time/time.h"
 #include "base/trace_event/memory_allocator_dump.h"
 #include "base/trace_event/process_memory_dump.h"
+#include "base/trace_event/trace_event_argument.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/boringssl/src/include/openssl/ssl.h"
 
@@ -325,16 +326,16 @@
       new base::trace_event::ProcessMemoryDump(nullptr, dump_args));
   cache.DumpMemoryStats(process_memory_dump.get());
 
-  const base::trace_event::ProcessMemoryDump::AllocatorDumpsMap&
-      allocator_dumps = process_memory_dump->allocator_dumps();
-
-  size_t num_entry_dump = 0;
-  for (const auto& pair : allocator_dumps) {
-    const std::string& dump_name = pair.first;
-    if (dump_name.find("net/ssl_session_cache/entry") != std::string::npos)
-      num_entry_dump++;
-  }
-  ASSERT_EQ(3u, num_entry_dump);
+  const base::trace_event::MemoryAllocatorDump* dump =
+      process_memory_dump->GetAllocatorDump("net/ssl_session_cache");
+  ASSERT_NE(nullptr, dump);
+  std::unique_ptr<base::Value> raw_attrs =
+      dump->attributes_for_testing()->ToBaseValue();
+  base::DictionaryValue* attrs;
+  ASSERT_TRUE(raw_attrs->GetAsDictionary(&attrs));
+  ASSERT_TRUE(attrs->HasKey("cert_count"));
+  ASSERT_TRUE(attrs->HasKey("serialized_cert_size"));
+  ASSERT_TRUE(attrs->HasKey(base::trace_event::MemoryAllocatorDump::kNameSize));
 }
 
 }  // namespace net
diff --git a/net/ssl/ssl_platform_key_android_unittest.cc b/net/ssl/ssl_platform_key_android_unittest.cc
index 118de12..3fb6800 100644
--- a/net/ssl/ssl_platform_key_android_unittest.cc
+++ b/net/ssl/ssl_platform_key_android_unittest.cc
@@ -35,14 +35,13 @@
 
 typedef base::android::ScopedJavaLocalRef<jobject> ScopedJava;
 
-// Resize a string to |size| bytes of data, then return its data buffer
-// address cast as an 'unsigned char*', as expected by OpenSSL functions.
+// Resize a string to |size| bytes of data, then return its data buffer address
+// cast as an 'uint8_t*', as expected by OpenSSL functions.
 // |str| the target string.
 // |size| the number of bytes to write into the string.
-// Return the string's new buffer in memory, as an 'unsigned char*'
-// pointer.
-unsigned char* OpenSSLWriteInto(std::string* str, size_t size) {
-  return reinterpret_cast<unsigned char*>(base::WriteInto(str, size + 1));
+// Return the string's new buffer in memory, as an 'uint8_t*' pointer.
+uint8_t* OpenSSLWriteInto(std::string* str, size_t size) {
+  return reinterpret_cast<uint8_t*>(base::WriteInto(str, size + 1));
 }
 
 bool ReadTestFile(const char* filename, std::string* pkcs8) {
@@ -51,45 +50,12 @@
   return base::ReadFileToString(file_path, pkcs8);
 }
 
-// Load a given private key file into an EVP_PKEY.
-// |filename| is the key file path.
-// Returns a new EVP_PKEY on success, NULL on failure.
-bssl::UniquePtr<EVP_PKEY> ImportPrivateKeyFile(const char* filename) {
-  std::string pkcs8;
-  if (!ReadTestFile(filename, &pkcs8))
-    return nullptr;
-
+// Parses a PKCS#8 key into an OpenSSL private key object.
+bssl::UniquePtr<EVP_PKEY> ImportPrivateKeyOpenSSL(const std::string& pkcs8) {
   crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
   CBS cbs;
   CBS_init(&cbs, reinterpret_cast<const uint8_t*>(pkcs8.data()), pkcs8.size());
-  bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_private_key(&cbs));
-  if (!pkey) {
-    LOG(ERROR) << "Could not load private key file: " << filename;
-    return nullptr;
-  }
-
-  return pkey;
-}
-
-// Imports the public key from the specified test certificate.
-bssl::UniquePtr<EVP_PKEY> ImportPublicKeyFromCertificateFile(
-    const char* filename) {
-  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
-
-  scoped_refptr<X509Certificate> cert =
-      ImportCertFromFile(GetTestCertsDirectory(), filename);
-  if (!cert) {
-    LOG(ERROR) << "Could not open certificate file: " << filename;
-    return nullptr;
-  }
-
-  bssl::UniquePtr<EVP_PKEY> pkey(X509_get_pubkey(cert->os_cert_handle()));
-  if (!pkey) {
-    LOG(ERROR) << "Could not load public key from certificate: " << filename;
-    return nullptr;
-  }
-
-  return pkey;
+  return bssl::UniquePtr<EVP_PKEY>(EVP_parse_private_key(&cbs));
 }
 
 // Retrieve a JNI local ref from encoded PKCS#8 data.
@@ -107,140 +73,42 @@
   return key;
 }
 
-const char kTestRsaKeyFile[] = "client_1.pk8";
-const char kTestRsaCertificateFile[] = "client_1.pem";
-
-// Retrieve a JNI local ref for our test RSA key.
-ScopedJava GetRSATestKeyJava() {
-  std::string key;
-  if (!ReadTestFile(kTestRsaKeyFile, &key))
-    return ScopedJava();
-  return GetPKCS8PrivateKeyJava(android::PRIVATE_KEY_TYPE_RSA, key);
-}
-
-const char kTestEcdsaKeyFile[] = "client_4.pk8";
-const char kTestEcdsaCertificateFile[] = "client_4.pem";
-
-// Retrieve a JNI local ref for our test ECDSA key.
-ScopedJava GetECDSATestKeyJava() {
-  std::string key;
-  if (!ReadTestFile(kTestEcdsaKeyFile, &key))
-    return ScopedJava();
-  return GetPKCS8PrivateKeyJava(android::PRIVATE_KEY_TYPE_ECDSA, key);
-}
-
-// Call this function to verify that one message signed with our
-// test ECDSA private key is correct. Since ECDSA signing introduces
-// random elements in the signature, it is not possible to compare
-// signature bits directly. However, one can use the public key
-// to do the check.
-bool VerifyTestECDSASignature(const base::StringPiece& message,
-                              const base::StringPiece& signature) {
+bool VerifyWithOpenSSL(const EVP_MD* md,
+                       const base::StringPiece& digest,
+                       EVP_PKEY* key,
+                       const base::StringPiece& signature) {
   crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
 
-  bssl::UniquePtr<EVP_PKEY> pkey =
-      ImportPublicKeyFromCertificateFile(kTestEcdsaCertificateFile);
-  if (!pkey)
-    return false;
-
-  EC_KEY* pub_key = EVP_PKEY_get0_EC_KEY(pkey.get());
-  if (!pub_key) {
-    LOG(ERROR) << "Could not get ECDSA public key";
+  bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(key, nullptr));
+  if (!ctx || !EVP_PKEY_verify_init(ctx.get()) ||
+      !EVP_PKEY_CTX_set_signature_md(ctx.get(), md) ||
+      !EVP_PKEY_verify(
+          ctx.get(), reinterpret_cast<const uint8_t*>(signature.data()),
+          signature.size(), reinterpret_cast<const uint8_t*>(digest.data()),
+          digest.size())) {
     return false;
   }
 
-  const unsigned char* digest =
-      reinterpret_cast<const unsigned char*>(message.data());
-  int digest_len = static_cast<int>(message.size());
-  const unsigned char* sigbuf =
-      reinterpret_cast<const unsigned char*>(signature.data());
-  int siglen = static_cast<int>(signature.size());
-
-  if (!ECDSA_verify(0, digest, digest_len, sigbuf, siglen, pub_key)) {
-    LOG(ERROR) << "ECDSA_verify() failed";
-    return false;
-  }
   return true;
 }
 
-// Sign a message with OpenSSL, return the result as a string.
-// |message| is the message to be signed.
-// |openssl_key| is an OpenSSL EVP_PKEY to use.
-// |result| receives the result.
-// Returns true on success, false otherwise.
-bool SignWithOpenSSL(int hash_nid,
-                     const base::StringPiece& message,
-                     EVP_PKEY* openssl_key,
+bool SignWithOpenSSL(const EVP_MD* md,
+                     const base::StringPiece& digest,
+                     EVP_PKEY* key,
                      std::string* result) {
   crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
 
-  RSA* rsa = EVP_PKEY_get0_RSA(openssl_key);
-  if (!rsa) {
-    LOG(ERROR) << "Could not get RSA from EVP_PKEY";
+  size_t sig_len;
+  bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(key, nullptr));
+  if (!ctx || !EVP_PKEY_sign_init(ctx.get()) ||
+      !EVP_PKEY_CTX_set_signature_md(ctx.get(), md) ||
+      !EVP_PKEY_sign(ctx.get(), OpenSSLWriteInto(result, EVP_PKEY_size(key)),
+                     &sig_len, reinterpret_cast<const uint8_t*>(digest.data()),
+                     digest.size())) {
     return false;
   }
 
-  const unsigned char* digest =
-      reinterpret_cast<const unsigned char*>(message.data());
-  unsigned int digest_len = static_cast<unsigned int>(message.size());
-
-  // With RSA, the signature will always be RSA_size() bytes.
-  size_t max_signature_size = static_cast<size_t>(RSA_size(rsa));
-  std::string signature;
-  unsigned char* p = OpenSSLWriteInto(&signature, max_signature_size);
-  unsigned int p_len = 0;
-  if (!RSA_sign(hash_nid, digest, digest_len, p, &p_len, rsa)) {
-    LOG(ERROR) << "RSA_sign() failed";
-    return false;
-  }
-
-  size_t signature_size = static_cast<size_t>(p_len);
-  if (signature_size == 0) {
-    LOG(ERROR) << "Signature is empty!";
-    return false;
-  }
-  if (signature_size > max_signature_size) {
-    LOG(ERROR) << "Signature size mismatch, actual " << signature_size
-               << ", expected <= " << max_signature_size;
-    return false;
-  }
-  signature.resize(signature_size);
-  result->swap(signature);
-  return true;
-}
-
-// Check that a generated signature for a given message matches
-// OpenSSL output byte-by-byte.
-// |message| is the input message.
-// |signature| is the generated signature for the message.
-// |openssl_key| is a raw EVP_PKEY for the same private key than the
-// one which was used to generate the signature.
-// Returns true on success, false otherwise.
-bool CompareSignatureWithOpenSSL(int hash_nid,
-                                 const base::StringPiece& message,
-                                 const base::StringPiece& signature,
-                                 EVP_PKEY* openssl_key) {
-  std::string openssl_signature;
-  if (!SignWithOpenSSL(hash_nid, message, openssl_key, &openssl_signature))
-    return false;
-
-  if (signature.size() != openssl_signature.size()) {
-    LOG(ERROR) << "Signature size mismatch, actual " << signature.size()
-               << ", expected " << openssl_signature.size();
-    return false;
-  }
-  for (size_t n = 0; n < signature.size(); ++n) {
-    if (openssl_signature[n] != signature[n]) {
-      LOG(ERROR) << "Signature byte mismatch at index " << n << "actual "
-                 << signature[n] << ", expected " << openssl_signature[n];
-      LOG(ERROR) << "Actual signature  : "
-                 << base::HexEncode(signature.data(), signature.size());
-      LOG(ERROR) << "Expected signature: "
-                 << base::HexEncode(openssl_signature.data(),
-                                    openssl_signature.size());
-      return false;
-    }
-  }
+  result->resize(sig_len);
   return true;
 }
 
@@ -282,81 +150,84 @@
     {"SHA-512", NID_sha512, SSLPrivateKey::Hash::SHA512},
 };
 
+struct TestKey {
+  const char* cert_file;
+  const char* key_file;
+  android::PrivateKeyType android_key_type;
+  SSLPrivateKey::Type key_type;
+};
+
+static const TestKey kTestKeys[] = {
+    {"client_1.pem", "client_1.pk8", android::PRIVATE_KEY_TYPE_RSA,
+     SSLPrivateKey::Type::RSA},
+    {"client_4.pem", "client_4.pk8", android::PRIVATE_KEY_TYPE_ECDSA,
+     SSLPrivateKey::Type::ECDSA_P256},
+    {"client_5.pem", "client_5.pk8", android::PRIVATE_KEY_TYPE_ECDSA,
+     SSLPrivateKey::Type::ECDSA_P384},
+    {"client_6.pem", "client_6.pk8", android::PRIVATE_KEY_TYPE_ECDSA,
+     SSLPrivateKey::Type::ECDSA_P521},
+};
+
 }  // namespace
 
-TEST(SSLPlatformKeyAndroid, RSA) {
+class SSLPlatformKeyAndroidTest : public testing::TestWithParam<TestKey> {};
+
+TEST_P(SSLPlatformKeyAndroidTest, SignHashes) {
   crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+  const TestKey& test_key = GetParam();
 
   scoped_refptr<X509Certificate> cert =
-      ImportCertFromFile(GetTestCertsDirectory(), kTestRsaCertificateFile);
+      ImportCertFromFile(GetTestCertsDirectory(), test_key.cert_file);
   ASSERT_TRUE(cert);
-  ScopedJava rsa_key = GetRSATestKeyJava();
-  ASSERT_FALSE(rsa_key.is_null());
+
+  std::string key_bytes;
+  ASSERT_TRUE(ReadTestFile(test_key.key_file, &key_bytes));
+  ScopedJava java_key =
+      GetPKCS8PrivateKeyJava(test_key.android_key_type, key_bytes);
+  ASSERT_FALSE(java_key.is_null());
 
   scoped_refptr<SSLPrivateKey> wrapper_key =
-      WrapJavaPrivateKey(cert.get(), rsa_key);
+      WrapJavaPrivateKey(cert.get(), java_key);
   ASSERT_TRUE(wrapper_key);
 
-  bssl::UniquePtr<EVP_PKEY> openssl_key = ImportPrivateKeyFile(kTestRsaKeyFile);
+  bssl::UniquePtr<EVP_PKEY> openssl_key = ImportPrivateKeyOpenSSL(key_bytes);
   ASSERT_TRUE(openssl_key);
 
   // Check that the wrapper key returns the correct length and type.
-  EXPECT_EQ(SSLPrivateKey::Type::RSA, wrapper_key->GetType());
+  EXPECT_EQ(test_key.key_type, wrapper_key->GetType());
   EXPECT_EQ(static_cast<size_t>(EVP_PKEY_size(openssl_key.get())),
             wrapper_key->GetMaxSignatureLengthInBytes());
 
   // Test signing against each hash.
   for (const auto& hash : kHashes) {
-    SCOPED_TRACE(hash.name);
-
-    const EVP_MD* md = EVP_get_digestbynid(hash.nid);
-    ASSERT_TRUE(md);
-    std::string digest(EVP_MD_size(md), 'a');
-
-    std::string signature;
-    DoKeySigningWithWrapper(wrapper_key.get(), hash.hash, digest, &signature);
-    ASSERT_TRUE(CompareSignatureWithOpenSSL(hash.nid, digest, signature,
-                                            openssl_key.get()));
-  }
-}
-
-TEST(SSLPlatformKeyAndroid, ECDSA) {
-  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
-
-  scoped_refptr<X509Certificate> cert =
-      ImportCertFromFile(GetTestCertsDirectory(), kTestEcdsaCertificateFile);
-  ASSERT_TRUE(cert);
-  ScopedJava ecdsa_key = GetECDSATestKeyJava();
-  ASSERT_FALSE(ecdsa_key.is_null());
-
-  scoped_refptr<SSLPrivateKey> wrapper_key =
-      WrapJavaPrivateKey(cert.get(), ecdsa_key);
-  ASSERT_TRUE(wrapper_key);
-
-  bssl::UniquePtr<EVP_PKEY> openssl_key =
-      ImportPrivateKeyFile(kTestEcdsaKeyFile);
-  ASSERT_TRUE(openssl_key);
-
-  // Check that the wrapper key returns the correct length and type.
-  EXPECT_EQ(SSLPrivateKey::Type::ECDSA_P256, wrapper_key->GetType());
-  EXPECT_EQ(static_cast<size_t>(EVP_PKEY_size(openssl_key.get())),
-            wrapper_key->GetMaxSignatureLengthInBytes());
-
-  // Test signing against each hash.
-  for (const auto& hash : kHashes) {
-    // ECDSA does not sign MD5-SHA1.
-    if (hash.nid == NID_md5_sha1)
+    // Only RSA signs MD5-SHA1.
+    if (test_key.key_type != SSLPrivateKey::Type::RSA &&
+        hash.nid == NID_md5_sha1) {
       continue;
+    }
 
     SCOPED_TRACE(hash.name);
+
     const EVP_MD* md = EVP_get_digestbynid(hash.nid);
     ASSERT_TRUE(md);
     std::string digest(EVP_MD_size(md), 'a');
 
     std::string signature;
     DoKeySigningWithWrapper(wrapper_key.get(), hash.hash, digest, &signature);
-    ASSERT_TRUE(VerifyTestECDSASignature(digest, signature));
+    EXPECT_TRUE(VerifyWithOpenSSL(md, digest, openssl_key.get(), signature));
+
+    // RSA signing is deterministic, so further check the signature matches.
+    if (test_key.key_type == SSLPrivateKey::Type::RSA) {
+      std::string openssl_signature;
+      ASSERT_TRUE(
+          SignWithOpenSSL(md, digest, openssl_key.get(), &openssl_signature));
+      EXPECT_EQ(openssl_signature, signature);
+    }
   }
 }
 
+INSTANTIATE_TEST_CASE_P(,
+                        SSLPlatformKeyAndroidTest,
+                        testing::ValuesIn(kTestKeys));
+
 }  // namespace net
diff --git a/net/ssl/ssl_platform_key_util.cc b/net/ssl/ssl_platform_key_util.cc
index 6c76220..39af9eb 100644
--- a/net/ssl/ssl_platform_key_util.cc
+++ b/net/ssl/ssl_platform_key_util.cc
@@ -88,7 +88,7 @@
           *out_type = SSLPrivateKey::Type::ECDSA_P384;
           break;
         case NID_secp521r1:
-          *out_type = SSLPrivateKey::Type::ECDSA_P384;
+          *out_type = SSLPrivateKey::Type::ECDSA_P521;
           break;
         default:
           LOG(ERROR) << "Unsupported curve type " << curve;
diff --git a/net/ssl/ssl_platform_key_util_unittest.cc b/net/ssl/ssl_platform_key_util_unittest.cc
index 1e7b9d3..8a00034 100644
--- a/net/ssl/ssl_platform_key_util_unittest.cc
+++ b/net/ssl/ssl_platform_key_util_unittest.cc
@@ -31,6 +31,10 @@
   return GetClientCertInfo(cert.get(), out_type, out_max_length);
 }
 
+size_t BitsToBytes(size_t bits) {
+  return (bits + 7) / 8;
+}
+
 }  // namespace
 
 TEST(SSLPlatformKeyUtil, GetClientCertInfo) {
@@ -43,7 +47,15 @@
 
   ASSERT_TRUE(GetClientCertInfoFromFile("client_4.pem", &type, &max_length));
   EXPECT_EQ(SSLPrivateKey::Type::ECDSA_P256, type);
-  EXPECT_EQ(ECDSA_SIG_max_len(256u / 8u), max_length);
+  EXPECT_EQ(ECDSA_SIG_max_len(BitsToBytes(256)), max_length);
+
+  ASSERT_TRUE(GetClientCertInfoFromFile("client_5.pem", &type, &max_length));
+  EXPECT_EQ(SSLPrivateKey::Type::ECDSA_P384, type);
+  EXPECT_EQ(ECDSA_SIG_max_len(BitsToBytes(384)), max_length);
+
+  ASSERT_TRUE(GetClientCertInfoFromFile("client_6.pem", &type, &max_length));
+  EXPECT_EQ(SSLPrivateKey::Type::ECDSA_P521, type);
+  EXPECT_EQ(ECDSA_SIG_max_len(BitsToBytes(521)), max_length);
 }
 
 }  // namespace net
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc
index 9a83f46..9d3e6b2 100644
--- a/net/tools/quic/end_to_end_test.cc
+++ b/net/tools/quic/end_to_end_test.cc
@@ -373,6 +373,7 @@
   bool Initialize() {
     QuicTagVector copt;
     server_config_.SetConnectionOptionsToSend(copt);
+    copt = client_extra_copts_;
 
     // TODO(nimia): Consider setting the congestion control algorithm for the
     // client as well according to the test parameter.
@@ -381,6 +382,10 @@
         FLAGS_quic_fix_cubic_convex_mode) {
       copt.push_back(kCCVX);
     }
+    if (GetParam().congestion_control_tag == kQBIC &&
+        FLAGS_quic_fix_cubic_bytes_quantization) {
+      copt.push_back(kCBQT);
+    }
     if (support_server_push_) {
       copt.push_back(kSPSH);
     }
@@ -570,6 +575,7 @@
   QuicConfig server_config_;
   QuicVersionVector client_supported_versions_;
   QuicVersionVector server_supported_versions_;
+  QuicTagVector client_extra_copts_;
   QuicVersion negotiated_version_;
   size_t chlo_multiplier_;
   QuicTestServer::StreamFactory* stream_factory_;
@@ -588,7 +594,8 @@
   QuicCryptoStream* crypto_stream =
       QuicSessionPeer::GetCryptoStream(client_->client()->session());
   QuicStreamSequencer* sequencer = QuicStreamPeer::sequencer(crypto_stream);
-  EXPECT_NE(FLAGS_quic_release_crypto_stream_buffer,
+  EXPECT_NE(FLAGS_quic_release_crypto_stream_buffer &&
+                FLAGS_quic_reduce_sequencer_buffer_memory_life_time,  // NOLINT
             QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer));
   server_thread_->Pause();
   QuicDispatcher* dispatcher =
@@ -596,7 +603,8 @@
   QuicSession* server_session = dispatcher->session_map().begin()->second.get();
   crypto_stream = QuicSessionPeer::GetCryptoStream(server_session);
   sequencer = QuicStreamPeer::sequencer(crypto_stream);
-  EXPECT_NE(FLAGS_quic_release_crypto_stream_buffer,
+  EXPECT_NE(FLAGS_quic_release_crypto_stream_buffer &&
+                FLAGS_quic_reduce_sequencer_buffer_memory_life_time,  // NOLINT
             QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer));
 }
 
@@ -1699,6 +1707,53 @@
   server_thread_->Resume();
 }
 
+// Test negotiation of IFWA connection option.
+TEST_P(EndToEndTest, NegotiatedServerInitialFlowControlWindow) {
+  FLAGS_quic_large_ifw_options = true;
+
+  const uint32_t kClientStreamIFCW = 123456;
+  const uint32_t kClientSessionIFCW = 234567;
+  set_client_initial_stream_flow_control_receive_window(kClientStreamIFCW);
+  set_client_initial_session_flow_control_receive_window(kClientSessionIFCW);
+
+  uint32_t kServerStreamIFCW = 32 * 1024;
+  uint32_t kServerSessionIFCW = 48 * 1024;
+  set_server_initial_stream_flow_control_receive_window(kServerStreamIFCW);
+  set_server_initial_session_flow_control_receive_window(kServerSessionIFCW);
+
+  // Bump the window.
+  const uint32_t kExpectedStreamIFCW = 1024 * 1024;
+  const uint32_t kExpectedSessionIFCW = 1.5 * 1024 * 1024;
+  client_extra_copts_.push_back(kIFWA);
+
+  ASSERT_TRUE(Initialize());
+
+  // Values are exchanged during crypto handshake, so wait for that to finish.
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
+  server_thread_->WaitForCryptoHandshakeConfirmed();
+
+  // Open a data stream to make sure the stream level flow control is updated.
+  QuicSpdyClientStream* stream = client_->GetOrCreateStream();
+  stream->WriteOrBufferBody("hello", false, nullptr);
+
+  // Client should have the right values for server's receive window.
+  EXPECT_EQ(kExpectedStreamIFCW,
+            client_->client()
+                ->session()
+                ->config()
+                ->ReceivedInitialStreamFlowControlWindowBytes());
+  EXPECT_EQ(kExpectedSessionIFCW,
+            client_->client()
+                ->session()
+                ->config()
+                ->ReceivedInitialSessionFlowControlWindowBytes());
+  EXPECT_EQ(kExpectedStreamIFCW, QuicFlowControllerPeer::SendWindowOffset(
+                                     stream->flow_controller()));
+  EXPECT_EQ(kExpectedSessionIFCW,
+            QuicFlowControllerPeer::SendWindowOffset(
+                client_->client()->session()->flow_controller()));
+}
+
 TEST_P(EndToEndTest, HeadersAndCryptoStreamsNoConnectionFlowControl) {
   // The special headers and crypto streams should be subject to per-stream flow
   // control limits, but should not be subject to connection level flow control
@@ -2636,7 +2691,8 @@
     DVLOG(1) << "response body " << response_body;
     EXPECT_EQ(expected_body, response_body);
   }
-  EXPECT_NE(FLAGS_quic_headers_stream_release_sequencer_buffer,
+  EXPECT_NE(FLAGS_quic_headers_stream_release_sequencer_buffer &&
+                FLAGS_quic_reduce_sequencer_buffer_memory_life_time,  // NOLINT
             QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer));
 }
 
@@ -2939,7 +2995,8 @@
   QuicHeadersStream* headers_stream =
       QuicSpdySessionPeer::GetHeadersStream(client_->client()->session());
   QuicStreamSequencer* sequencer = QuicStreamPeer::sequencer(headers_stream);
-  EXPECT_NE(FLAGS_quic_headers_stream_release_sequencer_buffer,
+  EXPECT_NE(FLAGS_quic_headers_stream_release_sequencer_buffer &&
+                FLAGS_quic_reduce_sequencer_buffer_memory_life_time,  // NOLINT
             QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer));
 }
 
diff --git a/net/tools/quic/quic_packet_reader.cc b/net/tools/quic/quic_packet_reader.cc
index 977249b..04a9373 100644
--- a/net/tools/quic/quic_packet_reader.cc
+++ b/net/tools/quic/quic_packet_reader.cc
@@ -10,7 +10,6 @@
 #include <features.h>
 #endif
 #include <string.h>
-#include <sys/epoll.h>
 
 #include "base/logging.h"
 #include "net/quic/core/quic_bug_tracker.h"
@@ -20,8 +19,6 @@
 #include "net/tools/quic/quic_dispatcher.h"
 #include "net/tools/quic/quic_process_packet_interface.h"
 
-#define MMSG_MORE 0
-
 #ifndef SO_RXQ_OVFL
 #define SO_RXQ_OVFL 40
 #endif
diff --git a/net/tools/quic/quic_packet_reader.h b/net/tools/quic/quic_packet_reader.h
index 71e9485c..13a8ccc 100644
--- a/net/tools/quic/quic_packet_reader.h
+++ b/net/tools/quic/quic_packet_reader.h
@@ -8,6 +8,8 @@
 #define NET_TOOLS_QUIC_QUIC_PACKET_READER_H_
 
 #include <netinet/in.h>
+// Include here to guarantee this header gets included (for MSG_WAITFORONE)
+// regardless of how the below transitive header include set may change.
 #include <sys/socket.h>
 
 #include "base/macros.h"
diff --git a/remoting/host/desktop_session_win.cc b/remoting/host/desktop_session_win.cc
index eed1888..8edd612a 100644
--- a/remoting/host/desktop_session_win.cc
+++ b/remoting/host/desktop_session_win.cc
@@ -618,11 +618,11 @@
 
   ReportElapsedTime("attached");
 
-  // Launch elevated on Win8 to be able to inject Alt+Tab.
+  // Launch elevated on Win8+ to enable injection of Alt+Tab and Ctrl+Alt+Del.
   bool launch_elevated = base::win::GetVersion() >= base::win::VERSION_WIN8;
 
   // Get the name of the executable to run. |kDesktopBinaryName| specifies
-  // uiAccess="true" in it's manifest.
+  // uiAccess="true" in its manifest.
   base::FilePath desktop_binary;
   bool result;
   if (launch_elevated) {
diff --git a/remoting/host/win/BUILD.gn b/remoting/host/win/BUILD.gn
index b034915..f6ddd335 100644
--- a/remoting/host/win/BUILD.gn
+++ b/remoting/host/win/BUILD.gn
@@ -430,7 +430,7 @@
   ]
 
   if (is_official_build) {
-    deps += [ ":dpi_aware_elevated_exe_manifest" ]
+    deps += [ ":dpi_aware_uiaccess_require_admin_exe_manifest" ]
   } else {
     deps += [ ":dpi_aware_exe_manifest" ]
   }
diff --git a/remoting/host/win/wts_session_process_delegate.cc b/remoting/host/win/wts_session_process_delegate.cc
index 780531c0..d959aca 100644
--- a/remoting/host/win/wts_session_process_delegate.cc
+++ b/remoting/host/win/wts_session_process_delegate.cc
@@ -155,6 +155,9 @@
   // If launching elevated, this is the pid of the launcher process.
   base::ProcessId elevated_launcher_pid_ = base::kNullProcessId;
 
+  // Tracks the id of the worker process.
+  base::ProcessId worker_process_pid_ = base::kNullProcessId;
+
   // The mojo child token for the process being launched.
   std::string mojo_child_token_;
 
@@ -252,8 +255,9 @@
 void WtsSessionProcessDelegate::Core::CloseChannel() {
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
 
-  if (!channel_)
+  if (!channel_) {
     return;
+  }
 
   channel_.reset();
   elevated_server_handle_.reset();
@@ -273,11 +277,13 @@
   launch_pending_ = false;
 
   if (launch_elevated_) {
-    if (job_.IsValid())
+    if (job_.IsValid()) {
       TerminateJobObject(job_.Get(), CONTROL_C_EXIT);
+    }
   } else {
-    if (worker_process_.IsValid())
+    if (worker_process_.IsValid()) {
       TerminateProcess(worker_process_.Get(), CONTROL_C_EXIT);
+    }
   }
 
   worker_process_.Close();
@@ -296,7 +302,9 @@
   DCHECK(io_task_runner_->BelongsToCurrentThread());
 
   // |bytes_transferred| is used in job object notifications to supply
-  // the message ID; |context| carries process ID.
+  // the message ID; |context| carries process ID for the events we listen for.
+  base::ProcessId process_id =
+      static_cast<base::ProcessId>(reinterpret_cast<uintptr_t>(context));
   switch (bytes_transferred) {
     case JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO: {
       caller_task_runner_->PostTask(
@@ -304,10 +312,38 @@
       break;
     }
     case JOB_OBJECT_MSG_NEW_PROCESS: {
-      caller_task_runner_->PostTask(
-          FROM_HERE, base::Bind(&Core::OnProcessLaunchDetected, this,
-                                static_cast<base::ProcessId>(
-                                    reinterpret_cast<uintptr_t>(context))));
+      if (elevated_launcher_pid_ == base::kNullProcessId) {
+        // Ignore process launch events when we don't have a valid launcher pid.
+        return;
+      }
+
+      if (process_id != elevated_launcher_pid_) {
+        DCHECK_EQ(worker_process_pid_, base::kNullProcessId);
+        worker_process_pid_ = process_id;
+      }
+      break;
+    }
+    case JOB_OBJECT_MSG_EXIT_PROCESS: {
+      if (process_id == worker_process_pid_) {
+        // In official builds the first launch of a UiAccess enabled binary
+        // will fail due to 'STATUS_ELEVATION_REQUIRED'.  This is an artifact of
+        // using ShellExecuteEx() to launch the process.  In this scenario, we
+        // will clear out the previously stored value for |worker_process_pid_|
+        // and retry after the subsequent relaunch of the worker process.
+        worker_process_pid_ = base::kNullProcessId;
+      } else if (process_id == elevated_launcher_pid_) {
+        if (worker_process_pid_ == base::kNullProcessId) {
+          // The elevated launcher process can fail to launch without attemping
+          // to launch the worker.  In this scenario, the failure will be
+          // detected outside this method and the elevated launcher will be
+          // launched again.
+          return;
+        }
+
+        caller_task_runner_->PostTask(
+            FROM_HERE, base::Bind(&Core::OnProcessLaunchDetected, this,
+                                  worker_process_pid_));
+      }
       break;
     }
   }
@@ -489,8 +525,9 @@
 
   job_ = std::move(job);
 
-  if (launch_pending_)
+  if (launch_pending_) {
     DoLaunchProcess();
+  }
 }
 
 void WtsSessionProcessDelegate::Core::OnActiveProcessZero() {
@@ -506,11 +543,11 @@
 void WtsSessionProcessDelegate::Core::OnProcessLaunchDetected(
     base::ProcessId pid) {
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
-  if (!elevated_server_handle_.is_valid())
-    return;
+  DCHECK_NE(pid, elevated_launcher_pid_);
 
-  if (pid == elevated_launcher_pid_)
+  if (!elevated_server_handle_.is_valid()) {
     return;
+  }
 
   DWORD desired_access =
       SYNCHRONIZE | PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION;
diff --git a/rlz/features/BUILD.gn b/rlz/features/BUILD.gn
new file mode 100644
index 0000000..58328e7
--- /dev/null
+++ b/rlz/features/BUILD.gn
@@ -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.
+
+import("//build/buildflag_header.gni")
+import("//rlz/features/features.gni")
+
+buildflag_header("features") {
+  header = "features.h"
+  flags = [ "ENABLE_RLZ=$enable_rlz" ]
+}
diff --git a/rlz/features/features.gni b/rlz/features/features.gni
new file mode 100644
index 0000000..d90c6e1
--- /dev/null
+++ b/rlz/features/features.gni
@@ -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.
+
+import("//build/config/chrome_build.gni")
+
+# Whether we are using the rlz library or not.  Platforms like Android send
+# rlz codes for searches but do not use the library.
+enable_rlz_support = is_win || is_mac || is_ios || is_chromeos
+
+enable_rlz = is_chrome_branded && enable_rlz_support
diff --git a/services/service_manager/public/cpp/service.gni b/services/service_manager/public/cpp/service.gni
index 2fb9991..04be44ed 100644
--- a/services/service_manager/public/cpp/service.gni
+++ b/services/service_manager/public/cpp/service.gni
@@ -94,6 +94,7 @@
     data_deps = service_data_deps
 
     deps = [
+      "//build/config/sanitizers:deps",
       "//services/service_manager/public/cpp/standalone_service:main",
     ]
 
diff --git a/services/service_manager/runner/common/switches.cc b/services/service_manager/runner/common/switches.cc
index 1f4a9a9..25c1766 100644
--- a/services/service_manager/runner/common/switches.cc
+++ b/services/service_manager/runner/common/switches.cc
@@ -18,6 +18,9 @@
 // primordial message pipe to the parent.
 const char kPrimordialPipeToken[] = "primordial-pipe-token";
 
+// The name of the service the process is starting for.
+const char kProcessServiceName[] = "process-service-name";
+
 // Specifies a JSON file from which to read a set of service metadata overrides.
 // This can be used with the standalone mojo_runner to override executable and
 // package resolution behavior.
diff --git a/services/service_manager/runner/common/switches.h b/services/service_manager/runner/common/switches.h
index d36cfda..a14b36a8 100644
--- a/services/service_manager/runner/common/switches.h
+++ b/services/service_manager/runner/common/switches.h
@@ -12,6 +12,7 @@
 extern const char kChildProcess[];
 extern const char kEnableSandbox[];
 extern const char kPrimordialPipeToken[];
+extern const char kProcessServiceName[];
 extern const char kServiceOverrides[];
 
 }  // namespace switches
diff --git a/services/service_manager/runner/host/child_process_host.cc b/services/service_manager/runner/host/child_process_host.cc
index 5d77b7b..faf2ba58 100644
--- a/services/service_manager/runner/host/child_process_host.cc
+++ b/services/service_manager/runner/host/child_process_host.cc
@@ -81,8 +81,9 @@
 
   child_command_line->AppendArguments(parent_command_line, false);
 
+  child_command_line->AppendSwitchASCII(::switches::kProcessServiceName,
+                                        target.name());
 #ifndef NDEBUG
-  child_command_line->AppendSwitchASCII("n", target.name());
   child_command_line->AppendSwitchASCII("u", target.user_id());
 #endif
 
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h
index 1f13d6c..f25d37ec 100644
--- a/skia/config/SkUserConfig.h
+++ b/skia/config/SkUserConfig.h
@@ -228,6 +228,10 @@
 #   define SK_DISABLE_COLOR_XFORM_PIPELINE
 #endif
 
+#ifndef    SK_SUPPORT_EXOTIC_CLIPOPS
+#   define SK_SUPPORT_EXOTIC_CLIPOPS
+#endif
+
 #ifndef    SK_SUPPORT_LEGACY_IMAGE_ENCODER_CLASS
 #   define SK_SUPPORT_LEGACY_IMAGE_ENCODER_CLASS
 #endif
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index 5e303fe..cfcafa1 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -17,7 +17,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -49,7 +49,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -80,7 +80,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -114,7 +114,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -146,7 +146,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -177,7 +177,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -209,7 +209,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -240,7 +240,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -271,7 +271,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -305,7 +305,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -337,7 +337,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -368,7 +368,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -402,7 +402,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -434,7 +434,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -465,7 +465,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -496,7 +496,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -527,7 +527,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -558,7 +558,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -589,7 +589,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -621,7 +621,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -652,7 +652,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -683,7 +683,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -714,7 +714,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -745,7 +745,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -777,7 +777,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -809,7 +809,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -841,7 +841,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -873,7 +873,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -908,7 +908,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -940,7 +940,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -971,7 +971,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1002,7 +1002,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1033,7 +1033,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1064,7 +1064,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1095,7 +1095,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1126,7 +1126,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1157,7 +1157,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1333,7 +1333,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1366,7 +1366,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1399,7 +1399,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1435,7 +1435,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1468,7 +1468,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1501,7 +1501,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1534,7 +1534,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1567,7 +1567,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1600,7 +1600,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1633,7 +1633,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1666,7 +1666,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1699,7 +1699,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1732,7 +1732,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1765,7 +1765,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1798,7 +1798,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1831,7 +1831,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1864,7 +1864,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1897,7 +1897,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1930,7 +1930,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1963,7 +1963,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1999,7 +1999,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2032,7 +2032,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2065,7 +2065,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2098,7 +2098,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2131,7 +2131,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2164,7 +2164,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2197,7 +2197,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2230,7 +2230,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2266,7 +2266,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2302,7 +2302,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2338,7 +2338,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2374,7 +2374,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2410,7 +2410,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2563,7 +2563,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2597,7 +2597,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2628,7 +2628,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2662,7 +2662,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2693,7 +2693,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2724,7 +2724,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2755,7 +2755,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2789,7 +2789,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2820,7 +2820,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2851,7 +2851,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2885,7 +2885,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2919,7 +2919,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2950,7 +2950,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2981,7 +2981,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -3012,7 +3012,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -3046,7 +3046,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -3077,7 +3077,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -3108,7 +3108,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -3139,7 +3139,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -3170,7 +3170,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -3201,7 +3201,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -3232,7 +3232,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -3263,7 +3263,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -3294,7 +3294,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -3325,7 +3325,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -3356,7 +3356,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -3387,7 +3387,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -3421,7 +3421,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -3452,7 +3452,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -3483,7 +3483,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -3514,7 +3514,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -3545,7 +3545,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -3576,7 +3576,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -3607,7 +3607,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -3638,7 +3638,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index bce8672..2d3b5c1 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -1586,7 +1586,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1618,7 +1618,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json
index 1087293..bfd3e45 100644
--- a/testing/buildbot/chromium.gpu.fyi.json
+++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -11,7 +11,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -42,7 +42,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -73,7 +73,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -364,7 +364,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -395,7 +395,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -426,7 +426,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -713,7 +713,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -744,7 +744,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -775,7 +775,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -806,7 +806,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1093,7 +1093,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1124,7 +1124,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1155,7 +1155,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1442,7 +1442,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1473,7 +1473,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1504,7 +1504,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -13553,6 +13553,25 @@
       },
       {
         "args": [
+          "--test-launcher-batch-limit=400",
+          "--deqp-egl-display-type=angle-d3d11"
+        ],
+        "name": "angle_deqp_gles3_d3d11_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "1002:6613",
+              "os": "Windows-2008ServerR2-SP1"
+            }
+          ],
+          "shards": 12
+        },
+        "test": "angle_deqp_gles3_tests",
+        "use_xvfb": false
+      },
+      {
+        "args": [
           "--use-gpu-in-tests",
           "--test-launcher-retry-limit=0"
         ],
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json
index e02833d..32ddf79 100644
--- a/testing/buildbot/chromium.linux.json
+++ b/testing/buildbot/chromium.linux.json
@@ -33,7 +33,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -65,7 +65,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -96,7 +96,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -130,7 +130,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -162,7 +162,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -193,7 +193,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -225,7 +225,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -256,7 +256,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -287,7 +287,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -321,7 +321,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -356,7 +356,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -388,7 +388,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -419,7 +419,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -450,7 +450,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -485,7 +485,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -517,7 +517,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -548,7 +548,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -579,7 +579,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -610,7 +610,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -641,7 +641,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -673,7 +673,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -704,7 +704,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -735,7 +735,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -766,7 +766,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -797,7 +797,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -829,7 +829,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -861,7 +861,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -893,7 +893,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -925,7 +925,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -960,7 +960,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -992,7 +992,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1023,7 +1023,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1054,7 +1054,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1085,7 +1085,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1116,7 +1116,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1147,7 +1147,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1178,7 +1178,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1209,7 +1209,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1308,7 +1308,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1340,7 +1340,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1371,7 +1371,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1405,7 +1405,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1437,7 +1437,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1468,7 +1468,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1500,7 +1500,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1531,7 +1531,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1562,7 +1562,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1596,7 +1596,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1631,7 +1631,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1663,7 +1663,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1694,7 +1694,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1725,7 +1725,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1760,7 +1760,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1792,7 +1792,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1823,7 +1823,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1854,7 +1854,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1885,7 +1885,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1916,7 +1916,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1948,7 +1948,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -1979,7 +1979,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2010,7 +2010,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2041,7 +2041,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2072,7 +2072,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2104,7 +2104,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2136,7 +2136,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2168,7 +2168,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2200,7 +2200,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2235,7 +2235,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2267,7 +2267,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2298,7 +2298,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2329,7 +2329,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2360,7 +2360,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2391,7 +2391,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2422,7 +2422,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2453,7 +2453,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
@@ -2484,7 +2484,7 @@
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
               "location": "bin",
-              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+              "revision": "git_revision:25755a2c316937ee44a6432163dc5e2f9c85cf58"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.perf.fyi.json b/testing/buildbot/chromium.perf.fyi.json
index 4a8ce94..0764442 100644
--- a/testing/buildbot/chromium.perf.fyi.json
+++ b/testing/buildbot/chromium.perf.fyi.json
@@ -5,6 +5,1374 @@
     "isolated_scripts": [
       {
         "args": [
+          "battor.power_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "battor.power_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "battor.power_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "battor.power_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "battor.power_cases_no_chrome_trace",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "battor.power_cases_no_chrome_trace",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "battor.power_cases_no_chrome_trace",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "battor.power_cases_no_chrome_trace.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "battor.steady_state",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "battor.steady_state",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "battor.steady_state",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "battor.steady_state.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "battor.tough_video_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "battor.tough_video_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "battor.tough_video_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "battor.tough_video_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "battor.trivial_pages",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "battor.trivial_pages",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "battor.trivial_pages",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "battor.trivial_pages.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.bindings",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.bindings",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.bindings",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.bindings.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.blink_gc",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.blink_gc",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.blink_gc",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.blink_gc.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.canvas",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.canvas",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.canvas",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.canvas.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.css",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.css",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.css",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.css.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.dom",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.dom",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.dom",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.dom.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.events",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.events",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.events",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.events.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.layout",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.layout",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.layout",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.layout.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.paint",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.paint",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.paint",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.paint.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.paint_slimmingpaintinvalidation",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.paint_slimmingpaintinvalidation",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.paint_slimmingpaintinvalidation",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.paint_slimmingpaintinvalidation.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.parser",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.parser",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.parser",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.parser.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.pywebsocket",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.pywebsocket",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.pywebsocket",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.pywebsocket.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.shadow_dom",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.shadow_dom",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.shadow_dom",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.shadow_dom.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.svg",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.svg",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.svg",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.svg.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.svg_slimmingpaintinvalidation",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.svg_slimmingpaintinvalidation",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.svg_slimmingpaintinvalidation",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.svg_slimmingpaintinvalidation.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.xml_http_request",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.xml_http_request",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.xml_http_request",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.xml_http_request.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_style.key_mobile_sites",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_style.key_mobile_sites",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_style.key_mobile_sites",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_style.key_mobile_sites.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_style.polymer",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_style.polymer",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_style.polymer",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_style.polymer.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_style.top_25",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_style.top_25",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_style.top_25",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_style.top_25.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blob_storage.blob_storage",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blob_storage.blob_storage",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blob_storage.blob_storage",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blob_storage.blob_storage.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
           "dromaeo.cssqueryjquery",
           "-v",
           "--upload-results",
@@ -21,7 +1389,7 @@
           "dimension_sets": [
             {
               "android_devices": "1",
-              "id": "build245-m4--device1",
+              "id": "build245-m4--device6",
               "os": "Android",
               "pool": "Chrome-perf"
             }
@@ -50,6 +1418,91 @@
           "dimension_sets": [
             {
               "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.domcoreattr",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.domcoreattr",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.domcoreattr",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.domcoreattr.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.domcoremodify",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.domcoremodify",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
               "id": "build245-m4--device1",
               "os": "Android",
               "pool": "Chrome-perf"
@@ -62,6 +1515,2828 @@
       },
       {
         "args": [
+          "dromaeo.domcoremodify",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.domcoremodify.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.domcorequery",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.domcorequery",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.domcorequery",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.domcorequery.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.domcoretraverse",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.domcoretraverse",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.domcoretraverse",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.domcoretraverse.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibattrjquery",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibattrjquery",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibattrjquery",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibattrjquery.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibattrprototype",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibattrprototype",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibattrprototype",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibattrprototype.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibeventjquery",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibeventjquery",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibeventjquery",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibeventjquery.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibeventprototype",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibeventprototype",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibeventprototype",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibeventprototype.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibmodifyjquery",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibmodifyjquery",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibmodifyjquery",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibmodifyjquery.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibmodifyprototype",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibmodifyprototype",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibmodifyprototype",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibmodifyprototype.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibstylejquery",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibstylejquery",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibstylejquery",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibstylejquery.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibstyleprototype",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibstyleprototype",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibstyleprototype",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibstyleprototype.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibtraversejquery",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibtraversejquery",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibtraversejquery",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibtraversejquery.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibtraverseprototype",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibtraverseprototype",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibtraverseprototype",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibtraverseprototype.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dummy_benchmark.noisy_benchmark_1",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dummy_benchmark.noisy_benchmark_1",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dummy_benchmark.noisy_benchmark_1",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dummy_benchmark.noisy_benchmark_1.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dummy_benchmark.stable_benchmark_1",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dummy_benchmark.stable_benchmark_1",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dummy_benchmark.stable_benchmark_1",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dummy_benchmark.stable_benchmark_1.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "gpu_times.gpu_rasterization.key_mobile_sites_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "gpu_times.gpu_rasterization.key_mobile_sites_smooth",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "gpu_times.gpu_rasterization.key_mobile_sites_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "gpu_times.gpu_rasterization.key_mobile_sites_smooth.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "gpu_times.gpu_rasterization.top_25_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "gpu_times.gpu_rasterization.top_25_smooth",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "gpu_times.gpu_rasterization.top_25_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "gpu_times.gpu_rasterization.top_25_smooth.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "gpu_times.key_mobile_sites_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "gpu_times.key_mobile_sites_smooth",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "gpu_times.key_mobile_sites_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "gpu_times.key_mobile_sites_smooth.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "gpu_times.top_25_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "gpu_times.top_25_smooth",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "gpu_times.top_25_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "gpu_times.top_25_smooth.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "image_decoding.image_decoding_measurement",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "image_decoding.image_decoding_measurement",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "image_decoding.image_decoding_measurement",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "image_decoding.image_decoding_measurement.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "indexeddb_perf",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "indexeddb_perf",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "indexeddb_perf",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "indexeddb_perf.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "jetstream",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "jetstream",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "jetstream",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "jetstream.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "jitter",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "jitter",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "jitter",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "jitter.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "kraken",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "kraken",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "kraken",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "kraken.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "loading.cluster_telemetry",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "loading.cluster_telemetry",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "loading.cluster_telemetry",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "loading.cluster_telemetry.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "loading.mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "loading.mobile",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "loading.mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "loading.mobile.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "media.android.tough_video_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "media.android.tough_video_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "media.android.tough_video_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "media.android.tough_video_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "media.chromeOS.tough_video_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "media.chromeOS.tough_video_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "media.chromeOS.tough_video_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "media.chromeOS.tough_video_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "media.chromeOS4kOnly.tough_video_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "media.chromeOS4kOnly.tough_video_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "media.chromeOS4kOnly.tough_video_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "media.chromeOS4kOnly.tough_video_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "media.media_cns_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "media.media_cns_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "media.media_cns_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "media.media_cns_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "media.mse_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "media.mse_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "media.mse_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "media.mse_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "media.tough_video_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "media.tough_video_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "media.tough_video_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "media.tough_video_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "media.tough_video_cases_extra",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "media.tough_video_cases_extra",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "media.tough_video_cases_extra",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "media.tough_video_cases_extra.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "memory.blink_memory_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "memory.blink_memory_mobile",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "memory.blink_memory_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "memory.blink_memory_mobile.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "memory.dual_browser_test",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "memory.dual_browser_test",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "memory.dual_browser_test",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "memory.dual_browser_test.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "memory.long_running_dual_browser_test",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "memory.long_running_dual_browser_test",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "memory.long_running_dual_browser_test",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "memory.long_running_dual_browser_test.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "memory.long_running_idle_gmail_background_tbmv2",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "memory.long_running_idle_gmail_background_tbmv2",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "memory.long_running_idle_gmail_background_tbmv2",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "memory.long_running_idle_gmail_background_tbmv2.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "memory.long_running_idle_gmail_tbmv2",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "memory.long_running_idle_gmail_tbmv2",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "memory.long_running_idle_gmail_tbmv2",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "memory.long_running_idle_gmail_tbmv2.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "memory.top_10_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "memory.top_10_mobile",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "memory.top_10_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "memory.top_10_mobile.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "memory.top_10_mobile_stress",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "memory.top_10_mobile_stress",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "memory.top_10_mobile_stress",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "memory.top_10_mobile_stress.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "octane",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "octane",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "octane",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "octane.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "oilpan_gc_times.blink_perf_stress",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "oilpan_gc_times.blink_perf_stress",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "oilpan_gc_times.blink_perf_stress",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "oilpan_gc_times.blink_perf_stress.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "oilpan_gc_times.key_silk_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "oilpan_gc_times.key_silk_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "oilpan_gc_times.key_silk_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "oilpan_gc_times.key_silk_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "oilpan_gc_times.sync_scroll.key_mobile_sites_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "oilpan_gc_times.sync_scroll.key_mobile_sites_smooth",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "oilpan_gc_times.sync_scroll.key_mobile_sites_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "oilpan_gc_times.sync_scroll.key_mobile_sites_smooth.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "oilpan_gc_times.tough_animation_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "oilpan_gc_times.tough_animation_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "oilpan_gc_times.tough_animation_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "oilpan_gc_times.tough_animation_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "oortonline",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "oortonline",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "oortonline",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "oortonline.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "oortonline_tbmv2",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "oortonline_tbmv2",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "oortonline_tbmv2",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "oortonline_tbmv2.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.basic_oopif",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.basic_oopif",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.basic_oopif",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.basic_oopif.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.intl_ar_fa_he",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.intl_ar_fa_he",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.intl_ar_fa_he",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.intl_ar_fa_he.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.intl_es_fr_pt-BR",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.intl_es_fr_pt-BR",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.intl_es_fr_pt-BR",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.intl_es_fr_pt-BR.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
           "page_cycler_v2.intl_hi_ru",
           "-v",
           "--upload-results",
@@ -78,7 +4353,7 @@
           "dimension_sets": [
             {
               "android_devices": "1",
-              "id": "build245-m4--device2",
+              "id": "build245-m4--device7",
               "os": "Android",
               "pool": "Chrome-perf"
             }
@@ -107,6 +4382,34 @@
           "dimension_sets": [
             {
               "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.intl_ja_zh",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.intl_ja_zh",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
               "id": "build245-m4--device2",
               "os": "Android",
               "pool": "Chrome-perf"
@@ -119,6 +4422,2543 @@
       },
       {
         "args": [
+          "page_cycler_v2.intl_ja_zh",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.intl_ja_zh.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.intl_ko_th_vi",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.intl_ko_th_vi",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.intl_ko_th_vi",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.intl_ko_th_vi.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.top_10_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.top_10_mobile",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.top_10_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.top_10_mobile.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.tough_layout_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.tough_layout_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.tough_layout_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.tough_layout_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.typical_25",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.typical_25",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.typical_25",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.typical_25.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2_site_isolation.basic_oopif",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2_site_isolation.basic_oopif",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2_site_isolation.basic_oopif",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2_site_isolation.basic_oopif.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.android_acceptance",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.android_acceptance",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.android_acceptance",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.android_acceptance.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.gpu_rasterization.top_10",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.gpu_rasterization.top_10",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.gpu_rasterization.top_10",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.gpu_rasterization.top_10.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.gpu_rasterization.top_25",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.gpu_rasterization.top_25",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.gpu_rasterization.top_25",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.gpu_rasterization.top_25.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.gpu_rasterization.typical_10_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.gpu_rasterization.typical_10_mobile",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.gpu_rasterization.typical_10_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.gpu_rasterization.typical_10_mobile.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.steady_state",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.steady_state",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.steady_state",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.steady_state.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.top_10",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.top_10",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.top_10",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.top_10.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.top_25",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.top_25",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.top_25",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.top_25.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.tough_ad_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.tough_ad_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.tough_ad_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.tough_ad_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.trivial_pages",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.trivial_pages",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.trivial_pages",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.trivial_pages.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.typical_10_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.typical_10_mobile",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.typical_10_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.typical_10_mobile.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.typical_10_mobile_reload",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.typical_10_mobile_reload",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.typical_10_mobile_reload",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.typical_10_mobile_reload.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "rasterize_and_record_micro.key_mobile_sites",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "rasterize_and_record_micro.key_mobile_sites",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "rasterize_and_record_micro.key_mobile_sites",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "rasterize_and_record_micro.key_mobile_sites.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "rasterize_and_record_micro.key_silk_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "rasterize_and_record_micro.key_silk_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "rasterize_and_record_micro.key_silk_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "rasterize_and_record_micro.key_silk_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "rasterize_and_record_micro.partial_invalidation",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "rasterize_and_record_micro.partial_invalidation",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "rasterize_and_record_micro.partial_invalidation",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "rasterize_and_record_micro.partial_invalidation.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "rasterize_and_record_micro.polymer",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "rasterize_and_record_micro.polymer",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "rasterize_and_record_micro.polymer",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "rasterize_and_record_micro.polymer.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "rasterize_and_record_micro.top_25",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "rasterize_and_record_micro.top_25",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "rasterize_and_record_micro.top_25",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "rasterize_and_record_micro.top_25.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "repaint.gpu_rasterization.key_mobile_sites_repaint",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "repaint.gpu_rasterization.key_mobile_sites_repaint",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "repaint.gpu_rasterization.key_mobile_sites_repaint",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "repaint.gpu_rasterization.key_mobile_sites_repaint.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "repaint.key_mobile_sites_repaint",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "repaint.key_mobile_sites_repaint",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "repaint.key_mobile_sites_repaint",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "repaint.key_mobile_sites_repaint.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "robohornet_pro",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "robohornet_pro",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "robohornet_pro",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "robohornet_pro.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "scheduler.tough_scheduling_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "scheduler.tough_scheduling_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "scheduler.tough_scheduling_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "scheduler.tough_scheduling_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "service_worker.service_worker",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "service_worker.service_worker",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "service_worker.service_worker",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "service_worker.service_worker.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "service_worker.service_worker_micro_benchmark",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "service_worker.service_worker_micro_benchmark",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "service_worker.service_worker_micro_benchmark",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "service_worker.service_worker_micro_benchmark.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.desktop_tough_pinch_zoom_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.desktop_tough_pinch_zoom_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.desktop_tough_pinch_zoom_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.desktop_tough_pinch_zoom_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.gpu_rasterization.polymer",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.gpu_rasterization.polymer",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.gpu_rasterization.polymer",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.gpu_rasterization.polymer.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.gpu_rasterization.top_25_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.gpu_rasterization.top_25_smooth",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.gpu_rasterization.top_25_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.gpu_rasterization.top_25_smooth.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.gpu_rasterization.tough_filters_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.gpu_rasterization.tough_filters_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.gpu_rasterization.tough_filters_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.gpu_rasterization.tough_filters_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.gpu_rasterization.tough_path_rendering_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.gpu_rasterization.tough_path_rendering_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.gpu_rasterization.tough_path_rendering_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.gpu_rasterization.tough_path_rendering_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.gpu_rasterization.tough_pinch_zoom_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.gpu_rasterization.tough_pinch_zoom_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.gpu_rasterization.tough_scrolling_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.gpu_rasterization.tough_scrolling_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.gpu_rasterization_and_decoding.image_decoding_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.gpu_rasterization_and_decoding.image_decoding_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.gpu_rasterization_and_decoding.image_decoding_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.gpu_rasterization_and_decoding.image_decoding_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.image_decoding_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.image_decoding_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.image_decoding_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.image_decoding_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.key_desktop_move_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.key_desktop_move_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.key_desktop_move_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.key_desktop_move_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.key_mobile_sites_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.key_mobile_sites_smooth",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.key_mobile_sites_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.key_mobile_sites_smooth.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.key_silk_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.key_silk_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.key_silk_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.key_silk_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.maps",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.maps",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.maps",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.maps.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.pathological_mobile_sites",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.pathological_mobile_sites",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.pathological_mobile_sites",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.pathological_mobile_sites.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.scrolling_tough_ad_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.scrolling_tough_ad_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.scrolling_tough_ad_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.scrolling_tough_ad_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.simple_mobile_sites",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.simple_mobile_sites",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.simple_mobile_sites",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.simple_mobile_sites.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.sync_scroll.key_mobile_sites_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.sync_scroll.key_mobile_sites_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
           "smoothness.top_25_smooth",
           "-v",
           "--upload-results",
@@ -135,7 +6975,7 @@
           "dimension_sets": [
             {
               "android_devices": "1",
-              "id": "build245-m4--device3",
+              "id": "build245-m4--device7",
               "os": "Android",
               "pool": "Chrome-perf"
             }
@@ -164,6 +7004,205 @@
           "dimension_sets": [
             {
               "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_ad_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_ad_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_ad_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_ad_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_animation_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_animation_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_animation_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_animation_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_canvas_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_canvas_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_canvas_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_canvas_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_filters_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_filters_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
               "id": "build245-m4--device3",
               "os": "Android",
               "pool": "Chrome-perf"
@@ -176,6 +7215,1232 @@
       },
       {
         "args": [
+          "smoothness.tough_filters_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_filters_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_image_decode_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_image_decode_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_image_decode_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_image_decode_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_path_rendering_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_path_rendering_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_path_rendering_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_path_rendering_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_pinch_zoom_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_pinch_zoom_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_pinch_zoom_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_pinch_zoom_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_scrolling_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_scrolling_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_scrolling_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_scrolling_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_texture_upload_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_texture_upload_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_texture_upload_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_texture_upload_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_webgl_ad_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_webgl_ad_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_webgl_ad_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_webgl_ad_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_webgl_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_webgl_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_webgl_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_webgl_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "spaceport",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "spaceport",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "spaceport",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "spaceport.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "speedometer",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "speedometer",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "speedometer-ignition",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "speedometer-ignition",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "speedometer-ignition",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "speedometer-ignition.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "speedometer",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "speedometer.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "start_with_ext.cold.blank_page",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "start_with_ext.cold.blank_page",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "start_with_ext.cold.blank_page",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "start_with_ext.cold.blank_page.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "start_with_ext.warm.blank_page",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "start_with_ext.warm.blank_page",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "start_with_ext.warm.blank_page",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "start_with_ext.warm.blank_page.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "start_with_url.cold.startup_pages",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "start_with_url.cold.startup_pages",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "start_with_url.cold.startup_pages",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "start_with_url.cold.startup_pages.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "start_with_url.warm.startup_pages",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "start_with_url.warm.startup_pages",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "start_with_url.warm.startup_pages",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "start_with_url.warm.startup_pages.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "startup.cold.blank_page",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "startup.cold.blank_page",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "startup.cold.blank_page",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "startup.cold.blank_page.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "startup.large_profile.cold.blank_page",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "startup.large_profile.cold.blank_page",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "startup.large_profile.cold.blank_page",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "startup.large_profile.cold.blank_page.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "startup.large_profile.warm.blank_page",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "startup.large_profile.warm.blank_page",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "startup.large_profile.warm.blank_page",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "startup.large_profile.warm.blank_page.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "startup.warm.blank_page",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "startup.warm.blank_page",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "startup.warm.blank_page",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "startup.warm.blank_page.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "startup.warm.chrome_signin",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "startup.warm.chrome_signin",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "startup.warm.chrome_signin",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "startup.warm.chrome_signin.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "storage.indexeddb_endure",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "storage.indexeddb_endure",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "storage.indexeddb_endure",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "storage.indexeddb_endure.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "storage.indexeddb_endure_tracing",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "storage.indexeddb_endure_tracing",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "storage.indexeddb_endure_tracing",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "storage.indexeddb_endure_tracing.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
           "sunspider",
           "-v",
           "--upload-results",
@@ -192,7 +8457,7 @@
           "dimension_sets": [
             {
               "android_devices": "1",
-              "id": "build245-m4--device4",
+              "id": "build245-m4--device6",
               "os": "Android",
               "pool": "Chrome-perf"
             }
@@ -221,6 +8486,34 @@
           "dimension_sets": [
             {
               "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "system_health.common_desktop",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "system_health.common_desktop",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
               "id": "build245-m4--device4",
               "os": "Android",
               "pool": "Chrome-perf"
@@ -233,6 +8526,206 @@
       },
       {
         "args": [
+          "system_health.common_desktop",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "system_health.common_desktop.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "system_health.common_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "system_health.common_mobile",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "system_health.common_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "system_health.common_mobile.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "system_health.memory_desktop",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "system_health.memory_desktop",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "system_health.memory_desktop",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "system_health.memory_desktop.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "system_health.memory_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "system_health.memory_mobile",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "system_health.memory_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "system_health.memory_mobile.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
           "system_health.webview_startup",
           "-v",
           "--upload-results",
@@ -249,7 +8742,7 @@
           "dimension_sets": [
             {
               "android_devices": "1",
-              "id": "build245-m4--device5",
+              "id": "build245-m4--device7",
               "os": "Android",
               "pool": "Chrome-perf"
             }
@@ -278,6 +8771,2172 @@
           "dimension_sets": [
             {
               "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "system_health.webview_startup_multiprocess",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "system_health.webview_startup_multiprocess",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "system_health.webview_startup_multiprocess",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "system_health.webview_startup_multiprocess.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "tab_switching.five_blank_pages",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "tab_switching.five_blank_pages",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "tab_switching.five_blank_pages",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "tab_switching.five_blank_pages.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "tab_switching.top_10",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "tab_switching.top_10",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "tab_switching.top_10",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "tab_switching.top_10.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "tab_switching.tough_energy_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "tab_switching.tough_energy_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "tab_switching.tough_energy_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "tab_switching.tough_energy_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "tab_switching.tough_image_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "tab_switching.tough_image_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "tab_switching.tough_image_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "tab_switching.tough_image_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "tab_switching.typical_25",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "tab_switching.typical_25",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "tab_switching.typical_25",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "tab_switching.typical_25.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "text_selection.character",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "text_selection.character",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "text_selection.character",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "text_selection.character.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "text_selection.direction",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "text_selection.direction",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "text_selection.direction",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "text_selection.direction.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.key_hit_test_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.key_hit_test_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.key_hit_test_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.key_hit_test_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.key_idle_power_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.key_idle_power_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.key_idle_power_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.key_idle_power_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device7",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.key_mobile_sites_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.key_mobile_sites_smooth",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.key_mobile_sites_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.key_mobile_sites_smooth.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.key_noop_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.key_noop_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.key_noop_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.key_noop_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.key_silk_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.key_silk_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.key_silk_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.key_silk_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.polymer",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.polymer",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.polymer",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.polymer.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.simple_mobile_sites",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.simple_mobile_sites",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.simple_mobile_sites",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.simple_mobile_sites.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.tough_compositor_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.tough_compositor_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.tough_compositor_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.tough_compositor_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.tough_scrolling_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.tough_scrolling_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.tough_scrolling_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.tough_scrolling_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "tracing.tracing_with_background_memory_infra",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "tracing.tracing_with_background_memory_infra",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "tracing.tracing_with_background_memory_infra",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "tracing.tracing_with_background_memory_infra.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "tracing.tracing_with_debug_overhead",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "tracing.tracing_with_debug_overhead",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "tracing.tracing_with_debug_overhead",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "tracing.tracing_with_debug_overhead.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.browsing_desktop",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.browsing_desktop",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.browsing_desktop",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.browsing_desktop.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.browsing_desktop_ignition",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.browsing_desktop_ignition",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.browsing_desktop_ignition",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.browsing_desktop_ignition.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.browsing_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.browsing_mobile",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.browsing_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.browsing_mobile.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.browsing_mobile_ignition",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.browsing_mobile_ignition",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.browsing_mobile_ignition",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.browsing_mobile_ignition.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.detached_context_age_in_gc",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.detached_context_age_in_gc",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.detached_context_age_in_gc",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.detached_context_age_in_gc.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device4",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.google",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.google",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.google",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.google.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.infinite_scroll-ignition_tbmv2",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.infinite_scroll-ignition_tbmv2",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.infinite_scroll-ignition_tbmv2",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.infinite_scroll-ignition_tbmv2.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.infinite_scroll_tbmv2",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.infinite_scroll_tbmv2",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.infinite_scroll_tbmv2",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.infinite_scroll_tbmv2.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.key_mobile_sites_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.key_mobile_sites_smooth",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.key_mobile_sites_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.key_mobile_sites_smooth.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.mobile_infinite_scroll_tbmv2",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.mobile_infinite_scroll_tbmv2",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.mobile_infinite_scroll_tbmv2",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.mobile_infinite_scroll_tbmv2.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.runtime_stats.top_25",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.runtime_stats.top_25",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.runtime_stats.top_25",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.runtime_stats.top_25.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.todomvc",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.todomvc",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.todomvc-ignition",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.todomvc-ignition",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.todomvc-ignition",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.todomvc-ignition.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device3",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.todomvc",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.todomvc.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.top_25_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.top_25_smooth",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.top_25_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.top_25_smooth.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "webrtc.datachannel",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "webrtc.datachannel",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "webrtc.datachannel",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "webrtc.datachannel.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device2",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "webrtc.getusermedia",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "webrtc.getusermedia",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "webrtc.getusermedia",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "webrtc.getusermedia.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "webrtc.peerconnection",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "webrtc.peerconnection",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "webrtc.peerconnection",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "webrtc.peerconnection.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device6",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "webrtc.stress",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "webrtc.stress",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "webrtc.stress",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "webrtc.stress.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device1",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "webrtc.webrtc_smoothness",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=android-chromium"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "webrtc.webrtc_smoothness",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
+              "id": "build245-m4--device5",
+              "os": "Android",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "webrtc.webrtc_smoothness",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "webrtc.webrtc_smoothness.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "android_devices": "1",
               "id": "build245-m4--device5",
               "os": "Android",
               "pool": "Chrome-perf"
@@ -301,7 +10960,1375 @@
           "dimension_sets": [
             {
               "gpu": "8086:22b1",
-              "id": "build48-b4",
+              "id": "build137-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "battor.power_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "battor.power_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build148-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "battor.power_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "battor.power_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build148-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "battor.power_cases_no_chrome_trace",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "battor.power_cases_no_chrome_trace",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build145-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "battor.power_cases_no_chrome_trace",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "battor.power_cases_no_chrome_trace.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build145-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "battor.steady_state",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "battor.steady_state",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build149-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "battor.steady_state",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "battor.steady_state.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build149-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "battor.tough_video_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "battor.tough_video_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build146-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "battor.tough_video_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "battor.tough_video_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build146-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "battor.trivial_pages",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "battor.trivial_pages",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build142-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "battor.trivial_pages",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "battor.trivial_pages.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build142-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.bindings",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.bindings",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build47-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.bindings",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.bindings.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build47-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.blink_gc",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.blink_gc",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build142-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.blink_gc",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.blink_gc.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build142-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.canvas",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.canvas",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build47-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.canvas",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.canvas.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build47-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.css",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.css",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build154-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.css",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.css.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build154-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.dom",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.dom",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build145-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.dom",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.dom.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build145-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.events",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.events",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build141-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.events",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.events.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build141-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.layout",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.layout",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build143-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.layout",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.layout.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build143-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.paint",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.paint",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build146-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.paint",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.paint.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build146-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.paint_slimmingpaintinvalidation",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.paint_slimmingpaintinvalidation",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build144-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.paint_slimmingpaintinvalidation",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.paint_slimmingpaintinvalidation.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build144-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.parser",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.parser",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build155-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.parser",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.parser.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build155-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.pywebsocket",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.pywebsocket",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build149-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.pywebsocket",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.pywebsocket.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build149-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.shadow_dom",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.shadow_dom",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build148-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.shadow_dom",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.shadow_dom.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build148-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.svg",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.svg",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build151-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.svg",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.svg.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build151-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.svg_slimmingpaintinvalidation",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.svg_slimmingpaintinvalidation",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build146-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.svg_slimmingpaintinvalidation",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.svg_slimmingpaintinvalidation.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build146-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.xml_http_request",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.xml_http_request",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build141-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_perf.xml_http_request",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_perf.xml_http_request.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build141-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_style.key_mobile_sites",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_style.key_mobile_sites",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build155-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_style.key_mobile_sites",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_style.key_mobile_sites.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build155-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_style.polymer",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_style.polymer",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build138-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_style.polymer",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_style.polymer.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build138-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_style.top_25",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_style.top_25",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build151-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blink_style.top_25",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blink_style.top_25.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build151-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blob_storage.blob_storage",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blob_storage.blob_storage",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build145-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "blob_storage.blob_storage",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "blob_storage.blob_storage.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build145-b1",
               "os": "Windows-10-10586",
               "pool": "Chrome-perf"
             }
@@ -320,7 +12347,7 @@
           "dimension_sets": [
             {
               "gpu": "8086:22b1",
-              "id": "build47-b4",
+              "id": "build136-b1",
               "os": "Windows-10-10586",
               "pool": "Chrome-perf"
             }
@@ -388,6 +12415,918 @@
         }
       },
       {
+        "args": [
+          "dromaeo.domcoreattr",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.domcoreattr",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build151-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.domcoreattr",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.domcoreattr.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build151-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.domcoremodify",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.domcoremodify",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build150-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.domcoremodify",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.domcoremodify.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build150-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.domcorequery",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.domcorequery",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build143-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.domcorequery",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.domcorequery.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build143-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.domcoretraverse",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.domcoretraverse",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build144-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.domcoretraverse",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.domcoretraverse.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build144-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibattrjquery",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibattrjquery",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build154-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibattrjquery",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibattrjquery.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build154-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibattrprototype",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibattrprototype",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build155-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibattrprototype",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibattrprototype.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build155-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibeventjquery",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibeventjquery",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build148-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibeventjquery",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibeventjquery.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build148-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibeventprototype",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibeventprototype",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build148-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibeventprototype",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibeventprototype.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build148-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibmodifyjquery",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibmodifyjquery",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build48-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibmodifyjquery",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibmodifyjquery.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build48-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibmodifyprototype",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibmodifyprototype",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build151-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibmodifyprototype",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibmodifyprototype.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build151-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibstylejquery",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibstylejquery",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build144-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibstylejquery",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibstylejquery.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build144-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibstyleprototype",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibstyleprototype",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build47-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibstyleprototype",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibstyleprototype.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build47-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibtraversejquery",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibtraversejquery",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build155-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibtraversejquery",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibtraversejquery.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build155-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibtraverseprototype",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibtraverseprototype",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build145-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dromaeo.jslibtraverseprototype",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dromaeo.jslibtraverseprototype.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build145-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dummy_benchmark.noisy_benchmark_1",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dummy_benchmark.noisy_benchmark_1",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build47-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dummy_benchmark.noisy_benchmark_1",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dummy_benchmark.noisy_benchmark_1.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build47-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dummy_benchmark.stable_benchmark_1",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dummy_benchmark.stable_benchmark_1",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build47-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "dummy_benchmark.stable_benchmark_1",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "dummy_benchmark.stable_benchmark_1.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build47-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
         "args": [],
         "isolate_name": "gpu_perftests",
         "name": "gpu_perftests",
@@ -396,7 +13335,520 @@
           "dimension_sets": [
             {
               "gpu": "8086:22b1",
-              "id": "build47-b4",
+              "id": "build136-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "gpu_times.gpu_rasterization.key_mobile_sites_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "gpu_times.gpu_rasterization.key_mobile_sites_smooth",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build153-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "gpu_times.gpu_rasterization.key_mobile_sites_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "gpu_times.gpu_rasterization.key_mobile_sites_smooth.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build153-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "gpu_times.gpu_rasterization.top_25_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "gpu_times.gpu_rasterization.top_25_smooth",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build155-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "gpu_times.gpu_rasterization.top_25_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "gpu_times.gpu_rasterization.top_25_smooth.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build155-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "gpu_times.key_mobile_sites_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "gpu_times.key_mobile_sites_smooth",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build146-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "gpu_times.key_mobile_sites_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "gpu_times.key_mobile_sites_smooth.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build146-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "gpu_times.top_25_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "gpu_times.top_25_smooth",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build141-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "gpu_times.top_25_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "gpu_times.top_25_smooth.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build141-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "image_decoding.image_decoding_measurement",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "image_decoding.image_decoding_measurement",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build147-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "image_decoding.image_decoding_measurement",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "image_decoding.image_decoding_measurement.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build147-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "indexeddb_perf",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "indexeddb_perf",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build154-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "indexeddb_perf",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "indexeddb_perf.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build154-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "jetstream",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "jetstream",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build154-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "jetstream",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "jetstream.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build154-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "jitter",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "jitter",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build150-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "jitter",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "jitter.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build150-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "kraken",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "kraken",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build146-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "kraken",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "kraken.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build146-b1",
               "os": "Windows-10-10586",
               "pool": "Chrome-perf"
             }
@@ -415,6 +13867,889 @@
           "dimension_sets": [
             {
               "gpu": "8086:22b1",
+              "id": "build136-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "loading.cluster_telemetry",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "loading.cluster_telemetry",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build138-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "loading.cluster_telemetry",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "loading.cluster_telemetry.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build138-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "loading.mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "loading.mobile",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build48-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "loading.mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "loading.mobile.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build48-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "media.android.tough_video_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "media.android.tough_video_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build142-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "media.android.tough_video_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "media.android.tough_video_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build142-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "media.chromeOS.tough_video_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "media.chromeOS.tough_video_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build141-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "media.chromeOS.tough_video_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "media.chromeOS.tough_video_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build141-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "media.chromeOS4kOnly.tough_video_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "media.chromeOS4kOnly.tough_video_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build148-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "media.chromeOS4kOnly.tough_video_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "media.chromeOS4kOnly.tough_video_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build148-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "media.media_cns_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "media.media_cns_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build153-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "media.media_cns_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "media.media_cns_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build153-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "media.mse_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "media.mse_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build143-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "media.mse_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "media.mse_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build143-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "media.tough_video_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "media.tough_video_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build147-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "media.tough_video_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "media.tough_video_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build147-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "media.tough_video_cases_extra",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "media.tough_video_cases_extra",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build142-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "media.tough_video_cases_extra",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "media.tough_video_cases_extra.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build142-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "memory.blink_memory_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "memory.blink_memory_mobile",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build137-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "memory.blink_memory_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "memory.blink_memory_mobile.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build137-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "memory.dual_browser_test",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "memory.dual_browser_test",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build138-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "memory.dual_browser_test",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "memory.dual_browser_test.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build138-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "memory.long_running_dual_browser_test",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "memory.long_running_dual_browser_test",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build143-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "memory.long_running_dual_browser_test",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "memory.long_running_dual_browser_test.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build143-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "memory.long_running_idle_gmail_background_tbmv2",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "memory.long_running_idle_gmail_background_tbmv2",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build152-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "memory.long_running_idle_gmail_background_tbmv2",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "memory.long_running_idle_gmail_background_tbmv2.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build152-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "memory.long_running_idle_gmail_tbmv2",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "memory.long_running_idle_gmail_tbmv2",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build140-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "memory.long_running_idle_gmail_tbmv2",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "memory.long_running_idle_gmail_tbmv2.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build140-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "memory.top_10_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "memory.top_10_mobile",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build155-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "memory.top_10_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "memory.top_10_mobile.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build155-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "memory.top_10_mobile_stress",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "memory.top_10_mobile_stress",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
               "id": "build47-b4",
               "os": "Windows-10-10586",
               "pool": "Chrome-perf"
@@ -427,6 +14762,605 @@
       },
       {
         "args": [
+          "memory.top_10_mobile_stress",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "memory.top_10_mobile_stress.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build47-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "octane",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "octane",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build142-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "octane",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "octane.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build142-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "oilpan_gc_times.blink_perf_stress",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "oilpan_gc_times.blink_perf_stress",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build152-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "oilpan_gc_times.blink_perf_stress",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "oilpan_gc_times.blink_perf_stress.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build152-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "oilpan_gc_times.key_silk_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "oilpan_gc_times.key_silk_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build141-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "oilpan_gc_times.key_silk_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "oilpan_gc_times.key_silk_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build141-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "oilpan_gc_times.sync_scroll.key_mobile_sites_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "oilpan_gc_times.sync_scroll.key_mobile_sites_smooth",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build47-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "oilpan_gc_times.sync_scroll.key_mobile_sites_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "oilpan_gc_times.sync_scroll.key_mobile_sites_smooth.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build47-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "oilpan_gc_times.tough_animation_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "oilpan_gc_times.tough_animation_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build150-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "oilpan_gc_times.tough_animation_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "oilpan_gc_times.tough_animation_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build150-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "oortonline",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "oortonline",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build155-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "oortonline",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "oortonline.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build155-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "oortonline_tbmv2",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "oortonline_tbmv2",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build140-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "oortonline_tbmv2",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "oortonline_tbmv2.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build140-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.basic_oopif",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.basic_oopif",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build150-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.basic_oopif",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.basic_oopif.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build150-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.intl_ar_fa_he",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.intl_ar_fa_he",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build147-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.intl_ar_fa_he",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.intl_ar_fa_he.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build147-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.intl_es_fr_pt-BR",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.intl_es_fr_pt-BR",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build145-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.intl_es_fr_pt-BR",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.intl_es_fr_pt-BR.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build145-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
           "page_cycler_v2.intl_hi_ru",
           "-v",
           "--upload-results",
@@ -443,7 +15377,7 @@
           "dimension_sets": [
             {
               "gpu": "8086:22b1",
-              "id": "build48-b4",
+              "id": "build143-b1",
               "os": "Windows-10-10586",
               "pool": "Chrome-perf"
             }
@@ -472,6 +15406,148 @@
           "dimension_sets": [
             {
               "gpu": "8086:22b1",
+              "id": "build143-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.intl_ja_zh",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.intl_ja_zh",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build137-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.intl_ja_zh",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.intl_ja_zh.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build137-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.intl_ko_th_vi",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.intl_ko_th_vi",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build141-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.intl_ko_th_vi",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.intl_ko_th_vi.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build141-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.top_10_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.top_10_mobile",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
               "id": "build48-b4",
               "os": "Windows-10-10586",
               "pool": "Chrome-perf"
@@ -483,6 +15559,206 @@
         }
       },
       {
+        "args": [
+          "page_cycler_v2.top_10_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.top_10_mobile.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build48-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.tough_layout_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.tough_layout_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build148-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.tough_layout_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.tough_layout_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build148-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.typical_25",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.typical_25",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build138-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2.typical_25",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2.typical_25.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build138-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2_site_isolation.basic_oopif",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2_site_isolation.basic_oopif",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build149-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "page_cycler_v2_site_isolation.basic_oopif",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "page_cycler_v2_site_isolation.basic_oopif.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build149-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
         "args": [],
         "isolate_name": "performance_browser_tests",
         "name": "performance_browser_tests",
@@ -491,6 +15767,547 @@
           "dimension_sets": [
             {
               "gpu": "8086:22b1",
+              "id": "build137-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.android_acceptance",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.android_acceptance",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build153-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.android_acceptance",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.android_acceptance.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build153-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.gpu_rasterization.top_10",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.gpu_rasterization.top_10",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build154-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.gpu_rasterization.top_10",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.gpu_rasterization.top_10.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build154-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.gpu_rasterization.top_25",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.gpu_rasterization.top_25",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build151-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.gpu_rasterization.top_25",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.gpu_rasterization.top_25.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build151-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.gpu_rasterization.typical_10_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.gpu_rasterization.typical_10_mobile",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build136-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.gpu_rasterization.typical_10_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.gpu_rasterization.typical_10_mobile.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build136-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.steady_state",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.steady_state",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build152-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.steady_state",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.steady_state.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build152-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.top_10",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.top_10",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build152-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.top_10",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.top_10.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build152-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.top_25",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.top_25",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build152-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.top_25",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.top_25.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build152-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.tough_ad_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.tough_ad_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build153-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.tough_ad_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.tough_ad_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build153-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.trivial_pages",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.trivial_pages",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build155-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.trivial_pages",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.trivial_pages.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build155-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.typical_10_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.typical_10_mobile",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
               "id": "build48-b4",
               "os": "Windows-10-10586",
               "pool": "Chrome-perf"
@@ -503,6 +16320,1688 @@
       },
       {
         "args": [
+          "power.typical_10_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.typical_10_mobile.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build48-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.typical_10_mobile_reload",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.typical_10_mobile_reload",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build155-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "power.typical_10_mobile_reload",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "power.typical_10_mobile_reload.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build155-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "rasterize_and_record_micro.key_mobile_sites",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "rasterize_and_record_micro.key_mobile_sites",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build154-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "rasterize_and_record_micro.key_mobile_sites",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "rasterize_and_record_micro.key_mobile_sites.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build154-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "rasterize_and_record_micro.key_silk_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "rasterize_and_record_micro.key_silk_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build136-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "rasterize_and_record_micro.key_silk_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "rasterize_and_record_micro.key_silk_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build136-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "rasterize_and_record_micro.partial_invalidation",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "rasterize_and_record_micro.partial_invalidation",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build152-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "rasterize_and_record_micro.partial_invalidation",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "rasterize_and_record_micro.partial_invalidation.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build152-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "rasterize_and_record_micro.polymer",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "rasterize_and_record_micro.polymer",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build140-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "rasterize_and_record_micro.polymer",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "rasterize_and_record_micro.polymer.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build140-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "rasterize_and_record_micro.top_25",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "rasterize_and_record_micro.top_25",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build150-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "rasterize_and_record_micro.top_25",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "rasterize_and_record_micro.top_25.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build150-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "repaint.gpu_rasterization.key_mobile_sites_repaint",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "repaint.gpu_rasterization.key_mobile_sites_repaint",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build151-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "repaint.gpu_rasterization.key_mobile_sites_repaint",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "repaint.gpu_rasterization.key_mobile_sites_repaint.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build151-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "repaint.key_mobile_sites_repaint",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "repaint.key_mobile_sites_repaint",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build147-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "repaint.key_mobile_sites_repaint",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "repaint.key_mobile_sites_repaint.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build147-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "robohornet_pro",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "robohornet_pro",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build142-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "robohornet_pro",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "robohornet_pro.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build142-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "scheduler.tough_scheduling_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "scheduler.tough_scheduling_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build151-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "scheduler.tough_scheduling_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "scheduler.tough_scheduling_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build151-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "service_worker.service_worker",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "service_worker.service_worker",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build149-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "service_worker.service_worker",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "service_worker.service_worker.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build149-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "service_worker.service_worker_micro_benchmark",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "service_worker.service_worker_micro_benchmark",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build48-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "service_worker.service_worker_micro_benchmark",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "service_worker.service_worker_micro_benchmark.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build48-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.desktop_tough_pinch_zoom_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.desktop_tough_pinch_zoom_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build153-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.desktop_tough_pinch_zoom_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.desktop_tough_pinch_zoom_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build153-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.gpu_rasterization.polymer",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.gpu_rasterization.polymer",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build137-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.gpu_rasterization.polymer",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.gpu_rasterization.polymer.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build137-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.gpu_rasterization.top_25_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.gpu_rasterization.top_25_smooth",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build145-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.gpu_rasterization.top_25_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.gpu_rasterization.top_25_smooth.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build145-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.gpu_rasterization.tough_filters_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.gpu_rasterization.tough_filters_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build141-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.gpu_rasterization.tough_filters_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.gpu_rasterization.tough_filters_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build141-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.gpu_rasterization.tough_path_rendering_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.gpu_rasterization.tough_path_rendering_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build48-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.gpu_rasterization.tough_path_rendering_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.gpu_rasterization.tough_path_rendering_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build48-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.gpu_rasterization.tough_pinch_zoom_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build146-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.gpu_rasterization.tough_pinch_zoom_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build146-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.gpu_rasterization.tough_scrolling_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build140-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.gpu_rasterization.tough_scrolling_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build140-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.gpu_rasterization_and_decoding.image_decoding_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.gpu_rasterization_and_decoding.image_decoding_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build140-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.gpu_rasterization_and_decoding.image_decoding_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.gpu_rasterization_and_decoding.image_decoding_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build140-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.image_decoding_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.image_decoding_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build147-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.image_decoding_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.image_decoding_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build147-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.key_desktop_move_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.key_desktop_move_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build152-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.key_desktop_move_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.key_desktop_move_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build152-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.key_mobile_sites_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.key_mobile_sites_smooth",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build142-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.key_mobile_sites_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.key_mobile_sites_smooth.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build142-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.key_silk_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.key_silk_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build142-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.key_silk_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.key_silk_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build142-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.maps",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.maps",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build138-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.maps",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.maps.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build138-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.pathological_mobile_sites",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.pathological_mobile_sites",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build145-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.pathological_mobile_sites",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.pathological_mobile_sites.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build145-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.scrolling_tough_ad_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.scrolling_tough_ad_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build144-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.scrolling_tough_ad_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.scrolling_tough_ad_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build144-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.simple_mobile_sites",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.simple_mobile_sites",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build136-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.simple_mobile_sites",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.simple_mobile_sites.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build136-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.sync_scroll.key_mobile_sites_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build47-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.sync_scroll.key_mobile_sites_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build47-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
           "smoothness.top_25_smooth",
           "-v",
           "--upload-results",
@@ -519,7 +18018,7 @@
           "dimension_sets": [
             {
               "gpu": "8086:22b1",
-              "id": "build47-b4",
+              "id": "build148-b1",
               "os": "Windows-10-10586",
               "pool": "Chrome-perf"
             }
@@ -548,6 +18047,1060 @@
           "dimension_sets": [
             {
               "gpu": "8086:22b1",
+              "id": "build148-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_ad_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_ad_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build148-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_ad_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_ad_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build148-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_animation_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_animation_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build140-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_animation_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_animation_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build140-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_canvas_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_canvas_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build48-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_canvas_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_canvas_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build48-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_filters_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_filters_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build146-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_filters_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_filters_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build146-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_image_decode_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_image_decode_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build140-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_image_decode_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_image_decode_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build140-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_path_rendering_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_path_rendering_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build153-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_path_rendering_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_path_rendering_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build153-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_pinch_zoom_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_pinch_zoom_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build141-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_pinch_zoom_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_pinch_zoom_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build141-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_scrolling_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_scrolling_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build153-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_scrolling_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_scrolling_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build153-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_texture_upload_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_texture_upload_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build143-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_texture_upload_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_texture_upload_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build143-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_webgl_ad_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_webgl_ad_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build146-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_webgl_ad_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_webgl_ad_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build146-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_webgl_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_webgl_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build149-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "smoothness.tough_webgl_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "smoothness.tough_webgl_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build149-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "spaceport",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "spaceport",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build155-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "spaceport",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "spaceport.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build155-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "speedometer",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "speedometer",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build147-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "speedometer-ignition",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "speedometer-ignition",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build153-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "speedometer-ignition",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "speedometer-ignition.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build153-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "speedometer",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "speedometer.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build147-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "start_with_ext.cold.blank_page",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "start_with_ext.cold.blank_page",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build152-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "start_with_ext.cold.blank_page",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "start_with_ext.cold.blank_page.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build152-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "start_with_ext.warm.blank_page",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "start_with_ext.warm.blank_page",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build149-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "start_with_ext.warm.blank_page",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "start_with_ext.warm.blank_page.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build149-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "start_with_url.cold.startup_pages",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "start_with_url.cold.startup_pages",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build140-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "start_with_url.cold.startup_pages",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "start_with_url.cold.startup_pages.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build140-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "start_with_url.warm.startup_pages",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "start_with_url.warm.startup_pages",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build143-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "start_with_url.warm.startup_pages",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "start_with_url.warm.startup_pages.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build143-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "startup.cold.blank_page",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "startup.cold.blank_page",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
               "id": "build47-b4",
               "os": "Windows-10-10586",
               "pool": "Chrome-perf"
@@ -560,6 +19113,377 @@
       },
       {
         "args": [
+          "startup.cold.blank_page",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "startup.cold.blank_page.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build47-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "startup.large_profile.cold.blank_page",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "startup.large_profile.cold.blank_page",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build144-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "startup.large_profile.cold.blank_page",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "startup.large_profile.cold.blank_page.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build144-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "startup.large_profile.warm.blank_page",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "startup.large_profile.warm.blank_page",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build150-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "startup.large_profile.warm.blank_page",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "startup.large_profile.warm.blank_page.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build150-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "startup.warm.blank_page",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "startup.warm.blank_page",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build150-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "startup.warm.blank_page",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "startup.warm.blank_page.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build150-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "startup.warm.chrome_signin",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "startup.warm.chrome_signin",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build48-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "startup.warm.chrome_signin",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "startup.warm.chrome_signin.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build48-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "storage.indexeddb_endure",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "storage.indexeddb_endure",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build143-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "storage.indexeddb_endure",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "storage.indexeddb_endure.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build143-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "storage.indexeddb_endure_tracing",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "storage.indexeddb_endure_tracing",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build142-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "storage.indexeddb_endure_tracing",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "storage.indexeddb_endure_tracing.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build142-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
           "sunspider",
           "-v",
           "--upload-results",
@@ -576,7 +19500,7 @@
           "dimension_sets": [
             {
               "gpu": "8086:22b1",
-              "id": "build48-b4",
+              "id": "build153-b1",
               "os": "Windows-10-10586",
               "pool": "Chrome-perf"
             }
@@ -605,7 +19529,235 @@
           "dimension_sets": [
             {
               "gpu": "8086:22b1",
-              "id": "build48-b4",
+              "id": "build153-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "system_health.common_desktop",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "system_health.common_desktop",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build139-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "system_health.common_desktop",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "system_health.common_desktop.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build139-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "system_health.common_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "system_health.common_mobile",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build139-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "system_health.common_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "system_health.common_mobile.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build139-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "system_health.memory_desktop",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "system_health.memory_desktop",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build136-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "system_health.memory_desktop",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "system_health.memory_desktop.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build136-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "system_health.memory_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "system_health.memory_mobile",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build147-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "system_health.memory_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "system_health.memory_mobile.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build147-b1",
               "os": "Windows-10-10586",
               "pool": "Chrome-perf"
             }
@@ -633,7 +19785,7 @@
           "dimension_sets": [
             {
               "gpu": "8086:22b1",
-              "id": "build47-b4",
+              "id": "build140-b1",
               "os": "Windows-10-10586",
               "pool": "Chrome-perf"
             }
@@ -662,6 +19814,604 @@
           "dimension_sets": [
             {
               "gpu": "8086:22b1",
+              "id": "build140-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "system_health.webview_startup_multiprocess",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "system_health.webview_startup_multiprocess",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build139-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "system_health.webview_startup_multiprocess",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "system_health.webview_startup_multiprocess.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build139-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "tab_switching.five_blank_pages",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "tab_switching.five_blank_pages",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build48-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "tab_switching.five_blank_pages",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "tab_switching.five_blank_pages.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build48-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "tab_switching.top_10",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "tab_switching.top_10",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build144-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "tab_switching.top_10",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "tab_switching.top_10.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build144-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "tab_switching.tough_energy_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "tab_switching.tough_energy_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build155-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "tab_switching.tough_energy_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "tab_switching.tough_energy_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build155-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "tab_switching.tough_image_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "tab_switching.tough_image_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build142-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "tab_switching.tough_image_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "tab_switching.tough_image_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build142-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "tab_switching.typical_25",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "tab_switching.typical_25",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build155-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "tab_switching.typical_25",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "tab_switching.typical_25.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build155-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "text_selection.character",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "text_selection.character",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build147-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "text_selection.character",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "text_selection.character.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build147-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "text_selection.direction",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "text_selection.direction",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build146-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "text_selection.direction",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "text_selection.direction.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build146-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.key_hit_test_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.key_hit_test_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build145-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.key_hit_test_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.key_hit_test_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build145-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.key_idle_power_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.key_idle_power_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build151-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.key_idle_power_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.key_idle_power_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build151-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.key_mobile_sites_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.key_mobile_sites_smooth",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
               "id": "build47-b4",
               "os": "Windows-10-10586",
               "pool": "Chrome-perf"
@@ -673,6 +20423,491 @@
         }
       },
       {
+        "args": [
+          "thread_times.key_mobile_sites_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.key_mobile_sites_smooth.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build47-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.key_noop_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.key_noop_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build143-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.key_noop_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.key_noop_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build143-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.key_silk_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.key_silk_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build155-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.key_silk_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.key_silk_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build155-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.polymer",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.polymer",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build140-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.polymer",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.polymer.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build140-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.simple_mobile_sites",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.simple_mobile_sites",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build150-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.simple_mobile_sites",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.simple_mobile_sites.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build150-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.tough_compositor_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.tough_compositor_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build141-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.tough_compositor_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.tough_compositor_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build141-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.tough_scrolling_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.tough_scrolling_cases",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build47-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "thread_times.tough_scrolling_cases",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "thread_times.tough_scrolling_cases.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build47-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "tracing.tracing_with_background_memory_infra",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "tracing.tracing_with_background_memory_infra",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build151-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "tracing.tracing_with_background_memory_infra",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "tracing.tracing_with_background_memory_infra.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build151-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "tracing.tracing_with_debug_overhead",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "tracing.tracing_with_debug_overhead",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build145-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "tracing.tracing_with_debug_overhead",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "tracing.tracing_with_debug_overhead.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build145-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
         "args": [],
         "isolate_name": "tracing_perftests",
         "name": "tracing_perftests",
@@ -681,6 +20916,689 @@
           "dimension_sets": [
             {
               "gpu": "8086:22b1",
+              "id": "build137-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.browsing_desktop",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.browsing_desktop",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build153-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.browsing_desktop",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.browsing_desktop.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build153-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.browsing_desktop_ignition",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.browsing_desktop_ignition",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build154-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.browsing_desktop_ignition",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.browsing_desktop_ignition.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build154-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.browsing_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.browsing_mobile",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build155-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.browsing_mobile",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.browsing_mobile.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build155-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.browsing_mobile_ignition",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.browsing_mobile_ignition",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build143-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.browsing_mobile_ignition",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.browsing_mobile_ignition.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build143-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.detached_context_age_in_gc",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.detached_context_age_in_gc",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build139-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.detached_context_age_in_gc",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.detached_context_age_in_gc.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build139-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.google",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.google",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build147-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.google",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.google.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build147-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.infinite_scroll-ignition_tbmv2",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.infinite_scroll-ignition_tbmv2",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build144-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.infinite_scroll-ignition_tbmv2",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.infinite_scroll-ignition_tbmv2.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build144-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.infinite_scroll_tbmv2",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.infinite_scroll_tbmv2",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build146-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.infinite_scroll_tbmv2",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.infinite_scroll_tbmv2.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build146-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.key_mobile_sites_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.key_mobile_sites_smooth",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build145-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.key_mobile_sites_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.key_mobile_sites_smooth.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build145-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.mobile_infinite_scroll_tbmv2",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.mobile_infinite_scroll_tbmv2",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build138-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.mobile_infinite_scroll_tbmv2",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.mobile_infinite_scroll_tbmv2.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build138-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.runtime_stats.top_25",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.runtime_stats.top_25",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build147-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.runtime_stats.top_25",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.runtime_stats.top_25.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build147-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.todomvc",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.todomvc",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build147-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.todomvc-ignition",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.todomvc-ignition",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
               "id": "build48-b4",
               "os": "Windows-10-10586",
               "pool": "Chrome-perf"
@@ -690,6 +21608,406 @@
           "hard_timeout": 7200,
           "io_timeout": 3600
         }
+      },
+      {
+        "args": [
+          "v8.todomvc-ignition",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.todomvc-ignition.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build48-b4",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.todomvc",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.todomvc.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build147-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.top_25_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.top_25_smooth",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build149-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "v8.top_25_smooth",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "v8.top_25_smooth.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build149-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "webrtc.datachannel",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "webrtc.datachannel",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build149-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "webrtc.datachannel",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "webrtc.datachannel.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build149-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "webrtc.getusermedia",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "webrtc.getusermedia",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build141-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "webrtc.getusermedia",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "webrtc.getusermedia.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build141-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "webrtc.peerconnection",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "webrtc.peerconnection",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build149-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "webrtc.peerconnection",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "webrtc.peerconnection.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build149-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "webrtc.stress",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "webrtc.stress",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build146-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "webrtc.stress",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "webrtc.stress.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build146-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "webrtc.webrtc_smoothness",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=release_x64"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "webrtc.webrtc_smoothness",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build152-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
+        "args": [
+          "webrtc.webrtc_smoothness",
+          "-v",
+          "--upload-results",
+          "--output-format=chartjson",
+          "--browser=reference",
+          "--output-trace-tag=_ref"
+        ],
+        "isolate_name": "telemetry_perf_tests",
+        "name": "webrtc.webrtc_smoothness.reference",
+        "override_compile_targets": [
+          "telemetry_perf_tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:22b1",
+              "id": "build152-b1",
+              "os": "Windows-10-10586",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
       }
     ]
   },
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
index 819718f6..d956eac 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
@@ -2159,9 +2159,8 @@
 Bug(none) fast/overflow/overflow-float-stacking.html [ Failure ]
 Bug(none) fast/overflow/overflow-stacking.html [ Failure ]
 
-# Paint property under-invalidation for clip changes needs investigation.
-crbug.com/645667 compositing/clip-change.html [ Failure ]
-crbug.com/645667 compositing/layer-creation/iframe-clip-removed.html [ Failure ]
+# Need to write SPv2 version of this code.
+crbug.com/157218 compositing/overflow/border-radius-styles-with-composited-child.html [ Failure ]
 
 # Notes about rebaselined tests:
 #
diff --git a/third_party/WebKit/LayoutTests/RandomOrderExpectations b/third_party/WebKit/LayoutTests/RandomOrderExpectations
index d9e8734d..cd4b977 100644
--- a/third_party/WebKit/LayoutTests/RandomOrderExpectations
+++ b/third_party/WebKit/LayoutTests/RandomOrderExpectations
@@ -20,7 +20,7 @@
 crbug.com/663849 fast/events/mouse-cursor.html [ Pass Failure ]
 crbug.com/663851 fast/events/onload-re-entry.html [ Pass Failure ]
 crbug.com/663853 fast/scroll-behavior/main-frame-interrupted-scroll.html [ Pass Failure ]
-crbug.com/671478 [ Win ] fast/table/percent-height-replaced-content-in-cell.html [ Pass Failure ]
+crbug.com/671478 fast/table/percent-height-replaced-content-in-cell.html [ Pass Failure ]
 crbug.com/663855 fast/text/ellipsis-ltr-text-in-rtl-flow-underline-composition.html [ Pass Failure ]
 crbug.com/663855 fast/text/ellipsis-rtl-text-in-ltr-flow.html [ Pass Failure ]
 crbug.com/663855 fast/text/ellipsis-rtl-text-in-rtl-flow.html [ Pass Failure ]
@@ -49,7 +49,7 @@
 crbug.com/663874 http/tests/fetch/window/thorough/redirect-password-other-https.html [ Pass Failure ]
 crbug.com/663874 http/tests/fetch/window/thorough/scheme-blob.html [ Pass Failure ]
 crbug.com/663874 http/tests/fetch/window/thorough/scheme-data-other-https.html [ Pass Failure ]
-crbug.com/671480 [ Win ] http/tests/inspector/file-system-project-mapping.html [ Pass Failure ]
+crbug.com/671480 http/tests/inspector/file-system-project-mapping.html [ Pass Failure ]
 crbug.com/663876 http/tests/loading/doc-write-sync-third-party-script-block-effectively-2g.html [ Pass Failure ]
 crbug.com/663877 http/tests/media/video-load-suspend.html [ Pass Failure ]
 crbug.com/663879 http/tests/misc/script-no-store.html [ Pass Failure ]
@@ -64,7 +64,7 @@
 crbug.com/664839 http/tests/security/link-crossorigin-preload-no-cors.html [ Pass Failure ]
 crbug.com/664839 http/tests/security/same-origin-css.html [ Pass Failure ]
 crbug.com/664839 http/tests/security/same-origin-css-in-quirks.html [ Pass Failure ]
-crbug.com/671475 [ Win ] http/tests/security/suborigins/suborigin-invalid-options.html [ Pass Failure ]
+crbug.com/671475 http/tests/security/suborigins/suborigin-invalid-options.html [ Pass Failure ]
 crbug.com/664839 http/tests/security/webgl-remote-read-remote-image-allowed.html [ Pass Failure ]
 crbug.com/664839 http/tests/security/webgl-remote-read-remote-image-allowed-with-credentials.html [ Pass Failure ]
 crbug.com/664840 http/tests/w3c/webperf/submission/Google/resource-timing/html/test_resource_script_types.html [ Pass Failure ]
@@ -88,7 +88,7 @@
 crbug.com/663874 virtual/mojo-loading/http/tests/fetch/window/thorough/redirect-password-other-https.html [ Pass Failure ]
 crbug.com/663874 virtual/mojo-loading/http/tests/fetch/window/thorough/scheme-blob.html [ Pass Failure ]
 crbug.com/663874 virtual/mojo-loading/http/tests/fetch/window/thorough/scheme-data-other-https.html [ Pass Failure ]
-crbug.com/671477 [ Win ] virtual/mojo-loading/http/tests/inspector/debugger/fetch-breakpoints.html [ Pass Failure ]
+crbug.com/671477 virtual/mojo-loading/http/tests/inspector/debugger/fetch-breakpoints.html [ Pass Failure ]
 crbug.com/663876 virtual/mojo-loading/http/tests/loading/doc-write-sync-third-party-script-block-effectively-2g.html [ Pass Failure ]
 crbug.com/663877 virtual/mojo-loading/http/tests/media/video-load-suspend.html [ Pass Failure ]
 crbug.com/663879 virtual/mojo-loading/http/tests/misc/script-no-store.html [ Pass Failure ]
@@ -108,11 +108,11 @@
 crbug.com/664840 virtual/mojo-loading/http/tests/w3c/webperf/submission/Google/resource-timing/html/test_resource_script_types.html [ Pass Failure ]
 crbug.com/664841 virtual/mojo-loading/http/tests/workers/worker-document-domain-security.html [ Pass Failure ]
 crbug.com/664841 virtual/mojo-loading/http/tests/workers/worker-performance-timeline.html [ Pass Failure ]
-crbug.com/673003 [ Win ] virtual/spinvalidation/paint/invalidation/svg/marker-viewBox-changes.svg [ Pass Failure ]
-crbug.com/673003 [ Win ] virtual/spinvalidation/paint/invalidation/outline-clip-change.html [ Pass Failure ]
+crbug.com/673003 virtual/spinvalidation/paint/invalidation/svg/marker-viewBox-changes.svg [ Pass Failure ]
+crbug.com/673003 virtual/spinvalidation/paint/invalidation/outline-clip-change.html [ Pass Failure ]
 crbug.com/664843 inspector/elements/styles-4/styles-update-from-js.html [ Pass Failure ]
 crbug.com/664842 inspector-protocol/heap-profiler/heap-snapshot-with-active-dom-object.html [ Pass Failure ]
-crbug.com/672204 [ Win ] media/avtrack/video-track-selected.html [ Pass Failure ]
+crbug.com/672204 media/avtrack/video-track-selected.html [ Pass Failure ]
 crbug.com/664844 media/track/track-cue-rendering-tree-is-removed-properly.html [ Pass Failure ]
 crbug.com/664844 media/track/track-default-attribute.html [ Pass Failure ]
 crbug.com/664844 media/track/track-kind-user-preference.html [ Pass Failure ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 66b2f82..2217dba 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -98,14 +98,10 @@
 crbug.com/646176 virtual/spinvalidation/ [ Skip ]
 crbug.com/646176 virtual/spinvalidation/paint/invalidation/ [ Pass ]
 
-crbug.com/645667 virtual/spinvalidation/paint/invalidation/outline-clip-change.html [ Crash Failure ]
 crbug.com/645667 virtual/spinvalidation/paint/invalidation/filter-repaint-accelerated-on-accelerated-filter.html [ Crash ]
 crbug.com/645667 virtual/spinvalidation/paint/invalidation/position-change-keeping-geometry.html [ Crash ]
-crbug.com/645667 virtual/spinvalidation/paint/invalidation/svg/marker-viewBox-changes.svg [ Crash Failure ]
-crbug.com/645667 virtual/spinvalidation/paint/invalidation/compositing/should-not-repaint-composited-descendants.html [ Crash ]
 crbug.com/645667 virtual/spinvalidation/paint/invalidation/compositing/resize-repaint.html [ Crash ]
 crbug.com/645667 virtual/spinvalidation/paint/invalidation/compositing/shrink-layer.html [ Crash ]
-crbug.com/645667 virtual/spinvalidation/paint/invalidation/compositing/clipping-should-not-repaint-composited-descendants.html [ Crash ]
 crbug.com/645667 virtual/spinvalidation/paint/invalidation/filter-repaint-on-accelerated-layer.html [ Crash ]
 
 # --- End SlimmingPaintInvalidation Tests ---
@@ -625,6 +621,12 @@
 crbug.com/635619 virtual/layout_ng/fast/block/float/trailing-float-with-content.html [ Skip ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/vertical-move-relayout.html [ Skip ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/width-update-after-clear.html [ Skip ]
+crbug.com/635619 virtual/layout_ng/fast/block/float/avoid-floats-when-negative-margin-top-2.html [ Skip ]
+crbug.com/635619 virtual/layout_ng/fast/block/float/avoid-floats-when-negative-margin-top-3.html [ Skip ]
+crbug.com/635619 virtual/layout_ng/fast/block/float/avoid-floats-when-negative-margin-top-4.html [ Skip ]
+crbug.com/635619 virtual/layout_ng/fast/block/float/avoid-floats-when-negative-margin-top-5.html [ Skip ]
+crbug.com/635619 virtual/layout_ng/fast/block/float/avoid-floats-when-negative-margin-top-6.html [ Skip ]
+crbug.com/635619 virtual/layout_ng/fast/block/float/avoid-floats-when-negative-margin-top.html [ Skip ]
 # ====== LayoutNG-only failures until here ======
 
 # Requires ServiceWorkerNavigationPreload feature enabled. Run under
@@ -1534,6 +1536,12 @@
 
 crbug.com/527270 accessibility/name-calc-img.html [ Failure Pass Timeout ]
 
+crbug.com/673632 fast/css-generated-content/dynamic-apply-after-for-inline.html [ Failure Pass ]
+crbug.com/673632 fast/css/collapsed-whitespace-reattach-in-style-recalc.html [ Failure Pass ]
+crbug.com/673632 fast/inline/reattach-inlines-in-anonymous-blocks-with-out-of-flow-siblings.html [ Failure Pass ]
+crbug.com/673632 fast/layout/display-none-no-relayout.html [ Failure Pass ]
+crbug.com/673632 fast/selectors/style-sharing-shadow.html [ Failure Pass ]
+
 # Win7 does not support the needed DirectWrite APIs for font fallback
 crbug.com/459056 [ Win7 ] fast/text/font-fallback-win.html [ Failure ]
 
@@ -1639,34 +1647,6 @@
 
 crbug.com/610464 [ Linux Win7 Debug ] inspector/components/throttler.html [ Failure Pass ]
 
-# TODO(jlebel): Remove when methods are implemented.
-crbug.com/624019 [ Mac ] bluetooth/characteristic/notifications/add-multiple-event-listeners.html [ Skip ]
-crbug.com/624019 [ Mac ] bluetooth/characteristic/notifications/concurrent-stops.html [ Skip ]
-crbug.com/624019 [ Mac ] bluetooth/characteristic/notifications/event-after-starting.html [ Skip ]
-crbug.com/624019 [ Mac ] bluetooth/characteristic/notifications/gc-with-pending-stop.html [ Skip ]
-crbug.com/624019 [ Mac ] bluetooth/characteristic/notifications/parallel-start-stop.html [ Skip ]
-crbug.com/624019 [ Mac ] bluetooth/characteristic/notifications/start-before-stop-resolves.html [ Skip ]
-crbug.com/624019 [ Mac ] bluetooth/characteristic/notifications/start-stop-start-stop.html [ Skip ]
-crbug.com/624019 [ Mac ] bluetooth/characteristic/notifications/start-succeeds.html [ Skip ]
-crbug.com/624019 [ Mac ] bluetooth/characteristic/notifications/stop-after-start-succeeds.html [ Skip ]
-crbug.com/624019 [ Mac ] bluetooth/characteristic/notifications/stop-twice.html [ Skip ]
-crbug.com/624019 [ Mac ] bluetooth/characteristic/notifications/stop-without-starting.html [ Skip ]
-crbug.com/624019 [ Mac ] bluetooth/characteristic/stopNotifications/gen-gatt-op-device-disconnects-before.html [ Skip ]
-crbug.com/624019 [ Mac ] bluetooth/characteristic/stopNotifications/device-reconnects-during-success.html [ Skip ]
-crbug.com/624019 [ Mac ] bluetooth/characteristic/stopNotifications/reconnect-during-success.html [ Skip ]
-crbug.com/624019 [ Mac ] bluetooth/characteristic/stopNotifications/gen-gatt-op-device-disconnects-during-success.html [ Skip ]
-crbug.com/624019 [ Mac ] bluetooth/characteristic/stopNotifications/gen-gatt-op-disconnect-called-during-success.html [ Skip ]
-crbug.com/624019 [ Mac ] bluetooth/characteristic/stopNotifications/gen-gatt-op-disconnect-called-before.html [ Skip ]
-crbug.com/624019 [ Mac ] bluetooth/characteristic/stopNotifications/gen-gatt-op-garbage-collection-ran-during-success.html [ Skip ]
-crbug.com/624019 [ Mac ] bluetooth/service/getCharacteristics/gen-device-disconnects-invalidates-objects.html [ Skip ]
-crbug.com/624019 [ Mac ] bluetooth/service/getCharacteristics/gen-disconnect-invalidates-objects-with-uuid.html [ Skip ]
-crbug.com/624019 [ Mac ] bluetooth/service/getCharacteristic/gen-device-disconnects-invalidates-objects.html [ Skip ]
-crbug.com/624019 [ Mac ] bluetooth/service/getCharacteristics/gen-disconnect-invalidates-objects.html [ Skip ]
-crbug.com/624019 [ Mac ] bluetooth/service/getCharacteristics/gen-device-disconnects-invalidates-objects-with-uuid.html [ Skip ]
-crbug.com/624019 [ Mac ] bluetooth/service/getCharacteristic/gen-disconnect-invalidates-objects.html [ Skip ]
-
-
-
 crbug.com/487344 paint/invalidation/video-paint-invalidation.html [ Failure ]
 crbug.com/487344 virtual/spinvalidation/paint/invalidation/video-paint-invalidation.html [ Skip ]
 crbug.com/487344 [ Win ] compositing/video/video-controls-layer-creation.html [ Pass Failure ]
@@ -1889,8 +1869,6 @@
 
 crbug.com/660295 inspector/elements/elements-panel-restore-selection-when-node-comes-later.html [ Pass Failure ]
 
-crbug.com/657968 storage/indexeddb/idbdatabase-createObjectStore-exception-order.html [ Pass Failure ]
-crbug.com/657968 storage/indexeddb/idbdatabase-deleteObjectStore-exception-order.html [ Pass Failure ]
 crbug.com/667236 fast/forms/select/menulist-appearance-basic.html [ NeedsRebaseline ]
 crbug.com/667236 [ Linux ] fast/forms/select/basic-selects.html [ NeedsRebaseline ]
 crbug.com/667236 [ Linux ] fast/forms/select/select-autofilled.html [ NeedsRebaseline ]
@@ -2262,3 +2240,9 @@
 # Added 2016-12-12
 crbug.com/610835 http/tests/security/XFrameOptions/x-frame-options-deny-multiple-clients.html [ Failure Pass ]
 crbug.com/610835 virtual/mojo-loading/http/tests/security/XFrameOptions/x-frame-options-deny-multiple-clients.html [ Failure Pass ]
+
+# Added 2016-12-12
+crbug.com/673463 [ Linux ] fast/forms/associatedFormControls-leak-nodes.html [ Pass Failure ]
+
+# Added 2016-12-12
+crbug.com/673539 [ Linux ] css3/filters/effect-contrast-hw.html [ Pass Failure ]
diff --git a/third_party/WebKit/LayoutTests/compositing/layer-creation/iframe-clip-removed.html b/third_party/WebKit/LayoutTests/compositing/layer-creation/iframe-clip-removed.html
deleted file mode 100644
index 6d9420e..0000000
--- a/third_party/WebKit/LayoutTests/compositing/layer-creation/iframe-clip-removed.html
+++ /dev/null
@@ -1,45 +0,0 @@
-<!DOCTYPE html>
-<style>
-  #subframe {
-    width: 400px;
-    height: 500px;
-    background-color: blue;
-    position: relative;
-  }
-
-  #scroller {
-    height: 200px;
-    width: 300px;
-    position: absolute;
-    overflow: scroll;
-  }
-
-  #clip {
-    position: absolute;
-    clip: rect(0px, 100px, 100px, 0px);
-  }
-</style>
-<script>
-  onload = function() {
-    // Render one frame with clipping, then remove the clip.
-    window.requestAnimationFrame(function() {
-      window.requestAnimationFrame(function() {
-        document.getElementById("clip").style.clip = "auto";
-        if (window.testRunner)
-          testRunner.notifyDone();
-      });
-    });
-  }
-
-  if (window.testRunner && window.internals) {
-    testRunner.waitUntilDone();
-    internals.settings.setPreferCompositingToLCDTextEnabled(true);
-  }
-
-</script>
-
-<div id="scroller">
-  <div id="clip">
-    <iframe id="subframe"></iframe>
-  </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/compositing/overflow/border-radius-styles-with-composited-child-expected.png b/third_party/WebKit/LayoutTests/compositing/overflow/border-radius-styles-with-composited-child-expected.png
new file mode 100644
index 0000000..249b8d4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/compositing/overflow/border-radius-styles-with-composited-child-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/compositing/overflow/border-radius-styles-with-composited-child-expected.txt b/third_party/WebKit/LayoutTests/compositing/overflow/border-radius-styles-with-composited-child-expected.txt
new file mode 100644
index 0000000..47100f7f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/compositing/overflow/border-radius-styles-with-composited-child-expected.txt
@@ -0,0 +1,17 @@
+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,10) size 784x580
+layer at (18,10) size 108x108 clip at (22,14) size 100x100
+  LayoutBlockFlow {DIV} at (10,0) size 108x108 [bgcolor=#ADD8E6] [border: (4px solid #000000)]
+layer at (18,128) size 108x108 clip at (22,132) size 100x100
+  LayoutBlockFlow {DIV} at (10,118) size 108x108 [bgcolor=#ADD8E6] [border: (4px dashed #000000)]
+layer at (18,246) size 108x108 clip at (22,250) size 100x100
+  LayoutBlockFlow {DIV} at (10,236) size 108x108 [bgcolor=#ADD8E6] [border: (4px solid #FF00007F)]
+layer at (22,14) size 96x96
+  LayoutBlockFlow {DIV} at (4,4) size 96x96 [bgcolor=#008000]
+layer at (22,132) size 96x96
+  LayoutBlockFlow {DIV} at (4,4) size 96x96 [bgcolor=#008000]
+layer at (22,250) size 96x96
+  LayoutBlockFlow {DIV} at (4,4) size 96x96 [bgcolor=#008000]
diff --git a/third_party/WebKit/LayoutTests/compositing/overflow/border-radius-styles-with-composited-child.html b/third_party/WebKit/LayoutTests/compositing/overflow/border-radius-styles-with-composited-child.html
new file mode 100644
index 0000000..37087f0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/compositing/overflow/border-radius-styles-with-composited-child.html
@@ -0,0 +1,41 @@
+<style>
+
+.outer {
+    border: 4px solid black;
+    width: 100px;
+    height: 100px;
+    border-radius: 40px;
+    background-color: lightblue;
+    overflow: hidden;
+    margin: 10px;
+}
+
+.inner {
+    width: 80px;
+    height: 80px;
+    background-color: green;
+    padding: .5em;
+    will-change: transform;
+}
+
+.dashed {
+    border-style: dashed;
+}
+
+.transparent {
+    border-color: rgba(255,0,0,0.5);
+}
+
+</style>
+
+<div class = "outer">
+    <div class = "inner"></div>
+</div>
+
+<div class = "outer dashed">
+    <div class = "inner"></div>
+</div>
+
+<div class = "outer transparent">
+    <div class = "inner"></div>
+</div>
diff --git a/third_party/WebKit/LayoutTests/compositing/overflow/empty-composited-child-of-border-radius-ancestor-expected.html b/third_party/WebKit/LayoutTests/compositing/overflow/empty-composited-child-of-border-radius-ancestor-expected.html
new file mode 100644
index 0000000..580191f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/compositing/overflow/empty-composited-child-of-border-radius-ancestor-expected.html
@@ -0,0 +1,14 @@
+<style>
+.outermost {
+  border: 4px solid #000;
+  border-radius: 40px;
+  width: 200px;
+  height: 200px;
+  overflow: hidden;
+}
+
+</style>
+
+<div class="outermost">
+</div>
+
diff --git a/third_party/WebKit/LayoutTests/compositing/overflow/empty-composited-child-of-border-radius-ancestor.html b/third_party/WebKit/LayoutTests/compositing/overflow/empty-composited-child-of-border-radius-ancestor.html
new file mode 100644
index 0000000..786c5ed
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/compositing/overflow/empty-composited-child-of-border-radius-ancestor.html
@@ -0,0 +1,24 @@
+<style>
+.outermost {
+  border: 4px solid #000;
+  border-radius: 40px;
+  width: 200px;
+  height: 200px;
+  overflow: hidden;
+}
+
+.inner {
+  width: 200px;
+  height: 200px;
+  position: relative;
+  left: 50px;
+  top: 50px;
+  will-change: transform;
+}
+</style>
+
+<div class="outermost">
+  <div class="inner">
+  </div>
+</div>
+
diff --git a/third_party/WebKit/LayoutTests/compositing/overflow/scrollbar-layer-placement-expected.txt b/third_party/WebKit/LayoutTests/compositing/overflow/scrollbar-layer-placement-expected.txt
index cd12323f..965e202 100644
--- a/third_party/WebKit/LayoutTests/compositing/overflow/scrollbar-layer-placement-expected.txt
+++ b/third_party/WebKit/LayoutTests/compositing/overflow/scrollbar-layer-placement-expected.txt
@@ -29,6 +29,7 @@
     {
       "name": "Scrolling Contents Layer",
       "bounds": [220, 236],
+      "contentsOpaque": true,
       "drawsContent": true
     },
     {
@@ -64,6 +65,7 @@
     {
       "name": "Scrolling Contents Layer",
       "bounds": [220, 236],
+      "contentsOpaque": true,
       "drawsContent": true
     },
     {
@@ -113,6 +115,7 @@
     {
       "name": "Scrolling Contents Layer",
       "bounds": [220, 236],
+      "contentsOpaque": true,
       "drawsContent": true
     },
     {
@@ -178,6 +181,7 @@
     {
       "name": "Scrolling Contents Layer",
       "bounds": [220, 236],
+      "contentsOpaque": true,
       "drawsContent": true
     },
     {
diff --git a/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-2-expected.txt b/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-2-expected.txt
new file mode 100644
index 0000000..9f54bd13
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-2-expected.txt
@@ -0,0 +1,4 @@
+crbug.com/666487: There should be a green square below.
+
+
+PASS
diff --git a/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-2.html b/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-2.html
new file mode 100644
index 0000000..8042753
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-2.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<style>
+body { margin: 0px; }
+.float { float: left; width: 50px; height: 100px; background: green;}
+.content { overflow: hidden; margin-top: -100px; width: 50px; height: 100px; background: green;}
+.container { width: 100px; background: red;}
+</style>
+<p>crbug.com/666487: There should be a green square below.</p>
+<div class="container">
+  <div class="float"></div>
+  <br clear=all>
+  <div style="width: 20px; height; 1px"></div>
+  <div class="content" data-offset-x=50></div>
+</div>
+<script src="../../../resources/check-layout.js"></script>
+<script>
+checkLayout('.content');
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-3-expected.txt b/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-3-expected.txt
new file mode 100644
index 0000000..9f54bd13
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-3-expected.txt
@@ -0,0 +1,4 @@
+crbug.com/666487: There should be a green square below.
+
+
+PASS
diff --git a/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-3.html b/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-3.html
new file mode 100644
index 0000000..0111b37
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-3.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<style>
+body { margin: 0px; }
+.float { float: left; width: 50px; height: 100px; background: green;}
+.content { overflow: hidden; margin-top: -100px; width: 50px; height: 100px; background: green;}
+.container { width: 100px; background: red;}
+</style>
+<p>crbug.com/666487: There should be a green square below.</p>
+<div class="container">
+  <div>
+    <div class="float"></div>
+    <br clear=all>
+  </div>
+  <div style="width: 20px; height; 1px"></div>
+  <div class="content" data-offset-x=50></div>
+</div>
+<script src="../../../resources/check-layout.js"></script>
+<script>
+checkLayout('.content');
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-4-expected.txt b/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-4-expected.txt
new file mode 100644
index 0000000..9f54bd13
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-4-expected.txt
@@ -0,0 +1,4 @@
+crbug.com/666487: There should be a green square below.
+
+
+PASS
diff --git a/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-4.html b/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-4.html
new file mode 100644
index 0000000..14f119a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-4.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<style>
+body { margin: 0px; }
+.float { float: left; width: 50px; height: 100px; background: green;}
+.content { overflow: hidden; margin-top: -100px; width: 50px; height: 100px; background: green;}
+.container { width: 100px; background: red;}
+</style>
+<p>crbug.com/666487: There should be a green square below.</p>
+<div class="container">
+  <div>
+    <div class="float"></div>
+    <br clear=all>
+  </div>
+  <div style="float:left;"></div>
+  <div class="content" data-offset-x=50></div>
+</div>
+<script src="../../../resources/check-layout.js"></script>
+<script>
+checkLayout('.content');
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-5-expected.txt b/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-5-expected.txt
new file mode 100644
index 0000000..9f54bd13
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-5-expected.txt
@@ -0,0 +1,4 @@
+crbug.com/666487: There should be a green square below.
+
+
+PASS
diff --git a/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-5.html b/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-5.html
new file mode 100644
index 0000000..9e711bd3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-5.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<style>
+body { margin: 0px; }
+.float { float: left; width: 50px; height: 100px; background: green;}
+.content { overflow: hidden; margin-top: -100px; width: 50px; height: 100px; background: green;}
+.container { width: 100px; background: red;}
+</style>
+<p>crbug.com/666487: There should be a green square below.</p>
+<div class="container">
+  <div>
+    <div class="float"></div>
+    <br clear=all>
+  </div>
+  <div style="position:absolute;"></div>
+  <div class="content" data-offset-x=50></div>
+</div>
+<script src="../../../resources/check-layout.js"></script>
+<script>
+checkLayout('.content');
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-6-expected.txt b/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-6-expected.txt
new file mode 100644
index 0000000..9f54bd13
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-6-expected.txt
@@ -0,0 +1,4 @@
+crbug.com/666487: There should be a green square below.
+
+
+PASS
diff --git a/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-6.html b/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-6.html
new file mode 100644
index 0000000..1c58540
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-6.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<style>
+body { margin: 0px; }
+.float { float: left; width: 50px; height: 100px; background: green;}
+.content { overflow: hidden; margin-top: -100px; width: 50px; height: 100px; background: green;}
+.container { width: 100px; background: red;}
+</style>
+<p>crbug.com/666487: There should be a green square below.</p>
+<div class="container">
+  <div>
+    <div class="float"></div>
+    <br clear=all>
+  </div>
+  <div style="overflow:hidden;"></div>
+  <div class="content" data-offset-x=50></div>
+</div>
+<script src="../../../resources/check-layout.js"></script>
+<script>
+checkLayout('.content');
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-expected.txt b/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-expected.txt
new file mode 100644
index 0000000..9f54bd13
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top-expected.txt
@@ -0,0 +1,4 @@
+crbug.com/666487: There should be a green square below.
+
+
+PASS
diff --git a/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top.html b/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top.html
new file mode 100644
index 0000000..2ff4b736
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/block/float/avoid-floats-when-negative-margin-top.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<style>
+body { margin: 0px; }
+.float { float: left; width: 50px; height: 100px; background: green;}
+.content { overflow: hidden; margin-top: -100px; width: 50px; height: 100px; background: green;}
+.container { width: 100px; background: red;}
+</style>
+<p>crbug.com/666487: There should be a green square below.</p>
+<div class="container">
+  <div class="float"></div>
+  <br clear=all>
+  <div></div>
+  <div class="content" data-offset-x=50></div>
+</div>
+<script src="../../../resources/check-layout.js"></script>
+<script>
+checkLayout('.content');
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/borders/border-radius-with-composited-child.html b/third_party/WebKit/LayoutTests/fast/borders/border-radius-with-composited-child.html
index 16fd438..1e8782d 100644
--- a/third_party/WebKit/LayoutTests/fast/borders/border-radius-with-composited-child.html
+++ b/third_party/WebKit/LayoutTests/fast/borders/border-radius-with-composited-child.html
@@ -1,6 +1,6 @@
 <!DOCTYPE HTML>
-<p>Below there should be a solid black circle.</p>
+<p>Below there should be a solid green circle with a black border and no red.</p>
 <br>
-<div style="position:relative; z-index:1; overflow:hidden; margin-top:100px; width:200px; height:200px; border-radius:50%; border:10px solid black; background:black;">
-    <div style="transform:translateZ(0); width:300px; height:300px; margin-left:-50px; margin-top:-50px; background:black;"></div>
+<div style="position:relative; z-index:1; overflow:hidden; margin-top:100px; width:200px; height:200px; border-radius:50%; border:10px solid black; background:red;">
+    <div style="transform:translateZ(0); width:300px; height:300px; margin-left:-50px; margin-top:-50px; background:green;"></div>
 </div>
diff --git a/third_party/WebKit/LayoutTests/fast/css/invalidation/independent-inheritance-fast-path.html b/third_party/WebKit/LayoutTests/fast/css/invalidation/independent-inheritance-fast-path.html
index d7d8dd50..f8ad807 100644
--- a/third_party/WebKit/LayoutTests/fast/css/invalidation/independent-inheritance-fast-path.html
+++ b/third_party/WebKit/LayoutTests/fast/css/invalidation/independent-inheritance-fast-path.html
@@ -18,6 +18,7 @@
     ["borderCollapse", "separate", "collapse"],
     ["emptyCells", "show", "hide"],
     ["captionSide", "left", "right"],
+    ["listStylePosition", "outside", "inside"],
 ];
 
 independent_properties.forEach(function(test_data)
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/dynamic/change-second-row-height.html b/third_party/WebKit/LayoutTests/fast/multicol/dynamic/change-second-row-height.html
new file mode 100644
index 0000000..17202ea
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/multicol/dynamic/change-second-row-height.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<p>The word "HEST" should be seen below.</p>
+<div style="position:relative; columns:2; column-gap:0; column-fill:auto; width:400px; height:40px; line-height:20px; orphans:1; widows:1;">
+    <div id="inner" style="columns:2; column-gap:0; column-fill:auto; height:80px;">
+        <div>
+            <br>
+            <br>
+            <br>
+            <br>
+            <br>
+            <span id="elm">HEST</span><br>
+        </div>
+    </div>
+</div>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script>
+test(() => {
+    var inner = document.getElementById("inner");
+    var elm = document.getElementById("elm");
+    assert_equals(elm.offsetLeft, 200);
+    document.body.offsetLeft;
+    inner.style.height = "72px";
+    assert_equals(elm.offsetLeft, 300);
+}, "Change inner multicol height, which only affects the second row.");
+</script>
diff --git a/third_party/WebKit/LayoutTests/fragmentation/single-large-cell-with-header-expected.html b/third_party/WebKit/LayoutTests/fragmentation/single-large-cell-with-header-expected.html
new file mode 100644
index 0000000..125579c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fragmentation/single-large-cell-with-header-expected.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<style>
+td, th {
+  background-color: #ddd;
+  border: 1px solid black;
+}
+</style>
+<p>crbug.com/669690: If the body's first row doesn't fit on a page then don't repeat headers.</p>
+<div style="columns:3; line-height: 18px; column-fill: auto; height:74px; background-color: yellow;">
+  <table>
+    <thead>
+      <tr>
+        <th>Col 1</th>
+      </tr>
+    </thead>
+    <tr><td>
+        <p>1</p>
+        <p>2</p>
+        <p>3</p>
+        <p>4</p>
+        <p>5</p>
+        <p>6</p>
+        <p>7</p>
+        <p>8</p>
+        <p>9</p>
+
+        <p>10</p>
+        <p>11</p>
+        <p>12</p>
+        <p>13</p>
+        <p>14</p>
+        <p>15</p>
+        <p>16</p>
+        <p>17</p>
+        <p>18</p>
+        <p>19</p>
+      </td></tr>
+  </table>
+</div>
+
diff --git a/third_party/WebKit/LayoutTests/fragmentation/single-large-cell-with-header.html b/third_party/WebKit/LayoutTests/fragmentation/single-large-cell-with-header.html
new file mode 100644
index 0000000..57b9768
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fragmentation/single-large-cell-with-header.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<style>
+td, th {
+  background-color: #ddd;
+  border: 1px solid black;
+}
+thead, tr {
+  break-inside: avoid;
+}
+</style>
+<p>crbug.com/669690: If the body's first row doesn't fit on a page then don't repeat headers.</p>
+<div style="columns:3; line-height: 18px; column-fill: auto; height:74px; background-color: yellow;">
+  <table>
+    <thead>
+      <tr>
+        <th>Col 1</th>
+      </tr>
+    </thead>
+    <tr><td>
+        <p>1</p>
+        <p>2</p>
+        <p>3</p>
+        <p>4</p>
+        <p>5</p>
+        <p>6</p>
+        <p>7</p>
+        <p>8</p>
+        <p>9</p>
+
+        <p>10</p>
+        <p>11</p>
+        <p>12</p>
+        <p>13</p>
+        <p>14</p>
+        <p>15</p>
+        <p>16</p>
+        <p>17</p>
+        <p>18</p>
+        <p>19</p>
+      </td></tr>
+  </table>
+</div>
+
diff --git a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-2-expected.html b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-2-expected.html
index 17923b9f..22a7b90 100644
--- a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-2-expected.html
+++ b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-2-expected.html
@@ -32,10 +32,8 @@
                     </tr></td>
                 </table>
         </tr></td>
-        <tr><td class="header" colspan=2>Col 1</td></tr>
         <tr><td style="padding-top: 0px;">
                 <table>
-                    <tr><td class="header" colspan=2>Col 1</td></tr>
                     <tr><td style="padding-top: 0px;">
                             <table>
                                 <tr><td class="header">Col 1</td><td class="header">Col 2</td></tr>
@@ -44,22 +42,20 @@
                                 <tr><td>Te</td><td>xt</td></tr>
                                 <tr><td>Te</td><td>xt</td></tr>
                                 <tr><td>Te</td><td>xt</td></tr>
+                                <tr><td>Te</td><td>xt</td></tr>
+                                <tr><td>Te</td><td>xt</td></tr>
                             </table>
                     </tr></td>
                 </table>
         </tr></td>
-        <tr><td class="header" colspan=2>Col 1</td></tr>
         <tr><td style="padding-top: 0px;">
                 <table>
-                    <tr><td class="header" colspan=2>Col 1</td></tr>
                     <tr><td style="padding-top: 0px;">
                             <table>
                                 <tr><td class="header">Col 1</td><td class="header">Col 2</td></tr>
                                 <tr><td>Te</td><td>xt</td></tr>
                                 <tr><td>Te</td><td>xt</td></tr>
                                 <tr><td>Te</td><td>xt</td></tr>
-                                <tr><td>Te</td><td>xt</td></tr>
-                                <tr><td>Te</td><td>xt</td></tr>
                             </table>
                     </tr></td>
                 </table>
diff --git a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-3-expected.html b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-3-expected.html
index e33e876..3d4ffc5 100644
--- a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-3-expected.html
+++ b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-3-expected.html
@@ -28,7 +28,6 @@
                     <tr><td>Te</td><td>xt</td></tr>
                 </table>
         </tr></td>
-        <tr><td class="header" colspan=2>Col 1</td></tr>
         <tr><td style="padding-top: 0px;">
                 <table>
                     <tr><td class="header">Col 1</td><td class="header">Col 2</td></tr>
@@ -38,9 +37,9 @@
                     <tr><td>Te</td><td>xt</td></tr>
                     <tr><td>Te</td><td>xt</td></tr>
                     <tr><td>Te</td><td>xt</td></tr>
+                    <tr><td>Te</td><td>xt</td></tr>
                 </table>
         </tr></td>
-        <tr><td class="header" colspan=2>Col 1</td></tr>
         <tr><td style="padding-top: 0px;">
                 <table>
                     <tr><td class="header">Col 1</td><td class="header">Col 2</td></tr>
@@ -49,7 +48,6 @@
                     <tr><td>Te</td><td>xt</td></tr>
                     <tr><td>Te</td><td>xt</td></tr>
                     <tr><td>Te</td><td>xt</td></tr>
-                    <tr><td>Te</td><td>xt</td></tr>
                 </table>
         </tr></td>
     </table>
diff --git a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-4-expected.html b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-4-expected.html
index 9a24a2e..6c8afcd 100644
--- a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-4-expected.html
+++ b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-4-expected.html
@@ -28,7 +28,6 @@
                     <tr><td>Te</td><td>xt</td></tr>
                 </table>
         </tr></td>
-        <tr><td class="header" colspan=2>Col 1</td></tr>
         <tr><td style="padding-top: 0px;">
                 <table>
                     <tr><td class="header">Col 1</td><td class="header">Col 2</td></tr>
@@ -38,9 +37,9 @@
                     <tr><td>Te</td><td>xt</td></tr>
                     <tr><td>Te</td><td>xt</td></tr>
                     <tr><td>Te</td><td>xt</td></tr>
+                    <tr><td>Te</td><td>xt</td></tr>
                 </table>
         </tr></td>
-        <tr><td class="header" colspan=2>Col 1</td></tr>
         <tr><td style="padding-top: 0px;">
                 <table>
                     <tr><td class="header">Col 1</td><td class="header">Col 2</td></tr>
@@ -49,7 +48,6 @@
                     <tr><td>Te</td><td>xt</td></tr>
                     <tr><td>Te</td><td>xt</td></tr>
                     <tr><td>Te</td><td>xt</td></tr>
-                    <tr><td>Te</td><td>xt</td></tr>
                 </table>
         </tr></td>
     </table>
diff --git a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-expected.html b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-expected.html
index e33e876..3d4ffc5 100644
--- a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-expected.html
+++ b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-expected.html
@@ -28,7 +28,6 @@
                     <tr><td>Te</td><td>xt</td></tr>
                 </table>
         </tr></td>
-        <tr><td class="header" colspan=2>Col 1</td></tr>
         <tr><td style="padding-top: 0px;">
                 <table>
                     <tr><td class="header">Col 1</td><td class="header">Col 2</td></tr>
@@ -38,9 +37,9 @@
                     <tr><td>Te</td><td>xt</td></tr>
                     <tr><td>Te</td><td>xt</td></tr>
                     <tr><td>Te</td><td>xt</td></tr>
+                    <tr><td>Te</td><td>xt</td></tr>
                 </table>
         </tr></td>
-        <tr><td class="header" colspan=2>Col 1</td></tr>
         <tr><td style="padding-top: 0px;">
                 <table>
                     <tr><td class="header">Col 1</td><td class="header">Col 2</td></tr>
@@ -49,7 +48,6 @@
                     <tr><td>Te</td><td>xt</td></tr>
                     <tr><td>Te</td><td>xt</td></tr>
                     <tr><td>Te</td><td>xt</td></tr>
-                    <tr><td>Te</td><td>xt</td></tr>
                 </table>
         </tr></td>
     </table>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js
index 518f686..e5f92c9 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js
@@ -360,11 +360,15 @@
 
     function dumpNavigatorTreeElement(prefix, treeElement)
     {
-        var titleText;
-        if (treeElement.title instanceof Element)
-            titleText = treeElement.title.firstChild.textContent + " [mapped]";
-        else
-            titleText = treeElement.title;
+        var titleText = treeElement.title;
+        if (treeElement._trailingIconsElement) {
+            var iconTypes = [];
+            for (var icon = treeElement._trailingIconsElement.firstChild; icon; icon = icon.nextSibling) {
+                iconTypes.push(icon._iconType);
+            }
+            if (iconTypes.length)
+                titleText = titleText + " [" + iconTypes.join(", ") + "]";
+        }
         if (treeElement._nodeType === Sources.NavigatorView.Types.FileSystem || treeElement._nodeType === Sources.NavigatorView.Types.FileSystemFolder) {
             var hasMappedFiles = treeElement.listItemElement.classList.contains("has-mapped-files");
             if (!hasMappedFiles)
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/font-face-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/network/font-face-expected.txt
index 86e95eb..a7969aa2 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/font-face-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/network/font-face-expected.txt
@@ -1,8 +1,8 @@
 Tests that a used font-face is reported and an unused font-face is not reported.
 
 
-Symbol(RequestStarted): font-face.html
-Symbol(RequestFinished): font-face.html
-Symbol(RequestStarted): used.ttf
-Symbol(RequestFinished): used.ttf
+RequestStarted: font-face.html
+RequestFinished: font-face.html
+RequestStarted: used.ttf
+RequestFinished: used.ttf
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/font-face.html b/third_party/WebKit/LayoutTests/http/tests/inspector/network/font-face.html
index 801cb8e5..3be4b01 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/font-face.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/network/font-face.html
@@ -9,17 +9,17 @@
 }
 
 function test() {
-    function onRequest(event)
+    function onRequest(eventType, event)
     {
         var request = event.data;
         if (request.name() === 'done') {
             InspectorTest.completeTest();
             return;
         }
-        InspectorTest.addResult(event.type.toString() + ": " + request.name());
+        InspectorTest.addResult(eventType + ": " + request.name());
     }
-    InspectorTest.networkManager.addEventListener(SDK.NetworkManager.Events.RequestStarted, onRequest);
-    InspectorTest.networkManager.addEventListener(SDK.NetworkManager.Events.RequestFinished, onRequest);
+    InspectorTest.networkManager.addEventListener(SDK.NetworkManager.Events.RequestStarted, onRequest.bind(null, "RequestStarted"));
+    InspectorTest.networkManager.addEventListener(SDK.NetworkManager.Events.RequestFinished, onRequest.bind(null, "RequestFinished"));
 
     InspectorTest.evaluateInPage("createIFrame()");
 }
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/persistence-navigator-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/persistence-navigator-expected.txt
index 1fd994c7..4b184db6 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/persistence-navigator-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/persistence-navigator-expected.txt
@@ -25,7 +25,7 @@
     inspector
       persistence
         resources
-          foo.js [mapped]
+          foo.js [smallicon-green-checkmark]
         persistence-navigator.html
         persistence-test.js
       debugger-test.js
@@ -33,7 +33,7 @@
       isolated-filesystem-test.js
 www
   inspector/persistence/resources
-    foo.js [mapped]
+    foo.js [smallicon-green-checkmark]
 
 Running: removeFileMapping
 top
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/redirected-response.html b/third_party/WebKit/LayoutTests/http/tests/serviceworker/redirected-response.html
index 56b7bdb..5839673 100644
--- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/redirected-response.html
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/redirected-response.html
@@ -7,11 +7,12 @@
 <script>
 
 function redirected_test(url,
+                         fetch_option,
                          fetch_method,
                          cache,
                          expected_redirected,
                          expected_url_list) {
-  return fetch_method(url).then(response => {
+  return fetch_method(url, fetch_option).then(response => {
         var cloned_response = response.clone();
         assert_equals(
             response.redirected, expected_redirected,
@@ -71,23 +72,87 @@
       .then(f => {
           frame = f;
           return Promise.all([
-              redirected_test(TARGET_URL, self.fetch, cache,
+              // Tests without service workers.
+              redirected_test(TARGET_URL, {}, self.fetch, cache,
                               false /* expected_redirected */,
                               [TARGET_URL]),
-              redirected_test(REDIRECT_TO_TARGET_URL, self.fetch, cache,
+              redirected_test(REDIRECT_TO_TARGET_URL, {}, self.fetch, cache,
                               true /* expected_redirected */,
                               [REDIRECT_TO_TARGET_URL, TARGET_URL]),
+              redirected_test(REDIRECT_TO_TARGET_URL + '&manual',
+                              {redirect: 'manual'}, self.fetch, cache,
+                              false /* expected_redirected */,
+                              [REDIRECT_TO_TARGET_URL + '&manual']),
+              promise_rejects(
+                  t, new TypeError(),
+                  self.fetch(REDIRECT_TO_TARGET_URL + '&error',
+                             {redirect:'error'}),
+                  'The redirect response from the server should be treated as' +
+                  ' an error when the redirect flag of request was \'error\'.'),
+
+              // Tests without redirects with service worker.
               redirected_test('./?url=' + encodeURIComponent(TARGET_URL),
+                              {},
                               frame.contentWindow.fetch,
                               cache,
                               false /* expected_redirected */,
                               [TARGET_URL]),
+
+              // The service worker returns a redirected response.
               redirected_test(
-                  './?url=' + encodeURIComponent(REDIRECT_TO_TARGET_URL),
+                  './?url=' + encodeURIComponent(REDIRECT_TO_TARGET_URL) +
+                  '&original-redirect-mode=follow',
+                  {redirect: 'follow'},
                   frame.contentWindow.fetch,
                   cache,
                   true /* expected_redirected */,
                   [REDIRECT_TO_TARGET_URL, TARGET_URL]),
+              promise_rejects(
+                  t, new TypeError(),
+                  frame.contentWindow.fetch(
+                      './?url=' + encodeURIComponent(REDIRECT_TO_TARGET_URL) +
+                      '&original-redirect-mode=error',
+                      {redirect: 'error'}),
+                  'The redirected response from the service worker should be ' +
+                  'treated as an error when the redirect flag of request was ' +
+                  '\'error\'.'),
+              promise_rejects(
+                  t, new TypeError(),
+                  frame.contentWindow.fetch(
+                      './?url=' + encodeURIComponent(REDIRECT_TO_TARGET_URL) +
+                      '&original-redirect-mode=manual',
+                      {redirect: 'manual'}),
+                  'The redirected response from the service worker should be ' +
+                  'treated as an error when the redirect flag of request was ' +
+                  '\'manual\'.'),
+
+            // The service worker returns an opaqueredirect response.
+            promise_rejects(
+                t, new TypeError(),
+                frame.contentWindow.fetch(
+                    './?url=' + encodeURIComponent(REDIRECT_TO_TARGET_URL) +
+                    '&original-redirect-mode=follow&redirect-mode=manual',
+                    {redirect: 'follow'}),
+                'The opaqueredirect response from the service worker should ' +
+                'be treated as an error when the redirect flag of request was' +
+                ' \'follow\'.'),
+            promise_rejects(
+                t, new TypeError(),
+                frame.contentWindow.fetch(
+                    './?url=' + encodeURIComponent(REDIRECT_TO_TARGET_URL) +
+                    '&original-redirect-mode=error&redirect-mode=manual',
+                    {redirect: 'error'}),
+                'The opaqueredirect response from the service worker should ' +
+                'be treated as an error when the redirect flag of request was' +
+                ' \'error\'.'),
+            redirected_test(
+                './?url=' + encodeURIComponent(REDIRECT_TO_TARGET_URL) +
+                '&original-redirect-mode=manual&redirect-mode=manual',
+                {redirect: 'manual'},
+                frame.contentWindow.fetch,
+                cache,
+                false /* expected_redirected */,
+                [REDIRECT_TO_TARGET_URL]),
             ]);
         })
       .then(_ => self.caches.delete(CACHE_NAME))
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/MANIFEST.json b/third_party/WebKit/LayoutTests/imported/wpt/MANIFEST.json
index e68cd8d..c414885 100644
--- a/third_party/WebKit/LayoutTests/imported/wpt/MANIFEST.json
+++ b/third_party/WebKit/LayoutTests/imported/wpt/MANIFEST.json
@@ -71,6 +71,12 @@
             "url": "/fullscreen/api/element-ready-check-not-in-document-manual.html"
           }
         ],
+        "fullscreen/api/element-request-fullscreen-and-exit-iframe-manual.html": [
+          {
+            "path": "fullscreen/api/element-request-fullscreen-and-exit-iframe-manual.html",
+            "url": "/fullscreen/api/element-request-fullscreen-and-exit-iframe-manual.html"
+          }
+        ],
         "fullscreen/api/element-request-fullscreen-manual.html": [
           {
             "path": "fullscreen/api/element-request-fullscreen-manual.html",
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/fullscreen/api/element-request-fullscreen-and-exit-iframe-manual.html b/third_party/WebKit/LayoutTests/imported/wpt/fullscreen/api/element-request-fullscreen-and-exit-iframe-manual.html
new file mode 100644
index 0000000..4483cca
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/fullscreen/api/element-request-fullscreen-and-exit-iframe-manual.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<title>Element#requestFullscreen() and Document#exitFullscreen() in iframe</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../trusted-click.js"></script>
+<div id="log"></div>
+<iframe allowfullscreen></iframe>
+<script>
+async_test(t => {
+  const iframe = document.querySelector('iframe');
+  const iframeDoc = iframe.contentDocument;
+  const iframeBody = iframeDoc.body;
+
+  let count = 0;
+  document.onfullscreenchange = iframeDoc.onfullscreenchange = t.step_func(event => {
+    count++;
+    assert_between_inclusive(count, 1, 4, 'number of fullscreenchange events');
+    const expected = {
+      target: count == 1 || count == 4 ? document : iframeDoc,
+      outerFullscreenElement: count <= 2 ? iframe : null,
+      innerFullscreenElement: count <= 2 ? iframeBody : null,
+    };
+    assert_equals(event.target, expected.target, 'event target');
+    assert_equals(document.fullscreenElement, expected.outerFullscreenElement, 'outer fullscreenElement');
+    assert_equals(iframeDoc.fullscreenElement, expected.innerFullscreenElement, 'inner fullscreenElement');
+    if (count == 2) {
+      iframeDoc.exitFullscreen();
+    } else if (count == 4) {
+      // Done, but set timeout to fail on extra events.
+      setTimeout(t.step_func_done());
+    }
+  });
+  document.onfullscreenerror = t.unreached_func('fullscreenerror event');
+  iframeDoc.onfullscreenerror = t.unreached_func('iframe fullscreenerror event');
+
+  trusted_request(iframeBody, document.body);
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/heap-profiler/resources/heap-snapshot-common.js b/third_party/WebKit/LayoutTests/inspector-protocol/heap-profiler/resources/heap-snapshot-common.js
index b78b51f..d0ee0fa 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/heap-profiler/resources/heap-snapshot-common.js
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/heap-profiler/resources/heap-snapshot-common.js
@@ -13,7 +13,6 @@
 InspectorTest.importScript("../../../../../Source/devtools/front_end/common/UIString.js");
 InspectorTest.importScript("../../../../../Source/devtools/front_end/profiler/HeapSnapshotCommon.js");
 InspectorTest.importScript("../../../../../Source/devtools/front_end/heap_snapshot_worker/HeapSnapshot.js");
-InspectorTest.importScript("../../../../../Source/devtools/front_end/heap_snapshot_worker/JSHeapSnapshot.js");
 InspectorTest.importScript("../../../../../Source/devtools/front_end/common/TextUtils.js");
 InspectorTest.importScript("../../../../../Source/devtools/front_end/heap_snapshot_worker/HeapSnapshotLoader.js");
 
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-format-expected.txt b/third_party/WebKit/LayoutTests/inspector/console/console-format-expected.txt
index 15fc787..d7e2218 100644
--- a/third_party/WebKit/LayoutTests/inspector/console/console-format-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/console/console-format-expected.txt
@@ -225,10 +225,10 @@
 console-format.html:8 [svg#svg-node]
 globals[25]
     <svg id="svg-node"></svg>
-console-format.html:7 Object {getFoo: function}
+console-format.html:7 Object {enumerableProp: 4, __underscoreEnumerableProp__: 5, __underscoreNonEnumerableProp: 2, abc: 3, getFoo: function…}
 console-format.html:8 [Object]
 globals[26]
-Object {getFoo: function}
+Object {enumerableProp: 4, __underscoreEnumerableProp__: 5, __underscoreNonEnumerableProp: 2, abc: 3, getFoo: function…}
 console-format.html:7 -0
 console-format.html:8 [-0]
 globals[27]
@@ -533,8 +533,12 @@
 globals[25]
     <svg id="svg-node"></svg>
 console-format.html:7 Object
+    enumerableProp: 4
+    __underscoreEnumerableProp__: 5
+    abc: 3
     bar: (...)
     getFoo: function ()
+    __underscoreNonEnumerableProp: 2
     get bar: function ()
     set bar: function (x)
     __proto__: Object
@@ -544,8 +548,12 @@
     __proto__: Array(0)
 globals[26]
 Object
+    enumerableProp: 4
+    __underscoreEnumerableProp__: 5
+    abc: 3
     bar: (...)
     getFoo: function ()
+    __underscoreNonEnumerableProp: 2
     get bar: function ()
     set bar: function (x)
     __proto__: Object
@@ -573,10 +581,6 @@
 globals[29]
 function Object() { [native code] }
 console-format.html:7 Object
-    __defineGetter__: function __defineGetter__()
-    __defineSetter__: function __defineSetter__()
-    __lookupGetter__: function __lookupGetter__()
-    __lookupSetter__: function __lookupSetter__()
     constructor: function Object()
     hasOwnProperty: function hasOwnProperty()
     isPrototypeOf: function isPrototypeOf()
@@ -584,6 +588,10 @@
     toLocaleString: function toLocaleString()
     toString: function toString()
     valueOf: function valueOf()
+    __defineGetter__: function __defineGetter__()
+    __defineSetter__: function __defineSetter__()
+    __lookupGetter__: function __lookupGetter__()
+    __lookupSetter__: function __lookupSetter__()
     get __proto__: function __proto__()
     set __proto__: function __proto__()
 console-format.html:8 Array(1)
@@ -592,10 +600,6 @@
     __proto__: Array(0)
 globals[30]
 Object
-    __defineGetter__: function __defineGetter__()
-    __defineSetter__: function __defineSetter__()
-    __lookupGetter__: function __lookupGetter__()
-    __lookupSetter__: function __lookupSetter__()
     constructor: function Object()
     hasOwnProperty: function hasOwnProperty()
     isPrototypeOf: function isPrototypeOf()
@@ -603,6 +607,10 @@
     toLocaleString: function toLocaleString()
     toString: function toString()
     valueOf: function valueOf()
+    __defineGetter__: function __defineGetter__()
+    __defineSetter__: function __defineSetter__()
+    __lookupGetter__: function __lookupGetter__()
+    __lookupSetter__: function __lookupSetter__()
     get __proto__: function __proto__()
     set __proto__: function __proto__()
 console-format.html:7 function ( /**/ foo/**/, /*/**/bar,
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-format.html b/third_party/WebKit/LayoutTests/inspector/console/console-format.html
index c1f39799..323a9e45 100644
--- a/third_party/WebKit/LayoutTests/inspector/console/console-format.html
+++ b/third_party/WebKit/LayoutTests/inspector/console/console-format.html
@@ -55,9 +55,13 @@
     var existingAttribute = document.getElementById("x").attributes[0];
     var throwingLengthGetter = {get length() { throw "Length called"; }};
     var objectWithNonEnumerables = Object.create({ foo: 1 }, {
+        __underscoreNonEnumerableProp: { value: 2, enumerable: false },
+        abc: { value: 3, enumerable: false },
         getFoo: { value: function() { return this.foo; } },
         bar: { get: function() { return this.bar; }, set: function(x) { this.bar = x; } }
     });
+    objectWithNonEnumerables.enumerableProp = 4;
+    objectWithNonEnumerables.__underscoreEnumerableProp__ = 5;
     var negZero = 1 / Number.NEGATIVE_INFINITY;
     var textNode = document.getElementById("x").nextSibling;
     var arrayLikeFunction = function( /**/ foo/**/, /*/**/bar,
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-log-object-with-getter-expected.txt b/third_party/WebKit/LayoutTests/inspector/console/console-log-object-with-getter-expected.txt
index ecd1be6..a8996db 100644
--- a/third_party/WebKit/LayoutTests/inspector/console/console-log-object-with-getter-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/console/console-log-object-with-getter-expected.txt
@@ -4,6 +4,6 @@
 
 console-log-object-with-getter.html:15 Object {}
 console-log-object-with-getter.html:16 [(...)]
-console-log-object-with-getter.html:15 Objectfoo: Objecta: 1b: 2__proto__: Objectset bar: function (x)get foo: function ()__proto__: Object
+console-log-object-with-getter.html:15 Objectfoo: Objecta: 1b: 2__proto__: Objectget foo: function ()set bar: function (x)__proto__: Object
 console-log-object-with-getter.html:16 Array(2)0: 1length: 2get 0: function ()set 1: function (x)__proto__: Array(0)
 
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-object-preview-expected.txt b/third_party/WebKit/LayoutTests/inspector/console/console-object-preview-expected.txt
index a57f53745..e69679b 100644
--- a/third_party/WebKit/LayoutTests/inspector/console/console-object-preview-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/console/console-object-preview-expected.txt
@@ -66,13 +66,13 @@
 console-object-preview.html:23 Object with many properties console-message > source-code > console-message-url devtools-link > console-message-text
 console-object-preview.html:28 Objectproperty_0: 0property_1: 1property_2: 2property_3: 3property_4: 4property_5: 5property_6: 6property_7: 7property_8: 8property_9: 9__proto__: Object console-message > source-code > console-message-url devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > value object-value-object > children
 console-object-preview.html:30 Array with many properties console-message > source-code > console-message-url devtools-link > console-message-text
-console-object-preview.html:35 Array(2)0: 01: 1length: 2property_0: 0property_1: 1property_2: 2property_3: 3property_4: 4property_5: 5property_6: 6property_7: 7property_8: 8property_9: 9__proto__: Array(0) console-message > source-code > console-message-url devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name object-properties-section-dimmed > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > value object-value-array > children
+console-object-preview.html:35 Array(2)0: 01: 1property_0: 0property_1: 1property_2: 2property_3: 3property_4: 4property_5: 5property_6: 6property_7: 7property_8: 8property_9: 9length: 2__proto__: Array(0) console-message > source-code > console-message-url devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name object-properties-section-dimmed > object-properties-section-separator > value object-value-number > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > value object-value-array > children
 console-object-preview.html:37 Object with proto console-message > source-code > console-message-url devtools-link > console-message-text
 console-object-preview.html:40 Objectd: 1__proto__: Object console-message > source-code > console-message-url devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > value object-value-number > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > value object-value-object > children
 console-object-preview.html:42 Sparse array console-message > source-code > console-message-url devtools-link > console-message-text
 console-object-preview.html:45 Array(150)50: 50length: 150__proto__: Array(0) console-message > source-code > console-message-url devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name object-properties-section-dimmed > object-properties-section-separator > value object-value-number > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > value object-value-array > children
 console-object-preview.html:47 Dense array with indexes and propeties console-message > source-code > console-message-url devtools-link > console-message-text
-console-object-preview.html:53 Array(150)[0 … 99][100 … 149]length: 150property_0: 0property_1: 1property_2: 2property_3: 3property_4: 4property_5: 5property_6: 6property_7: 7property_8: 8property_9: 9property_10: 10property_11: 11property_12: 12property_13: 13property_14: 14property_15: 15property_16: 16property_17: 17property_18: 18property_19: 19property_20: 20property_21: 21property_22: 22property_23: 23property_24: 24property_25: 25property_26: 26property_27: 27property_28: 28property_29: 29property_30: 30property_31: 31property_32: 32property_33: 33property_34: 34property_35: 35property_36: 36property_37: 37property_38: 38property_39: 39property_40: 40property_41: 41property_42: 42property_43: 43property_44: 44property_45: 45property_46: 46property_47: 47property_48: 48property_49: 49property_50: 50property_51: 51property_52: 52property_53: 53property_54: 54property_55: 55property_56: 56property_57: 57property_58: 58property_59: 59property_60: 60property_61: 61property_62: 62property_63: 63property_64:  console-message > source-code > console-message-url devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > object-state-note info-note > children expanded > parent object-properties-section-name > selection fill > tree-element-title > children > parent object-properties-section-name > selection fill > tree-element-title > children > selection fill > name object-properties-section-dimmed > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > value object-value-array > children
+console-object-preview.html:53 Array(150)[0 … 99][100 … 149]property_0: 0property_1: 1property_2: 2property_3: 3property_4: 4property_5: 5property_6: 6property_7: 7property_8: 8property_9: 9property_10: 10property_11: 11property_12: 12property_13: 13property_14: 14property_15: 15property_16: 16property_17: 17property_18: 18property_19: 19property_20: 20property_21: 21property_22: 22property_23: 23property_24: 24property_25: 25property_26: 26property_27: 27property_28: 28property_29: 29property_30: 30property_31: 31property_32: 32property_33: 33property_34: 34property_35: 35property_36: 36property_37: 37property_38: 38property_39: 39property_40: 40property_41: 41property_42: 42property_43: 43property_44: 44property_45: 45property_46: 46property_47: 47property_48: 48property_49: 49property_50: 50property_51: 51property_52: 52property_53: 53property_54: 54property_55: 55property_56: 56property_57: 57property_58: 58property_59: 59property_60: 60property_61: 61property_62: 62property_63: 63property_64: 64property_ console-message > source-code > console-message-url devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > object-state-note info-note > children expanded > parent object-properties-section-name > selection fill > tree-element-title > children > parent object-properties-section-name > selection fill > tree-element-title > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name > object-properties-section-separator > value object-value-number > children > selection fill > name object-properties-section-dimmed > object-properties-section-separator > value object-value-number > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > value object-value-array > children
 console-object-preview.html:55 Object with properties containing whitespaces console-message > source-code > console-message-url devtools-link > console-message-text
 console-object-preview.html:62 Object"": """  ": "  "" a b ": " a b ""a↵↵b↵c": "a↵↵b↵c"c d: "c d"__proto__: Object console-message > source-code > console-message-url devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > value object-value-string > children > selection fill > name > object-properties-section-separator > value object-value-string > children > selection fill > name > object-properties-section-separator > value object-value-string > children > selection fill > name > object-properties-section-separator > value object-value-string > children > selection fill > name > object-properties-section-separator > value object-value-string > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > value object-value-object > children
 console-object-preview.html:64 Object with a document.all property console-message > source-code > console-message-url devtools-link > console-message-text
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/edit/set-outer-html-test.js b/third_party/WebKit/LayoutTests/inspector/elements/edit/set-outer-html-test.js
index 4c98f10..d552395 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/edit/set-outer-html-test.js
+++ b/third_party/WebKit/LayoutTests/inspector/elements/edit/set-outer-html-test.js
@@ -24,6 +24,8 @@
 
         for (var key in SDK.DOMModel.Events) {
             var eventName = SDK.DOMModel.Events[key];
+            if (eventName === SDK.DOMModel.Events.MarkersChanged || eventName === SDK.DOMModel.Events.DOMMutated)
+                continue;
             InspectorTest.domModel.addEventListener(eventName, InspectorTest.recordEvent.bind(InspectorTest, eventName));
         }
 
@@ -33,7 +35,7 @@
 
 InspectorTest.recordEvent = function(eventName, event)
 {
-    if (!event.data || event.type === SDK.DOMModel.Events.MarkersChanged || event.type === SDK.DOMModel.Events.DOMMutated)
+    if (!event.data)
         return;
     var node = event.data.node || event.data;
     var parent = event.data.parent;
diff --git a/third_party/WebKit/LayoutTests/inspector/geolocation-emulation-tests-expected.txt b/third_party/WebKit/LayoutTests/inspector/geolocation-emulation-tests-expected.txt
index 430fb28..6af6e45f 100644
--- a/third_party/WebKit/LayoutTests/inspector/geolocation-emulation-tests-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/geolocation-emulation-tests-expected.txt
@@ -16,7 +16,6 @@
 error: Protocol Error: Invalid type of argument 'latitude' for method 'Emulation.setGeolocationOverride' call. It must be 'number' but it is 'boolean'.
 
 Running: testInvalidGeolocation
-error: Request Emulation.setGeolocationOverride failed. {"code":-32603,"message":"Invalid geolocation"}
 
 Running: testTimestampOfOverridenPosition
 
diff --git a/third_party/WebKit/LayoutTests/inspector/screen-orientation-override-expected.txt b/third_party/WebKit/LayoutTests/inspector/screen-orientation-override-expected.txt
index 711aab48..e954faa 100644
--- a/third_party/WebKit/LayoutTests/inspector/screen-orientation-override-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/screen-orientation-override-expected.txt
@@ -7,13 +7,13 @@
 Running: initial
 
 Running: setWrongAngle1
-error: Request Emulation.setDeviceMetricsOverride failed. {"code":-32602,"message":"Missing or invalid 'Screen orientation angle must be non-negative, less than 360' parameter"}
+error: Request Emulation.setDeviceMetricsOverride failed. {"code":-32602,"message":"Screen orientation angle must be non-negative, less than 360"}
 
 Running: setWrongAngle2
-error: Request Emulation.setDeviceMetricsOverride failed. {"code":-32602,"message":"Missing or invalid 'Screen orientation angle must be non-negative, less than 360' parameter"}
+error: Request Emulation.setDeviceMetricsOverride failed. {"code":-32602,"message":"Screen orientation angle must be non-negative, less than 360"}
 
 Running: setWrongType
-error: Request Emulation.setDeviceMetricsOverride failed. {"code":-32602,"message":"Missing or invalid 'Invalid screen orientation type value' parameter"}
+error: Request Emulation.setDeviceMetricsOverride failed. {"code":-32602,"message":"Invalid screen orientation type value"}
 
 Running: setPortraitPrimary
 angle: 0; type: portrait-primary
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-breakpoints/breakpoint-manager.js b/third_party/WebKit/LayoutTests/inspector/sources/debugger-breakpoints/breakpoint-manager.js
index 707e998..1abfd1619 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-breakpoints/breakpoint-manager.js
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-breakpoints/breakpoint-manager.js
@@ -236,6 +236,8 @@
         return this._target;
     }
 
+    setBeforePausedCallback(callback) { }
+
     _targetDisposed() { }
 
     debuggerEnabled()
diff --git a/third_party/WebKit/LayoutTests/intersection-observer/observer-in-iframe.html b/third_party/WebKit/LayoutTests/intersection-observer/observer-in-iframe.html
new file mode 100644
index 0000000..6a31e5f8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/intersection-observer/observer-in-iframe.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<iframe id="target-iframe" src="../resources/intersection-observer-in-iframe.html" style="height:100px; overflow-y:scroll"></iframe>
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/compositing/absolute-to-static-with-clip-expected.html b/third_party/WebKit/LayoutTests/paint/invalidation/compositing/absolute-to-static-with-clip-expected.html
new file mode 100644
index 0000000..f718ea6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/compositing/absolute-to-static-with-clip-expected.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<div style="width: 100px; height: 100px; background-color: green"></div>
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/compositing/absolute-to-static-with-clip.html b/third_party/WebKit/LayoutTests/paint/invalidation/compositing/absolute-to-static-with-clip.html
new file mode 100644
index 0000000..ad3f434
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/compositing/absolute-to-static-with-clip.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<div id="clipper" style="position: absolute; width: 100px; height: 100px;
+    background-color: green; clip: rect(25px 75px 75px 25px)">
+</div>
+<script src="../../../resources/run-after-layout-and-paint.js"></script>
+<script>
+runAfterLayoutAndPaint(function() {
+  clipper.style.position = 'static';
+}, true);
+</script>
diff --git a/third_party/WebKit/LayoutTests/compositing/clip-change-expected.png b/third_party/WebKit/LayoutTests/paint/invalidation/compositing/clip-change-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/compositing/clip-change-expected.png
rename to third_party/WebKit/LayoutTests/paint/invalidation/compositing/clip-change-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/compositing/clip-change-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/compositing/clip-change-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/compositing/clip-change-expected.txt
rename to third_party/WebKit/LayoutTests/paint/invalidation/compositing/clip-change-expected.txt
diff --git a/third_party/WebKit/LayoutTests/compositing/clip-change.html b/third_party/WebKit/LayoutTests/paint/invalidation/compositing/clip-change.html
similarity index 93%
rename from third_party/WebKit/LayoutTests/compositing/clip-change.html
rename to third_party/WebKit/LayoutTests/paint/invalidation/compositing/clip-change.html
index 6e8be7f..239fbccf 100644
--- a/third_party/WebKit/LayoutTests/compositing/clip-change.html
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/compositing/clip-change.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 <head>
-  <script src="../resources/run-after-layout-and-paint.js"></script>
+  <script src="../../../resources/run-after-layout-and-paint.js"></script>
   <style>
     #indicator {
       position: absolute;
diff --git a/third_party/WebKit/LayoutTests/compositing/layer-creation/iframe-clip-removed-expected.html b/third_party/WebKit/LayoutTests/paint/invalidation/compositing/iframe-clip-removed-expected.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/compositing/layer-creation/iframe-clip-removed-expected.html
rename to third_party/WebKit/LayoutTests/paint/invalidation/compositing/iframe-clip-removed-expected.html
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/compositing/iframe-clip-removed.html b/third_party/WebKit/LayoutTests/paint/invalidation/compositing/iframe-clip-removed.html
new file mode 100644
index 0000000..0c554ebb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/compositing/iframe-clip-removed.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<style>
+  #subframe {
+    width: 400px;
+    height: 500px;
+    background-color: blue;
+    position: relative;
+  }
+
+  #scroller {
+    height: 200px;
+    width: 300px;
+    position: absolute;
+    overflow: scroll;
+  }
+
+  #clip {
+    position: absolute;
+    clip: rect(0px, 100px, 100px, 0px);
+  }
+</style>
+<div id="scroller">
+  <div id="clip">
+    <iframe id="subframe"></iframe>
+  </div>
+</div>
+<script src="../../../resources/run-after-layout-and-paint.js"></script>
+<script>
+if (window.internals)
+  internals.settings.setPreferCompositingToLCDTextEnabled(true);
+runAfterLayoutAndPaint(function() {
+  clip.style.clip = "auto";
+}, true);
+</script>
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/compositing/static-to-absolute-with-clip-expected.html b/third_party/WebKit/LayoutTests/paint/invalidation/compositing/static-to-absolute-with-clip-expected.html
new file mode 100644
index 0000000..e9387b97
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/compositing/static-to-absolute-with-clip-expected.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<div style="position: relative; top: 25px; left: 25px;
+    width: 50px; height: 50px; background-color: green">
+</div>
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/compositing/static-to-absolute-with-clip.html b/third_party/WebKit/LayoutTests/paint/invalidation/compositing/static-to-absolute-with-clip.html
new file mode 100644
index 0000000..6667a72
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/compositing/static-to-absolute-with-clip.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<div id="clipper" style="width: 100px; height: 100px;
+    background-color: green; clip: rect(25px 75px 75px 25px)">
+</div>
+<script src="../../../resources/run-after-layout-and-paint.js"></script>
+<script>
+runAfterLayoutAndPaint(function() {
+  clipper.style.position = 'absolute';
+}, true);
+</script>
diff --git a/third_party/WebKit/LayoutTests/platform/android/compositing/overflow/scrollbar-layer-placement-expected.txt b/third_party/WebKit/LayoutTests/platform/android/compositing/overflow/scrollbar-layer-placement-expected.txt
deleted file mode 100644
index f817084..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/compositing/overflow/scrollbar-layer-placement-expected.txt
+++ /dev/null
@@ -1,256 +0,0 @@
-{
-  "name": "Content Root Layer",
-  "bounds": [800, 600],
-  "children": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "drawsContent": true,
-      "children": [
-        {
-          "name": "LayoutBlockFlow (positioned) DIV class='outer A'",
-          "position": [6, 6],
-          "bounds": [340, 282],
-          "drawsContent": true,
-          "children": [
-            {
-              "name": "LayoutBlockFlow (relative positioned) DIV class='scroller'",
-              "position": [32, 32],
-              "bounds": [278, 218],
-              "shouldFlattenTransform": false,
-              "drawsContent": true,
-              "backgroundColor": "#FFFFFF",
-              "children": [
-                {
-                  "name": "Scrolling Layer",
-                  "position": [29, 29],
-                  "bounds": [220, 160],
-                  "shouldFlattenTransform": false,
-                  "children": [
-                    {
-                      "name": "Scrolling Contents Layer",
-                      "bounds": [220, 236],
-                      "drawsContent": true
-                    }
-                  ]
-                },
-                {
-                  "name": "Overflow Controls Host Layer",
-                  "position": [24, 24],
-                  "bounds": [230, 170],
-                  "children": [
-                    {
-                      "name": "Vertical Scrollbar Layer",
-                      "position": [218, 5],
-                      "bounds": [7, 160]
-                    }
-                  ]
-                }
-              ]
-            }
-          ]
-        },
-        {
-          "name": "LayoutBlockFlow (positioned) DIV class='outer B'",
-          "position": [355, 6],
-          "bounds": [340, 282],
-          "drawsContent": true,
-          "children": [
-            {
-              "name": "LayoutBlockFlow DIV class='scroller'",
-              "position": [32, 32],
-              "bounds": [278, 218],
-              "shouldFlattenTransform": false,
-              "drawsContent": true,
-              "backgroundColor": "#FFFFFF",
-              "children": [
-                {
-                  "name": "Scrolling Layer",
-                  "position": [29, 29],
-                  "bounds": [220, 160],
-                  "shouldFlattenTransform": false,
-                  "children": [
-                    {
-                      "name": "Scrolling Contents Layer",
-                      "bounds": [220, 236],
-                      "drawsContent": true
-                    }
-                  ]
-                }
-              ]
-            },
-            {
-              "name": "LayoutBlockFlow (relative positioned) DIV class='content'",
-              "position": [73, 73],
-              "bounds": [196, 212],
-              "contentsOpaque": true,
-              "drawsContent": true,
-              "backgroundColor": "#DDDDDD"
-            },
-            {
-              "name": "Overflow Controls Host Layer",
-              "position": [56, 56],
-              "bounds": [230, 170],
-              "children": [
-                {
-                  "name": "Vertical Scrollbar Layer",
-                  "position": [218, 5],
-                  "bounds": [7, 160]
-                }
-              ]
-            }
-          ]
-        },
-        {
-          "name": "LayoutBlockFlow (positioned) DIV class='outer C'",
-          "position": [6, 297],
-          "bounds": [340, 282],
-          "drawsContent": true,
-          "children": [
-            {
-              "name": "Ancestor Clipping Layer",
-              "position": [40, 40],
-              "bounds": [260, 100],
-              "shouldFlattenTransform": false,
-              "children": [
-                {
-                  "name": "LayoutBlockFlow DIV class='scroller'",
-                  "position": [-9, -9],
-                  "bounds": [278, 218],
-                  "shouldFlattenTransform": false,
-                  "drawsContent": true,
-                  "backgroundColor": "#FFFFFF",
-                  "children": [
-                    {
-                      "name": "Scrolling Layer",
-                      "position": [29, 29],
-                      "bounds": [220, 160],
-                      "shouldFlattenTransform": false,
-                      "children": [
-                        {
-                          "name": "Scrolling Contents Layer",
-                          "bounds": [220, 236],
-                          "drawsContent": true
-                        }
-                      ]
-                    }
-                  ]
-                }
-              ]
-            },
-            {
-              "name": "LayoutBlockFlow (relative positioned) DIV class='content'",
-              "position": [72, 72],
-              "bounds": [196, 212],
-              "contentsOpaque": true,
-              "drawsContent": true,
-              "backgroundColor": "#DDDDDD"
-            },
-            {
-              "name": "Overflow Controls Ancestor Clipping Layer",
-              "position": [40, 40],
-              "bounds": [260, 100],
-              "children": [
-                {
-                  "name": "Overflow Controls Host Layer",
-                  "position": [15, 15],
-                  "bounds": [230, 170],
-                  "children": [
-                    {
-                      "name": "Vertical Scrollbar Layer",
-                      "position": [218, 5],
-                      "bounds": [7, 160]
-                    }
-                  ]
-                }
-              ]
-            }
-          ]
-        },
-        {
-          "name": "LayoutBlockFlow (positioned) DIV class='outer D'",
-          "position": [355, 297],
-          "bounds": [340, 282],
-          "drawsContent": true,
-          "children": [
-            {
-              "name": "LayoutBlockFlow (relative positioned) DIV class='clipper'",
-              "position": [24, 24],
-              "bounds": [292, 200],
-              "drawsContent": true,
-              "children": [
-                {
-                  "name": "Child Containment Layer",
-                  "position": [10, 10],
-                  "bounds": [272, 180],
-                  "children": [
-                    {
-                      "name": "Ancestor Clipping Layer",
-                      "position": [6, 6],
-                      "bounds": [260, 100],
-                      "shouldFlattenTransform": false,
-                      "children": [
-                        {
-                          "name": "LayoutBlockFlow DIV class='scroller'",
-                          "position": [-9, -9],
-                          "bounds": [278, 218],
-                          "shouldFlattenTransform": false,
-                          "drawsContent": true,
-                          "backgroundColor": "#FFFFFF",
-                          "children": [
-                            {
-                              "name": "Scrolling Layer",
-                              "position": [29, 29],
-                              "bounds": [220, 160],
-                              "shouldFlattenTransform": false,
-                              "children": [
-                                {
-                                  "name": "Scrolling Contents Layer",
-                                  "bounds": [220, 236],
-                                  "drawsContent": true
-                                }
-                              ]
-                            }
-                          ]
-                        }
-                      ]
-                    }
-                  ]
-                }
-              ]
-            },
-            {
-              "name": "LayoutBlockFlow (relative positioned) DIV class='content'",
-              "position": [72, 72],
-              "bounds": [196, 212],
-              "contentsOpaque": true,
-              "drawsContent": true,
-              "backgroundColor": "#DDDDDD"
-            },
-            {
-              "name": "Overflow Controls Ancestor Clipping Layer",
-              "position": [40, 40],
-              "bounds": [260, 100],
-              "children": [
-                {
-                  "name": "Overflow Controls Host Layer",
-                  "position": [15, 15],
-                  "bounds": [230, 170],
-                  "children": [
-                    {
-                      "name": "Vertical Scrollbar Layer",
-                      "position": [218, 5],
-                      "bounds": [7, 160]
-                    }
-                  ]
-                }
-              ]
-            }
-          ]
-        }
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/WebKit/LayoutTests/platform/android/svg/W3C-SVG-1.1-SE/coords-dom-02-f-expected.png b/third_party/WebKit/LayoutTests/platform/android/svg/W3C-SVG-1.1-SE/coords-dom-02-f-expected.png
index 54ff006c..d607997 100644
--- a/third_party/WebKit/LayoutTests/platform/android/svg/W3C-SVG-1.1-SE/coords-dom-02-f-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/android/svg/W3C-SVG-1.1-SE/coords-dom-02-f-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/svg/W3C-SVG-1.1-SE/coords-dom-02-f-expected.txt b/third_party/WebKit/LayoutTests/platform/android/svg/W3C-SVG-1.1-SE/coords-dom-02-f-expected.txt
index 9501ac5..ca7947be 100644
--- a/third_party/WebKit/LayoutTests/platform/android/svg/W3C-SVG-1.1-SE/coords-dom-02-f-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/android/svg/W3C-SVG-1.1-SE/coords-dom-02-f-expected.txt
@@ -1,5 +1,16 @@
 layer at (0,0) size 480x360
   LayoutView at (0,0) size 480x360
 layer at (0,0) size 480x360
-  LayoutBlockFlow {HTML} at (0,0) size 480x360
-    LayoutBlockFlow {BODY} at (8,8) size 464x344
+  LayoutSVGRoot {svg} at (0,0) size 480x360
+    LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
+    LayoutSVGContainer {g} at (160,140) size 160x80
+      LayoutSVGContainer {g} at (-60,-20) size 160x80 [transform={m=((1.00,0.00)(0.00,1.00)) t=(220.00,160.00)}]
+        LayoutSVGContainer {g} at (-60,-20) size 160x80
+          LayoutSVGEllipse {circle} at (-40,-40) size 80x80 [transform={m=((2.00,0.00)(0.00,1.00)) t=(20.00,20.00)}] [fill={[type=SOLID] [color=#FF0000]}] [cx=0.00] [cy=0.00] [r=40.00]
+        LayoutSVGContainer {g} at (-40,-40) size 80x80 [transform={m=((2.00,0.00)(0.00,1.00)) t=(20.00,20.00)}]
+          LayoutSVGEllipse {circle} at (-40,-40) size 80x80 [fill={[type=SOLID] [color=#00FF00]}] [cx=0.00] [cy=0.00] [r=40.00]
+    LayoutSVGContainer {g} at (10,311) size 231x36
+      LayoutSVGText {text} at (10,311) size 231x36 contains 1 chunk(s)
+        LayoutSVGInlineText {#text} at (10,311) size 231x36
+          chunk 1 text run 1 at (10.00,340.00) startOffset 0 endOffset 16 width 231.00: "$Revision: 1.7 $"
+    LayoutSVGRect {rect} at (1,1) size 478x358 [stroke={[type=SOLID] [color=#000000]}] [x=1.00] [y=1.00] [width=478.00] [height=358.00]
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-with-composited-child-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-with-composited-child-expected.png
index 7659089c..615d698f 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-with-composited-child-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-with-composited-child-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-with-composited-child-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-with-composited-child-expected.txt
index 89b3ca3..fd7a43ae 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-with-composited-child-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-with-composited-child-expected.txt
@@ -4,11 +4,11 @@
   LayoutBlockFlow {HTML} at (0,0) size 800x400
     LayoutBlockFlow {BODY} at (8,16) size 784x376
       LayoutBlockFlow {P} at (0,0) size 784x20
-        LayoutText {#text} at (0,0) size 255x19
-          text run at (0,0) width 255: "Below there should be a solid black circle."
+        LayoutText {#text} at (0,0) size 446x19
+          text run at (0,0) width 446: "Below there should be a solid green circle with a black border and no red."
       LayoutBlockFlow (anonymous) at (0,36) size 784x20
         LayoutBR {BR} at (0,0) size 0x19
 layer at (8,172) size 220x220 clip at (18,182) size 200x200 scrollWidth 250 scrollHeight 250
-  LayoutBlockFlow (relative positioned) zI: 1 {DIV} at (0,156) size 220x220 [bgcolor=#000000] [border: (10px solid #000000)]
+  LayoutBlockFlow (relative positioned) zI: 1 {DIV} at (0,156) size 220x220 [bgcolor=#FF0000] [border: (10px solid #000000)]
 layer at (-32,132) size 300x300 backgroundClip at (18,182) size 200x200 clip at (18,182) size 200x200
-  LayoutBlockFlow {DIV} at (-40,-40) size 300x300
+  LayoutBlockFlow {DIV} at (-40,-40) size 300x300 [bgcolor=#008000]
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/clip/overflow-border-radius-composited-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/clip/overflow-border-radius-composited-expected.png
index 3121adf..b936637 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/clip/overflow-border-radius-composited-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/clip/overflow-border-radius-composited-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/prefer_compositing_to_lcd_text/compositing/overflow/scrollbar-layer-placement-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/prefer_compositing_to_lcd_text/compositing/overflow/scrollbar-layer-placement-expected.txt
deleted file mode 100644
index cd12323f..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/prefer_compositing_to_lcd_text/compositing/overflow/scrollbar-layer-placement-expected.txt
+++ /dev/null
@@ -1,208 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "drawsContent": true
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='outer A'",
-      "position": [6, 6],
-      "bounds": [340, 282],
-      "drawsContent": true
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='scroller'",
-      "position": [32, 32],
-      "bounds": [278, 218],
-      "shouldFlattenTransform": false,
-      "drawsContent": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "position": [29, 29],
-      "bounds": [220, 160],
-      "shouldFlattenTransform": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [220, 236],
-      "drawsContent": true
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "position": [24, 24],
-      "bounds": [230, 170]
-    },
-    {
-      "name": "Vertical Scrollbar Layer",
-      "position": [218, 5],
-      "bounds": [7, 160]
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='outer B'",
-      "position": [355, 6],
-      "bounds": [340, 282],
-      "drawsContent": true
-    },
-    {
-      "name": "LayoutBlockFlow DIV class='scroller'",
-      "position": [32, 32],
-      "bounds": [278, 218],
-      "shouldFlattenTransform": false,
-      "drawsContent": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "position": [29, 29],
-      "bounds": [220, 160],
-      "shouldFlattenTransform": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [220, 236],
-      "drawsContent": true
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='content'",
-      "position": [73, 73],
-      "bounds": [196, 212],
-      "contentsOpaque": true,
-      "drawsContent": true,
-      "backgroundColor": "#DDDDDD"
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "position": [56, 56],
-      "bounds": [230, 170]
-    },
-    {
-      "name": "Vertical Scrollbar Layer",
-      "position": [218, 5],
-      "bounds": [7, 160]
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='outer C'",
-      "position": [6, 297],
-      "bounds": [340, 282],
-      "drawsContent": true
-    },
-    {
-      "name": "Ancestor Clipping Layer",
-      "position": [40, 40],
-      "bounds": [260, 100],
-      "shouldFlattenTransform": false
-    },
-    {
-      "name": "LayoutBlockFlow DIV class='scroller'",
-      "position": [-9, -9],
-      "bounds": [278, 218],
-      "shouldFlattenTransform": false,
-      "drawsContent": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "position": [29, 29],
-      "bounds": [220, 160],
-      "shouldFlattenTransform": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [220, 236],
-      "drawsContent": true
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='content'",
-      "position": [72, 72],
-      "bounds": [196, 212],
-      "contentsOpaque": true,
-      "drawsContent": true,
-      "backgroundColor": "#DDDDDD"
-    },
-    {
-      "name": "Overflow Controls Ancestor Clipping Layer",
-      "position": [40, 40],
-      "bounds": [260, 100]
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "position": [15, 15],
-      "bounds": [230, 170]
-    },
-    {
-      "name": "Vertical Scrollbar Layer",
-      "position": [218, 5],
-      "bounds": [7, 160]
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='outer D'",
-      "position": [355, 297],
-      "bounds": [340, 282],
-      "drawsContent": true
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='clipper'",
-      "position": [24, 24],
-      "bounds": [292, 200],
-      "drawsContent": true
-    },
-    {
-      "name": "Child Containment Layer",
-      "position": [10, 10],
-      "bounds": [272, 180]
-    },
-    {
-      "name": "Ancestor Clipping Layer",
-      "position": [6, 6],
-      "bounds": [260, 100],
-      "shouldFlattenTransform": false
-    },
-    {
-      "name": "LayoutBlockFlow DIV class='scroller'",
-      "position": [-9, -9],
-      "bounds": [278, 218],
-      "shouldFlattenTransform": false,
-      "drawsContent": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "position": [29, 29],
-      "bounds": [220, 160],
-      "shouldFlattenTransform": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [220, 236],
-      "drawsContent": true
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='content'",
-      "position": [72, 72],
-      "bounds": [196, 212],
-      "contentsOpaque": true,
-      "drawsContent": true,
-      "backgroundColor": "#DDDDDD"
-    },
-    {
-      "name": "Overflow Controls Ancestor Clipping Layer",
-      "position": [40, 40],
-      "bounds": [260, 100]
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "position": [15, 15],
-      "bounds": [230, 170]
-    },
-    {
-      "name": "Vertical Scrollbar Layer",
-      "position": [218, 5],
-      "bounds": [7, 160]
-    }
-  ]
-}
-
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/prefer_compositing_to_lcd_text/compositing/overflow/scrollbar-layer-placement-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/prefer_compositing_to_lcd_text/compositing/overflow/scrollbar-layer-placement-expected.txt
deleted file mode 100644
index cd12323f..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/prefer_compositing_to_lcd_text/compositing/overflow/scrollbar-layer-placement-expected.txt
+++ /dev/null
@@ -1,208 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "drawsContent": true
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='outer A'",
-      "position": [6, 6],
-      "bounds": [340, 282],
-      "drawsContent": true
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='scroller'",
-      "position": [32, 32],
-      "bounds": [278, 218],
-      "shouldFlattenTransform": false,
-      "drawsContent": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "position": [29, 29],
-      "bounds": [220, 160],
-      "shouldFlattenTransform": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [220, 236],
-      "drawsContent": true
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "position": [24, 24],
-      "bounds": [230, 170]
-    },
-    {
-      "name": "Vertical Scrollbar Layer",
-      "position": [218, 5],
-      "bounds": [7, 160]
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='outer B'",
-      "position": [355, 6],
-      "bounds": [340, 282],
-      "drawsContent": true
-    },
-    {
-      "name": "LayoutBlockFlow DIV class='scroller'",
-      "position": [32, 32],
-      "bounds": [278, 218],
-      "shouldFlattenTransform": false,
-      "drawsContent": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "position": [29, 29],
-      "bounds": [220, 160],
-      "shouldFlattenTransform": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [220, 236],
-      "drawsContent": true
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='content'",
-      "position": [73, 73],
-      "bounds": [196, 212],
-      "contentsOpaque": true,
-      "drawsContent": true,
-      "backgroundColor": "#DDDDDD"
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "position": [56, 56],
-      "bounds": [230, 170]
-    },
-    {
-      "name": "Vertical Scrollbar Layer",
-      "position": [218, 5],
-      "bounds": [7, 160]
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='outer C'",
-      "position": [6, 297],
-      "bounds": [340, 282],
-      "drawsContent": true
-    },
-    {
-      "name": "Ancestor Clipping Layer",
-      "position": [40, 40],
-      "bounds": [260, 100],
-      "shouldFlattenTransform": false
-    },
-    {
-      "name": "LayoutBlockFlow DIV class='scroller'",
-      "position": [-9, -9],
-      "bounds": [278, 218],
-      "shouldFlattenTransform": false,
-      "drawsContent": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "position": [29, 29],
-      "bounds": [220, 160],
-      "shouldFlattenTransform": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [220, 236],
-      "drawsContent": true
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='content'",
-      "position": [72, 72],
-      "bounds": [196, 212],
-      "contentsOpaque": true,
-      "drawsContent": true,
-      "backgroundColor": "#DDDDDD"
-    },
-    {
-      "name": "Overflow Controls Ancestor Clipping Layer",
-      "position": [40, 40],
-      "bounds": [260, 100]
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "position": [15, 15],
-      "bounds": [230, 170]
-    },
-    {
-      "name": "Vertical Scrollbar Layer",
-      "position": [218, 5],
-      "bounds": [7, 160]
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='outer D'",
-      "position": [355, 297],
-      "bounds": [340, 282],
-      "drawsContent": true
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='clipper'",
-      "position": [24, 24],
-      "bounds": [292, 200],
-      "drawsContent": true
-    },
-    {
-      "name": "Child Containment Layer",
-      "position": [10, 10],
-      "bounds": [272, 180]
-    },
-    {
-      "name": "Ancestor Clipping Layer",
-      "position": [6, 6],
-      "bounds": [260, 100],
-      "shouldFlattenTransform": false
-    },
-    {
-      "name": "LayoutBlockFlow DIV class='scroller'",
-      "position": [-9, -9],
-      "bounds": [278, 218],
-      "shouldFlattenTransform": false,
-      "drawsContent": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "position": [29, 29],
-      "bounds": [220, 160],
-      "shouldFlattenTransform": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [220, 236],
-      "drawsContent": true
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='content'",
-      "position": [72, 72],
-      "bounds": [196, 212],
-      "contentsOpaque": true,
-      "drawsContent": true,
-      "backgroundColor": "#DDDDDD"
-    },
-    {
-      "name": "Overflow Controls Ancestor Clipping Layer",
-      "position": [40, 40],
-      "bounds": [260, 100]
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "position": [15, 15],
-      "bounds": [230, 170]
-    },
-    {
-      "name": "Vertical Scrollbar Layer",
-      "position": [218, 5],
-      "bounds": [7, 160]
-    }
-  ]
-}
-
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/borders/border-radius-with-composited-child-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/borders/border-radius-with-composited-child-expected.png
index 667be4d..dd51cdc 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/borders/border-radius-with-composited-child-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/borders/border-radius-with-composited-child-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/borders/border-radius-with-composited-child-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/borders/border-radius-with-composited-child-expected.txt
index 52b99ab0..981b686 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/borders/border-radius-with-composited-child-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/borders/border-radius-with-composited-child-expected.txt
@@ -4,11 +4,11 @@
   LayoutBlockFlow {HTML} at (0,0) size 800x396
     LayoutBlockFlow {BODY} at (8,16) size 784x372
       LayoutBlockFlow {P} at (0,0) size 784x18
-        LayoutText {#text} at (0,0) size 272x18
-          text run at (0,0) width 272: "Below there should be a solid black circle."
+        LayoutText {#text} at (0,0) size 473x18
+          text run at (0,0) width 473: "Below there should be a solid green circle with a black border and no red."
       LayoutBlockFlow (anonymous) at (0,34) size 784x18
         LayoutBR {BR} at (0,0) size 0x18
 layer at (8,168) size 220x220 clip at (18,178) size 200x200 scrollWidth 250 scrollHeight 250
-  LayoutBlockFlow (relative positioned) zI: 1 {DIV} at (0,152) size 220x220 [bgcolor=#000000] [border: (10px solid #000000)]
+  LayoutBlockFlow (relative positioned) zI: 1 {DIV} at (0,152) size 220x220 [bgcolor=#FF0000] [border: (10px solid #000000)]
 layer at (-32,128) size 300x300 backgroundClip at (18,178) size 200x200 clip at (18,178) size 200x200
-  LayoutBlockFlow {DIV} at (-40,-40) size 300x300
+  LayoutBlockFlow {DIV} at (-40,-40) size 300x300 [bgcolor=#008000]
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/clip/overflow-border-radius-composited-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/clip/overflow-border-radius-composited-expected.png
index ee32eca..4bf08438 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/clip/overflow-border-radius-composited-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/clip/overflow-border-radius-composited-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/borders/border-radius-with-composited-child-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/borders/border-radius-with-composited-child-expected.png
index e78d1de6..566c0b5c 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/borders/border-radius-with-composited-child-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/borders/border-radius-with-composited-child-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/borders/border-radius-with-composited-child-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/borders/border-radius-with-composited-child-expected.txt
index b9168fc1..9be3ba9 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/borders/border-radius-with-composited-child-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/borders/border-radius-with-composited-child-expected.txt
@@ -4,11 +4,11 @@
   LayoutBlockFlow {HTML} at (0,0) size 800x396
     LayoutBlockFlow {BODY} at (8,16) size 784x372
       LayoutBlockFlow {P} at (0,0) size 784x18
-        LayoutText {#text} at (0,0) size 272x17
-          text run at (0,0) width 272: "Below there should be a solid black circle."
+        LayoutText {#text} at (0,0) size 473x17
+          text run at (0,0) width 473: "Below there should be a solid green circle with a black border and no red."
       LayoutBlockFlow (anonymous) at (0,34) size 784x18
         LayoutBR {BR} at (0,0) size 0x17
 layer at (8,168) size 220x220 clip at (18,178) size 200x200 scrollWidth 250 scrollHeight 250
-  LayoutBlockFlow (relative positioned) zI: 1 {DIV} at (0,152) size 220x220 [bgcolor=#000000] [border: (10px solid #000000)]
+  LayoutBlockFlow (relative positioned) zI: 1 {DIV} at (0,152) size 220x220 [bgcolor=#FF0000] [border: (10px solid #000000)]
 layer at (-32,128) size 300x300 backgroundClip at (18,178) size 200x200 clip at (18,178) size 200x200
-  LayoutBlockFlow {DIV} at (-40,-40) size 300x300
+  LayoutBlockFlow {DIV} at (-40,-40) size 300x300 [bgcolor=#008000]
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/clip/overflow-border-radius-composited-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/clip/overflow-border-radius-composited-expected.png
index bf9eaea3..3c48d1f 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/clip/overflow-border-radius-composited-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/clip/overflow-border-radius-composited-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/prefer_compositing_to_lcd_text/compositing/overflow/scrollbar-layer-placement-expected.txt b/third_party/WebKit/LayoutTests/platform/win/virtual/prefer_compositing_to_lcd_text/compositing/overflow/scrollbar-layer-placement-expected.txt
deleted file mode 100644
index cd12323f..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/prefer_compositing_to_lcd_text/compositing/overflow/scrollbar-layer-placement-expected.txt
+++ /dev/null
@@ -1,208 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "drawsContent": true
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='outer A'",
-      "position": [6, 6],
-      "bounds": [340, 282],
-      "drawsContent": true
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='scroller'",
-      "position": [32, 32],
-      "bounds": [278, 218],
-      "shouldFlattenTransform": false,
-      "drawsContent": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "position": [29, 29],
-      "bounds": [220, 160],
-      "shouldFlattenTransform": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [220, 236],
-      "drawsContent": true
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "position": [24, 24],
-      "bounds": [230, 170]
-    },
-    {
-      "name": "Vertical Scrollbar Layer",
-      "position": [218, 5],
-      "bounds": [7, 160]
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='outer B'",
-      "position": [355, 6],
-      "bounds": [340, 282],
-      "drawsContent": true
-    },
-    {
-      "name": "LayoutBlockFlow DIV class='scroller'",
-      "position": [32, 32],
-      "bounds": [278, 218],
-      "shouldFlattenTransform": false,
-      "drawsContent": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "position": [29, 29],
-      "bounds": [220, 160],
-      "shouldFlattenTransform": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [220, 236],
-      "drawsContent": true
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='content'",
-      "position": [73, 73],
-      "bounds": [196, 212],
-      "contentsOpaque": true,
-      "drawsContent": true,
-      "backgroundColor": "#DDDDDD"
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "position": [56, 56],
-      "bounds": [230, 170]
-    },
-    {
-      "name": "Vertical Scrollbar Layer",
-      "position": [218, 5],
-      "bounds": [7, 160]
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='outer C'",
-      "position": [6, 297],
-      "bounds": [340, 282],
-      "drawsContent": true
-    },
-    {
-      "name": "Ancestor Clipping Layer",
-      "position": [40, 40],
-      "bounds": [260, 100],
-      "shouldFlattenTransform": false
-    },
-    {
-      "name": "LayoutBlockFlow DIV class='scroller'",
-      "position": [-9, -9],
-      "bounds": [278, 218],
-      "shouldFlattenTransform": false,
-      "drawsContent": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "position": [29, 29],
-      "bounds": [220, 160],
-      "shouldFlattenTransform": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [220, 236],
-      "drawsContent": true
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='content'",
-      "position": [72, 72],
-      "bounds": [196, 212],
-      "contentsOpaque": true,
-      "drawsContent": true,
-      "backgroundColor": "#DDDDDD"
-    },
-    {
-      "name": "Overflow Controls Ancestor Clipping Layer",
-      "position": [40, 40],
-      "bounds": [260, 100]
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "position": [15, 15],
-      "bounds": [230, 170]
-    },
-    {
-      "name": "Vertical Scrollbar Layer",
-      "position": [218, 5],
-      "bounds": [7, 160]
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='outer D'",
-      "position": [355, 297],
-      "bounds": [340, 282],
-      "drawsContent": true
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='clipper'",
-      "position": [24, 24],
-      "bounds": [292, 200],
-      "drawsContent": true
-    },
-    {
-      "name": "Child Containment Layer",
-      "position": [10, 10],
-      "bounds": [272, 180]
-    },
-    {
-      "name": "Ancestor Clipping Layer",
-      "position": [6, 6],
-      "bounds": [260, 100],
-      "shouldFlattenTransform": false
-    },
-    {
-      "name": "LayoutBlockFlow DIV class='scroller'",
-      "position": [-9, -9],
-      "bounds": [278, 218],
-      "shouldFlattenTransform": false,
-      "drawsContent": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "position": [29, 29],
-      "bounds": [220, 160],
-      "shouldFlattenTransform": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [220, 236],
-      "drawsContent": true
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='content'",
-      "position": [72, 72],
-      "bounds": [196, 212],
-      "contentsOpaque": true,
-      "drawsContent": true,
-      "backgroundColor": "#DDDDDD"
-    },
-    {
-      "name": "Overflow Controls Ancestor Clipping Layer",
-      "position": [40, 40],
-      "bounds": [260, 100]
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "position": [15, 15],
-      "bounds": [230, 170]
-    },
-    {
-      "name": "Vertical Scrollbar Layer",
-      "position": [218, 5],
-      "bounds": [7, 160]
-    }
-  ]
-}
-
diff --git a/third_party/WebKit/LayoutTests/resources/intersection-observer-in-iframe.html b/third_party/WebKit/LayoutTests/resources/intersection-observer-in-iframe.html
new file mode 100644
index 0000000..e06b1d1c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/resources/intersection-observer-in-iframe.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script src="../resources/intersection-observer-helper-functions.js"></script>
+
+<div style="height: 200px; width: 100px;"></div>
+<div id="target" style="background-color: green; width:100px; height:100px"></div>
+<div style="height: 200px; width: 100px;"></div>
+
+<script>
+setup({message_events: [], output_document: window.parent.document});
+onload = function() {
+  var entries = [];
+  var observer = new IntersectionObserver(function(changes) { entries = entries.concat(changes) }, {});
+  var target = document.getElementById("target");
+  var scroller = document.scrollingElement;
+  observer.observe(target);
+  entries = entries.concat(observer.takeRecords());
+  var t = async_test("IntersectionObserver in iframe with explicit root.");
+  test(function() { assert_equals(entries.length, 0) }, "No initial notifications.")
+  waitForNotification(t.step_func(step1));
+
+  function step1() {
+    test(function() { assert_equals(entries.length, 0) }, "No notifications after first rAF.");
+    scroller.scrollTop = 250;
+    waitForNotification(t.step_func(step2));
+  }
+
+  function step2() {
+    test(function() { assert_equals(entries.length, 1) }, "One notification.");
+    if (entries.length) {
+      test(function() { assert_equals(entries[0].boundingClientRect.left, 8) }, "entries[0].boundingClientRect.left");
+      test(function() { assert_equals(entries[0].boundingClientRect.right, 108) }, "entries[0].boundingClientRect.right");
+      test(function() { assert_equals(entries[0].boundingClientRect.top, -42) }, "entries[0].boundingClientRect.top");
+      test(function() { assert_equals(entries[0].boundingClientRect.bottom, 58) }, "entries[0].boundingClientRect.bottom");
+      test(function() { assert_equals(entries[0].intersectionRect.left, 8) }, "entries[0].intersectionRect.left");
+      test(function() { assert_equals(entries[0].intersectionRect.right, 108) }, "entries[0].intersectionRect.right");
+      test(function() { assert_equals(entries[0].intersectionRect.top, 0) }, "entries[0].intersectionRect.top");
+      test(function() { assert_equals(entries[0].intersectionRect.bottom, 58) }, "entries[0].intersectionRect.bottom");
+      test(function() { assert_equals(entries[0].rootBounds.left, 0) }, "entries[0].rootBounds.left");
+      test(function() { assert_equals(entries[0].rootBounds.right, 800) }, "entries[0].rootBounds.right");
+      test(function() { assert_equals(entries[0].rootBounds.top, 0) }, "entries[0].rootBounds.top");
+      test(function() { assert_equals(entries[0].rootBounds.bottom, 600) }, "entries[0].rootBounds.bottom");
+      test(function() { assert_true(entries[0].target === target) }, "entries[0].target object identity");
+    }
+    t.done();
+  }
+};
+</script>
diff --git a/third_party/WebKit/LayoutTests/sensor/resources/sensor-helpers.js b/third_party/WebKit/LayoutTests/sensor/resources/sensor-helpers.js
index ff79ae5..262145f 100644
--- a/third_party/WebKit/LayoutTests/sensor/resources/sensor-helpers.js
+++ b/third_party/WebKit/LayoutTests/sensor/resources/sensor-helpers.js
@@ -244,10 +244,10 @@
       }
 
       // Returns initialized Sensor proxy to the client.
-      getSensor(type, stub) {
+      getSensor(type, request) {
         if (this.get_sensor_should_fail_) {
-          return getSensorResponse(null,
-              connection.bindProxy(null, sensor.SensorClient));
+          var ignored = new sensor.SensorClientPtr();
+          return getSensorResponse(null, bindings.makeRequest(ignored));
         }
 
         let offset =
@@ -258,6 +258,7 @@
         }
 
         if (this.active_sensor_ == null) {
+          var stub = connection.bindHandleToStub(request.handle, sensor.Sensor);
           let mockSensor = new MockSensor(stub, this.shared_buffer_handle_,
               offset, this.reading_size_in_bytes_, reporting_mode);
           this.active_sensor_ = mockSensor;
@@ -284,10 +285,11 @@
           this.resolve_func_(this.active_sensor_);
         }
 
-        var client_handle = connection.bindProxy(proxy => {
-          this.active_sensor_.client_ = proxy;
-          }, sensor.SensorClient);
-        return getSensorResponse(init_params, client_handle);
+        var client_request = new bindings.InterfaceRequest(
+            connection.bindProxy(proxy => {
+              this.active_sensor_.client_ = proxy;
+            }, sensor.SensorClient));
+        return getSensorResponse(init_params, client_request);
       }
 
       // Binds object to mojo message pipe
diff --git a/third_party/WebKit/LayoutTests/storage/indexeddb/idbdatabase-createObjectStore-exception-order.html b/third_party/WebKit/LayoutTests/storage/indexeddb/idbdatabase-createObjectStore-exception-order.html
index 5de8ed6..490019d 100644
--- a/third_party/WebKit/LayoutTests/storage/indexeddb/idbdatabase-createObjectStore-exception-order.html
+++ b/third_party/WebKit/LayoutTests/storage/indexeddb/idbdatabase-createObjectStore-exception-order.html
@@ -11,17 +11,18 @@
   (t, db, req) => {
     db.createObjectStore('s');
 
-    req.transaction.abort();
+    req.transaction.onabort = () => {
+      setTimeout(t.step_func(() => {
+        assert_throws(
+          'InvalidStateError', () => { db.createObjectStore('s2'); },
+          '"running an upgrade transaction" check (InvalidStateError) ' +
+          'should precede "not active" check (TransactionInactiveError)');
+
+        t.done();
+      }), 0);
+    };
     req.onerror = null;
-
-    setTimeout(t.step_func(() => {
-      assert_throws(
-        'InvalidStateError', () => { db.createObjectStore('s2'); },
-        '"running an upgrade transaction" check (InvalidStateError) ' +
-        'should precede "not active" check (TransactionInactiveError)');
-
-      t.done();
-    }), 0);
+    req.transaction.abort();
   },
   (t, db) => { t.assert_unreached('open should fail'); },
   'IDBDatabase.createObjectStore exception order: ' +
@@ -32,8 +33,8 @@
   (t, db, req) => {
     const store = db.createObjectStore('s');
 
-    req.transaction.abort();
     req.onerror = null;
+    req.transaction.abort();
 
     assert_throws(
       'TransactionInactiveError',
diff --git a/third_party/WebKit/LayoutTests/storage/indexeddb/idbdatabase-deleteObjectStore-exception-order.html b/third_party/WebKit/LayoutTests/storage/indexeddb/idbdatabase-deleteObjectStore-exception-order.html
index a45190c0..b411393 100644
--- a/third_party/WebKit/LayoutTests/storage/indexeddb/idbdatabase-deleteObjectStore-exception-order.html
+++ b/third_party/WebKit/LayoutTests/storage/indexeddb/idbdatabase-deleteObjectStore-exception-order.html
@@ -10,15 +10,17 @@
 indexeddb_test(
   (t, db, req) => {
     db.createObjectStore('s');
-    req.transaction.abort();
+    req.transaction.onabort = () => {
+      setTimeout(t.step_func(() => {
+        assert_throws(
+          'InvalidStateError', () => { db.deleteObjectStore('s'); },
+          '"running an upgrade transaction" check (InvalidStateError) ' +
+          'should precede "not active" check (TransactionInactiveError)');
+        t.done();
+      }), 0);
+    };
     req.onerror = null;
-    setTimeout(t.step_func(() => {
-      assert_throws(
-        'InvalidStateError', () => { db.deleteObjectStore('s'); },
-        '"running an upgrade transaction" check (InvalidStateError) ' +
-        'should precede "not active" check (TransactionInactiveError)');
-      t.done();
-    }), 0);
+    req.transaction.abort();
   },
   (t, db) => { t.assert_unreached('open should fail'); },
   'IDBDatabase.deleteObjectStore exception order: ' +
@@ -27,8 +29,8 @@
 
 indexeddb_test(
   (t, db, req) => {
-    req.transaction.abort();
     req.onerror = null;
+    req.transaction.abort();
     assert_throws(
       'TransactionInactiveError', () => { db.deleteObjectStore('nope'); },
       '"not active" check (TransactionInactiveError) should precede ' +
diff --git a/third_party/WebKit/LayoutTests/svg/transforms/text-with-transform-and-zoom-expected.html b/third_party/WebKit/LayoutTests/svg/transforms/text-with-transform-and-zoom-expected.html
new file mode 100644
index 0000000..5fc78bb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/transforms/text-with-transform-and-zoom-expected.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<div style="width: 200px; height: 100px; background-color: green"></div>
diff --git a/third_party/WebKit/LayoutTests/svg/transforms/text-with-transform-and-zoom.html b/third_party/WebKit/LayoutTests/svg/transforms/text-with-transform-and-zoom.html
new file mode 100644
index 0000000..e795309
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/transforms/text-with-transform-and-zoom.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<script src="../../resources/ahem.js"></script>
+<svg height="100" width="100" style="zoom: 2" fill="green" font-family="Ahem" font-size="50px">
+  <text transform="translate(-50,-40)" x="50" y="80">X</text>
+  <text style="transform: translate(-50px, -40px)" x="100" y="80">X</text>
+</svg>
diff --git a/third_party/WebKit/LayoutTests/usb/resources/usb-helpers.js b/third_party/WebKit/LayoutTests/usb/resources/usb-helpers.js
index b0687fb..455601e 100644
--- a/third_party/WebKit/LayoutTests/usb/resources/usb-helpers.js
+++ b/third_party/WebKit/LayoutTests/usb/resources/usb-helpers.js
@@ -374,18 +374,19 @@
         return Promise.resolve({ results: devices });
       }
 
-      getDevice(guid, stub) {
-        let device = this.mockDevices_.get(guid);
-        if (device === undefined) {
-          bindings.StubBindings(stub).close();
+      getDevice(guid, request) {
+        let deviceData = this.mockDevices_.get(guid);
+        if (deviceData === undefined) {
+          request.close();
         } else {
-          var mock = new MockDevice(device.info);
+          var stub = connection.bindHandleToStub(request.handle, device.Device);
+          var mock = new MockDevice(deviceData.info);
           bindings.StubBindings(stub).delegate = mock;
           bindings.StubBindings(stub).connectionErrorHandler = () => {
             if (this.deviceCloseHandler_)
-              this.deviceCloseHandler_(device.info);
+              this.deviceCloseHandler_(deviceData.info);
           };
-          device.stubs.push(stub);
+          deviceData.stubs.push(stub);
         }
       }
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScheduledAction.cpp b/third_party/WebKit/Source/bindings/core/v8/ScheduledAction.cpp
index aace7e2..183a6f5 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScheduledAction.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScheduledAction.cpp
@@ -61,17 +61,7 @@
   visitor->trace(m_code);
 }
 
-ScheduledAction::~ScheduledAction() {
-  // Verify that owning DOMTimer has eagerly disposed.
-  DCHECK(m_info.IsEmpty());
-}
-
-void ScheduledAction::dispose() {
-  m_code.dispose();
-  m_info.Clear();
-  m_function.clear();
-  m_scriptState.clear();
-}
+ScheduledAction::~ScheduledAction() {}
 
 void ScheduledAction::execute(ExecutionContext* context) {
   if (context->isDocument()) {
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScheduledAction.h b/third_party/WebKit/Source/bindings/core/v8/ScheduledAction.h
index b65d36ee..28a80e4 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScheduledAction.h
+++ b/third_party/WebKit/Source/bindings/core/v8/ScheduledAction.h
@@ -56,8 +56,6 @@
   static ScheduledAction* create(ScriptState*, const String& handler);
 
   ~ScheduledAction();
-  void dispose();
-
   DECLARE_TRACE();
 
   void execute(ExecutionContext*);
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptSourceCode.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptSourceCode.cpp
index ef9de04..9c7f78f 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptSourceCode.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptSourceCode.cpp
@@ -36,13 +36,6 @@
 
 ScriptSourceCode::~ScriptSourceCode() {}
 
-void ScriptSourceCode::dispose() {
-  m_source = String();
-  m_resource = nullptr;
-  m_streamer = nullptr;
-  m_url = KURL();
-}
-
 DEFINE_TRACE(ScriptSourceCode) {
   visitor->trace(m_resource);
   visitor->trace(m_streamer);
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptSourceCode.h b/third_party/WebKit/Source/bindings/core/v8/ScriptSourceCode.h
index 15651270..3af0431 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptSourceCode.h
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptSourceCode.h
@@ -56,7 +56,6 @@
   ScriptSourceCode(ScriptStreamer*, ScriptResource*);
 
   ~ScriptSourceCode();
-  void dispose();
   DECLARE_TRACE();
 
   bool isEmpty() const { return m_source.isEmpty(); }
@@ -66,13 +65,13 @@
   bool isNull() const { return m_source.isNull(); }
 
   const String& source() const { return m_source; }
-  ScriptResource* resource() const { return m_resource; }
+  ScriptResource* resource() const { return m_resource.get(); }
   const KURL& url() const;
   int startLine() const { return m_startPosition.m_line.oneBasedInt(); }
   const TextPosition& startPosition() const { return m_startPosition; }
   String sourceMapUrl() const;
 
-  ScriptStreamer* streamer() const { return m_streamer; }
+  ScriptStreamer* streamer() const { return m_streamer.get(); }
 
  private:
   void treatNullSourceAsEmpty();
diff --git a/third_party/WebKit/Source/bindings/scripts/code_generator_web_module.py b/third_party/WebKit/Source/bindings/scripts/code_generator_web_module.py
index 0e44aea..5868b00 100644
--- a/third_party/WebKit/Source/bindings/scripts/code_generator_web_module.py
+++ b/third_party/WebKit/Source/bindings/scripts/code_generator_web_module.py
@@ -38,46 +38,62 @@
 
 
 def interface_context(idl_interface):
-    attributes = []
-    methods = []
-    includes = set()
+    builder = InterfaceContextBuilder(MODULE_PYNAME)
+    builder.set_class_name(idl_interface.name)
+
     for idl_attribute in idl_interface.attributes:
-        attributes.append(Attribute.create(idl_attribute))
-        includes.update(includes_for_type(idl_attribute.idl_type))
+        builder.add_attribute(idl_attribute)
+
     for idl_operation in idl_interface.operations:
+        builder.add_operation(idl_operation)
+
+    return builder.build()
+
+
+class InterfaceContextBuilder(object):
+    def __init__(self, code_generator):
+        self.result = {'code_generator': code_generator}
+
+    def set_class_name(self, class_name):
+        self.result['class_name'] = class_name
+
+    def _ensure_set(self, name):
+        return self.result.setdefault(name, set())
+
+    def _ensure_list(self, name):
+        return self.result.setdefault(name, [])
+
+    def add_attribute(self, idl_attribute):
+        self._ensure_list('attributes').append(
+            self.create_attribute(idl_attribute))
+        self._ensure_set('cpp_includes').update(
+            includes_for_type(idl_attribute.idl_type))
+
+    def add_operation(self, idl_operation):
         if idl_operation.name:
-            methods.append(Method.create(idl_operation))
-    return {
-        'code_generator': MODULE_PYNAME,
-        'class_name': idl_interface.name,
-        'cpp_includes': includes,
-        'attributes': attributes,
-        'methods': methods,
-    }
+            self._ensure_list('methods').append(
+                self.create_method(idl_operation))
+            self._ensure_set('cpp_includes').update(
+                includes_for_type(idl_operation.idl_type))
 
-
-class Attribute(object):
-    def __init__(self, name, return_type):
-        self.name = name
-        self.return_type = return_type
-
-    @staticmethod
-    def create(idl_attribute):
-        name = idl_attribute.name
-        return_type = idl_attribute.idl_type.preprocessed_type.base_type
-        return Attribute(name, return_type)
-
-
-class Method(object):
-    def __init__(self, name, return_type):
-        self.name = name
-        self.return_type = return_type
-
-    @staticmethod
-    def create(idl_operation):
+    def create_method(self, idl_operation):
         name = idl_operation.name
         return_type = idl_operation.idl_type.preprocessed_type.base_type
-        return Method(name, return_type)
+        return {
+            'name': name,
+            'return_type': return_type
+        }
+
+    def create_attribute(self, idl_attribute):
+        name = idl_attribute.name
+        return_type = idl_attribute.idl_type.preprocessed_type.base_type
+        return {
+            'name': name,
+            'return_type': return_type
+        }
+
+    def build(self):
+        return self.result
 
 
 class CodeGeneratorWebModule(CodeGeneratorBase):
@@ -102,7 +118,7 @@
         # TODO(dglazkov): Implement callback interfaces.
         # TODO(dglazkov): Make sure partial interfaces are handled.
         if interface.is_callback or interface.is_partial:
-            raise ValueError("Partial or callback interfaces are not supported")
+            raise ValueError('Partial or callback interfaces are not supported')
 
         template_context = interface_context(interface)
 
diff --git a/third_party/WebKit/Source/bindings/scripts/code_generator_web_module_test.py b/third_party/WebKit/Source/bindings/scripts/code_generator_web_module_test.py
new file mode 100644
index 0000000..28c81af
--- /dev/null
+++ b/third_party/WebKit/Source/bindings/scripts/code_generator_web_module_test.py
@@ -0,0 +1,77 @@
+# 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.
+
+# pylint: disable=import-error,print-statement,relative-import
+
+"""Unit tests for code_generator_web_module.py."""
+
+import unittest
+
+from code_generator_web_module import InterfaceContextBuilder
+
+
+class IdlTestingHelper(object):
+    """A collection of stub makers and helper utils to make testing code
+    generation easy."""
+
+    def make_stub_object(self):
+        return type('', (), {})()
+
+    def add_idl_type_to_stub(self, stub, return_type):
+        stub.idl_type = self.make_stub_object()
+        stub.idl_type.preprocessed_type = self.make_stub_object()
+        stub.idl_type.preprocessed_type.base_type = return_type
+
+    def make_stub_idl_attribute(self, name, return_type):
+        idl_attribute_stub = self.make_stub_object()
+        idl_attribute_stub.name = name
+        self.add_idl_type_to_stub(idl_attribute_stub, return_type)
+        return idl_attribute_stub
+
+    def make_stub_idl_operation(self, name, return_type):
+        idl_operation_stub = self.make_stub_object()
+        idl_operation_stub.name = name
+        self.add_idl_type_to_stub(idl_operation_stub, return_type)
+        return idl_operation_stub
+
+
+class InterfaceContextBuilderTest(unittest.TestCase):
+
+    def test_empty(self):
+        builder = InterfaceContextBuilder('test')
+
+        self.assertEqual({'code_generator': 'test'}, builder.build())
+
+    def test_set_name(self):
+        builder = InterfaceContextBuilder('test')
+
+        builder.set_class_name('foo')
+        self.assertEqual({
+            'code_generator': 'test',
+            'class_name': 'foo',
+        }, builder.build())
+
+    def test_add_attribute(self):
+        helper = IdlTestingHelper()
+        builder = InterfaceContextBuilder('test')
+
+        attribute = helper.make_stub_idl_attribute('foo', 'bar')
+        builder.add_attribute(attribute)
+        self.assertEqual({
+            'code_generator': 'test',
+            'cpp_includes': set(['bar']),
+            'attributes': [{'name': 'foo', 'return_type': 'bar'}],
+        }, builder.build())
+
+    def test_add_method(self):
+        helper = IdlTestingHelper()
+        builder = InterfaceContextBuilder('test')
+
+        operation = helper.make_stub_idl_operation('foo', 'bar')
+        builder.add_operation(operation)
+        self.assertEqual({
+            'code_generator': 'test',
+            'cpp_includes': set(['bar']),
+            'methods': [{'name': 'foo', 'return_type': 'bar'}],
+        }, builder.build())
diff --git a/third_party/WebKit/Source/bindings/templates/web_module_interface.h.tmpl b/third_party/WebKit/Source/bindings/templates/web_module_interface.h.tmpl
index bf9489f..199c7b3 100644
--- a/third_party/WebKit/Source/bindings/templates/web_module_interface.h.tmpl
+++ b/third_party/WebKit/Source/bindings/templates/web_module_interface.h.tmpl
@@ -2,6 +2,24 @@
 
 {% include 'copyright_block.txt' %}
 
-// TODO(dglazkov): Implement generating the header file.
+// TODO(dglazkov): Use chromium-style path.
+#ifndef {{class_name}}_h
+#define {{class_name}}_h
 
-{% endfilter %}
\ No newline at end of file
+{% for include_file in header_includes %}
+#include "{{include_file}}"
+{% endfor %}
+
+namespace blink {
+namespace api {
+
+class {{class_name}} {
+
+};
+
+}  // namespace api
+}  // namespace blink
+
+#endif  // {{class_name}}_h
+
+{% endfilter %}
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/WebTestInterface3.cpp b/third_party/WebKit/Source/bindings/tests/results/core/WebTestInterface3.cpp
index a8675cd..f6715a41 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/WebTestInterface3.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/WebTestInterface3.cpp
@@ -10,6 +10,8 @@
 #include "WebTestInterface3.h"
 
 // TODO(dglazkov): Implement generating includes.
+#include "Webvoid.h"
+#include "WebIterator.h"
 #include "WebDOMString.h"
 
 namespace blink {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/WebTestInterface3.h b/third_party/WebKit/Source/bindings/tests/results/core/WebTestInterface3.h
index d998585..35de42be 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/WebTestInterface3.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/WebTestInterface3.h
@@ -7,4 +7,17 @@
 
 // clang-format off
 
-// TODO(dglazkov): Implement generating the header file.
+// TODO(dglazkov): Use chromium-style path.
+#ifndef TestInterface3_h
+#define TestInterface3_h
+
+namespace blink {
+namespace api {
+
+class TestInterface3 {
+};
+
+}  // namespace api
+}  // namespace blink
+
+#endif  // TestInterface3_h
diff --git a/third_party/WebKit/Source/build/scripts/make_computed_style_base.py b/third_party/WebKit/Source/build/scripts/make_computed_style_base.py
index 19a0e73..b88d4132 100755
--- a/third_party/WebKit/Source/build/scripts/make_computed_style_base.py
+++ b/third_party/WebKit/Source/build/scripts/make_computed_style_base.py
@@ -35,8 +35,8 @@
         self.name = kwargs.pop('name')
         # Name of property field is for
         self.property_name = kwargs.pop('property_name')
-        # Field storage type
-        self.type = kwargs.pop('type')
+        # Internal field storage type
+        self.storage_type = kwargs.pop('storage_type')
         # Bits needed for storage
         self.size = kwargs.pop('size')
         # Default value for field
@@ -112,7 +112,7 @@
                         'inherited_flag',
                         name='m_' + field_name_suffix_lower,
                         property_name=property['name'],
-                        type='bool',
+                        storage_type='bool',
                         size=1,
                         default_value='true',
                         getter_method_name=field_name_suffix_lower,
@@ -128,7 +128,7 @@
                     property_name=property['name'],
                     inherited=property['inherited'],
                     independent=property['independent'],
-                    type=type_name,
+                    storage_type=type_name,
                     size=int(math.ceil(bits_needed)),
                     default_value=default_value,
                     getter_method_name=property_name_lower,
diff --git a/third_party/WebKit/Source/build/scripts/templates/ComputedStyleBase.h.tmpl b/third_party/WebKit/Source/build/scripts/templates/ComputedStyleBase.h.tmpl
index 515603c..b7da448d 100644
--- a/third_party/WebKit/Source/build/scripts/templates/ComputedStyleBase.h.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/ComputedStyleBase.h.tmpl
@@ -100,16 +100,16 @@
   // use resetFoo(), which can be more efficient.
   {% for field in fields %}
   // {{field.property_name}}
-  inline static {{field.type}} {{field.initial_method_name}}() { return {{field.default_value}}; }
-  {{field.type}} {{field.getter_method_name}}() const { return static_cast<{{field.type}}>({{field.name}}); }
-  void {{field.setter_method_name}}({{field.type}} v) { {{field.name}} = static_cast<unsigned>(v); }
+  inline static {{field.storage_type}} {{field.initial_method_name}}() { return {{field.default_value}}; }
+  {{field.storage_type}} {{field.getter_method_name}}() const { return static_cast<{{field.storage_type}}>({{field.name}}); }
+  void {{field.setter_method_name}}({{field.storage_type}} v) { {{field.name}} = static_cast<unsigned>(v); }
   inline void {{field.resetter_method_name}}() { {{field.name}} = {{default_value(field)}}; }
 
   {% endfor %}
  protected:
   // Storage.
   {% for field in fields %}
-  unsigned {{field.name}} : {{field.size}}; // {{field.type}}
+  unsigned {{field.name}} : {{field.size}}; // {{field.storage_type}}
   {% endfor %}
 };
 
diff --git a/third_party/WebKit/Source/core/animation/AnimationClock.cpp b/third_party/WebKit/Source/core/animation/AnimationClock.cpp
index f8f4ec0..761be63 100644
--- a/third_party/WebKit/Source/core/animation/AnimationClock.cpp
+++ b/third_party/WebKit/Source/core/animation/AnimationClock.cpp
@@ -43,16 +43,16 @@
 
 namespace blink {
 
-unsigned AnimationClock::s_currentTask = 0;
+unsigned AnimationClock::s_currentlyRunningTask = 0;
 
 void AnimationClock::updateTime(double time) {
   if (time > m_time)
     m_time = time;
-  m_currentTask = s_currentTask;
+  m_taskForWhichTimeWasCalculated = s_currentlyRunningTask;
 }
 
 double AnimationClock::currentTime() {
-  if (m_currentTask != s_currentTask) {
+  if (m_taskForWhichTimeWasCalculated != s_currentlyRunningTask) {
     const double currentTime = m_monotonicallyIncreasingTime();
     if (m_time < currentTime) {
       // Advance to the first estimated frame after the current time.
@@ -63,7 +63,7 @@
       DCHECK_LE(newTime, currentTime + approximateFrameTime);
       updateTime(newTime);
     } else {
-      m_currentTask = s_currentTask;
+      m_taskForWhichTimeWasCalculated = s_currentlyRunningTask;
     }
   }
   return m_time;
@@ -71,8 +71,8 @@
 
 void AnimationClock::resetTimeForTesting(double time) {
   m_time = time;
-  m_currentTask = 0;
-  s_currentTask = 0;
+  m_taskForWhichTimeWasCalculated = 0;
+  s_currentlyRunningTask = 0;
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/animation/AnimationClock.h b/third_party/WebKit/Source/core/animation/AnimationClock.h
index c5d38f0..f668463 100644
--- a/third_party/WebKit/Source/core/animation/AnimationClock.h
+++ b/third_party/WebKit/Source/core/animation/AnimationClock.h
@@ -35,10 +35,14 @@
 #include "wtf/Allocator.h"
 #include "wtf/CurrentTime.h"
 #include "wtf/Noncopyable.h"
+
 #include <limits>
 
 namespace blink {
 
+// Maintains a stationary clock time during script execution.  Tries to track
+// the glass time (the moment photons leave the screen) of the current animation
+// frame.
 class CORE_EXPORT AnimationClock {
   DISALLOW_NEW();
   WTF_MAKE_NONCOPYABLE(AnimationClock);
@@ -48,19 +52,21 @@
                               WTF::monotonicallyIncreasingTime)
       : m_monotonicallyIncreasingTime(monotonicallyIncreasingTime),
         m_time(0),
-        m_currentTask(std::numeric_limits<unsigned>::max()) {}
+        m_taskForWhichTimeWasCalculated(std::numeric_limits<unsigned>::max()) {}
 
   void updateTime(double time);
   double currentTime();
   void resetTimeForTesting(double time = 0);
 
-  static void notifyTaskStart() { ++s_currentTask; }
+  // notifyTaskStart should be called right before the main message loop starts
+  // to run the next task from the message queue.
+  static void notifyTaskStart() { ++s_currentlyRunningTask; }
 
  private:
   WTF::TimeFunction m_monotonicallyIncreasingTime;
   double m_time;
-  unsigned m_currentTask;
-  static unsigned s_currentTask;
+  unsigned m_taskForWhichTimeWasCalculated;
+  static unsigned s_currentlyRunningTask;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/ActiveStyleSheets.cpp b/third_party/WebKit/Source/core/css/ActiveStyleSheets.cpp
index 5c53263..cca65e7 100644
--- a/third_party/WebKit/Source/core/css/ActiveStyleSheets.cpp
+++ b/third_party/WebKit/Source/core/css/ActiveStyleSheets.cpp
@@ -16,7 +16,7 @@
 ActiveSheetsChange compareActiveStyleSheets(
     const ActiveStyleSheetVector& oldStyleSheets,
     const ActiveStyleSheetVector& newStyleSheets,
-    HeapVector<Member<RuleSet>>& changedRuleSets) {
+    HeapHashSet<Member<RuleSet>>& changedRuleSets) {
   unsigned newStyleSheetCount = newStyleSheets.size();
   unsigned oldStyleSheetCount = oldStyleSheets.size();
 
@@ -32,32 +32,34 @@
       continue;
 
     if (newStyleSheets[index].second)
-      changedRuleSets.append(newStyleSheets[index].second);
+      changedRuleSets.add(newStyleSheets[index].second);
     if (oldStyleSheets[index].second)
-      changedRuleSets.append(oldStyleSheets[index].second);
+      changedRuleSets.add(oldStyleSheets[index].second);
   }
 
   if (index == oldStyleSheetCount) {
-    if (index == newStyleSheetCount)
-      return changedRuleSets.size() ? ActiveSheetsChanged
-                                    : NoActiveSheetsChanged;
+    if (index == newStyleSheetCount) {
+      return changedRuleSets.isEmpty() ? NoActiveSheetsChanged
+                                       : ActiveSheetsChanged;
+    }
 
     // Sheets added at the end.
     for (; index < newStyleSheetCount; index++) {
       if (newStyleSheets[index].second)
-        changedRuleSets.append(newStyleSheets[index].second);
+        changedRuleSets.add(newStyleSheets[index].second);
     }
-    return changedRuleSets.size() ? ActiveSheetsAppended
-                                  : NoActiveSheetsChanged;
+    return changedRuleSets.isEmpty() ? NoActiveSheetsChanged
+                                     : ActiveSheetsAppended;
   }
 
   if (index == newStyleSheetCount) {
     // Sheets removed from the end.
     for (; index < oldStyleSheetCount; index++) {
       if (oldStyleSheets[index].second)
-        changedRuleSets.append(oldStyleSheets[index].second);
+        changedRuleSets.add(oldStyleSheets[index].second);
     }
-    return changedRuleSets.size() ? ActiveSheetsChanged : NoActiveSheetsChanged;
+    return changedRuleSets.isEmpty() ? NoActiveSheetsChanged
+                                     : ActiveSheetsChanged;
   }
 
   DCHECK(index < oldStyleSheetCount && index < newStyleSheetCount);
@@ -83,7 +85,7 @@
         (*mergedIterator).first != sheet1.first) {
       // Sheet either removed or inserted.
       if (sheet1.second)
-        changedRuleSets.append(sheet1.second);
+        changedRuleSets.add(sheet1.second);
       continue;
     }
 
@@ -96,11 +98,12 @@
     // Active rules for the given stylesheet changed.
     // DOM, CSSOM, or media query changes.
     if (sheet1.second)
-      changedRuleSets.append(sheet1.second);
+      changedRuleSets.add(sheet1.second);
     if (sheet2.second)
-      changedRuleSets.append(sheet2.second);
+      changedRuleSets.add(sheet2.second);
   }
-  return changedRuleSets.size() ? ActiveSheetsChanged : NoActiveSheetsChanged;
+  return changedRuleSets.isEmpty() ? NoActiveSheetsChanged
+                                   : ActiveSheetsChanged;
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/ActiveStyleSheets.h b/third_party/WebKit/Source/core/css/ActiveStyleSheets.h
index 266f86a5..3fd84492 100644
--- a/third_party/WebKit/Source/core/css/ActiveStyleSheets.h
+++ b/third_party/WebKit/Source/core/css/ActiveStyleSheets.h
@@ -25,7 +25,7 @@
 CORE_EXPORT ActiveSheetsChange
 compareActiveStyleSheets(const ActiveStyleSheetVector& oldStyleSheets,
                          const ActiveStyleSheetVector& newStyleSheets,
-                         HeapVector<Member<RuleSet>>& changedRuleSets);
+                         HeapHashSet<Member<RuleSet>>& changedRuleSets);
 
 }  // namespace blink
 
diff --git a/third_party/WebKit/Source/core/css/ActiveStyleSheetsTest.cpp b/third_party/WebKit/Source/core/css/ActiveStyleSheetsTest.cpp
index 4a46941d..288b3a3 100644
--- a/third_party/WebKit/Source/core/css/ActiveStyleSheetsTest.cpp
+++ b/third_party/WebKit/Source/core/css/ActiveStyleSheetsTest.cpp
@@ -57,7 +57,7 @@
 TEST_F(ActiveStyleSheetsTest, CompareActiveStyleSheets_NoChange) {
   ActiveStyleSheetVector oldSheets;
   ActiveStyleSheetVector newSheets;
-  HeapVector<Member<RuleSet>> changedRuleSets;
+  HeapHashSet<Member<RuleSet>> changedRuleSets;
 
   EXPECT_EQ(NoActiveSheetsChanged,
             compareActiveStyleSheets(oldSheets, newSheets, changedRuleSets));
@@ -80,7 +80,7 @@
 TEST_F(ActiveStyleSheetsTest, CompareActiveStyleSheets_AppendedToEmpty) {
   ActiveStyleSheetVector oldSheets;
   ActiveStyleSheetVector newSheets;
-  HeapVector<Member<RuleSet>> changedRuleSets;
+  HeapHashSet<Member<RuleSet>> changedRuleSets;
 
   CSSStyleSheet* sheet1 = createSheet();
   CSSStyleSheet* sheet2 = createSheet();
@@ -96,7 +96,7 @@
 TEST_F(ActiveStyleSheetsTest, CompareActiveStyleSheets_AppendedToNonEmpty) {
   ActiveStyleSheetVector oldSheets;
   ActiveStyleSheetVector newSheets;
-  HeapVector<Member<RuleSet>> changedRuleSets;
+  HeapHashSet<Member<RuleSet>> changedRuleSets;
 
   CSSStyleSheet* sheet1 = createSheet();
   CSSStyleSheet* sheet2 = createSheet();
@@ -113,7 +113,7 @@
 TEST_F(ActiveStyleSheetsTest, CompareActiveStyleSheets_Mutated) {
   ActiveStyleSheetVector oldSheets;
   ActiveStyleSheetVector newSheets;
-  HeapVector<Member<RuleSet>> changedRuleSets;
+  HeapHashSet<Member<RuleSet>> changedRuleSets;
 
   CSSStyleSheet* sheet1 = createSheet();
   CSSStyleSheet* sheet2 = createSheet();
@@ -135,15 +135,15 @@
 
   EXPECT_EQ(ActiveSheetsChanged,
             compareActiveStyleSheets(oldSheets, newSheets, changedRuleSets));
-  ASSERT_EQ(2u, changedRuleSets.size());
-  EXPECT_EQ(&sheet2->contents()->ruleSet(), changedRuleSets[0]);
-  EXPECT_EQ(oldSheets[1].second, changedRuleSets[1]);
+  EXPECT_EQ(2u, changedRuleSets.size());
+  EXPECT_TRUE(changedRuleSets.contains(&sheet2->contents()->ruleSet()));
+  EXPECT_TRUE(changedRuleSets.contains(oldSheets[1].second));
 }
 
 TEST_F(ActiveStyleSheetsTest, CompareActiveStyleSheets_Inserted) {
   ActiveStyleSheetVector oldSheets;
   ActiveStyleSheetVector newSheets;
-  HeapVector<Member<RuleSet>> changedRuleSets;
+  HeapHashSet<Member<RuleSet>> changedRuleSets;
 
   CSSStyleSheet* sheet1 = createSheet();
   CSSStyleSheet* sheet2 = createSheet();
@@ -158,14 +158,14 @@
 
   EXPECT_EQ(ActiveSheetsChanged,
             compareActiveStyleSheets(oldSheets, newSheets, changedRuleSets));
-  ASSERT_EQ(1u, changedRuleSets.size());
-  EXPECT_EQ(&sheet2->contents()->ruleSet(), changedRuleSets[0]);
+  EXPECT_EQ(1u, changedRuleSets.size());
+  EXPECT_TRUE(changedRuleSets.contains(&sheet2->contents()->ruleSet()));
 }
 
 TEST_F(ActiveStyleSheetsTest, CompareActiveStyleSheets_Removed) {
   ActiveStyleSheetVector oldSheets;
   ActiveStyleSheetVector newSheets;
-  HeapVector<Member<RuleSet>> changedRuleSets;
+  HeapHashSet<Member<RuleSet>> changedRuleSets;
 
   CSSStyleSheet* sheet1 = createSheet();
   CSSStyleSheet* sheet2 = createSheet();
@@ -180,14 +180,14 @@
 
   EXPECT_EQ(ActiveSheetsChanged,
             compareActiveStyleSheets(oldSheets, newSheets, changedRuleSets));
-  ASSERT_EQ(1u, changedRuleSets.size());
-  EXPECT_EQ(&sheet2->contents()->ruleSet(), changedRuleSets[0]);
+  EXPECT_EQ(1u, changedRuleSets.size());
+  EXPECT_TRUE(changedRuleSets.contains(&sheet2->contents()->ruleSet()));
 }
 
 TEST_F(ActiveStyleSheetsTest, CompareActiveStyleSheets_RemovedAll) {
   ActiveStyleSheetVector oldSheets;
   ActiveStyleSheetVector newSheets;
-  HeapVector<Member<RuleSet>> changedRuleSets;
+  HeapHashSet<Member<RuleSet>> changedRuleSets;
 
   CSSStyleSheet* sheet1 = createSheet();
   CSSStyleSheet* sheet2 = createSheet();
@@ -205,7 +205,7 @@
 TEST_F(ActiveStyleSheetsTest, CompareActiveStyleSheets_InsertedAndRemoved) {
   ActiveStyleSheetVector oldSheets;
   ActiveStyleSheetVector newSheets;
-  HeapVector<Member<RuleSet>> changedRuleSets;
+  HeapHashSet<Member<RuleSet>> changedRuleSets;
 
   CSSStyleSheet* sheet1 = createSheet();
   CSSStyleSheet* sheet2 = createSheet();
@@ -219,15 +219,15 @@
 
   EXPECT_EQ(ActiveSheetsChanged,
             compareActiveStyleSheets(oldSheets, newSheets, changedRuleSets));
-  ASSERT_EQ(2u, changedRuleSets.size());
-  EXPECT_EQ(&sheet1->contents()->ruleSet(), changedRuleSets[0]);
-  EXPECT_EQ(&sheet3->contents()->ruleSet(), changedRuleSets[1]);
+  EXPECT_EQ(2u, changedRuleSets.size());
+  EXPECT_TRUE(changedRuleSets.contains(&sheet1->contents()->ruleSet()));
+  EXPECT_TRUE(changedRuleSets.contains(&sheet3->contents()->ruleSet()));
 }
 
 TEST_F(ActiveStyleSheetsTest, CompareActiveStyleSheets_AddNullRuleSet) {
   ActiveStyleSheetVector oldSheets;
   ActiveStyleSheetVector newSheets;
-  HeapVector<Member<RuleSet>> changedRuleSets;
+  HeapHashSet<Member<RuleSet>> changedRuleSets;
 
   CSSStyleSheet* sheet1 = createSheet();
   CSSStyleSheet* sheet2 = createSheet();
@@ -245,7 +245,7 @@
 TEST_F(ActiveStyleSheetsTest, CompareActiveStyleSheets_RemoveNullRuleSet) {
   ActiveStyleSheetVector oldSheets;
   ActiveStyleSheetVector newSheets;
-  HeapVector<Member<RuleSet>> changedRuleSets;
+  HeapHashSet<Member<RuleSet>> changedRuleSets;
 
   CSSStyleSheet* sheet1 = createSheet();
   CSSStyleSheet* sheet2 = createSheet();
@@ -263,7 +263,7 @@
 TEST_F(ActiveStyleSheetsTest, CompareActiveStyleSheets_AddRemoveNullRuleSet) {
   ActiveStyleSheetVector oldSheets;
   ActiveStyleSheetVector newSheets;
-  HeapVector<Member<RuleSet>> changedRuleSets;
+  HeapHashSet<Member<RuleSet>> changedRuleSets;
 
   CSSStyleSheet* sheet1 = createSheet();
   CSSStyleSheet* sheet2 = createSheet();
@@ -284,7 +284,7 @@
        CompareActiveStyleSheets_RemoveNullRuleSetAndAppend) {
   ActiveStyleSheetVector oldSheets;
   ActiveStyleSheetVector newSheets;
-  HeapVector<Member<RuleSet>> changedRuleSets;
+  HeapHashSet<Member<RuleSet>> changedRuleSets;
 
   CSSStyleSheet* sheet1 = createSheet();
   CSSStyleSheet* sheet2 = createSheet();
@@ -298,14 +298,14 @@
 
   EXPECT_EQ(ActiveSheetsChanged,
             compareActiveStyleSheets(oldSheets, newSheets, changedRuleSets));
-  ASSERT_EQ(1u, changedRuleSets.size());
-  EXPECT_EQ(&sheet3->contents()->ruleSet(), changedRuleSets[0]);
+  EXPECT_EQ(1u, changedRuleSets.size());
+  EXPECT_TRUE(changedRuleSets.contains(&sheet3->contents()->ruleSet()));
 }
 
 TEST_F(ActiveStyleSheetsTest, CompareActiveStyleSheets_ReorderedImportSheets) {
   ActiveStyleSheetVector oldSheets;
   ActiveStyleSheetVector newSheets;
-  HeapVector<Member<RuleSet>> changedRuleSets;
+  HeapHashSet<Member<RuleSet>> changedRuleSets;
 
   CSSStyleSheet* sheet1 = createSheet();
   CSSStyleSheet* sheet2 = createSheet();
diff --git a/third_party/WebKit/Source/core/css/BUILD.gn b/third_party/WebKit/Source/core/css/BUILD.gn
index ee9de4d..3adf69f9 100644
--- a/third_party/WebKit/Source/core/css/BUILD.gn
+++ b/third_party/WebKit/Source/core/css/BUILD.gn
@@ -344,6 +344,11 @@
     "parser/MediaQueryParser.cpp",
     "parser/SizesAttributeParser.cpp",
     "parser/SizesCalcParser.cpp",
+    "properties/CSSPropertyAPI.h",
+    "properties/CSSPropertyAPIPadding.cpp",
+    "properties/CSSPropertyAPIPadding.h",
+    "properties/CSSPropertyDescriptor.cpp",
+    "properties/CSSPropertyDescriptor.h",
     "resolver/AnimatedStyleBuilder.cpp",
     "resolver/AnimatedStyleBuilder.h",
     "resolver/CSSToStyleMap.cpp",
diff --git a/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h b/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
index a270ca7d..84f09b5 100644
--- a/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
+++ b/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
@@ -2791,13 +2791,13 @@
 inline CSSIdentifierValue::CSSIdentifierValue(EOverflowAnchor e)
     : CSSValue(IdentifierClass) {
   switch (e) {
-    case AnchorVisible:
+    case EOverflowAnchor::Visible:
       m_valueID = CSSValueVisible;
       break;
-    case AnchorNone:
+    case EOverflowAnchor::None:
       m_valueID = CSSValueNone;
       break;
-    case AnchorAuto:
+    case EOverflowAnchor::Auto:
       m_valueID = CSSValueAuto;
       break;
   }
@@ -2807,17 +2807,17 @@
 inline EOverflowAnchor CSSIdentifierValue::convertTo() const {
   switch (m_valueID) {
     case CSSValueVisible:
-      return AnchorVisible;
+      return EOverflowAnchor::Visible;
     case CSSValueNone:
-      return AnchorNone;
+      return EOverflowAnchor::None;
     case CSSValueAuto:
-      return AnchorAuto;
+      return EOverflowAnchor::Auto;
     default:
       break;
   }
 
   NOTREACHED();
-  return AnchorNone;
+  return EOverflowAnchor::None;
 }
 
 template <>
diff --git a/third_party/WebKit/Source/core/css/CSSProperties.in b/third_party/WebKit/Source/core/css/CSSProperties.in
index f548744..5983a69 100644
--- a/third_party/WebKit/Source/core/css/CSSProperties.in
+++ b/third_party/WebKit/Source/core/css/CSSProperties.in
@@ -266,7 +266,7 @@
 lighting-color interpolable, svg, converter=convertColor
 line-height interpolable, inherited, getter=specifiedLineHeight, converter=convertLineHeight
 list-style-image interpolable, inherited, custom_value, typedom_types=[Image]
-list-style-position inherited, keyword_only, keywords=[outside|inside], initial_keyword=outside
+list-style-position inherited, independent, keyword_only, keywords=[outside|inside], initial_keyword=outside
 list-style-type inherited
 margin-bottom interpolable, initial=initialMargin, converter=convertQuirkyLength
 margin-left interpolable, initial=initialMargin, converter=convertQuirkyLength
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
index daef2e7..3987a7b 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
@@ -41,6 +41,7 @@
 #include "core/css/parser/CSSParserIdioms.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 #include "core/css/parser/CSSVariableParser.h"
+#include "core/css/properties/CSSPropertyDescriptor.h"
 #include "core/frame/UseCounter.h"
 #include "core/layout/LayoutTheme.h"
 #include "core/svg/SVGPathUtilities.h"
@@ -3465,6 +3466,17 @@
                                   m_range.peek().id());
     return consumeIdent(m_range);
   }
+
+  // Gets the parsing function for our current property from the property API.
+  // If it has been implemented, we call this function, otherwise we manually
+  // parse this value in the switch statement below. As we implement APIs for
+  // other properties, those properties will be taken out of the switch
+  // statement.
+  const CSSPropertyDescriptor& cssPropertyDesc =
+      CSSPropertyDescriptor::get(property);
+  if (cssPropertyDesc.temporaryCanReadValue)
+    return cssPropertyDesc.parseSingleValue(m_range, m_context);
+
   switch (property) {
     case CSSPropertyWillChange:
       return consumeWillChange(m_range);
@@ -3558,13 +3570,6 @@
       return consumeLengthOrPercent(m_range, m_context.mode(),
                                     ValueRangeNonNegative,
                                     UnitlessQuirk::Allow);
-    case CSSPropertyWebkitPaddingStart:
-    case CSSPropertyWebkitPaddingEnd:
-    case CSSPropertyWebkitPaddingBefore:
-    case CSSPropertyWebkitPaddingAfter:
-      return consumeLengthOrPercent(m_range, m_context.mode(),
-                                    ValueRangeNonNegative,
-                                    UnitlessQuirk::Forbid);
     case CSSPropertyClip:
       return consumeClip(m_range, m_context.mode());
     case CSSPropertyTouchAction:
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPI.h b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPI.h
new file mode 100644
index 0000000..3a62dbf
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPI.h
@@ -0,0 +1,43 @@
+// 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 CSSPropertyAPI_h
+#define CSSPropertyAPI_h
+
+#include "core/CSSPropertyNames.h"
+#include "core/css/CSSValue.h"
+#include "core/css/parser/CSSParserMode.h"
+#include "core/css/parser/CSSParserTokenRange.h"
+
+namespace blink {
+
+// We will use this API to represent all functions used for property-specific
+// logic inside the blink style engine. All specific properties are subclasses
+// of CSSPropertyAPI.
+//
+// To add a new property using this API:
+// - Make a class that implements CSSPropertyAPI, and implement the static
+//   methods.
+// - Update the cssPropertyDescriptors array in CSSPropertyDescriptor.cpp to
+//   call GET_DESCRIPTOR(classname).
+//
+// To add new functions using this API:
+// - New functions and static variables can be added in this class. A default
+//   implementation of functions can optionally be provided.
+// - When adding new functions, also add them to GET_DESCRIPTOR, and the get()
+//   method in CSSPropertyDescriptors.cpp, and the descriptor struct in
+//   CSSPropertyDescriptor.h.
+class CSSPropertyAPI {
+  STATIC_ONLY(CSSPropertyAPI);
+
+ public:
+  // Parses a single CSS property and returns the corresponding CSSValue. If the
+  // input is invalid it returns nullptr.
+  static const CSSValue* parseSingleValue(CSSParserTokenRange&,
+                                          const CSSParserContext&);
+};
+
+}  // namespace blink
+
+#endif  // CSSPropertyAPI_h
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIPadding.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIPadding.cpp
new file mode 100644
index 0000000..5a46c31e
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIPadding.cpp
@@ -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.
+
+#include "core/css/properties/CSSPropertyAPIPadding.h"
+
+#include "core/css/parser/CSSParserTokenRange.h"
+#include "core/css/parser/CSSPropertyParserHelpers.h"
+
+namespace blink {
+
+const CSSValue* CSSPropertyAPIWebkitPadding::parseSingleValue(
+    CSSParserTokenRange& range,
+    const CSSParserContext& context) {
+  return consumeLengthOrPercent(
+      range, context.mode(), ValueRangeNonNegative,
+      CSSPropertyParserHelpers::UnitlessQuirk::Forbid);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIPadding.h b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIPadding.h
new file mode 100644
index 0000000..3e57dac
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIPadding.h
@@ -0,0 +1,26 @@
+// 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 CSSPropertyAPIPadding_h
+#define CSSPropertyAPIPadding_h
+
+#include "core/CSSPropertyNames.h"
+#include "core/css/properties/CSSPropertyAPI.h"
+
+namespace blink {
+
+// TODO(aazzam): Generate API .h files
+
+class CSSParserTokenRange;
+class CSSParserContext;
+
+class CSSPropertyAPIWebkitPadding : public CSSPropertyAPI {
+ public:
+  static const CSSValue* parseSingleValue(CSSParserTokenRange&,
+                                          const CSSParserContext&);
+};
+
+}  // namespace blink
+
+#endif  // CSSPropertyAPIPadding_h
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyDescriptor.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyDescriptor.cpp
new file mode 100644
index 0000000..10e7726
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyDescriptor.cpp
@@ -0,0 +1,50 @@
+// 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/css/properties/CSSPropertyDescriptor.h"
+
+#include "core/css/properties/CSSPropertyAPIPadding.h"
+
+namespace blink {
+
+// Initialises a CSSPropertyDescriptor. When functions are added to
+// CSSPropertyAPI, also add them to the struct initaliser below.
+#define GET_DESCRIPTOR(X) \
+  { X::parseSingleValue, true }
+
+// Initialises an invalid CSSPropertyDescriptor. When functions are added to
+// CSSPropertyAPI, add a nullptr to represent their function pointers in the
+// struct initaliser.
+#define GET_INVALID_DESCRIPTOR() \
+  { nullptr, false }
+
+static_assert(
+    std::is_pod<CSSPropertyDescriptor>::value,
+    "CSSPropertyDescriptor must be a POD to support using initializer lists.");
+
+static CSSPropertyDescriptor cssPropertyDescriptors[] = {
+    GET_INVALID_DESCRIPTOR(), GET_DESCRIPTOR(CSSPropertyAPIWebkitPadding),
+};
+
+const CSSPropertyDescriptor& CSSPropertyDescriptor::get(CSSPropertyID id) {
+  // TODO(aazzam): We are currently using hard-coded indexes for
+  // cssPropertyDescriptor since we have only implemented a few properties.
+  // Later, generate this switch statement, or alternatively return
+  // cssPropertyDescriptors[id], and generate the cssPropertyDescriptors array
+  // to hold invalid descriptors for methods which haven't been implemented yet.
+  switch (id) {
+    case CSSPropertyWebkitPaddingEnd:
+      return cssPropertyDescriptors[1];
+    case CSSPropertyWebkitPaddingStart:
+      return cssPropertyDescriptors[1];
+    case CSSPropertyWebkitPaddingBefore:
+      return cssPropertyDescriptors[1];
+    case CSSPropertyWebkitPaddingAfter:
+      return cssPropertyDescriptors[1];
+    default:
+      return cssPropertyDescriptors[0];
+  }
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyDescriptor.h b/third_party/WebKit/Source/core/css/properties/CSSPropertyDescriptor.h
new file mode 100644
index 0000000..ad1f73bc
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyDescriptor.h
@@ -0,0 +1,31 @@
+// 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/CSSPropertyNames.h"
+
+namespace blink {
+
+class CSSValue;
+class CSSParserTokenRange;
+class CSSParserContext;
+
+// Stores function pointers matching those declared in CSSPropertyAPI.
+struct CSSPropertyDescriptor {
+  const CSSValue* (*parseSingleValue)(CSSParserTokenRange&,
+                                      const CSSParserContext&);
+
+  // Stores whether or not this descriptor is for a valid property. Do not
+  // access the contents of this descriptor unless this value is true.
+  // TODO(aazzam): Remove this once the switch in
+  // CSSPropertyParser::parseSingleValue() has been completely replaced by
+  // CSSPropertyDescriptors.
+  bool temporaryCanReadValue;
+
+  // Returns the corresponding CSSPropertyDescriptor for a given CSSPropertyID.
+  // Use this function to access the API for a property. Returns a descriptor
+  // with isValid set to false if no descriptor exists for this ID.
+  static const CSSPropertyDescriptor& get(CSSPropertyID);
+};
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/BUILD.gn b/third_party/WebKit/Source/core/dom/BUILD.gn
index 55c3620..ac209c0 100644
--- a/third_party/WebKit/Source/core/dom/BUILD.gn
+++ b/third_party/WebKit/Source/core/dom/BUILD.gn
@@ -124,6 +124,8 @@
     "ElementDataCache.h",
     "ElementFullscreen.cpp",
     "ElementFullscreen.h",
+    "ElementIntersectionObserverData.cpp",
+    "ElementIntersectionObserverData.h",
     "ElementRareData.cpp",
     "ElementRareData.h",
     "ElementTraversal.h",
@@ -155,8 +157,6 @@
     "IgnoreDestructiveWriteCountIncrementer.h",
     "IncrementLoadEventDelayCount.cpp",
     "IncrementLoadEventDelayCount.h",
-    "IntersectionGeometry.cpp",
-    "IntersectionGeometry.h",
     "IntersectionObservation.cpp",
     "IntersectionObservation.h",
     "IntersectionObserver.cpp",
@@ -196,8 +196,6 @@
     "NodeFilter.cpp",
     "NodeFilter.h",
     "NodeFilterCondition.h",
-    "NodeIntersectionObserverData.cpp",
-    "NodeIntersectionObserverData.h",
     "NodeIterator.cpp",
     "NodeIterator.h",
     "NodeIteratorBase.cpp",
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp
index b40ae4a..13592b8 100644
--- a/third_party/WebKit/Source/core/dom/Document.cpp
+++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -93,7 +93,6 @@
 #include "core/dom/NodeChildRemovalTracker.h"
 #include "core/dom/NodeComputedStyle.h"
 #include "core/dom/NodeFilter.h"
-#include "core/dom/NodeIntersectionObserverData.h"
 #include "core/dom/NodeIterator.h"
 #include "core/dom/NodeRareData.h"
 #include "core/dom/NodeTraversal.h"
@@ -409,7 +408,9 @@
       m_evaluateMediaQueriesOnStyleRecalc(false),
       m_pendingSheetLayout(NoLayoutWithPendingSheets),
       m_frame(initializer.frame()),
-      m_domWindow(m_frame ? m_frame->localDOMWindow() : 0),
+      // TODO(dcheng): Why does this need both a LocalFrame and LocalDOMWindow
+      // pointer?
+      m_domWindow(m_frame ? m_frame->domWindow() : nullptr),
       m_importsController(this, initializer.importsController()),
       m_contextFeatures(ContextFeatures::defaultSwitch()),
       m_wellFormed(false),
@@ -499,10 +500,10 @@
     m_fetcher = m_frame->loader().documentLoader()->fetcher();
     FrameFetchContext::provideDocumentToContext(m_fetcher->context(), this);
 
+    // TODO(dcheng): Why does this need to check that DOMWindow is non-null?
     CustomElementRegistry* registry =
-        m_frame->localDOMWindow()
-            ? m_frame->localDOMWindow()->maybeCustomElements()
-            : nullptr;
+        m_frame->domWindow() ? m_frame->domWindow()->maybeCustomElements()
+                             : nullptr;
     if (registry && m_registrationContext)
       registry->entangle(m_registrationContext);
   } else if (m_importsController) {
@@ -1209,7 +1210,7 @@
   return String();
 }
 
-void Document::setReadyState(ReadyState readyState) {
+void Document::setReadyState(DocumentReadyState readyState) {
   if (readyState == m_readyState)
     return;
 
@@ -1804,7 +1805,7 @@
         StyleChangeReasonForTracing::create(StyleChangeReason::FontSizeChange));
   }
 
-  EOverflowAnchor overflowAnchor = AnchorAuto;
+  EOverflowAnchor overflowAnchor = EOverflowAnchor::Auto;
   EOverflow overflowX = OverflowAuto;
   EOverflow overflowY = OverflowAuto;
   float columnGap = 0;
@@ -1818,8 +1819,8 @@
       overflowX = OverflowAuto;
     if (overflowY == OverflowVisible)
       overflowY = OverflowAuto;
-    if (overflowAnchor == AnchorVisible)
-      overflowAnchor = AnchorAuto;
+    if (overflowAnchor == EOverflowAnchor::Visible)
+      overflowAnchor = EOverflowAnchor::Auto;
     // Column-gap is (ab)used by the current paged overflow implementation (in
     // lack of other ways to specify gaps between pages), so we have to
     // propagate it too.
@@ -3028,11 +3029,10 @@
         DocumentLoadTiming& timing = documentLoader->timing();
         DCHECK(timing.navigationStart());
         timing.markUnloadEventStart();
-        m_frame->localDOMWindow()->dispatchEvent(unloadEvent, this);
+        m_frame->domWindow()->dispatchEvent(unloadEvent, this);
         timing.markUnloadEventEnd();
       } else {
-        m_frame->localDOMWindow()->dispatchEvent(unloadEvent,
-                                                 m_frame->document());
+        m_frame->domWindow()->dispatchEvent(unloadEvent, m_frame->document());
       }
     }
     m_loadEventProgress = UnloadEventHandled;
@@ -5718,12 +5718,6 @@
   return *m_intersectionObserverController;
 }
 
-NodeIntersectionObserverData& Document::ensureIntersectionObserverData() {
-  if (!m_intersectionObserverData)
-    m_intersectionObserverData = new NodeIntersectionObserverData();
-  return *m_intersectionObserverData;
-}
-
 ResizeObserverController& Document::ensureResizeObserverController() {
   if (!m_resizeObserverController)
     m_resizeObserverController = new ResizeObserverController();
@@ -6374,21 +6368,11 @@
 bool Document::isSecureContext(
     String& errorMessage,
     const SecureContextCheck privilegeContextCheck) const {
-  bool isSecure = isSecureContextImpl(privilegeContextCheck);
-  if (getSandboxFlags() != SandboxNone) {
-    UseCounter::count(
-        *this, isSecure
-                   ? UseCounter::SecureContextCheckForSandboxedOriginPassed
-                   : UseCounter::SecureContextCheckForSandboxedOriginFailed);
+  if (!isSecureContext(privilegeContextCheck)) {
+    errorMessage = SecurityOrigin::isPotentiallyTrustworthyErrorMessage();
+    return false;
   }
-  UseCounter::count(*this, isSecure ? UseCounter::SecureContextCheckPassed
-                                    : UseCounter::SecureContextCheckFailed);
-
-  if (isSecure)
-    return true;
-
-  errorMessage = SecurityOrigin::isPotentiallyTrustworthyErrorMessage();
-  return false;
+  return true;
 }
 
 bool Document::isSecureContext(
@@ -6529,7 +6513,6 @@
   visitor->trace(m_contextDocument);
   visitor->trace(m_canvasFontCache);
   visitor->trace(m_intersectionObserverController);
-  visitor->trace(m_intersectionObserverData);
   visitor->trace(m_snapCoordinator);
   visitor->trace(m_resizeObserverController);
   visitor->trace(m_propertyRegistry);
diff --git a/third_party/WebKit/Source/core/dom/Document.h b/third_party/WebKit/Source/core/dom/Document.h
index 67ac81e..dedff943 100644
--- a/third_party/WebKit/Source/core/dom/Document.h
+++ b/third_party/WebKit/Source/core/dom/Document.h
@@ -136,7 +136,6 @@
 class MediaQueryListListener;
 class MediaQueryMatcher;
 class NodeFilter;
-class NodeIntersectionObserverData;
 class NodeIterator;
 class NthIndexCache;
 class OriginAccessEntry;
@@ -674,8 +673,10 @@
   }
   bool inNoQuirksMode() const { return m_compatibilityMode == NoQuirksMode; }
 
-  enum ReadyState { Loading, Interactive, Complete };
-  void setReadyState(ReadyState);
+  // https://html.spec.whatwg.org/multipage/dom.html#documentreadystate
+  enum DocumentReadyState { Loading, Interactive, Complete };
+
+  void setReadyState(DocumentReadyState);
   bool isLoadCompleted();
 
   enum ParsingState { Parsing, InDOMContentLoaded, FinishedParsing };
@@ -813,7 +814,6 @@
 
   IntersectionObserverController* intersectionObserverController();
   IntersectionObserverController& ensureIntersectionObserverController();
-  NodeIntersectionObserverData& ensureIntersectionObserverData();
 
   ResizeObserverController* resizeObserverController() const {
     return m_resizeObserverController;
@@ -1512,7 +1512,8 @@
   const Member<VisitedLinkState> m_visitedLinkState;
 
   bool m_visuallyOrdered;
-  ReadyState m_readyState;
+
+  DocumentReadyState m_readyState;
   ParsingState m_parsingState;
 
   bool m_gotoAnchorNeededAfterStylesheetsLoad;
@@ -1654,7 +1655,6 @@
   Member<CanvasFontCache> m_canvasFontCache;
 
   Member<IntersectionObserverController> m_intersectionObserverController;
-  Member<NodeIntersectionObserverData> m_intersectionObserverData;
   Member<ResizeObserverController> m_resizeObserverController;
 
   int m_nodeCount;
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp
index 7c28693..c92dcff 100644
--- a/third_party/WebKit/Source/core/dom/Element.cpp
+++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -57,6 +57,7 @@
 #include "core/dom/ClientRectList.h"
 #include "core/dom/DatasetDOMStringMap.h"
 #include "core/dom/ElementDataCache.h"
+#include "core/dom/ElementIntersectionObserverData.h"
 #include "core/dom/ElementRareData.h"
 #include "core/dom/ElementTraversal.h"
 #include "core/dom/ExceptionCode.h"
@@ -67,7 +68,6 @@
 #include "core/dom/MutationRecord.h"
 #include "core/dom/NamedNodeMap.h"
 #include "core/dom/NodeComputedStyle.h"
-#include "core/dom/NodeIntersectionObserverData.h"
 #include "core/dom/PresentationAttributeStyle.h"
 #include "core/dom/PseudoElement.h"
 #include "core/dom/ScriptableDocumentParser.h"
@@ -2876,13 +2876,13 @@
   return nullptr;
 }
 
-NodeIntersectionObserverData* Element::intersectionObserverData() const {
+ElementIntersectionObserverData* Element::intersectionObserverData() const {
   if (hasRareData())
     return elementRareData()->intersectionObserverData();
   return nullptr;
 }
 
-NodeIntersectionObserverData& Element::ensureIntersectionObserverData() {
+ElementIntersectionObserverData& Element::ensureIntersectionObserverData() {
   return ensureElementRareData().ensureIntersectionObserverData();
 }
 
diff --git a/third_party/WebKit/Source/core/dom/Element.h b/third_party/WebKit/Source/core/dom/Element.h
index 3733b52..1160929 100644
--- a/third_party/WebKit/Source/core/dom/Element.h
+++ b/third_party/WebKit/Source/core/dom/Element.h
@@ -61,7 +61,7 @@
 class Locale;
 class MutableStylePropertySet;
 class NamedNodeMap;
-class NodeIntersectionObserverData;
+class ElementIntersectionObserverData;
 class PseudoElement;
 class ResizeObservation;
 class ResizeObserver;
@@ -717,8 +717,8 @@
 
   SpellcheckAttributeState spellcheckAttributeState() const;
 
-  NodeIntersectionObserverData* intersectionObserverData() const;
-  NodeIntersectionObserverData& ensureIntersectionObserverData();
+  ElementIntersectionObserverData* intersectionObserverData() const;
+  ElementIntersectionObserverData& ensureIntersectionObserverData();
 
   HeapHashMap<Member<ResizeObserver>, Member<ResizeObservation>>*
   resizeObserverData() const;
diff --git a/third_party/WebKit/Source/core/dom/ElementIntersectionObserverData.cpp b/third_party/WebKit/Source/core/dom/ElementIntersectionObserverData.cpp
new file mode 100644
index 0000000..ff76561d
--- /dev/null
+++ b/third_party/WebKit/Source/core/dom/ElementIntersectionObserverData.cpp
@@ -0,0 +1,78 @@
+// 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/ElementIntersectionObserverData.h"
+
+#include "core/dom/Document.h"
+#include "core/dom/IntersectionObservation.h"
+#include "core/dom/IntersectionObserver.h"
+#include "core/dom/IntersectionObserverController.h"
+
+namespace blink {
+
+ElementIntersectionObserverData::ElementIntersectionObserverData() {}
+
+IntersectionObservation* ElementIntersectionObserverData::getObservationFor(
+    IntersectionObserver& observer) {
+  auto i = m_intersectionObservations.find(&observer);
+  if (i == m_intersectionObservations.end())
+    return nullptr;
+  return i->value;
+}
+
+void ElementIntersectionObserverData::addObserver(
+    IntersectionObserver& observer) {
+  m_intersectionObservers.add(&observer);
+}
+
+void ElementIntersectionObserverData::removeObserver(
+    IntersectionObserver& observer) {
+  m_intersectionObservers.remove(&observer);
+}
+
+void ElementIntersectionObserverData::addObservation(
+    IntersectionObservation& observation) {
+  m_intersectionObservations.add(
+      TraceWrapperMember<IntersectionObserver>(this, &observation.observer()),
+      &observation);
+}
+
+void ElementIntersectionObserverData::removeObservation(
+    IntersectionObserver& observer) {
+  m_intersectionObservations.remove(&observer);
+}
+
+void ElementIntersectionObserverData::activateValidIntersectionObservers(
+    Node& node) {
+  for (auto& observer : m_intersectionObservers) {
+    observer->trackingDocument()
+        .ensureIntersectionObserverController()
+        .addTrackedObserver(*observer);
+  }
+}
+
+void ElementIntersectionObserverData::deactivateAllIntersectionObservers(
+    Node& node) {
+  for (auto& observer : m_intersectionObservers) {
+    observer->trackingDocument()
+        .ensureIntersectionObserverController()
+        .addTrackedObserver(*observer);
+  }
+  node.document()
+      .ensureIntersectionObserverController()
+      .removeTrackedObserversForRoot(node);
+}
+
+DEFINE_TRACE(ElementIntersectionObserverData) {
+  visitor->trace(m_intersectionObservers);
+  visitor->trace(m_intersectionObservations);
+}
+
+DEFINE_TRACE_WRAPPERS(ElementIntersectionObserverData) {
+  for (auto& entry : m_intersectionObservations) {
+    visitor->traceWrappers(entry.key);
+  }
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/NodeIntersectionObserverData.h b/third_party/WebKit/Source/core/dom/ElementIntersectionObserverData.h
similarity index 76%
rename from third_party/WebKit/Source/core/dom/NodeIntersectionObserverData.h
rename to third_party/WebKit/Source/core/dom/ElementIntersectionObserverData.h
index 0bf1dc0..e9647e95 100644
--- a/third_party/WebKit/Source/core/dom/NodeIntersectionObserverData.h
+++ b/third_party/WebKit/Source/core/dom/ElementIntersectionObserverData.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 NodeIntersectionObserverData_h
-#define NodeIntersectionObserverData_h
+#ifndef ElementIntersectionObserverData_h
+#define ElementIntersectionObserverData_h
 
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/TraceWrapperMember.h"
@@ -15,13 +15,15 @@
 class IntersectionObservation;
 class IntersectionObserver;
 
-class NodeIntersectionObserverData
-    : public GarbageCollected<NodeIntersectionObserverData>,
+class ElementIntersectionObserverData
+    : public GarbageCollected<ElementIntersectionObserverData>,
       public TraceWrapperBase {
  public:
-  NodeIntersectionObserverData();
+  ElementIntersectionObserverData();
 
   IntersectionObservation* getObservationFor(IntersectionObserver&);
+  void addObserver(IntersectionObserver&);
+  void removeObserver(IntersectionObserver&);
   void addObservation(IntersectionObservation&);
   void removeObservation(IntersectionObserver&);
   void activateValidIntersectionObservers(Node&);
@@ -41,4 +43,4 @@
 
 }  // namespace blink
 
-#endif  // NodeIntersectionObserverData_h
+#endif  // ElementIntersectionObserverData_h
diff --git a/third_party/WebKit/Source/core/dom/ElementRareData.h b/third_party/WebKit/Source/core/dom/ElementRareData.h
index 88c6a54..36eaf6b 100644
--- a/third_party/WebKit/Source/core/dom/ElementRareData.h
+++ b/third_party/WebKit/Source/core/dom/ElementRareData.h
@@ -28,8 +28,8 @@
 #include "core/dom/Attr.h"
 #include "core/dom/CompositorProxiedPropertySet.h"
 #include "core/dom/DatasetDOMStringMap.h"
+#include "core/dom/ElementIntersectionObserverData.h"
 #include "core/dom/NamedNodeMap.h"
-#include "core/dom/NodeIntersectionObserverData.h"
 #include "core/dom/NodeRareData.h"
 #include "core/dom/PseudoElement.h"
 #include "core/dom/PseudoElementData.h"
@@ -161,12 +161,12 @@
     ScriptWrappableVisitor::writeBarrier(this, attr);
   }
 
-  NodeIntersectionObserverData* intersectionObserverData() const {
+  ElementIntersectionObserverData* intersectionObserverData() const {
     return m_intersectionObserverData.get();
   }
-  NodeIntersectionObserverData& ensureIntersectionObserverData() {
+  ElementIntersectionObserverData& ensureIntersectionObserverData() {
     if (!m_intersectionObserverData) {
-      m_intersectionObserverData = new NodeIntersectionObserverData();
+      m_intersectionObserverData = new ElementIntersectionObserverData();
       ScriptWrappableVisitor::writeBarrier(this, m_intersectionObserverData);
     }
     return *m_intersectionObserverData;
@@ -200,7 +200,7 @@
   std::unique_ptr<CompositorProxiedPropertySet> m_proxiedProperties;
 
   Member<ElementAnimations> m_elementAnimations;
-  Member<NodeIntersectionObserverData> m_intersectionObserverData;
+  Member<ElementIntersectionObserverData> m_intersectionObserverData;
   Member<ResizeObserverDataMap> m_resizeObserverData;
 
   RefPtr<ComputedStyle> m_computedStyle;
diff --git a/third_party/WebKit/Source/core/dom/Fullscreen.cpp b/third_party/WebKit/Source/core/dom/Fullscreen.cpp
index 9095f98..60a9166 100644
--- a/third_party/WebKit/Source/core/dom/Fullscreen.cpp
+++ b/third_party/WebKit/Source/core/dom/Fullscreen.cpp
@@ -194,20 +194,38 @@
   return event;
 }
 
+// Walks the frame tree and returns the first local ancestor frame, if any.
+LocalFrame* nextLocalAncestor(Frame& frame) {
+  Frame* parent = frame.tree().parent();
+  if (!parent)
+    return nullptr;
+  if (parent->isLocalFrame())
+    return toLocalFrame(parent);
+  return nextLocalAncestor(*parent);
+}
+
+// Walks the document's frame tree and returns the document of the first local
+// ancestor frame, if any.
+Document* nextLocalAncestor(Document& document) {
+  LocalFrame* frame = document.frame();
+  if (!frame)
+    return nullptr;
+  LocalFrame* next = nextLocalAncestor(*document.frame());
+  if (!next)
+    return nullptr;
+  DCHECK(next->document());
+  return next->document();
+}
+
 // Helper to walk the ancestor chain and return the Document of the topmost
 // local ancestor frame. Note that this is not the same as the topmost frame's
 // Document, which might be unavailable in OOPIF scenarios. For example, with
 // OOPIFs, when called on the bottom frame's Document in a A-B-C-B hierarchy in
 // process B, this will skip remote frame C and return this frame: A-[B]-C-B.
 Document& topmostLocalAncestor(Document& document) {
-  Document* topmost = &document;
-  Frame* frame = document.frame();
-  while (frame) {
-    frame = frame->tree().parent();
-    if (frame && frame->isLocalFrame())
-      topmost = toLocalFrame(frame)->document();
-  }
-  return *topmost;
+  if (Document* next = nextLocalAncestor(document))
+    return topmostLocalAncestor(*next);
+  return document;
 }
 
 // Helper to find the browsing context container in |doc| that embeds the
@@ -389,13 +407,8 @@
     // process, where the message should be queued up and processed after
     // the IPC that dispatches fullscreenchange.
     HeapDeque<Member<Document>> docs;
-
-    docs.prepend(&document);
-    for (Frame* frame = document.frame()->tree().parent(); frame;
-         frame = frame->tree().parent()) {
-      if (frame->isLocalFrame())
-        docs.prepend(toLocalFrame(frame)->document());
-    }
+    for (Document* doc = &document; doc; doc = nextLocalAncestor(*doc))
+      docs.prepend(doc);
 
     // 4. For each document in docs, run these substeps:
     HeapDeque<Member<Document>>::iterator current = docs.begin(),
@@ -548,13 +561,8 @@
     // TODO(alexmos): Deal with nested fullscreen cases, see
     // https://crbug.com/617369.
     if (!newTop) {
-      Frame* frame = currentDoc->frame()->tree().parent();
-      while (frame && frame->isRemoteFrame())
-        frame = frame->tree().parent();
-      if (frame) {
-        currentDoc = toLocalFrame(frame)->document();
-        continue;
-      }
+      currentDoc = nextLocalAncestor(*currentDoc);
+      continue;
     }
 
     // 4. Otherwise, set doc to null.
diff --git a/third_party/WebKit/Source/core/dom/IntersectionGeometry.cpp b/third_party/WebKit/Source/core/dom/IntersectionGeometry.cpp
deleted file mode 100644
index 1956b7b6..0000000
--- a/third_party/WebKit/Source/core/dom/IntersectionGeometry.cpp
+++ /dev/null
@@ -1,241 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "core/dom/IntersectionGeometry.h"
-
-#include "core/dom/Element.h"
-#include "core/dom/ElementRareData.h"
-#include "core/frame/FrameView.h"
-#include "core/frame/LocalFrame.h"
-#include "core/layout/LayoutBox.h"
-#include "core/layout/LayoutView.h"
-#include "core/layout/api/LayoutAPIShim.h"
-#include "core/layout/api/LayoutViewItem.h"
-#include "core/paint/PaintLayer.h"
-
-namespace blink {
-
-namespace {
-
-bool isContainingBlockChainDescendant(LayoutObject* descendant,
-                                      LayoutObject* ancestor) {
-  LocalFrame* ancestorFrame = ancestor->document().frame();
-  LocalFrame* descendantFrame = descendant->document().frame();
-
-  if (ancestor->isLayoutView())
-    return descendantFrame && descendantFrame->tree().top() == ancestorFrame;
-
-  if (ancestorFrame != descendantFrame)
-    return false;
-
-  while (descendant && descendant != ancestor)
-    descendant = descendant->containingBlock();
-  return descendant;
-}
-
-void mapRectUpToDocument(LayoutRect& rect,
-                         const LayoutObject& layoutObject,
-                         const Document& document) {
-  FloatQuad mappedQuad = layoutObject.localToAbsoluteQuad(
-      FloatQuad(FloatRect(rect)), UseTransforms | ApplyContainerFlip);
-  rect = LayoutRect(mappedQuad.boundingBox());
-}
-
-void mapRectDownToDocument(LayoutRect& rect,
-                           LayoutBoxModelObject& layoutObject,
-                           const Document& document) {
-  FloatQuad mappedQuad = document.layoutView()->ancestorToLocalQuad(
-      &layoutObject, FloatQuad(FloatRect(rect)),
-      UseTransforms | ApplyContainerFlip | TraverseDocumentBoundaries);
-  rect = LayoutRect(mappedQuad.boundingBox());
-}
-
-LayoutUnit computeMargin(const Length& length, LayoutUnit referenceLength) {
-  if (length.type() == Percent) {
-    return LayoutUnit(
-        static_cast<int>(referenceLength.toFloat() * length.percent() / 100.0));
-  }
-  DCHECK_EQ(length.type(), Fixed);
-  return LayoutUnit(length.intValue());
-}
-
-}  // namespace
-
-IntersectionGeometry::IntersectionGeometry(
-    Node* root,
-    Element* target,
-    const Vector<Length>& rootMargin,
-    ReportRootBounds shouldReportRootBounds)
-    : m_root(root),
-      m_target(target),
-      m_rootMargin(rootMargin),
-      m_shouldReportRootBounds(shouldReportRootBounds) {
-  DCHECK(m_target);
-  DCHECK(rootMargin.isEmpty() || rootMargin.size() == 4);
-}
-
-IntersectionGeometry::~IntersectionGeometry() {}
-
-Element* IntersectionGeometry::root() const {
-  if (m_root && !m_root->isDocumentNode())
-    return toElement(m_root);
-  return nullptr;
-}
-
-LayoutObject* IntersectionGeometry::getRootLayoutObject() const {
-  DCHECK(m_root);
-  if (m_root->isDocumentNode()) {
-    return LayoutAPIShim::layoutObjectFrom(
-        toDocument(m_root)->layoutViewItem());
-  }
-  return toElement(m_root)->layoutObject();
-}
-
-void IntersectionGeometry::initializeGeometry() {
-  initializeTargetRect();
-  m_intersectionRect = m_targetRect;
-  initializeRootRect();
-  m_doesIntersect = true;
-}
-
-void IntersectionGeometry::initializeTargetRect() {
-  LayoutObject* targetLayoutObject = m_target->layoutObject();
-  DCHECK(targetLayoutObject && targetLayoutObject->isBoxModelObject());
-  m_targetRect = LayoutRect(
-      toLayoutBoxModelObject(targetLayoutObject)->borderBoundingBox());
-}
-
-void IntersectionGeometry::initializeRootRect() {
-  LayoutObject* rootLayoutObject = getRootLayoutObject();
-  if (rootLayoutObject->isLayoutView()) {
-    m_rootRect = LayoutRect(
-        toLayoutView(rootLayoutObject)->frameView()->visibleContentRect());
-  } else if (rootLayoutObject->isBox() && rootLayoutObject->hasOverflowClip()) {
-    m_rootRect = LayoutRect(toLayoutBox(rootLayoutObject)->contentBoxRect());
-  } else {
-    m_rootRect = LayoutRect(
-        toLayoutBoxModelObject(rootLayoutObject)->borderBoundingBox());
-  }
-  applyRootMargin();
-}
-
-void IntersectionGeometry::applyRootMargin() {
-  if (m_rootMargin.isEmpty())
-    return;
-
-  // TODO(szager): Make sure the spec is clear that left/right margins are
-  // resolved against width and not height.
-  LayoutUnit topMargin = computeMargin(m_rootMargin[0], m_rootRect.height());
-  LayoutUnit rightMargin = computeMargin(m_rootMargin[1], m_rootRect.width());
-  LayoutUnit bottomMargin = computeMargin(m_rootMargin[2], m_rootRect.height());
-  LayoutUnit leftMargin = computeMargin(m_rootMargin[3], m_rootRect.width());
-
-  m_rootRect.setX(m_rootRect.x() - leftMargin);
-  m_rootRect.setWidth(m_rootRect.width() + leftMargin + rightMargin);
-  m_rootRect.setY(m_rootRect.y() - topMargin);
-  m_rootRect.setHeight(m_rootRect.height() + topMargin + bottomMargin);
-}
-
-void IntersectionGeometry::clipToRoot() {
-  // Map and clip rect into root element coordinates.
-  // TODO(szager): the writing mode flipping needs a test.
-  LayoutBox* rootLayoutObject = toLayoutBox(getRootLayoutObject());
-  LayoutObject* targetLayoutObject = m_target->layoutObject();
-
-  m_doesIntersect = targetLayoutObject->mapToVisualRectInAncestorSpace(
-      rootLayoutObject, m_intersectionRect, EdgeInclusive);
-  if (rootLayoutObject->hasOverflowClip())
-    m_intersectionRect.move(-rootLayoutObject->scrolledContentOffset());
-
-  if (!m_doesIntersect)
-    return;
-  LayoutRect rootClipRect(m_rootRect);
-  rootLayoutObject->flipForWritingMode(rootClipRect);
-  m_doesIntersect &= m_intersectionRect.inclusiveIntersect(rootClipRect);
-}
-
-void IntersectionGeometry::mapTargetRectToTargetFrameCoordinates() {
-  LayoutObject& targetLayoutObject = *m_target->layoutObject();
-  Document& targetDocument = m_target->document();
-  LayoutSize scrollPosition =
-      LayoutSize(targetDocument.view()->getScrollOffset());
-  mapRectUpToDocument(m_targetRect, targetLayoutObject, targetDocument);
-  m_targetRect.move(-scrollPosition);
-}
-
-void IntersectionGeometry::mapRootRectToRootFrameCoordinates() {
-  LayoutObject& rootLayoutObject = *getRootLayoutObject();
-  Document& rootDocument = rootLayoutObject.document();
-  LayoutSize scrollPosition =
-      LayoutSize(rootDocument.view()->getScrollOffset());
-  mapRectUpToDocument(m_rootRect, rootLayoutObject,
-                      rootLayoutObject.document());
-  m_rootRect.move(-scrollPosition);
-}
-
-void IntersectionGeometry::mapRootRectToTargetFrameCoordinates() {
-  LayoutObject& rootLayoutObject = *getRootLayoutObject();
-  Document& targetDocument = m_target->document();
-  LayoutSize scrollPosition =
-      LayoutSize(targetDocument.view()->getScrollOffset());
-
-  if (&targetDocument == &rootLayoutObject.document()) {
-    mapRectUpToDocument(m_intersectionRect, rootLayoutObject, targetDocument);
-  } else {
-    mapRectDownToDocument(m_intersectionRect,
-                          toLayoutBoxModelObject(rootLayoutObject),
-                          targetDocument);
-  }
-
-  m_intersectionRect.move(-scrollPosition);
-}
-
-void IntersectionGeometry::computeGeometry() {
-  // In the first few lines here, before initializeGeometry is called, "return
-  // true" effectively means "if the previous observed state was that root and
-  // target were intersecting, then generate a notification indicating that they
-  // are no longer intersecting."  This happens, for example, when root or
-  // target is removed from the DOM tree and not reinserted before the next
-  // frame is generated, or display:none is set on the root or target.
-  if (!m_target->isConnected())
-    return;
-  Element* rootElement = root();
-  if (rootElement && !rootElement->isConnected())
-    return;
-
-  LayoutObject* rootLayoutObject = getRootLayoutObject();
-  if (!rootLayoutObject || !rootLayoutObject->isBoxModelObject())
-    return;
-  // TODO(szager): Support SVG
-  LayoutObject* targetLayoutObject = m_target->layoutObject();
-  if (!targetLayoutObject)
-    return;
-  if (!targetLayoutObject->isBoxModelObject() && !targetLayoutObject->isText())
-    return;
-  if (!isContainingBlockChainDescendant(targetLayoutObject, rootLayoutObject))
-    return;
-
-  initializeGeometry();
-
-  clipToRoot();
-
-  mapTargetRectToTargetFrameCoordinates();
-
-  if (m_doesIntersect)
-    mapRootRectToTargetFrameCoordinates();
-  else
-    m_intersectionRect = LayoutRect();
-
-  // Small optimization: if we're not going to report root bounds, don't bother
-  // transforming them to the frame.
-  if (m_shouldReportRootBounds == ReportRootBounds::kShouldReportRootBounds)
-    mapRootRectToRootFrameCoordinates();
-}
-
-DEFINE_TRACE(IntersectionGeometry) {
-  visitor->trace(m_root);
-  visitor->trace(m_target);
-}
-
-}  // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/IntersectionGeometry.h b/third_party/WebKit/Source/core/dom/IntersectionGeometry.h
deleted file mode 100644
index ba94456..0000000
--- a/third_party/WebKit/Source/core/dom/IntersectionGeometry.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IntersectionGeometry_h
-#define IntersectionGeometry_h
-
-#include "platform/Length.h"
-#include "platform/geometry/LayoutRect.h"
-#include "platform/heap/Handle.h"
-#include "wtf/Vector.h"
-
-namespace blink {
-
-class Node;
-class Element;
-class LayoutObject;
-
-class IntersectionGeometry final
-    : public GarbageCollectedFinalized<IntersectionGeometry> {
- public:
-  enum ReportRootBounds {
-    kShouldReportRootBounds,
-    kShouldNotReportRootBounds,
-  };
-
-  IntersectionGeometry(Node* root,
-                       Element* target,
-                       const Vector<Length>& rootMargin,
-                       ReportRootBounds shouldReportRootBounds);
-  ~IntersectionGeometry();
-
-  void computeGeometry();
-  LayoutRect targetRect() const { return m_targetRect; }
-  LayoutRect intersectionRect() const { return m_intersectionRect; }
-  LayoutRect rootRect() const { return m_rootRect; }
-  bool doesIntersect() const { return m_doesIntersect; }
-
-  IntRect intersectionIntRect() const {
-    return pixelSnappedIntRect(m_intersectionRect);
-  }
-
-  IntRect targetIntRect() const { return pixelSnappedIntRect(m_targetRect); }
-
-  IntRect rootIntRect() const { return pixelSnappedIntRect(m_rootRect); }
-
-  DECLARE_TRACE();
-
- private:
-  void initializeGeometry();
-  void initializeTargetRect();
-  void initializeRootRect();
-  void clipToRoot();
-  void mapTargetRectToTargetFrameCoordinates();
-  void mapRootRectToRootFrameCoordinates();
-  void mapRootRectToTargetFrameCoordinates();
-  Element* root() const;
-  LayoutObject* getRootLayoutObject() const;
-  void applyRootMargin();
-
-  Member<Node> m_root;
-  Member<Element> m_target;
-  const Vector<Length> m_rootMargin;
-  const ReportRootBounds m_shouldReportRootBounds;
-  LayoutRect m_targetRect;
-  LayoutRect m_intersectionRect;
-  LayoutRect m_rootRect;
-  bool m_doesIntersect = false;
-};
-
-}  // namespace blink
-
-#endif  // IntersectionGeometry_h
diff --git a/third_party/WebKit/Source/core/dom/IntersectionObservation.cpp b/third_party/WebKit/Source/core/dom/IntersectionObservation.cpp
index f6d3ceaa..6effa41 100644
--- a/third_party/WebKit/Source/core/dom/IntersectionObservation.cpp
+++ b/third_party/WebKit/Source/core/dom/IntersectionObservation.cpp
@@ -6,18 +6,16 @@
 
 #include "core/dom/ElementRareData.h"
 #include "core/dom/IntersectionObserver.h"
+#include "core/layout/IntersectionGeometry.h"
 
 namespace blink {
 
-IntersectionObservation::IntersectionObservation(
-    IntersectionObserver& observer,
-    Element& target,
-    IntersectionGeometry::ReportRootBounds shouldReportRootBounds)
+IntersectionObservation::IntersectionObservation(IntersectionObserver& observer,
+                                                 Element& target,
+                                                 bool shouldReportRootBounds)
     : m_observer(observer),
       m_target(&target),
-      m_shouldReportRootBounds(
-          shouldReportRootBounds ==
-          IntersectionGeometry::ReportRootBounds::kShouldReportRootBounds),
+      m_shouldReportRootBounds(shouldReportRootBounds),
       m_lastThresholdIndex(0) {}
 
 void IntersectionObservation::computeIntersectionObservations(
@@ -29,11 +27,8 @@
   rootMargin[1] = m_observer->rightMargin();
   rootMargin[2] = m_observer->bottomMargin();
   rootMargin[3] = m_observer->leftMargin();
-  IntersectionGeometry geometry(
-      m_observer->rootNode(), target(), rootMargin,
-      m_shouldReportRootBounds
-          ? IntersectionGeometry::ReportRootBounds::kShouldReportRootBounds
-          : IntersectionGeometry::ReportRootBounds::kShouldNotReportRootBounds);
+  IntersectionGeometry geometry(m_observer->root(), *target(), rootMargin,
+                                m_shouldReportRootBounds);
   geometry.computeGeometry();
 
   // Some corner cases for threshold index:
diff --git a/third_party/WebKit/Source/core/dom/IntersectionObservation.h b/third_party/WebKit/Source/core/dom/IntersectionObservation.h
index 3b1ec65d..68fe7337 100644
--- a/third_party/WebKit/Source/core/dom/IntersectionObservation.h
+++ b/third_party/WebKit/Source/core/dom/IntersectionObservation.h
@@ -6,7 +6,6 @@
 #define IntersectionObservation_h
 
 #include "core/dom/DOMHighResTimeStamp.h"
-#include "core/dom/IntersectionGeometry.h"
 #include "platform/heap/Handle.h"
 
 namespace blink {
@@ -17,10 +16,9 @@
 class IntersectionObservation final
     : public GarbageCollected<IntersectionObservation> {
  public:
-  IntersectionObservation(
-      IntersectionObserver&,
-      Element&,
-      IntersectionGeometry::ReportRootBounds shouldReportRootBounds);
+  IntersectionObservation(IntersectionObserver&,
+                          Element&,
+                          bool shouldReportRootBounds);
 
   IntersectionObserver& observer() const { return *m_observer; }
   Element* target() const { return m_target; }
diff --git a/third_party/WebKit/Source/core/dom/IntersectionObserver.cpp b/third_party/WebKit/Source/core/dom/IntersectionObserver.cpp
index 09e1dc56f..91a4f0be 100644
--- a/third_party/WebKit/Source/core/dom/IntersectionObserver.cpp
+++ b/third_party/WebKit/Source/core/dom/IntersectionObserver.cpp
@@ -8,18 +8,18 @@
 #include "core/css/parser/CSSParserTokenRange.h"
 #include "core/css/parser/CSSTokenizer.h"
 #include "core/dom/Element.h"
+#include "core/dom/ElementIntersectionObserverData.h"
 #include "core/dom/ExceptionCode.h"
 #include "core/dom/ExecutionContext.h"
 #include "core/dom/IntersectionObserverCallback.h"
 #include "core/dom/IntersectionObserverController.h"
 #include "core/dom/IntersectionObserverEntry.h"
 #include "core/dom/IntersectionObserverInit.h"
-#include "core/dom/NodeIntersectionObserverData.h"
 #include "core/frame/FrameView.h"
 #include "core/frame/LocalDOMWindow.h"
 #include "core/frame/LocalFrame.h"
-#include "core/html/HTMLFrameOwnerElement.h"
 #include "core/inspector/ConsoleMessage.h"
+#include "core/layout/LayoutView.h"
 #include "core/timing/DOMWindowPerformance.h"
 #include "core/timing/Performance.h"
 #include "platform/Timer.h"
@@ -128,34 +128,13 @@
   std::sort(thresholds.begin(), thresholds.end());
 }
 
-// Returns the root Node of a given Document to use as the IntersectionObserver
-// root when no root is given.
-// TODO(szager): it doesn't support RemoteFrames, see https://crbug.com/615156
-Node* getRootNode(Document* document) {
-  Frame* mainFrame = document->frame()->tree().top();
-  if (mainFrame && mainFrame->isLocalFrame())
-    return toLocalFrame(mainFrame)->document();
-  return nullptr;
-}
-
 }  // anonymous namespace
 
 IntersectionObserver* IntersectionObserver::create(
     const IntersectionObserverInit& observerInit,
     IntersectionObserverCallback& callback,
     ExceptionState& exceptionState) {
-  Node* root = observerInit.root();
-  if (!root) {
-    ExecutionContext* context = callback.getExecutionContext();
-    DCHECK(context->isDocument());
-    root = getRootNode(toDocument(context));
-  }
-  if (!root) {
-    exceptionState.throwDOMException(
-        HierarchyRequestError,
-        "Unable to get root node in main frame to track.");
-    return nullptr;
-  }
+  Element* root = observerInit.root();
 
   Vector<Length> rootMargin;
   parseRootMargin(observerInit.rootMargin(), rootMargin, exceptionState);
@@ -167,7 +146,7 @@
   if (exceptionState.hadException())
     return nullptr;
 
-  return new IntersectionObserver(callback, *root, rootMargin, thresholds);
+  return new IntersectionObserver(callback, root, rootMargin, thresholds);
 }
 
 IntersectionObserver* IntersectionObserver::create(
@@ -176,32 +155,25 @@
     Document* document,
     std::unique_ptr<EventCallback> callback,
     ExceptionState& exceptionState) {
-  Node* root = getRootNode(document);
-  if (!root) {
-    exceptionState.throwDOMException(
-        HierarchyRequestError,
-        "Unable to get root node in main frame to track.");
-    return nullptr;
-  }
-
   IntersectionObserverCallbackImpl* intersectionObserverCallback =
       new IntersectionObserverCallbackImpl(document, std::move(callback));
-  return new IntersectionObserver(*intersectionObserverCallback, *root,
+  return new IntersectionObserver(*intersectionObserverCallback, nullptr,
                                   rootMargin, thresholds);
 }
 
 IntersectionObserver::IntersectionObserver(
     IntersectionObserverCallback& callback,
-    Node& root,
+    Element* root,
     const Vector<Length>& rootMargin,
     const Vector<float>& thresholds)
     : m_callback(&callback),
-      m_root(&root),
+      m_root(root),
       m_thresholds(thresholds),
       m_topMargin(Fixed),
       m_rightMargin(Fixed),
       m_bottomMargin(Fixed),
       m_leftMargin(Fixed),
+      m_rootIsImplicit(root ? 0 : 1),
       m_initialState(InitialState::kHidden) {
   switch (rootMargin.size()) {
     case 0:
@@ -229,61 +201,84 @@
       NOTREACHED();
       break;
   }
-  root.document().ensureIntersectionObserverController().addTrackedObserver(
+  if (root)
+    root->ensureIntersectionObserverData().addObserver(*this);
+  trackingDocument().ensureIntersectionObserverController().addTrackedObserver(
       *this);
 }
 
 void IntersectionObserver::clearWeakMembers(Visitor* visitor) {
-  if (ThreadHeap::isHeapObjectAlive(m_root))
+  if (ThreadHeap::isHeapObjectAlive(root()))
     return;
   IgnorableExceptionState exceptionState;
   disconnect(exceptionState);
   m_root = nullptr;
 }
 
+bool IntersectionObserver::rootIsValid() const {
+  return rootIsImplicit() || root();
+}
+
+Document& IntersectionObserver::trackingDocument() const {
+  Document* document = nullptr;
+  if (rootIsImplicit()) {
+    DCHECK(m_callback->getExecutionContext());
+    document = toDocument(m_callback->getExecutionContext());
+  } else {
+    DCHECK(root());
+    document = &root()->document();
+  }
+  DCHECK(document);
+  DCHECK(document->frame());
+  return *document->frame()->localFrameRoot()->document();
+}
+
 void IntersectionObserver::observe(Element* target,
                                    ExceptionState& exceptionState) {
-  if (!m_root) {
+  if (!rootIsValid()) {
     exceptionState.throwDOMException(
         InvalidStateError,
         "observe() called on an IntersectionObserver with an invalid root.");
     return;
   }
 
-  if (!target || m_root.get() == target)
+  if (!target || root() == target)
+    return;
+
+  LocalFrame* targetFrame = target->document().frame();
+  if (!targetFrame)
     return;
 
   if (target->ensureIntersectionObserverData().getObservationFor(*this))
     return;
-  bool shouldReportRootBounds = false;
-  bool isDOMDescendant = false;
-  LocalFrame* targetFrame = target->document().frame();
-  LocalFrame* rootFrame = m_root->document().frame();
 
-  if (target->document() == rootNode()->document()) {
+  bool isDOMDescendant = true;
+  bool shouldReportRootBounds = false;
+  if (rootIsImplicit()) {
+    Frame* rootFrame = targetFrame->tree().top();
+    DCHECK(rootFrame);
+    if (rootFrame == targetFrame) {
+      shouldReportRootBounds = true;
+    } else {
+      shouldReportRootBounds =
+          targetFrame->securityContext()->getSecurityOrigin()->canAccess(
+              rootFrame->securityContext()->getSecurityOrigin());
+    }
+  } else {
     shouldReportRootBounds = true;
-    isDOMDescendant = rootNode()->isShadowIncludingInclusiveAncestorOf(target);
-  } else if (targetFrame && rootFrame) {
-    shouldReportRootBounds =
-        targetFrame->securityContext()->getSecurityOrigin()->canAccess(
-            rootFrame->securityContext()->getSecurityOrigin());
-    isDOMDescendant = (targetFrame->tree().top() == rootFrame);
+    isDOMDescendant = root()->isShadowIncludingInclusiveAncestorOf(target);
   }
 
-  IntersectionObservation* observation = new IntersectionObservation(
-      *this, *target,
-      shouldReportRootBounds
-          ? IntersectionGeometry::ReportRootBounds::kShouldReportRootBounds
-          : IntersectionGeometry::ReportRootBounds::kShouldNotReportRootBounds);
+  IntersectionObservation* observation =
+      new IntersectionObservation(*this, *target, shouldReportRootBounds);
   target->ensureIntersectionObserverData().addObservation(*observation);
   m_observations.add(observation);
 
   if (!isDOMDescendant) {
-    m_root->document().addConsoleMessage(
+    root()->document().addConsoleMessage(
         ConsoleMessage::create(JSMessageSource, WarningMessageLevel,
                                "IntersectionObserver.observe(target): target "
                                "element is not a descendant of root."));
-    return;
   }
 
   if (m_initialState == InitialState::kAuto) {
@@ -291,15 +286,13 @@
       observation->setLastThresholdIndex(std::numeric_limits<unsigned>::max());
   }
 
-  if (!rootFrame)
-    return;
-  if (FrameView* rootFrameView = rootFrame->view())
-    rootFrameView->scheduleAnimation();
+  if (FrameView* frameView = targetFrame->view())
+    frameView->scheduleAnimation();
 }
 
 void IntersectionObserver::unobserve(Element* target,
                                      ExceptionState& exceptionState) {
-  if (!m_root) {
+  if (!rootIsValid()) {
     exceptionState.throwDOMException(
         InvalidStateError,
         "unobserve() called on an IntersectionObserver with an invalid root.");
@@ -308,13 +301,15 @@
 
   if (!target || !target->intersectionObserverData())
     return;
-  // TODO(szager): unobserve callback
+
   if (IntersectionObservation* observation =
           target->intersectionObserverData()->getObservationFor(*this))
     observation->disconnect();
 }
 
 void IntersectionObserver::computeIntersectionObservations() {
+  if (!rootIsValid())
+    return;
   Document* callbackDocument = toDocument(m_callback->getExecutionContext());
   if (!callbackDocument)
     return;
@@ -328,7 +323,7 @@
 }
 
 void IntersectionObserver::disconnect(ExceptionState& exceptionState) {
-  if (!m_root) {
+  if (!rootIsValid()) {
     exceptionState.throwDOMException(
         InvalidStateError,
         "disconnect() called on an IntersectionObserver with an invalid root.");
@@ -354,24 +349,18 @@
     ExceptionState& exceptionState) {
   HeapVector<Member<IntersectionObserverEntry>> entries;
 
-  if (!m_root)
+  if (!rootIsValid()) {
     exceptionState.throwDOMException(InvalidStateError,
                                      "takeRecords() called on an "
                                      "IntersectionObserver with an invalid "
                                      "root.");
-  else
+  } else {
     entries.swap(m_entries);
+  }
 
   return entries;
 }
 
-Element* IntersectionObserver::root() const {
-  Node* node = rootNode();
-  if (node && !node->isDocumentNode())
-    return toElement(node);
-  return nullptr;
-}
-
 static void appendLength(StringBuilder& stringBuilder, const Length& length) {
   stringBuilder.appendNumber(length.intValue());
   if (length.type() == Percent)
diff --git a/third_party/WebKit/Source/core/dom/IntersectionObserver.h b/third_party/WebKit/Source/core/dom/IntersectionObserver.h
index cb3913595..c4e7493 100644
--- a/third_party/WebKit/Source/core/dom/IntersectionObserver.h
+++ b/third_party/WebKit/Source/core/dom/IntersectionObserver.h
@@ -35,12 +35,18 @@
   // Defines the assumed initial state of the observed element. If the actual
   // state is the same as the initial state, then no observation will be
   // delivered. kAuto means the initial observation will always get sent.
-  enum class InitialState {
+  enum InitialState {
     // TODO(skyostil): Add support for kVisible.
-    kAuto,
-    kHidden,
+    kAuto = 0,
+    kHidden = 1,
+    kDoNotUseMax = 2
   };
 
+  // InitialState is stored in a single bit in m_initialState.  If adding new
+  // enum values, increase the size of m_initialState and update the assert.
+  static_assert(InitialState::kDoNotUseMax == 2,
+                "InitialState fits in a single bit.");
+
   static IntersectionObserver* create(const IntersectionObserverInit&,
                                       IntersectionObserverCallback&,
                                       ExceptionState&);
@@ -58,11 +64,21 @@
   HeapVector<Member<IntersectionObserverEntry>> takeRecords(ExceptionState&);
 
   // API attributes.
-  Element* root() const;
+  Element* root() const { return m_root.get(); }
   String rootMargin() const;
   const Vector<float>& thresholds() const { return m_thresholds; }
 
-  Node* rootNode() const { return m_root.get(); }
+  // An observer can either track intersections with an explicit root Element,
+  // or with the the top-level frame's viewport (the "implicit root").  When
+  // tracking the implicit root, m_root will be null, but because m_root is a
+  // weak pointer, we cannot surmise that this observer tracks the implicit
+  // root just because m_root is null.  Hence m_rootIsImplicit.
+  bool rootIsImplicit() const { return m_rootIsImplicit; }
+
+  // This is the document which is responsible for running
+  // computeIntersectionObservations at frame generation time.
+  Document& trackingDocument() const;
+
   const Length& topMargin() const { return m_topMargin; }
   const Length& rightMargin() const { return m_rightMargin; }
   const Length& bottomMargin() const { return m_bottomMargin; }
@@ -88,13 +104,17 @@
 
  private:
   explicit IntersectionObserver(IntersectionObserverCallback&,
-                                Node&,
+                                Element*,
                                 const Vector<Length>& rootMargin,
                                 const Vector<float>& thresholds);
   void clearWeakMembers(Visitor*);
 
+  // Returns false if this observer has an explicit root element which has been
+  // deleted; true otherwise.
+  bool rootIsValid() const;
+
   Member<IntersectionObserverCallback> m_callback;
-  WeakMember<Node> m_root;
+  WeakMember<Element> m_root;
   HeapLinkedHashSet<WeakMember<IntersectionObservation>> m_observations;
   HeapVector<Member<IntersectionObserverEntry>> m_entries;
   Vector<float> m_thresholds;
@@ -102,7 +122,9 @@
   Length m_rightMargin;
   Length m_bottomMargin;
   Length m_leftMargin;
-  InitialState m_initialState;
+  unsigned m_rootIsImplicit : 1;
+  // m_initialState contains values from enum InitialState
+  unsigned m_initialState : 1;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/IntersectionObserverController.cpp b/third_party/WebKit/Source/core/dom/IntersectionObserverController.cpp
index d0888bc..caf859d 100644
--- a/third_party/WebKit/Source/core/dom/IntersectionObserverController.cpp
+++ b/third_party/WebKit/Source/core/dom/IntersectionObserverController.cpp
@@ -5,6 +5,7 @@
 #include "core/dom/IntersectionObserverController.h"
 
 #include "core/dom/Document.h"
+#include "core/dom/Element.h"
 #include "core/dom/TaskRunnerHelper.h"
 #include "platform/tracing/TraceEvent.h"
 
@@ -26,9 +27,7 @@
 
 IntersectionObserverController::~IntersectionObserverController() {}
 
-void IntersectionObserverController::scheduleIntersectionObserverForDelivery(
-    IntersectionObserver& observer) {
-  m_pendingIntersectionObservers.add(&observer);
+void IntersectionObserverController::postTaskToDeliverObservations() {
   if (!m_weakPtrFactory.hasWeakPtrs()) {
     // TODO(ojan): These tasks decide whether to throttle a subframe, so they
     // need to be unthrottled, but we should throttle all the other tasks
@@ -41,12 +40,18 @@
   }
 }
 
+void IntersectionObserverController::scheduleIntersectionObserverForDelivery(
+    IntersectionObserver& observer) {
+  m_pendingIntersectionObservers.add(&observer);
+  postTaskToDeliverObservations();
+}
+
 void IntersectionObserverController::resume() {
   // If the callback fired while DOM objects were suspended, notifications might
   // be late, so deliver them right away (rather than waiting to fire again).
   if (m_callbackFiredWhileSuspended) {
     m_callbackFiredWhileSuspended = false;
-    deliverIntersectionObservations();
+    postTaskToDeliverObservations();
   }
 }
 
@@ -86,7 +91,7 @@
     const Node& root) {
   HeapVector<Member<IntersectionObserver>> toRemove;
   for (auto& observer : m_trackedIntersectionObservers) {
-    if (observer->rootNode() == &root)
+    if (observer->root() == &root)
       toRemove.append(observer);
   }
   m_trackedIntersectionObservers.removeAll(toRemove);
diff --git a/third_party/WebKit/Source/core/dom/IntersectionObserverController.h b/third_party/WebKit/Source/core/dom/IntersectionObserverController.h
index c081ca82..bafbc53 100644
--- a/third_party/WebKit/Source/core/dom/IntersectionObserverController.h
+++ b/third_party/WebKit/Source/core/dom/IntersectionObserverController.h
@@ -39,6 +39,7 @@
 
  private:
   explicit IntersectionObserverController(Document*);
+  void postTaskToDeliverObservations();
 
  private:
   // IntersectionObservers for which this is the tracking document.
diff --git a/third_party/WebKit/Source/core/dom/NodeIntersectionObserverData.cpp b/third_party/WebKit/Source/core/dom/NodeIntersectionObserverData.cpp
deleted file mode 100644
index 7a3fc71f..0000000
--- a/third_party/WebKit/Source/core/dom/NodeIntersectionObserverData.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "core/dom/NodeIntersectionObserverData.h"
-
-#include "core/dom/Document.h"
-#include "core/dom/IntersectionObservation.h"
-#include "core/dom/IntersectionObserver.h"
-#include "core/dom/IntersectionObserverController.h"
-
-namespace blink {
-
-NodeIntersectionObserverData::NodeIntersectionObserverData() {}
-
-IntersectionObservation* NodeIntersectionObserverData::getObservationFor(
-    IntersectionObserver& observer) {
-  auto i = m_intersectionObservations.find(&observer);
-  if (i == m_intersectionObservations.end())
-    return nullptr;
-  return i->value;
-}
-
-void NodeIntersectionObserverData::addObservation(
-    IntersectionObservation& observation) {
-  m_intersectionObservations.add(
-      TraceWrapperMember<IntersectionObserver>(this, &observation.observer()),
-      &observation);
-}
-
-void NodeIntersectionObserverData::removeObservation(
-    IntersectionObserver& observer) {
-  m_intersectionObservations.remove(&observer);
-}
-
-void NodeIntersectionObserverData::activateValidIntersectionObservers(
-    Node& node) {
-  IntersectionObserverController& controller =
-      node.document().ensureIntersectionObserverController();
-  for (auto& observer : m_intersectionObservers)
-    controller.addTrackedObserver(*observer);
-}
-
-void NodeIntersectionObserverData::deactivateAllIntersectionObservers(
-    Node& node) {
-  node.document()
-      .ensureIntersectionObserverController()
-      .removeTrackedObserversForRoot(node);
-}
-
-DEFINE_TRACE(NodeIntersectionObserverData) {
-  visitor->trace(m_intersectionObservers);
-  visitor->trace(m_intersectionObservations);
-}
-
-DEFINE_TRACE_WRAPPERS(NodeIntersectionObserverData) {
-  for (auto& entry : m_intersectionObservations) {
-    visitor->traceWrappers(entry.key);
-  }
-}
-
-}  // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/StyleEngine.cpp b/third_party/WebKit/Source/core/dom/StyleEngine.cpp
index 3830d87..4fe3ecaf 100644
--- a/third_party/WebKit/Source/core/dom/StyleEngine.cpp
+++ b/third_party/WebKit/Source/core/dom/StyleEngine.cpp
@@ -895,7 +895,7 @@
 
 void StyleEngine::scheduleRuleSetInvalidationsForElement(
     Element& element,
-    const HeapVector<Member<RuleSet>>& ruleSets) {
+    const HeapHashSet<Member<RuleSet>>& ruleSets) {
   AtomicString id;
   const SpaceSplitString* classNames = nullptr;
 
@@ -938,7 +938,7 @@
 
 void StyleEngine::scheduleInvalidationsForRuleSets(
     TreeScope& treeScope,
-    const HeapVector<Member<RuleSet>>& ruleSets) {
+    const HeapHashSet<Member<RuleSet>>& ruleSets) {
 #if DCHECK_IS_ON()
   // Full scope recalcs should be handled while collecting the ruleSets before
   // calling this method.
@@ -1097,7 +1097,7 @@
   FullRecalcRules = 1 << 2
 };
 
-unsigned getRuleSetFlags(const HeapVector<Member<RuleSet>> ruleSets) {
+unsigned getRuleSetFlags(const HeapHashSet<Member<RuleSet>> ruleSets) {
   unsigned flags = 0;
   for (auto& ruleSet : ruleSets) {
     ruleSet->compactRulesIfNeeded();
@@ -1117,7 +1117,7 @@
     TreeScope& treeScope,
     const ActiveStyleSheetVector& oldStyleSheets,
     const ActiveStyleSheetVector& newStyleSheets) {
-  HeapVector<Member<RuleSet>> changedRuleSets;
+  HeapHashSet<Member<RuleSet>> changedRuleSets;
 
   ScopedStyleResolver* scopedResolver = treeScope.scopedStyleResolver();
   bool appendAllSheets =
diff --git a/third_party/WebKit/Source/core/dom/StyleEngine.h b/third_party/WebKit/Source/core/dom/StyleEngine.h
index bd4e74ba3..390bcd8 100644
--- a/third_party/WebKit/Source/core/dom/StyleEngine.h
+++ b/third_party/WebKit/Source/core/dom/StyleEngine.h
@@ -250,7 +250,7 @@
                                               Element& afterElement);
   void scheduleNthPseudoInvalidations(ContainerNode&);
   void scheduleInvalidationsForRuleSets(TreeScope&,
-                                        const HeapVector<Member<RuleSet>>&);
+                                        const HeapHashSet<Member<RuleSet>>&);
 
   unsigned styleForElementCount() const { return m_styleForElementCount; }
   void incStyleForElementCount() { m_styleForElementCount++; }
@@ -323,7 +323,7 @@
   bool shouldSkipInvalidationFor(const Element&) const;
   void scheduleRuleSetInvalidationsForElement(
       Element&,
-      const HeapVector<Member<RuleSet>>&);
+      const HeapHashSet<Member<RuleSet>>&);
   void invalidateSlottedElements(HTMLSlotElement&);
 
   void updateViewport();
diff --git a/third_party/WebKit/Source/core/dom/StyleEngineTest.cpp b/third_party/WebKit/Source/core/dom/StyleEngineTest.cpp
index fcac598..0d586c7 100644
--- a/third_party/WebKit/Source/core/dom/StyleEngineTest.cpp
+++ b/third_party/WebKit/Source/core/dom/StyleEngineTest.cpp
@@ -50,13 +50,13 @@
   StyleSheetContents* sheet =
       StyleSheetContents::create(CSSParserContext(HTMLStandardMode, nullptr));
   sheet->parseString(cssText);
-  HeapVector<Member<RuleSet>> ruleSets;
+  HeapHashSet<Member<RuleSet>> ruleSets;
   RuleSet& ruleSet = sheet->ensureRuleSet(MediaQueryEvaluator(),
                                           RuleHasDocumentSecurityOrigin);
   ruleSet.compactRulesIfNeeded();
   if (ruleSet.needsFullRecalcForRuleSetInvalidation())
     return RuleSetInvalidationFullRecalc;
-  ruleSets.append(&ruleSet);
+  ruleSets.add(&ruleSet);
   styleEngine().scheduleInvalidationsForRuleSets(treeScope, ruleSets);
   return RuleSetInvalidationsScheduled;
 }
diff --git a/third_party/WebKit/Source/core/dom/custom/CustomElementRegistryTest.cpp b/third_party/WebKit/Source/core/dom/custom/CustomElementRegistryTest.cpp
index fbb93b6c..fc29919 100644
--- a/third_party/WebKit/Source/core/dom/custom/CustomElementRegistryTest.cpp
+++ b/third_party/WebKit/Source/core/dom/custom/CustomElementRegistryTest.cpp
@@ -35,7 +35,7 @@
   Document& document() { return m_page->document(); }
 
   CustomElementRegistry& registry() {
-    return *m_page->frame().localDOMWindow()->customElements();
+    return *m_page->frame().domWindow()->customElements();
   }
 
   ScriptState* scriptState() {
diff --git a/third_party/WebKit/Source/core/dom/custom/CustomElementTest.cpp b/third_party/WebKit/Source/core/dom/custom/CustomElementTest.cpp
index 672589a..d414e65 100644
--- a/third_party/WebKit/Source/core/dom/custom/CustomElementTest.cpp
+++ b/third_party/WebKit/Source/core/dom/custom/CustomElementTest.cpp
@@ -208,7 +208,7 @@
   // register a definition
   std::unique_ptr<DummyPageHolder> holder(DummyPageHolder::create());
   CustomElementRegistry* registry =
-      holder->frame().localDOMWindow()->customElements();
+      holder->frame().domWindow()->customElements();
   NonThrowableExceptionState shouldNotThrow;
   {
     CEReactionsScope reactions;
diff --git a/third_party/WebKit/Source/core/editing/FrameSelection.cpp b/third_party/WebKit/Source/core/editing/FrameSelection.cpp
index 6cf39773..efaf58b 100644
--- a/third_party/WebKit/Source/core/editing/FrameSelection.cpp
+++ b/third_party/WebKit/Source/core/editing/FrameSelection.cpp
@@ -276,7 +276,7 @@
   notifyAccessibilityForSelectionChange();
   notifyCompositorForSelectionChange();
   notifyEventHandlerForSelectionChange();
-  m_frame->localDOMWindow()->enqueueDocumentEvent(
+  m_frame->domWindow()->enqueueDocumentEvent(
       Event::create(EventTypeNames::selectionchange));
 }
 
diff --git a/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp b/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
index 3450d97..e54aa91 100644
--- a/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
+++ b/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
@@ -103,6 +103,18 @@
   return !originB->isSameSchemeHostPort(originA.get());
 }
 
+void addRedirectsToTimingInfo(Resource* resource, ResourceTimingInfo* info) {
+  // Store redirect responses that were packed inside the final response.
+  const auto& responses = resource->response().redirectResponses();
+  for (size_t i = 0; i < responses.size(); ++i) {
+    const KURL& newURL = i + 1 < responses.size()
+                             ? KURL(responses[i + 1].url())
+                             : resource->resourceRequest().url();
+    bool crossOrigin = IsCrossOrigin(responses[i].url(), newURL);
+    info->addRedirect(responses[i], crossOrigin);
+  }
+}
+
 }  // namespace
 
 static void RecordSriResourceIntegrityMismatchEvent(
@@ -597,7 +609,6 @@
         resource->setLinkPreload(false);
       break;
   }
-
   if (!resource)
     return nullptr;
   if (resource->getType() != factory.type()) {
@@ -641,7 +652,6 @@
 
   if (!startLoad(resource))
     return nullptr;
-
   scopedResourceLoadTracker.resourceLoadContinuesBeyondScope();
 
   DCHECK(!resource->errorOccurred() ||
@@ -757,7 +767,7 @@
   return resource;
 }
 
-void ResourceFetcher::storeResourceTimingInitiatorInformation(
+void ResourceFetcher::storePerformanceTimingInitiatorInformation(
     Resource* resource) {
   const AtomicString& fetchInitiator = resource->options().initiatorInfo.name;
   if (fetchInitiator == FetchInitiatorTypeNames::internal)
@@ -771,6 +781,14 @@
                          ? resource->resourceRequest().navigationStartTime()
                          : monotonicallyIncreasingTime();
 
+  // This buffer is created and populated for providing transferSize
+  // and redirect timing opt-in information.
+  if (isMainResource) {
+    DCHECK(!m_navigationTimingInfo);
+    m_navigationTimingInfo =
+        ResourceTimingInfo::create(fetchInitiator, startTime, isMainResource);
+  }
+
   std::unique_ptr<ResourceTimingInfo> info =
       ResourceTimingInfo::create(fetchInitiator, startTime, isMainResource);
 
@@ -782,8 +800,9 @@
   }
 
   if (!isMainResource ||
-      context().updateTimingInfoForIFrameNavigation(info.get()))
+      context().updateTimingInfoForIFrameNavigation(info.get())) {
     m_resourceTimingInfoMap.add(resource, std::move(info));
+  }
 }
 
 ResourceFetcher::RevalidationPolicy
@@ -1125,6 +1144,10 @@
   return m_archive ? m_archive->mainResource() : nullptr;
 }
 
+ResourceTimingInfo* ResourceFetcher::getNavigationTimingInfo() {
+  return m_navigationTimingInfo.get();
+}
+
 void ResourceFetcher::didFinishLoading(Resource* resource,
                                        double finishTime,
                                        DidFinishLoadingReason finishReason) {
@@ -1143,18 +1166,19 @@
   DCHECK(finishReason == DidFinishFirstPartInMultipart ||
          !m_nonBlockingLoaders.contains(resource->loader()));
 
+  if (resource->getType() == Resource::MainResource) {
+    DCHECK(m_navigationTimingInfo);
+    // Store redirect responses that were packed inside the final response.
+    addRedirectsToTimingInfo(resource, m_navigationTimingInfo.get());
+    if (resource->response().isHTTP()) {
+      m_navigationTimingInfo->addFinalTransferSize(
+          encodedDataLength == -1 ? 0 : encodedDataLength);
+    }
+  }
   if (std::unique_ptr<ResourceTimingInfo> info =
           m_resourceTimingInfoMap.take(resource)) {
     // Store redirect responses that were packed inside the final response.
-    const Vector<ResourceResponse>& responses =
-        resource->response().redirectResponses();
-    for (size_t i = 0; i < responses.size(); ++i) {
-      const KURL& newURL = i + 1 < responses.size()
-                               ? KURL(responses[i + 1].url())
-                               : resource->resourceRequest().url();
-      bool crossOrigin = IsCrossOrigin(responses[i].url(), newURL);
-      info->addRedirect(responses[i], crossOrigin);
-    }
+    addRedirectsToTimingInfo(resource, info.get());
 
     if (resource->response().isHTTP() &&
         resource->response().httpStatusCode() < 400) {
@@ -1326,7 +1350,7 @@
   else
     m_nonBlockingLoaders.add(loader);
 
-  storeResourceTimingInitiatorInformation(resource);
+  storePerformanceTimingInitiatorInformation(resource);
   resource->setFetcherSecurityOrigin(sourceOrigin);
 
   loader->activateCacheAwareLoadingIfNeeded(request);
@@ -1419,6 +1443,13 @@
     bool crossOrigin = IsCrossOrigin(redirectResponse.url(), newRequest.url());
     it->value->addRedirect(redirectResponse, crossOrigin);
   }
+
+  if (resource->getType() == Resource::MainResource) {
+    DCHECK(m_navigationTimingInfo);
+    bool crossOrigin = IsCrossOrigin(redirectResponse.url(), newRequest.url());
+    m_navigationTimingInfo->addRedirect(redirectResponse, crossOrigin);
+  }
+
   newRequest.setAllowStoredCredentials(resource->options().allowCredentials ==
                                        AllowStoredCredentials);
   willSendRequest(resource->identifier(), newRequest, redirectResponse,
diff --git a/third_party/WebKit/Source/core/fetch/ResourceFetcher.h b/third_party/WebKit/Source/core/fetch/ResourceFetcher.h
index efe804a..08972762 100644
--- a/third_party/WebKit/Source/core/fetch/ResourceFetcher.h
+++ b/third_party/WebKit/Source/core/fetch/ResourceFetcher.h
@@ -152,6 +152,9 @@
 
   void reloadLoFiImages();
 
+  // Calling this method before main document resource is fetched is invalid.
+  ResourceTimingInfo* getNavigationTimingInfo();
+
   // This is only exposed for testing purposes.
   HeapListHashSet<Member<Resource>>* preloads() { return m_preloads.get(); }
 
@@ -171,7 +174,7 @@
   Resource* createResourceForLoading(FetchRequest&,
                                      const String& charset,
                                      const ResourceFactory&);
-  void storeResourceTimingInitiatorInformation(Resource*);
+  void storePerformanceTimingInitiatorInformation(Resource*);
   ResourceLoadPriority computeLoadPriority(Resource::Type,
                                            const FetchRequest&,
                                            ResourcePriority::VisibilityStatus);
@@ -237,6 +240,8 @@
       HeapHashMap<Member<Resource>, std::unique_ptr<ResourceTimingInfo>>;
   ResourceTimingInfoMap m_resourceTimingInfoMap;
 
+  std::unique_ptr<ResourceTimingInfo> m_navigationTimingInfo;
+
   Vector<std::unique_ptr<ResourceTimingInfo>> m_scheduledResourceTimingReports;
 
   HeapHashSet<Member<ResourceLoader>> m_loaders;
diff --git a/third_party/WebKit/Source/core/fetch/ResourceFetcherTest.cpp b/third_party/WebKit/Source/core/fetch/ResourceFetcherTest.cpp
index 80ff9d0..83c82de 100644
--- a/third_party/WebKit/Source/core/fetch/ResourceFetcherTest.cpp
+++ b/third_party/WebKit/Source/core/fetch/ResourceFetcherTest.cpp
@@ -144,6 +144,47 @@
   memoryCache()->remove(resource);
 }
 
+TEST_F(ResourceFetcherTest, NavigationTimingInfo) {
+  KURL url(ParsedURLString, "http://127.0.0.1:8000/foo.html");
+  ResourceResponse response;
+  response.setURL(url);
+  response.setHTTPStatusCode(200);
+
+  ResourceFetcher* fetcher = ResourceFetcher::create(
+      MockFetchContext::create(MockFetchContext::kShouldLoadNewResource));
+  ResourceRequest resourceRequest(url);
+  resourceRequest.setFrameType(WebURLRequest::FrameTypeNested);
+  resourceRequest.setRequestContext(WebURLRequest::RequestContextForm);
+  FetchRequest fetchRequest =
+      FetchRequest(resourceRequest, FetchInitiatorInfo());
+  Platform::current()->getURLLoaderMockFactory()->registerURL(
+      url, WebURLResponse(), "");
+  Resource* resource =
+      RawResource::fetchMainResource(fetchRequest, fetcher, SubstituteData());
+  resource->responseReceived(response, nullptr);
+  EXPECT_EQ(resource->getType(), Resource::MainResource);
+
+  ResourceTimingInfo* navigationTimingInfo = fetcher->getNavigationTimingInfo();
+  ASSERT_TRUE(navigationTimingInfo);
+  long long encodedDataLength = 123;
+  resource->loader()->didFinishLoading(0.0, encodedDataLength, 0);
+  EXPECT_EQ(navigationTimingInfo->transferSize(), encodedDataLength);
+
+  // When there are redirects.
+  KURL redirectURL(ParsedURLString, "http://127.0.0.1:8000/redirect.html");
+  ResourceResponse redirectResponse;
+  redirectResponse.setURL(redirectURL);
+  redirectResponse.setHTTPStatusCode(200);
+  long long redirectEncodedDataLength = 123;
+  redirectResponse.setEncodedDataLength(redirectEncodedDataLength);
+  ResourceRequest redirectResourceRequest(url);
+  fetcher->willFollowRedirect(resource, redirectResourceRequest,
+                              redirectResponse);
+  EXPECT_EQ(navigationTimingInfo->transferSize(),
+            encodedDataLength + redirectEncodedDataLength);
+  Platform::current()->getURLLoaderMockFactory()->unregisterURL(url);
+}
+
 TEST_F(ResourceFetcherTest, VaryOnBack) {
   MockFetchContext* context =
       MockFetchContext::create(MockFetchContext::kShouldLoadNewResource);
diff --git a/third_party/WebKit/Source/core/frame/DOMTimer.cpp b/third_party/WebKit/Source/core/frame/DOMTimer.cpp
index a6140804..0a4bc85 100644
--- a/third_party/WebKit/Source/core/frame/DOMTimer.cpp
+++ b/third_party/WebKit/Source/core/frame/DOMTimer.cpp
@@ -47,7 +47,7 @@
 static const double minimumInterval = 0.004;
 
 static inline bool shouldForwardUserGesture(int interval, int nestingLevel) {
-  return UserGestureIndicator::processingUserGesture() &&
+  return UserGestureIndicator::processingUserGestureThreadSafe() &&
          interval <= maxIntervalForUserGestureForwarding &&
          nestingLevel ==
              1;  // Gestures should not be forwarded to nested timers.
@@ -90,8 +90,11 @@
       m_nestingLevel(context->timers()->timerNestingLevel() + 1),
       m_action(action) {
   ASSERT(timeoutID > 0);
-  if (shouldForwardUserGesture(interval, m_nestingLevel))
+  if (shouldForwardUserGesture(interval, m_nestingLevel)) {
+    // Thread safe because shouldForwardUserGesture will only return true if
+    // execution is on the the main thread.
     m_userGestureToken = UserGestureIndicator::currentToken();
+  }
 
   InspectorInstrumentation::asyncTaskScheduled(
       context, singleShot ? "setTimeout" : "setInterval", this, !singleShot);
@@ -107,10 +110,7 @@
     startRepeating(intervalMilliseconds, BLINK_FROM_HERE);
 }
 
-DOMTimer::~DOMTimer() {
-  if (m_action)
-    m_action->dispose();
-}
+DOMTimer::~DOMTimer() {}
 
 void DOMTimer::stop() {
   InspectorInstrumentation::asyncTaskCanceled(getExecutionContext(), this);
@@ -118,8 +118,6 @@
   // Need to release JS objects potentially protected by ScheduledAction
   // because they can form circular references back to the ExecutionContext
   // which will cause a memory leak.
-  if (m_action)
-    m_action->dispose();
   m_action = nullptr;
   SuspendableTimer::stop();
 }
@@ -177,8 +175,6 @@
   executionContext->timers()->setTimerNestingLevel(0);
   // Eagerly unregister as ExecutionContext observer.
   clearContext();
-  // Eagerly clear out |action|'s resources.
-  action->dispose();
 }
 
 WebTaskRunner* DOMTimer::timerTaskRunner() const {
diff --git a/third_party/WebKit/Source/core/frame/DOMWindowProperty.cpp b/third_party/WebKit/Source/core/frame/DOMWindowProperty.cpp
index 312beaa..fef480ff 100644
--- a/third_party/WebKit/Source/core/frame/DOMWindowProperty.cpp
+++ b/third_party/WebKit/Source/core/frame/DOMWindowProperty.cpp
@@ -38,7 +38,7 @@
   if (m_frame) {
     // FIXME: Need to figure out what to do with DOMWindowProperties on
     // remote DOM windows.
-    m_frame->localDOMWindow()->registerProperty(this);
+    m_frame->domWindow()->registerProperty(this);
   }
 }
 
diff --git a/third_party/WebKit/Source/core/frame/Deprecation.cpp b/third_party/WebKit/Source/core/frame/Deprecation.cpp
index 6284adb2..1f0bd83 100644
--- a/third_party/WebKit/Source/core/frame/Deprecation.cpp
+++ b/third_party/WebKit/Source/core/frame/Deprecation.cpp
@@ -413,6 +413,12 @@
     case UseCounter::HTMLObjectElementLegacyCall:
       return willBeRemoved("HTMLObjectElement legacy caller", M58,
                            "5715026367217664");
+    case UseCounter::
+        ServiceWorkerRespondToNavigationRequestWithRedirectedResponse:
+      return String::format(
+          "The service worker responded to the navigation request with a "
+          "redirected response. This will result in an error in %s.",
+          milestoneString(M59));
 
     // Features that aren't deprecated don't have a deprecation message.
     default:
diff --git a/third_party/WebKit/Source/core/frame/Frame.cpp b/third_party/WebKit/Source/core/frame/Frame.cpp
index 9680704..aa43af8 100644
--- a/third_party/WebKit/Source/core/frame/Frame.cpp
+++ b/third_party/WebKit/Source/core/frame/Frame.cpp
@@ -64,6 +64,7 @@
   visitor->trace(m_treeNode);
   visitor->trace(m_host);
   visitor->trace(m_owner);
+  visitor->trace(m_domWindow);
   visitor->trace(m_client);
 }
 
diff --git a/third_party/WebKit/Source/core/frame/Frame.h b/third_party/WebKit/Source/core/frame/Frame.h
index 098c603..2abf68fc 100644
--- a/third_party/WebKit/Source/core/frame/Frame.h
+++ b/third_party/WebKit/Source/core/frame/Frame.h
@@ -74,7 +74,6 @@
   virtual bool isLocalFrame() const = 0;
   virtual bool isRemoteFrame() const = 0;
 
-  virtual DOMWindow* domWindow() const = 0;
   virtual WindowProxy* windowProxy(DOMWrapperWorld&) = 0;
 
   virtual void navigate(Document& originDocument,
@@ -107,6 +106,8 @@
   void setOwner(FrameOwner* owner) { m_owner = owner; }
   HTMLFrameOwnerElement* deprecatedLocalOwner() const;
 
+  DOMWindow* domWindow() const { return m_domWindow; }
+
   FrameTree& tree() const;
   ChromeClient& chromeClient() const;
 
@@ -153,6 +154,7 @@
 
   Member<FrameHost> m_host;
   Member<FrameOwner> m_owner;
+  Member<DOMWindow> m_domWindow;
 
   bool m_isDetaching = false;
 
diff --git a/third_party/WebKit/Source/core/frame/FrameClient.h b/third_party/WebKit/Source/core/frame/FrameClient.h
index 4af7581..6b8af79 100644
--- a/third_party/WebKit/Source/core/frame/FrameClient.h
+++ b/third_party/WebKit/Source/core/frame/FrameClient.h
@@ -35,8 +35,6 @@
 
   virtual void frameFocused() const = 0;
 
-  virtual BlameContext* frameBlameContext() { return nullptr; }
-
   virtual ~FrameClient() {}
 
   DEFINE_INLINE_VIRTUAL_TRACE() {}
diff --git a/third_party/WebKit/Source/core/frame/FrameView.cpp b/third_party/WebKit/Source/core/frame/FrameView.cpp
index 196f5626..27eb979 100644
--- a/third_party/WebKit/Source/core/frame/FrameView.cpp
+++ b/third_party/WebKit/Source/core/frame/FrameView.cpp
@@ -965,7 +965,7 @@
   return RuntimeEnabledFeatures::scrollAnchoringEnabled() &&
          !RuntimeEnabledFeatures::rootLayerScrollingEnabled() &&
          m_scrollAnchor.hasScroller() &&
-         layoutBox()->style()->overflowAnchor() != AnchorNone &&
+         layoutBox()->style()->overflowAnchor() != EOverflowAnchor::None &&
          !m_frame->document()->finishingOrIsPrinting();
 }
 
diff --git a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
index 603823a..b3d3098 100644
--- a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
@@ -532,7 +532,7 @@
     if (!frames[i]->isLocalFrame())
       continue;
     toLocalFrame(frames[i].get())
-        ->localDOMWindow()
+        ->domWindow()
         ->dispatchEvent(Event::create(EventTypeNames::orientationchange));
   }
 }
diff --git a/third_party/WebKit/Source/core/frame/LocalFrame.cpp b/third_party/WebKit/Source/core/frame/LocalFrame.cpp
index eff2a0c..c5b21581 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrame.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalFrame.cpp
@@ -349,10 +349,6 @@
   Supplementable<LocalFrame>::trace(visitor);
 }
 
-DOMWindow* LocalFrame::domWindow() const {
-  return m_domWindow.get();
-}
-
 WindowProxy* LocalFrame::windowProxy(DOMWrapperWorld& world) {
   return m_script->windowProxy(world);
 }
@@ -429,9 +425,9 @@
   script().clearForClose();
   setView(nullptr);
 
-  m_host->eventHandlerRegistry().didRemoveAllEventHandlers(*localDOMWindow());
+  m_host->eventHandlerRegistry().didRemoveAllEventHandlers(*domWindow());
 
-  localDOMWindow()->frameDestroyed();
+  domWindow()->frameDestroyed();
 
   // 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,
@@ -474,7 +470,7 @@
       targetFrameDescription + " from frame with URL '" +
       document()->url().getString() + "'. " + reason + "\n";
 
-  localDOMWindow()->printErrorMessage(message);
+  domWindow()->printErrorMessage(message);
 }
 
 WindowProxyManager* LocalFrame::getWindowProxyManager() const {
@@ -500,6 +496,10 @@
   inputMethodController().documentAttached(document());
 }
 
+LocalDOMWindow* LocalFrame::domWindow() const {
+  return toLocalDOMWindow(m_domWindow);
+}
+
 void LocalFrame::setDOMWindow(LocalDOMWindow* domWindow) {
   // TODO(haraken): Update this comment.
   // Oilpan: setDOMWindow() cannot be used when finalizing. Which
@@ -519,8 +519,8 @@
   if (domWindow)
     script().clearWindowProxy();
 
-  if (m_domWindow)
-    m_domWindow->reset();
+  if (this->domWindow())
+    this->domWindow()->reset();
   m_domWindow = domWindow;
 }
 
diff --git a/third_party/WebKit/Source/core/frame/LocalFrame.h b/third_party/WebKit/Source/core/frame/LocalFrame.h
index c979b7b..fb15870 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrame.h
+++ b/third_party/WebKit/Source/core/frame/LocalFrame.h
@@ -106,7 +106,6 @@
   // Frame overrides:
   ~LocalFrame() override;
   DECLARE_VIRTUAL_TRACE();
-  DOMWindow* domWindow() const override;
   WindowProxy* windowProxy(DOMWrapperWorld&) override;
   void navigate(Document& originDocument,
                 const KURL&,
@@ -125,7 +124,7 @@
   void detachChildren();
   void documentAttached();
 
-  LocalDOMWindow* localDOMWindow() const;
+  LocalDOMWindow* domWindow() const;
   void setDOMWindow(LocalDOMWindow*);
   FrameView* view() const;
   Document* document() const;
@@ -249,7 +248,6 @@
   Member<NavigationScheduler> m_navigationScheduler;
 
   Member<FrameView> m_view;
-  Member<LocalDOMWindow> m_domWindow;
   // Usually 0. Non-null if this is the top frame of PagePopup.
   Member<Element> m_pagePopupOwner;
 
@@ -279,10 +277,6 @@
   m_loader.init();
 }
 
-inline LocalDOMWindow* LocalFrame::localDOMWindow() const {
-  return m_domWindow.get();
-}
-
 inline FrameLoader& LocalFrame::loader() const {
   return m_loader;
 }
diff --git a/third_party/WebKit/Source/core/frame/RemoteDOMWindow.h b/third_party/WebKit/Source/core/frame/RemoteDOMWindow.h
index 2507461..13c6538 100644
--- a/third_party/WebKit/Source/core/frame/RemoteDOMWindow.h
+++ b/third_party/WebKit/Source/core/frame/RemoteDOMWindow.h
@@ -7,6 +7,7 @@
 
 #include "core/frame/DOMWindow.h"
 #include "core/frame/RemoteFrame.h"
+#include "wtf/Assertions.h"
 
 namespace blink {
 
@@ -109,6 +110,12 @@
   Member<RemoteFrame> m_frame;
 };
 
+DEFINE_TYPE_CASTS(RemoteDOMWindow,
+                  DOMWindow,
+                  x,
+                  x->isRemoteDOMWindow(),
+                  x.isRemoteDOMWindow());
+
 }  // namespace blink
 
 #endif  // DOMWindow_h
diff --git a/third_party/WebKit/Source/core/frame/RemoteFrame.cpp b/third_party/WebKit/Source/core/frame/RemoteFrame.cpp
index 4abb8f84..730c0173 100644
--- a/third_party/WebKit/Source/core/frame/RemoteFrame.cpp
+++ b/third_party/WebKit/Source/core/frame/RemoteFrame.cpp
@@ -30,8 +30,9 @@
                                 FrameOwner* owner)
     : Frame(client, host, owner),
       m_securityContext(RemoteSecurityContext::create()),
-      m_domWindow(RemoteDOMWindow::create(*this)),
-      m_windowProxyManager(WindowProxyManager::create(*this)) {}
+      m_windowProxyManager(WindowProxyManager::create(*this)) {
+  m_domWindow = RemoteDOMWindow::create(*this);
+}
 
 RemoteFrame* RemoteFrame::create(RemoteFrameClient* client,
                                  FrameHost* host,
@@ -46,15 +47,10 @@
 DEFINE_TRACE(RemoteFrame) {
   visitor->trace(m_view);
   visitor->trace(m_securityContext);
-  visitor->trace(m_domWindow);
   visitor->trace(m_windowProxyManager);
   Frame::trace(visitor);
 }
 
-DOMWindow* RemoteFrame::domWindow() const {
-  return m_domWindow.get();
-}
-
 WindowProxy* RemoteFrame::windowProxy(DOMWrapperWorld& world) {
   WindowProxy* windowProxy = m_windowProxyManager->windowProxy(world);
   ASSERT(windowProxy);
@@ -155,7 +151,7 @@
   // persistent strong references to RemoteDOMWindow will prevent the GCing
   // of all these objects. Break the cycle by notifying of detachment.
   if (!m_view)
-    m_domWindow->frameDetached();
+    toRemoteDOMWindow(m_domWindow)->frameDetached();
 }
 
 void RemoteFrame::createView() {
diff --git a/third_party/WebKit/Source/core/frame/RemoteFrame.h b/third_party/WebKit/Source/core/frame/RemoteFrame.h
index 9d55b14..9c1c8094 100644
--- a/third_party/WebKit/Source/core/frame/RemoteFrame.h
+++ b/third_party/WebKit/Source/core/frame/RemoteFrame.h
@@ -15,7 +15,6 @@
 class Event;
 class IntRect;
 class LocalFrame;
-class RemoteDOMWindow;
 class RemoteFrameClient;
 class RemoteFrameView;
 class WebLayer;
@@ -30,7 +29,6 @@
 
   // Frame overrides:
   DECLARE_VIRTUAL_TRACE();
-  DOMWindow* domWindow() const override;
   WindowProxy* windowProxy(DOMWrapperWorld&) override;
   void navigate(Document& originDocument,
                 const KURL&,
@@ -81,7 +79,6 @@
 
   Member<RemoteFrameView> m_view;
   Member<RemoteSecurityContext> m_securityContext;
-  Member<RemoteDOMWindow> m_domWindow;
   Member<WindowProxyManager> m_windowProxyManager;
   WebLayer* m_webLayer = nullptr;
 };
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.h b/third_party/WebKit/Source/core/frame/UseCounter.h
index 4a3af7d..ae0a4947 100644
--- a/third_party/WebKit/Source/core/frame/UseCounter.h
+++ b/third_party/WebKit/Source/core/frame/UseCounter.h
@@ -1387,6 +1387,7 @@
     V8BarcodeDetector_Detect_Method = 1694,
     V8FaceDetector_Detect_Method = 1695,
     FullscreenAllowedByOrientationChange = 1696,
+    ServiceWorkerRespondToNavigationRequestWithRedirectedResponse = 1697,
 
     // Add new features immediately above this line. Don't change assigned
     // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/WebKit/Source/core/html/AutoplayUmaHelper.cpp b/third_party/WebKit/Source/core/html/AutoplayUmaHelper.cpp
index 0ab3aad..bf2d6ff 100644
--- a/third_party/WebKit/Source/core/html/AutoplayUmaHelper.cpp
+++ b/third_party/WebKit/Source/core/html/AutoplayUmaHelper.cpp
@@ -210,6 +210,7 @@
 
 void AutoplayUmaHelper::handlePauseEvent() {
   maybeStopRecordingMutedVideoOffscreenDuration();
+  maybeRecordUserPausedAutoplayingCrossOriginVideo();
 }
 
 void AutoplayUmaHelper::contextDestroyed() {
@@ -299,21 +300,55 @@
   m_mutedVideoOffscreenDurationVisibilityObserver->stop();
   m_mutedVideoOffscreenDurationVisibilityObserver = nullptr;
   m_mutedVideoAutoplayOffscreenDurationMS = 0;
-  m_element->removeEventListener(EventTypeNames::pause, this, false);
+  maybeUnregisterMediaElementPauseListener();
   maybeUnregisterContextDestroyedObserver();
 }
 
+void AutoplayUmaHelper::maybeRecordUserPausedAutoplayingCrossOriginVideo() {
+  if (!shouldRecordUserPausedAutoplayingCrossOriginVideo())
+    return;
+
+  if (m_element->ended() || m_element->seeking())
+    return;
+
+  Platform::current()->recordRapporURL(
+      "Media.Autoplay.CrossOrigin.UserPausedAutoplayingVideo.ChildFrame",
+      m_element->document().url());
+  Platform::current()->recordRapporURL(
+      "Media.Autoplay.CrossOrigin.UserPausedAutoplayingVideo."
+      "TopLevelFrame",
+      m_element->document().topDocument().url());
+
+  m_hasRecordedUserPausedAutoplayingCrossOriginVideo = true;
+  maybeUnregisterMediaElementPauseListener();
+}
+
 void AutoplayUmaHelper::maybeUnregisterContextDestroyedObserver() {
   if (!shouldListenToContextDestroyed()) {
     setContext(nullptr);
   }
 }
 
+void AutoplayUmaHelper::maybeUnregisterMediaElementPauseListener() {
+  if (m_mutedVideoOffscreenDurationVisibilityObserver)
+    return;
+  if (shouldRecordUserPausedAutoplayingCrossOriginVideo())
+    return;
+  m_element->removeEventListener(EventTypeNames::pause, this, false);
+}
+
 bool AutoplayUmaHelper::shouldListenToContextDestroyed() const {
   return m_mutedVideoPlayMethodVisibilityObserver ||
          m_mutedVideoOffscreenDurationVisibilityObserver;
 }
 
+bool AutoplayUmaHelper::shouldRecordUserPausedAutoplayingCrossOriginVideo()
+    const {
+  return m_element->isInCrossOriginFrame() && m_element->isHTMLVideoElement() &&
+         m_source != AutoplaySource::NumberOfSources &&
+         !m_hasRecordedUserPausedAutoplayingCrossOriginVideo;
+}
+
 DEFINE_TRACE(AutoplayUmaHelper) {
   EventListener::trace(visitor);
   ContextLifecycleObserver::trace(visitor);
diff --git a/third_party/WebKit/Source/core/html/AutoplayUmaHelper.h b/third_party/WebKit/Source/core/html/AutoplayUmaHelper.h
index aafa273..88bd8df 100644
--- a/third_party/WebKit/Source/core/html/AutoplayUmaHelper.h
+++ b/third_party/WebKit/Source/core/html/AutoplayUmaHelper.h
@@ -86,6 +86,7 @@
   virtual void handleContextDestroyed();  // Make virtual for testing.
 
   void maybeUnregisterContextDestroyedObserver();
+  void maybeUnregisterMediaElementPauseListener();
 
   void maybeStartRecordingMutedVideoPlayMethodBecomeVisible();
   void maybeStopRecordingMutedVideoPlayMethodBecomeVisible(bool isVisible);
@@ -93,10 +94,13 @@
   void maybeStartRecordingMutedVideoOffscreenDuration();
   void maybeStopRecordingMutedVideoOffscreenDuration();
 
+  void maybeRecordUserPausedAutoplayingCrossOriginVideo();
+
   void onVisibilityChangedForMutedVideoOffscreenDuration(bool isVisibile);
   void onVisibilityChangedForMutedVideoPlayMethodBecomeVisible(bool isVisible);
 
   bool shouldListenToContextDestroyed() const;
+  bool shouldRecordUserPausedAutoplayingCrossOriginVideo() const;
 
   // The autoplay source. Use AutoplaySource::NumberOfSources for invalid
   // source.
@@ -126,6 +130,9 @@
 
   std::set<CrossOriginAutoplayResult> m_recordedCrossOriginAutoplayResults;
 
+  // Whether the UMA helper has recorded user pausing a cross-origin video.
+  bool m_hasRecordedUserPausedAutoplayingCrossOriginVideo;
+
   // The observer is used to observer an autoplaying muted video changing it's
   // visibility, which is used for offscreen duration UMA.  The UMA is pending
   // for recording as long as this observer is non-null.
diff --git a/third_party/WebKit/Source/core/html/AutoplayUmaHelperTest.cpp b/third_party/WebKit/Source/core/html/AutoplayUmaHelperTest.cpp
index 77f75ad..f5be095 100644
--- a/third_party/WebKit/Source/core/html/AutoplayUmaHelperTest.cpp
+++ b/third_party/WebKit/Source/core/html/AutoplayUmaHelperTest.cpp
@@ -45,37 +45,34 @@
     return toHTMLVideoElement(*element);
   }
 
-  MockAutoplayUmaHelper& umaHelper() {
-    return *(static_cast<MockAutoplayUmaHelper*>(
-        mediaElement().m_autoplayUmaHelper.get()));
-  }
+  MockAutoplayUmaHelper& umaHelper() { return *m_umaHelper; }
 
   std::unique_ptr<DummyPageHolder>& pageHolder() { return m_pageHolder; }
 
-  MOCK_METHOD0(TestEnded, void());
-
  private:
   void SetUp() override {
     m_pageHolder = DummyPageHolder::create(IntSize(800, 600));
     document().documentElement()->setInnerHTML("<video id=video></video>",
                                                ASSERT_NO_EXCEPTION);
     HTMLMediaElement& element = mediaElement();
-    element.m_autoplayUmaHelper = new MockAutoplayUmaHelper(&element);
+    m_umaHelper = new MockAutoplayUmaHelper(&element);
+    element.m_autoplayUmaHelper = m_umaHelper;
   }
 
+  void TearDown() override { m_umaHelper.clear(); }
+
   std::unique_ptr<DummyPageHolder> m_pageHolder;
+  Persistent<MockAutoplayUmaHelper> m_umaHelper;
 };
 
 TEST_F(AutoplayUmaHelperTest, VisibilityChangeWhenUnload) {
-  // This is to avoid handleContextDestroyed() to be called during TearDown().
-  EXPECT_CALL(*this, TestEnded())
-      .After(EXPECT_CALL(umaHelper(), handleContextDestroyed()));
+  EXPECT_CALL(umaHelper(), handleContextDestroyed());
 
   mediaElement().setMuted(true);
   umaHelper().onAutoplayInitiated(AutoplaySource::Attribute);
   umaHelper().handlePlayingEvent();
   pageHolder().reset();
-  TestEnded();
+  ::testing::Mock::VerifyAndClear(&umaHelper());
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
index 3dc61ac..6bea516 100644
--- a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
@@ -39,7 +39,6 @@
 #include "core/dom/ElementTraversal.h"
 #include "core/dom/ElementVisibilityObserver.h"
 #include "core/dom/Fullscreen.h"
-#include "core/dom/IntersectionGeometry.h"
 #include "core/dom/TaskRunnerHelper.h"
 #include "core/dom/shadow/ShadowRoot.h"
 #include "core/events/Event.h"
@@ -66,6 +65,7 @@
 #include "core/html/track/VideoTrack.h"
 #include "core/html/track/VideoTrackList.h"
 #include "core/inspector/ConsoleMessage.h"
+#include "core/layout/IntersectionGeometry.h"
 #include "core/layout/LayoutMedia.h"
 #include "core/layout/api/LayoutViewItem.h"
 #include "core/layout/compositing/PaintLayerCompositor.h"
@@ -4069,9 +4069,9 @@
 void HTMLMediaElement::checkViewportIntersectionChanged() {
   // TODO(xjz): Early return if we not in tab mirroring.
 
-  IntersectionGeometry geometry(
-      document().frame()->localFrameRoot()->document(), this, Vector<Length>(),
-      IntersectionGeometry::ReportRootBounds::kShouldReportRootBounds);
+  bool shouldReportRootBounds = true;
+  IntersectionGeometry geometry(nullptr, *this, Vector<Length>(),
+                                shouldReportRootBounds);
   geometry.computeGeometry();
   IntRect intersectRect = geometry.intersectionIntRect();
   if (m_currentIntersectRect == intersectRect)
diff --git a/third_party/WebKit/Source/core/html/ImageDocumentTest.cpp b/third_party/WebKit/Source/core/html/ImageDocumentTest.cpp
index 9873d8db..28b344e 100644
--- a/third_party/WebKit/Source/core/html/ImageDocumentTest.cpp
+++ b/third_party/WebKit/Source/core/html/ImageDocumentTest.cpp
@@ -98,7 +98,7 @@
   LocalFrame& frame = m_dummyPageHolder->frame();
   frame.document()->shutdown();
   DocumentInit init(KURL(), &frame);
-  frame.localDOMWindow()->installNewDocument("image/jpeg", init);
+  frame.domWindow()->installNewDocument("image/jpeg", init);
 }
 
 void ImageDocumentTest::createDocument(int viewWidth, int viewHeight) {
diff --git a/third_party/WebKit/Source/core/layout/BUILD.gn b/third_party/WebKit/Source/core/layout/BUILD.gn
index fad269e2..24b609a 100644
--- a/third_party/WebKit/Source/core/layout/BUILD.gn
+++ b/third_party/WebKit/Source/core/layout/BUILD.gn
@@ -39,6 +39,8 @@
     "HitTestingTransformState.h",
     "ImageQualityController.cpp",
     "ImageQualityController.h",
+    "IntersectionGeometry.cpp",
+    "IntersectionGeometry.h",
     "LayoutAnalyzer.cpp",
     "LayoutAnalyzer.h",
     "LayoutBR.cpp",
diff --git a/third_party/WebKit/Source/core/layout/IntersectionGeometry.cpp b/third_party/WebKit/Source/core/layout/IntersectionGeometry.cpp
new file mode 100644
index 0000000..8274879
--- /dev/null
+++ b/third_party/WebKit/Source/core/layout/IntersectionGeometry.cpp
@@ -0,0 +1,215 @@
+// 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/layout/IntersectionGeometry.h"
+
+#include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
+#include "core/html/HTMLFrameOwnerElement.h"
+#include "core/layout/LayoutBox.h"
+#include "core/layout/LayoutView.h"
+#include "core/layout/api/LayoutAPIShim.h"
+#include "core/layout/api/LayoutViewItem.h"
+#include "core/paint/PaintLayer.h"
+
+namespace blink {
+
+namespace {
+
+bool isContainingBlockChainDescendant(LayoutObject* descendant,
+                                      LayoutObject* ancestor) {
+  LocalFrame* ancestorFrame = ancestor->document().frame();
+  LocalFrame* descendantFrame = descendant->document().frame();
+  if (ancestorFrame != descendantFrame)
+    return false;
+
+  while (descendant && descendant != ancestor)
+    descendant = descendant->containingBlock();
+  return descendant;
+}
+
+void mapRectUpToDocument(LayoutRect& rect,
+                         const LayoutObject& descendant,
+                         const Document& document) {
+  FloatQuad mappedQuad = descendant.localToAncestorQuad(
+      FloatQuad(FloatRect(rect)), document.layoutView(),
+      UseTransforms | ApplyContainerFlip);
+  rect = LayoutRect(mappedQuad.boundingBox());
+}
+
+void mapRectDownToDocument(LayoutRect& rect,
+                           LayoutBoxModelObject* ancestor,
+                           const Document& document) {
+  FloatQuad mappedQuad = document.layoutView()->ancestorToLocalQuad(
+      ancestor, FloatQuad(FloatRect(rect)),
+      UseTransforms | ApplyContainerFlip | TraverseDocumentBoundaries);
+  rect = LayoutRect(mappedQuad.boundingBox());
+}
+
+LayoutUnit computeMargin(const Length& length, LayoutUnit referenceLength) {
+  if (length.type() == Percent) {
+    return LayoutUnit(
+        static_cast<int>(referenceLength.toFloat() * length.percent() / 100.0));
+  }
+  DCHECK_EQ(length.type(), Fixed);
+  return LayoutUnit(length.intValue());
+}
+
+LayoutView* localRootView(Element& element) {
+  LocalFrame* frame = element.document().frame();
+  LocalFrame* frameRoot = frame ? frame->localFrameRoot() : nullptr;
+  return frameRoot ? frameRoot->contentLayoutObject() : nullptr;
+}
+
+}  // namespace
+
+IntersectionGeometry::IntersectionGeometry(Element* root,
+                                           Element& target,
+                                           const Vector<Length>& rootMargin,
+                                           bool shouldReportRootBounds)
+    : m_root(root ? root->layoutObject() : localRootView(target)),
+      m_target(target.layoutObject()),
+      m_rootMargin(rootMargin),
+      m_doesIntersect(0),
+      m_shouldReportRootBounds(shouldReportRootBounds),
+      m_rootIsImplicit(!root),
+      m_canComputeGeometry(initializeCanComputeGeometry(root, target)) {
+  if (m_canComputeGeometry)
+    initializeGeometry();
+}
+
+IntersectionGeometry::~IntersectionGeometry() {}
+
+bool IntersectionGeometry::initializeCanComputeGeometry(Element* root,
+                                                        Element& target) const {
+  DCHECK(m_rootMargin.isEmpty() || m_rootMargin.size() == 4);
+  if (root && !root->isConnected())
+    return false;
+  if (!m_root || !m_root->isBox())
+    return false;
+  if (!target.isConnected())
+    return false;
+  if (!m_target || (!m_target->isBoxModelObject() && !m_target->isText()))
+    return false;
+  if (root && !isContainingBlockChainDescendant(m_target, m_root))
+    return false;
+  return true;
+}
+
+void IntersectionGeometry::initializeGeometry() {
+  initializeTargetRect();
+  m_intersectionRect = m_targetRect;
+  initializeRootRect();
+}
+
+void IntersectionGeometry::initializeTargetRect() {
+  m_targetRect =
+      LayoutRect(toLayoutBoxModelObject(target())->borderBoundingBox());
+}
+
+void IntersectionGeometry::initializeRootRect() {
+  // TODO(szager): In OOPIF, m_root will be the LayoutView of the
+  // localFrameRoot().  Once viewport intersection support lands,
+  // add a call to mapToVisualRectInAncestorSpace to map the rect up to
+  // top-level frame coordinates.
+  if (m_root->isLayoutView()) {
+    m_rootRect =
+        LayoutRect(toLayoutView(m_root)->frameView()->visibleContentRect());
+  } else if (m_root->isBox() && m_root->hasOverflowClip()) {
+    m_rootRect = LayoutRect(toLayoutBox(m_root)->contentBoxRect());
+  } else {
+    m_rootRect =
+        LayoutRect(toLayoutBoxModelObject(m_root)->borderBoundingBox());
+  }
+  applyRootMargin();
+}
+
+void IntersectionGeometry::applyRootMargin() {
+  if (m_rootMargin.isEmpty())
+    return;
+
+  // TODO(szager): Make sure the spec is clear that left/right margins are
+  // resolved against width and not height.
+  LayoutUnit topMargin = computeMargin(m_rootMargin[0], m_rootRect.height());
+  LayoutUnit rightMargin = computeMargin(m_rootMargin[1], m_rootRect.width());
+  LayoutUnit bottomMargin = computeMargin(m_rootMargin[2], m_rootRect.height());
+  LayoutUnit leftMargin = computeMargin(m_rootMargin[3], m_rootRect.width());
+
+  m_rootRect.setX(m_rootRect.x() - leftMargin);
+  m_rootRect.setWidth(m_rootRect.width() + leftMargin + rightMargin);
+  m_rootRect.setY(m_rootRect.y() - topMargin);
+  m_rootRect.setHeight(m_rootRect.height() + topMargin + bottomMargin);
+}
+
+void IntersectionGeometry::clipToRoot() {
+  // Map and clip rect into root element coordinates.
+  // TODO(szager): the writing mode flipping needs a test.
+  // TODO(szager): Once the OOPIF viewport intersection code lands,
+  // use nullptr for ancestor to map to the top frame.
+  LayoutBox* ancestor = toLayoutBox(m_root);
+  m_doesIntersect = m_target->mapToVisualRectInAncestorSpace(
+      ancestor, m_intersectionRect, EdgeInclusive);
+  if (ancestor && ancestor->hasOverflowClip())
+    m_intersectionRect.move(-ancestor->scrolledContentOffset());
+  if (!m_doesIntersect)
+    return;
+  LayoutRect rootClipRect(m_rootRect);
+  if (ancestor)
+    ancestor->flipForWritingMode(rootClipRect);
+  m_doesIntersect &= m_intersectionRect.inclusiveIntersect(rootClipRect);
+}
+
+void IntersectionGeometry::mapTargetRectToTargetFrameCoordinates() {
+  Document& targetDocument = m_target->document();
+  LayoutSize scrollPosition =
+      LayoutSize(targetDocument.view()->getScrollOffset());
+  mapRectUpToDocument(m_targetRect, *m_target, targetDocument);
+  m_targetRect.move(-scrollPosition);
+}
+
+void IntersectionGeometry::mapRootRectToRootFrameCoordinates() {
+  Document& rootDocument = m_root->document();
+  if (!rootIsImplicit())
+    mapRectUpToDocument(m_rootRect, *m_root, rootDocument);
+  // TODO(szager): When OOPIF support lands, this scroll offset adjustment
+  // will probably be wrong.
+  LayoutSize scrollPosition =
+      LayoutSize(rootDocument.view()->getScrollOffset());
+  m_rootRect.move(-scrollPosition);
+}
+
+void IntersectionGeometry::mapIntersectionRectToTargetFrameCoordinates() {
+  Document& targetDocument = m_target->document();
+  if (rootIsImplicit()) {
+    LocalFrame* targetFrame = targetDocument.frame();
+    Frame* rootFrame = targetFrame->tree().top();
+    LayoutSize scrollPosition =
+        LayoutSize(targetDocument.view()->getScrollOffset());
+    if (targetFrame != rootFrame)
+      mapRectDownToDocument(m_intersectionRect, nullptr, targetDocument);
+    m_intersectionRect.move(-scrollPosition);
+  } else {
+    LayoutSize scrollPosition =
+        LayoutSize(targetDocument.view()->getScrollOffset());
+    mapRectUpToDocument(m_intersectionRect, *m_root, m_root->document());
+    m_intersectionRect.move(-scrollPosition);
+  }
+}
+
+void IntersectionGeometry::computeGeometry() {
+  if (!canComputeGeometry())
+    return;
+  clipToRoot();
+  mapTargetRectToTargetFrameCoordinates();
+  if (m_doesIntersect)
+    mapIntersectionRectToTargetFrameCoordinates();
+  else
+    m_intersectionRect = LayoutRect();
+  // Small optimization: if we're not going to report root bounds, don't bother
+  // transforming them to the frame.
+  if (shouldReportRootBounds())
+    mapRootRectToRootFrameCoordinates();
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/IntersectionGeometry.h b/third_party/WebKit/Source/core/layout/IntersectionGeometry.h
new file mode 100644
index 0000000..6244ddd
--- /dev/null
+++ b/third_party/WebKit/Source/core/layout/IntersectionGeometry.h
@@ -0,0 +1,88 @@
+// 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 IntersectionGeometry_h
+#define IntersectionGeometry_h
+
+#include "platform/Length.h"
+#include "platform/geometry/LayoutRect.h"
+#include "platform/heap/Handle.h"
+#include "wtf/Vector.h"
+
+namespace blink {
+
+class Element;
+class LayoutObject;
+
+// Computes the intersection between an ancestor (root) element and a
+// descendant (target) element, with overflow and CSS clipping applied, but not
+// paint occlusion.
+//
+// If the root argument to the constructor is null, computes the intersection
+// of the target with the top-level frame viewport (AKA the "implicit root").
+class IntersectionGeometry {
+  STACK_ALLOCATED()
+ public:
+  IntersectionGeometry(Element* root,
+                       Element& target,
+                       const Vector<Length>& rootMargin,
+                       bool shouldReportRootBounds);
+  ~IntersectionGeometry();
+
+  void computeGeometry();
+
+  LayoutObject* root() const { return m_root; }
+  LayoutObject* target() const { return m_target; }
+
+  // Client rect in the coordinate system of the frame containing target.
+  LayoutRect targetRect() const { return m_targetRect; }
+
+  // Client rect in the coordinate system of the frame containing target.
+  LayoutRect intersectionRect() const { return m_intersectionRect; }
+
+  // Client rect in the coordinate system of the frame containing root.
+  LayoutRect rootRect() const { return m_rootRect; }
+
+  bool doesIntersect() const { return m_doesIntersect; }
+
+  IntRect intersectionIntRect() const {
+    return pixelSnappedIntRect(m_intersectionRect);
+  }
+
+  IntRect targetIntRect() const { return pixelSnappedIntRect(m_targetRect); }
+
+  IntRect rootIntRect() const { return pixelSnappedIntRect(m_rootRect); }
+
+ private:
+  bool initializeCanComputeGeometry(Element* root, Element& target) const;
+  void initializeGeometry();
+  void initializeTargetRect();
+  void initializeRootRect();
+  void clipToRoot();
+  void mapTargetRectToTargetFrameCoordinates();
+  void mapRootRectToRootFrameCoordinates();
+  void mapIntersectionRectToTargetFrameCoordinates();
+  void applyRootMargin();
+
+  // Returns true iff it's possible to compute an intersection between root
+  // and target.
+  bool canComputeGeometry() const { return m_canComputeGeometry; }
+  bool rootIsImplicit() const { return m_rootIsImplicit; }
+  bool shouldReportRootBounds() const { return m_shouldReportRootBounds; }
+
+  LayoutObject* m_root;
+  LayoutObject* m_target;
+  const Vector<Length> m_rootMargin;
+  LayoutRect m_targetRect;
+  LayoutRect m_intersectionRect;
+  LayoutRect m_rootRect;
+  unsigned m_doesIntersect : 1;
+  const unsigned m_shouldReportRootBounds : 1;
+  const unsigned m_rootIsImplicit : 1;
+  const unsigned m_canComputeGeometry : 1;
+};
+
+}  // namespace blink
+
+#endif  // IntersectionGeometry_h
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
index 03b3619..da28bc8 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
@@ -1709,10 +1709,10 @@
 
   LayoutObject* prev = child.previousSibling();
   LayoutBlockFlow* previousBlockFlow =
-      prev && prev->isLayoutBlockFlow() &&
-              !prev->isFloatingOrOutOfFlowPositioned()
-          ? toLayoutBlockFlow(prev)
-          : 0;
+      prev && prev->isLayoutBlockFlow() ? toLayoutBlockFlow(prev) : nullptr;
+  bool previousBlockFlowCanSelfCollapse =
+      previousBlockFlow &&
+      !previousBlockFlow->isFloatingOrOutOfFlowPositioned();
   // If the child's previous sibling is a self-collapsing block that cleared a
   // float then its top border edge has been set at the bottom border edge of
   // the float. Since we want to collapse the child's top margin with the self-
@@ -1720,7 +1720,8 @@
   // height to match the margin top of the self-collapsing block. If the
   // resulting collapsed margin leaves the child still intruding into the float
   // then we will want to clear it.
-  if (!marginInfo.canCollapseWithMarginBefore() && previousBlockFlow &&
+  if (!marginInfo.canCollapseWithMarginBefore() &&
+      previousBlockFlowCanSelfCollapse &&
       marginInfo.lastChildIsSelfCollapsingBlockWithClearance())
     setLogicalHeight(
         logicalHeight() -
@@ -1801,18 +1802,28 @@
     setLogicalHeight(logicalHeight() + (logicalTop - oldLogicalTop));
   }
 
-  if (previousBlockFlow) {
-    // If |child| is a self-collapsing block it may have collapsed into a
-    // previous sibling and although it hasn't reduced the height of the parent
-    // yet any floats from the parent will now overhang.
+  // If |child| has moved up into previous siblings it needs to avoid or clear
+  // any floats they contain.
+  if (logicalTop < beforeCollapseLogicalTop) {
     LayoutUnit oldLogicalHeight = logicalHeight();
     setLogicalHeight(logicalTop);
-    if (!previousBlockFlow->avoidsFloats() &&
-        (previousBlockFlow->logicalTop() +
-         previousBlockFlow->lowestFloatLogicalBottom()) > logicalTop)
-      addOverhangingFloats(previousBlockFlow, false);
+    while (previousBlockFlow) {
+      auto lowestFloat = previousBlockFlow->logicalTop() +
+                         previousBlockFlow->lowestFloatLogicalBottom();
+      if (lowestFloat > logicalTop)
+        addOverhangingFloats(previousBlockFlow, false);
+      else
+        break;
+      LayoutObject* prev = previousBlockFlow->previousSibling();
+      if (prev && prev->isLayoutBlockFlow())
+        previousBlockFlow = toLayoutBlockFlow(prev);
+      else
+        previousBlockFlow = nullptr;
+    }
     setLogicalHeight(oldLogicalHeight);
+  }
 
+  if (previousBlockFlowCanSelfCollapse) {
     // If |child|'s previous sibling is or contains a self-collapsing block that
     // cleared a float and margin collapsing resulted in |child| moving up
     // into the margin area of the self-collapsing block then the float it
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
index 894f7d8..f061939e 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -2257,6 +2257,13 @@
       return false;
   }
 
+  // If the box paints into its own backing, we can assume that it's painting
+  // may have some effect. For example, honoring the border-radius clip on
+  // a composited child paints into a mask for an otherwise non-painting
+  // element, because children of that element will require the mask.
+  if (hasLayer() && layer()->compositingState() == PaintsIntoOwnBacking)
+    return false;
+
   return true;
 }
 
@@ -4720,6 +4727,7 @@
   // just marking and bailing here.
   if (child.isFloating())
     return true;
+  const LayoutFlowThread* flowThread = child.flowThreadContainingBlock();
   LayoutUnit logicalTop = child.logicalTop();
   // Figure out if we really need to force re-layout of the child. We only need
   // to do this if there's a chance that we need to recalculate pagination
@@ -4733,6 +4741,10 @@
       // location as before.
       if (child.offsetToNextPage() != remainingSpace)
         return true;
+      // If column height isn't guaranteed to be uniform, we have no way of
+      // telling what has happened after the first break.
+      if (flowThread && flowThread->mayHaveNonUniformPageLogicalHeight())
+        return true;
     } else if (logicalHeight > remainingSpace) {
       // Last time we laid out this child, we didn't need to break, but now we
       // have to. So we need to relayout.
@@ -4747,7 +4759,6 @@
   // It seems that we can skip layout of this child, but we need to ask the flow
   // thread for permission first. We currently cannot skip over objects
   // containing column spanners.
-  LayoutFlowThread* flowThread = child.flowThreadContainingBlock();
   return flowThread && !flowThread->canSkipLayout(child);
 }
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp
index d35fc7f..17369a27 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp
@@ -129,12 +129,6 @@
   if (!style()->hasAutoClip())
     return BackgroundPaintInGraphicsLayer;
 
-  // TODO(flackr): Remove this when box shadows are still painted correctly when
-  // painting into the composited scrolling contents layer.
-  // https://crbug.com/646464
-  if (style()->boxShadow())
-    return BackgroundPaintInGraphicsLayer;
-
   // Assume optimistically that the background can be painted in the scrolling
   // contents until we find otherwise.
   BackgroundPaintLocation paintLocation = BackgroundPaintInScrollingContents;
@@ -232,13 +226,8 @@
 
   FloatStateForStyleChange::setWasFloating(this, isFloating());
 
-  if (const ComputedStyle* oldStyle = style()) {
-    if (hasLayer() && diff.needsPaintInvalidationSubtree()) {
-      if (oldStyle->hasAutoClip() != newStyle.hasAutoClip() ||
-          oldStyle->clip() != newStyle.clip())
-        layer()->clipper().clearClipRectsIncludingDescendants();
-    }
-  }
+  if (hasLayer() && diff.cssClipChanged())
+    layer()->clipper().clearClipRectsIncludingDescendants();
 
   LayoutObject::styleWillChange(diff, newStyle);
 }
diff --git a/third_party/WebKit/Source/core/layout/LayoutFlowThread.h b/third_party/WebKit/Source/core/layout/LayoutFlowThread.h
index 594eafd9..354991c 100644
--- a/third_party/WebKit/Source/core/layout/LayoutFlowThread.h
+++ b/third_party/WebKit/Source/core/layout/LayoutFlowThread.h
@@ -141,6 +141,7 @@
       LayoutUnit contentLogicalHeight) const;
 
   virtual bool isPageLogicalHeightKnown() const { return true; }
+  virtual bool mayHaveNonUniformPageLogicalHeight() const = 0;
   bool pageLogicalSizeChanged() const { return m_pageLogicalSizeChanged; }
 
   // Return the visual bounding box based on the supplied flow-thread bounding
diff --git a/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.cpp b/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.cpp
index 807fe96..f532eda6 100644
--- a/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.cpp
@@ -365,6 +365,15 @@
   return false;
 }
 
+bool LayoutMultiColumnFlowThread::mayHaveNonUniformPageLogicalHeight() const {
+  const LayoutMultiColumnSet* columnSet = firstMultiColumnSet();
+  if (!columnSet)
+    return false;
+  if (columnSet->nextSiblingMultiColumnSet())
+    return true;
+  return enclosingFragmentationContext();
+}
+
 LayoutSize LayoutMultiColumnFlowThread::flowThreadTranslationAtOffset(
     LayoutUnit offsetInFlowThread,
     PageBoundaryRule rule,
diff --git a/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.h b/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.h
index a1ad047..8264eb4 100644
--- a/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.h
+++ b/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.h
@@ -216,6 +216,7 @@
   virtual bool needsNewWidth() const;
 
   bool isPageLogicalHeightKnown() const final;
+  bool mayHaveNonUniformPageLogicalHeight() const final;
 
   LayoutSize flowThreadTranslationAtOffset(LayoutUnit,
                                            PageBoundaryRule,
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.cpp b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
index fa98e5a..88ed08c 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObject.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
@@ -1467,25 +1467,6 @@
       diff.setNeedsFullLayout();
   }
 
-  if (RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled()) {
-    // Text nodes share style with their parents but the checked styles don't
-    // apply to them, hence the !isText() check.
-    if (!isText() && (diff.transformChanged() || diff.opacityChanged() ||
-                      diff.zIndexChanged() || diff.filterChanged() ||
-                      diff.backdropFilterChanged())) {
-      // We don't need to invalidate paint of objects on SPv2 when only paint
-      // property or paint order change. Mark the painting layer needing repaint
-      // for changed paint property or paint order. Raster invalidation will be
-      // issued if needed during paint.
-      if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
-        ObjectPaintInvalidator(*this).slowSetPaintingLayerNeedsRepaint();
-
-      // When transform, opacity, etc. change, paint properties will also change
-      // so we need to mark this object as needing an update.
-      getMutableForPainting().setNeedsPaintPropertyUpdate();
-    }
-  }
-
   if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     // If transform changed, and the layer does not paint into its own separate
     // backing, then we need to invalidate paints.
@@ -1530,6 +1511,11 @@
     }
   }
 
+  // TODO(wangxianzhu): We may avoid subtree paint invalidation on CSS clip
+  // change for SPv2.
+  if (diff.cssClipChanged())
+    diff.setNeedsPaintInvalidationSubtree();
+
   // Optimization: for decoration/color property changes, invalidation is only
   // needed if we have style or text affected by these properties.
   if (diff.textDecorationOrColorChanged() && !diff.needsPaintInvalidation()) {
@@ -1738,6 +1724,20 @@
   else if (diff.needsPaintInvalidationObject() ||
            updatedDiff.needsPaintInvalidationObject())
     setShouldDoFullPaintInvalidation();
+
+  // Text nodes share style with their parents but the paint properties don't
+  // apply to them, hence the !isText() check.
+  if (RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled() &&
+      diff.needsPaintPropertyUpdate() && !isText()) {
+    setNeedsPaintPropertyUpdate();
+
+    // We don't need to invalidate paint of objects on SPv2 when only paint
+    // property or paint order change. Mark the painting layer needing repaint
+    // for changed paint property or paint order. Raster invalidation will be
+    // issued if needed during paint.
+    if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
+      ObjectPaintInvalidator(*this).slowSetPaintingLayerNeedsRepaint();
+  }
 }
 
 void LayoutObject::styleWillChange(StyleDifference diff,
diff --git a/third_party/WebKit/Source/core/layout/LayoutState.cpp b/third_party/WebKit/Source/core/layout/LayoutState.cpp
index 4c0d537..0b86e46 100644
--- a/third_party/WebKit/Source/core/layout/LayoutState.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutState.cpp
@@ -53,7 +53,6 @@
     m_flowThread = m_next->flowThread();
   m_paginationStateChanged = m_next->m_paginationStateChanged;
   layoutObject.view()->pushLayoutState(*this);
-  m_heightOffsetForTableHeaders = m_next->heightOffsetForTableHeaders();
 
   if (layoutObject.isLayoutFlowThread()) {
     // Entering a new pagination context.
diff --git a/third_party/WebKit/Source/core/layout/LayoutState.h b/third_party/WebKit/Source/core/layout/LayoutState.h
index b666ec43..aab4c7e 100644
--- a/third_party/WebKit/Source/core/layout/LayoutState.h
+++ b/third_party/WebKit/Source/core/layout/LayoutState.h
@@ -84,13 +84,6 @@
   LayoutUnit pageLogicalOffset(const LayoutBox&,
                                const LayoutUnit& childLogicalOffset) const;
 
-  LayoutUnit heightOffsetForTableHeaders() const {
-    return m_heightOffsetForTableHeaders;
-  };
-  void setHeightOffsetForTableHeaders(LayoutUnit offset) {
-    m_heightOffsetForTableHeaders = offset;
-  };
-
   const LayoutSize& paginationOffset() const { return m_paginationOffset; }
   bool containingBlockLogicalWidthChanged() const {
     return m_containingBlockLogicalWidthChanged;
@@ -121,10 +114,6 @@
   // relative positioning or scroll offsets.
   LayoutSize m_paginationOffset;
 
-  // The height we need to make available for repeating table headers in
-  // paginated layout.
-  LayoutUnit m_heightOffsetForTableHeaders;
-
   LayoutObject& m_layoutObject;
 };
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutTable.cpp b/third_party/WebKit/Source/core/layout/LayoutTable.cpp
index 9ef0d6f1..a174e715 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTable.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTable.cpp
@@ -635,16 +635,12 @@
         if (sectionLogicalHeight <
                 section->pageLogicalHeightForOffset(section->logicalTop()) &&
             section->getPaginationBreakability() != AllowAnyBreaks) {
-          LayoutUnit offsetForTableHeaders =
-              state.heightOffsetForTableHeaders();
           // Don't include any strut in the header group - we only want the
           // height from its content.
-          offsetForTableHeaders += sectionLogicalHeight;
+          LayoutUnit offsetForTableHeaders = sectionLogicalHeight;
           if (LayoutTableRow* row = section->firstRow())
             offsetForTableHeaders -= row->paginationStrut();
-          section->setOffsetForRepeatingHeader(
-              state.heightOffsetForTableHeaders());
-          state.setHeightOffsetForTableHeaders(offsetForTableHeaders);
+          setRowOffsetFromRepeatingHeader(offsetForTableHeaders);
         }
       }
     }
diff --git a/third_party/WebKit/Source/core/layout/LayoutTable.h b/third_party/WebKit/Source/core/layout/LayoutTable.h
index 09ac5911..1a98e177 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTable.h
+++ b/third_party/WebKit/Source/core/layout/LayoutTable.h
@@ -256,6 +256,13 @@
   LayoutTableSection* footer() const { return m_foot; }
   LayoutTableSection* firstBody() const { return m_firstBody; }
 
+  void setRowOffsetFromRepeatingHeader(LayoutUnit offset) {
+    m_rowOffsetFromRepeatingHeader = offset;
+  }
+  LayoutUnit rowOffsetFromRepeatingHeader() const {
+    return m_rowOffsetFromRepeatingHeader;
+  }
+
   // This function returns 0 if the table has no section.
   LayoutTableSection* topSection() const;
   LayoutTableSection* bottomSection() const;
@@ -575,6 +582,7 @@
   int m_borderEnd;
 
   LayoutUnit m_blockOffsetToFirstRepeatableHeader;
+  LayoutUnit m_rowOffsetFromRepeatingHeader;
 };
 
 inline LayoutTableSection* LayoutTable::topSection() const {
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp b/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp
index caf148b..bf09516 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp
@@ -106,8 +106,7 @@
       m_outerBorderAfter(0),
       m_needsCellRecalc(false),
       m_forceSlowPaintPathWithOverflowingCell(false),
-      m_hasMultipleCellLevels(false),
-      m_offsetForRepeatingHeader(LayoutUnit()) {
+      m_hasMultipleCellLevels(false) {
   // init LayoutObject attributes
   setInline(false);  // our object is not Inline
 }
@@ -1983,7 +1982,6 @@
 
 void LayoutTableSection::adjustRowForPagination(LayoutTableRow& rowObject,
                                                 SubtreeLayoutScope& layouter) {
-  LayoutState& state = *view()->layoutState();
   rowObject.setPaginationStrut(LayoutUnit());
   rowObject.setLogicalHeight(LayoutUnit(logicalHeightForRow(rowObject)));
   int paginationStrut =
@@ -1991,9 +1989,12 @@
   bool rowIsAtTopOfColumn = false;
   LayoutUnit offsetFromTopOfPage;
   if (!paginationStrut) {
-    if (state.heightOffsetForTableHeaders()) {
+    LayoutUnit pageLogicalHeight =
+        pageLogicalHeightForOffset(rowObject.logicalTop());
+    if (pageLogicalHeight && table()->header() &&
+        table()->rowOffsetFromRepeatingHeader()) {
       offsetFromTopOfPage =
-          pageLogicalHeightForOffset(rowObject.logicalTop()) -
+          pageLogicalHeight -
           pageRemainingLogicalHeightForOffset(rowObject.logicalTop(),
                                               AssociateWithLatterPage);
       rowIsAtTopOfColumn = !offsetFromTopOfPage ||
@@ -2014,8 +2015,7 @@
   if (!rowObject.rowIndex() && header &&
       table()->sectionAbove(this) == header &&
       header->getPaginationBreakability() != AllowAnyBreaks) {
-    state.setHeightOffsetForTableHeaders(state.heightOffsetForTableHeaders() -
-                                         header->logicalHeight());
+    table()->setRowOffsetFromRepeatingHeader(LayoutUnit());
   }
   // Border spacing from the previous row has pushed this row just past the top
   // of the page, so we must reposition it to the top of the page and avoid any
@@ -2025,7 +2025,8 @@
 
   // If we have a header group we will paint it at the top of each page,
   // move the rows down to accomodate it.
-  paginationStrut += state.heightOffsetForTableHeaders().toInt();
+  if (header)
+    paginationStrut += table()->rowOffsetFromRepeatingHeader().toInt();
   rowObject.setPaginationStrut(LayoutUnit(paginationStrut));
 
   // We have inserted a pagination strut before the row. Adjust the logical top
@@ -2058,9 +2059,12 @@
   // page, then don't repeat the header on each page.
   // See https://drafts.csswg.org/css-tables-3/#repeated-headers
   LayoutTableSection* sectionBelow = table()->sectionBelow(this);
-  if (sectionBelow && sectionBelow->firstRow() &&
-      sectionBelow->firstRow()->paginationStrut())
-    return false;
+  if (!sectionBelow)
+    return true;
+  if (LayoutTableRow* firstRow = sectionBelow->firstRow()) {
+    if (firstRow->paginationStrut() || firstRow->logicalHeight() > pageHeight)
+      return false;
+  }
 
   return true;
 }
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableSection.h b/third_party/WebKit/Source/core/layout/LayoutTableSection.h
index 5c0b9f70..916aab9 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableSection.h
+++ b/third_party/WebKit/Source/core/layout/LayoutTableSection.h
@@ -318,13 +318,6 @@
 
   int paginationStrutForRow(LayoutTableRow*, LayoutUnit logicalOffset) const;
 
-  void setOffsetForRepeatingHeader(LayoutUnit offset) {
-    m_offsetForRepeatingHeader = offset;
-  }
-  LayoutUnit offsetForRepeatingHeader() const {
-    return m_offsetForRepeatingHeader;
-  }
-
   bool mapToVisualRectInAncestorSpace(
       const LayoutBoxModelObject* ancestor,
       LayoutRect&,
@@ -470,8 +463,6 @@
   // The use is to disable a painting optimization where we just paint the
   // invalidated cells.
   bool m_hasMultipleCellLevels;
-
-  LayoutUnit m_offsetForRepeatingHeader;
 };
 
 DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutTableSection, isTableSection());
diff --git a/third_party/WebKit/Source/core/layout/ScrollAnchor.cpp b/third_party/WebKit/Source/core/layout/ScrollAnchor.cpp
index 01f12bc8..fdd8e69 100644
--- a/third_party/WebKit/Source/core/layout/ScrollAnchor.cpp
+++ b/third_party/WebKit/Source/core/layout/ScrollAnchor.cpp
@@ -140,7 +140,7 @@
   if (!candidateMayMoveWithScroller(candidate, m_scroller))
     return ExamineResult(Skip);
 
-  if (candidate->style()->overflowAnchor() == AnchorNone)
+  if (candidate->style()->overflowAnchor() == EOverflowAnchor::None)
     return ExamineResult(Skip);
 
   LayoutRect candidateRect = relativeBounds(candidate, m_scroller);
diff --git a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp
index d238b39..2d831e1e 100644
--- a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp
+++ b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp
@@ -202,7 +202,7 @@
     }
   }
 
-  updateClippingLayers(false, false);
+  updateClippingLayers(false, false, false);
   updateOverflowControlsLayers(false, false, false, false);
   updateChildTransformLayer(false);
   updateForegroundLayer(false);
@@ -246,6 +246,7 @@
     m_graphicsLayer->removeFromParent();
 
   m_ancestorClippingLayer = nullptr;
+  m_ancestorClippingMaskLayer = nullptr;
   m_graphicsLayer = nullptr;
   m_foregroundLayer = nullptr;
   m_backgroundLayer = nullptr;
@@ -472,29 +473,34 @@
       m_owningLayer.getSquashingDisallowedReasons());
 }
 
-bool CompositedLayerMapping::
-    owningLayerClippedByLayerNotAboveCompositedAncestor(
-        const PaintLayer* scrollParent) {
+void CompositedLayerMapping::
+    owningLayerClippedOrMaskedByLayerNotAboveCompositedAncestor(
+        const PaintLayer* scrollParent,
+        bool& owningLayerIsClipped,
+        bool& owningLayerIsMasked) {
+  owningLayerIsClipped = false;
+  owningLayerIsMasked = false;
+
   if (!m_owningLayer.parent())
-    return false;
+    return;
 
   const PaintLayer* compositingAncestor =
       m_owningLayer.enclosingLayerWithCompositedLayerMapping(ExcludeSelf);
   if (!compositingAncestor)
-    return false;
+    return;
 
   const LayoutObject* clippingContainer = m_owningLayer.clippingContainer();
   if (!clippingContainer)
-    return false;
+    return;
 
   if (clippingContainer->enclosingLayer() == scrollParent)
-    return false;
+    return;
 
   if (clippingContainer->enclosingLayer()->hasRootScrollerAsDescendant())
-    return false;
+    return;
 
   if (compositingAncestor->layoutObject()->isDescendantOf(clippingContainer))
-    return false;
+    return;
 
   // We ignore overflow clip here; we want composited overflow content to
   // behave as if it lives in an unclipped universe so it can prepaint, etc.
@@ -509,7 +515,14 @@
   clipRectsContext.setIgnoreOverflowClip();
   IntRect parentClipRect = pixelSnappedIntRect(
       m_owningLayer.clipper().backgroundClipRect(clipRectsContext).rect());
-  return parentClipRect != LayoutRect::infiniteIntRect();
+  owningLayerIsClipped = parentClipRect != LayoutRect::infiniteIntRect();
+
+  // TODO(schenney): CSS clips are not applied to composited children, and
+  // should be via mask or by compositing the parent too.
+  // https://bugs.chromium.org/p/chromium/issues/detail?id=615870
+  DCHECK(clippingContainer->style());
+  owningLayerIsMasked =
+      owningLayerIsClipped && clippingContainer->style()->hasBorderRadius();
 }
 
 const PaintLayer* CompositedLayerMapping::scrollParent() {
@@ -565,10 +578,12 @@
   // layoutObject hierarchy, but a sibling in the z-order hierarchy. Further,
   // that sibling need not be composited at all. In such scenarios, an ancestor
   // clipping layer is necessary to apply the composited clip for this layer.
-  bool needsAncestorClip =
-      owningLayerClippedByLayerNotAboveCompositedAncestor(scrollParent);
-
-  if (updateClippingLayers(needsAncestorClip, needsDescendantsClippingLayer))
+  bool needsAncestorClip = false;
+  bool needsAncestorClippingMask = false;
+  owningLayerClippedOrMaskedByLayerNotAboveCompositedAncestor(
+      scrollParent, needsAncestorClip, needsAncestorClippingMask);
+  if (updateClippingLayers(needsAncestorClip, needsAncestorClippingMask,
+                           needsDescendantsClippingLayer))
     layerConfigChanged = true;
 
   bool scrollingConfigChanged = false;
@@ -1100,6 +1115,13 @@
   m_ancestorClippingLayer->setOffsetFromLayoutObject(
       parentClipRect.location() - snappedOffsetFromCompositedAncestor);
 
+  if (m_ancestorClippingMaskLayer) {
+    m_ancestorClippingMaskLayer->setOffsetFromLayoutObject(
+        m_ancestorClippingLayer->offsetFromLayoutObject());
+    m_ancestorClippingMaskLayer->setSize(m_ancestorClippingLayer->size());
+    m_ancestorClippingMaskLayer->setNeedsDisplay();
+  }
+
   // The primary layer is then parented in, and positioned relative to this
   // clipping layer.
   graphicsLayerParentLocation = parentClipRect.location();
@@ -1651,6 +1673,9 @@
   if (m_decorationOutlineLayer)
     m_decorationOutlineLayer->setDrawsContent(true);
 
+  if (m_ancestorClippingMaskLayer)
+    m_ancestorClippingMaskLayer->setDrawsContent(true);
+
   if (m_maskLayer)
     m_maskLayer->setDrawsContent(true);
 
@@ -1668,8 +1693,10 @@
 }
 
 // Return true if the layers changed.
-bool CompositedLayerMapping::updateClippingLayers(bool needsAncestorClip,
-                                                  bool needsDescendantClip) {
+bool CompositedLayerMapping::updateClippingLayers(
+    bool needsAncestorClip,
+    bool needsAncestorClippingMask,
+    bool needsDescendantClip) {
   bool layersChanged = false;
 
   if (needsAncestorClip) {
@@ -1681,11 +1708,32 @@
       layersChanged = true;
     }
   } else if (m_ancestorClippingLayer) {
+    if (m_ancestorClippingMaskLayer) {
+      m_ancestorClippingMaskLayer->removeFromParent();
+      m_ancestorClippingMaskLayer = nullptr;
+    }
     m_ancestorClippingLayer->removeFromParent();
     m_ancestorClippingLayer = nullptr;
     layersChanged = true;
   }
 
+  if (needsAncestorClippingMask) {
+    DCHECK(m_ancestorClippingLayer);
+    if (!m_ancestorClippingMaskLayer) {
+      m_ancestorClippingMaskLayer =
+          createGraphicsLayer(CompositingReasonLayerForAncestorClippingMask);
+      m_ancestorClippingMaskLayer->setPaintingPhase(
+          GraphicsLayerPaintAncestorClippingMask);
+      m_ancestorClippingLayer->setMaskLayer(m_ancestorClippingMaskLayer.get());
+      layersChanged = true;
+    }
+  } else if (m_ancestorClippingMaskLayer) {
+    m_ancestorClippingMaskLayer->removeFromParent();
+    m_ancestorClippingMaskLayer = nullptr;
+    m_ancestorClippingLayer->setMaskLayer(nullptr);
+    layersChanged = true;
+  }
+
   if (needsDescendantClip) {
     // We don't need a child containment layer if we're the main frame layout
     // view layer. It's redundant as the frame clip above us will handle this
@@ -1915,6 +1963,10 @@
        (mode & ApplyToNonScrollingContentLayers)) &&
       mapping->childClippingMaskLayer())
     f(mapping->childClippingMaskLayer());
+  if (((mode & ApplyToMaskLayers) || (mode & ApplyToContentLayers) ||
+       (mode & ApplyToNonScrollingContentLayers)) &&
+      mapping->ancestorClippingMaskLayer())
+    f(mapping->ancestorClippingMaskLayer());
 
   if (((mode & ApplyToBackgroundLayer) || (mode & ApplyToContentLayers) ||
        (mode & ApplyToNonScrollingContentLayers)) &&
@@ -1950,7 +2002,7 @@
   // Some compositing reasons depend on the compositing state of ancestors. So
   // if we want a rendering context id for the context root, we cannot ask for
   // the id of its associated WebLayer now; it may not have one yet. We could do
-  // a second past after doing the compositing updates to get these ids, but
+  // a second pass after doing the compositing updates to get these ids, but
   // this would actually be harmful. We do not want to attach any semantic
   // meaning to the context id other than the fact that they group a number of
   // layers together for the sake of 3d sorting. So instead we will ask the
@@ -2254,7 +2306,11 @@
 
 void CompositedLayerMapping::updateClipParent(const PaintLayer* scrollParent) {
   const PaintLayer* clipParent = nullptr;
-  if (!owningLayerClippedByLayerNotAboveCompositedAncestor(scrollParent)) {
+  bool haveAncestorClipLayer = false;
+  bool haveAncestorMaskLayer = false;
+  owningLayerClippedOrMaskedByLayerNotAboveCompositedAncestor(
+      scrollParent, haveAncestorClipLayer, haveAncestorMaskLayer);
+  if (!haveAncestorClipLayer) {
     clipParent = m_owningLayer.clipParent();
     if (clipParent)
       clipParent =
@@ -2794,6 +2850,8 @@
   if (!(paintLayerFlags & PaintLayerPaintingOverflowContents)) {
     LayoutRect bounds = paintInfo.compositedBounds;
     bounds.move(paintInfo.paintLayer->subpixelAccumulation());
+    if (paintLayerFlags & PaintLayerPaintingAncestorClippingMaskPhase)
+      bounds.move(offset);
     dirtyRect.intersect(pixelSnappedIntRect(bounds));
   } else {
     dirtyRect.move(
@@ -3071,6 +3129,8 @@
     paintLayerFlags |= PaintLayerPaintingCompositingMaskPhase;
   if (graphicsLayerPaintingPhase & GraphicsLayerPaintChildClippingMask)
     paintLayerFlags |= PaintLayerPaintingChildClippingMaskPhase;
+  if (graphicsLayerPaintingPhase & GraphicsLayerPaintAncestorClippingMask)
+    paintLayerFlags |= PaintLayerPaintingAncestorClippingMaskPhase;
   if (graphicsLayerPaintingPhase & GraphicsLayerPaintOverflowContents)
     paintLayerFlags |= PaintLayerPaintingOverflowContents;
   if (graphicsLayerPaintingPhase & GraphicsLayerPaintCompositedScroll)
@@ -3090,7 +3150,8 @@
       graphicsLayer == m_maskLayer.get() ||
       graphicsLayer == m_childClippingMaskLayer.get() ||
       graphicsLayer == m_scrollingContentsLayer.get() ||
-      graphicsLayer == m_decorationOutlineLayer.get()) {
+      graphicsLayer == m_decorationOutlineLayer.get() ||
+      graphicsLayer == m_ancestorClippingMaskLayer.get()) {
     bool paintRootBackgroundOntoScrollingContentsLayer =
         m_backgroundPaintsOntoScrollingContentsLayer;
     DCHECK(!paintRootBackgroundOntoScrollingContentsLayer ||
@@ -3345,6 +3406,8 @@
            ")";
   } else if (graphicsLayer == m_ancestorClippingLayer.get()) {
     name = "Ancestor Clipping Layer";
+  } else if (graphicsLayer == m_ancestorClippingMaskLayer.get()) {
+    name = "Ancestor Clipping Mask Layer";
   } else if (graphicsLayer == m_foregroundLayer.get()) {
     name = m_owningLayer.debugName() + " (foreground) Layer";
   } else if (graphicsLayer == m_backgroundLayer.get()) {
diff --git a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.h b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.h
index 6ee087cb..3e98bde 100644
--- a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.h
+++ b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.h
@@ -117,6 +117,10 @@
     return m_ancestorClippingLayer.get();
   }
 
+  GraphicsLayer* ancestorClippingMaskLayer() const {
+    return m_ancestorClippingMaskLayer.get();
+  }
+
   GraphicsLayer* foregroundLayer() const { return m_foregroundLayer.get(); }
 
   GraphicsLayer* backgroundLayer() const { return m_backgroundLayer.get(); }
@@ -383,6 +387,9 @@
   void updateInternalHierarchy();
   void updatePaintingPhases();
   bool updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip);
+  bool updateClippingLayers(bool needsAncestorClip,
+                            bool needsAncestorClippingMask,
+                            bool needsDescendantClip);
   bool updateChildTransformLayer(bool needsChildTransformLayer);
   bool updateOverflowControlsLayers(bool needsHorizontalScrollbarLayer,
                                     bool needsVerticalScrollbarLayer,
@@ -477,10 +484,16 @@
       const GraphicsLayerPaintInfo&,
       const Vector<GraphicsLayerPaintInfo>& layers);
 
-  // Return true if |m_owningLayer|'s compositing ancestor is not a descendant
-  // (inclusive) of the clipping container for |m_owningLayer|.
-  bool owningLayerClippedByLayerNotAboveCompositedAncestor(
-      const PaintLayer* scrollParent);
+  // Return true in |owningLayerIsClipped| iff |m_owningLayer|'s compositing
+  // ancestor is not a descendant (inclusive) of the clipping container for
+  // |m_owningLayer|. Return true in |owningLayerIsMasked| iff
+  // |owningLayerIsClipped| is true and |m_owningLayer|'s compositing ancestor
+  // is not a descendant (inclusive) of a container that applies a mask for
+  // |m_owningLayer|.
+  void owningLayerClippedOrMaskedByLayerNotAboveCompositedAncestor(
+      const PaintLayer* scrollParent,
+      bool& owningLayerIsClipped,
+      bool& owningLayerIsMasked);
 
   const PaintLayer* scrollParent();
 
@@ -529,9 +542,20 @@
   // In this case B is clipped by another layer that doesn't happen to be its
   // ancestor: A.  So we create an ancestor clipping layer for B, [+], which
   // ensures that B is clipped as if it had been A's descendant.
+  // In addition, the m_ancestorClippingLayer will have an associated
+  // mask layer if the ancestor, A, has a border radius that requires a
+  // rounded corner clip rect. The mask is not part of the layer tree; rather
+  // it is attached to the m_ancestorClippingLayer itself.
+  //
+  // Layers that require a CSS mask also have a mask layer attached to them.
 
   // Only used if we are clipped by an ancestor which is not a stacking context.
   std::unique_ptr<GraphicsLayer> m_ancestorClippingLayer;
+
+  // Only used is there is an m_ancestorClippingLayer that also needs to apply
+  // a clipping mask (for CSS clips or border radius).
+  std::unique_ptr<GraphicsLayer> m_ancestorClippingMaskLayer;
+
   std::unique_ptr<GraphicsLayer> m_graphicsLayer;
 
   // Only used if we have clipping on a stacking context with compositing
diff --git a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMappingTest.cpp b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMappingTest.cpp
index b5087ac..f20e8160 100644
--- a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMappingTest.cpp
+++ b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMappingTest.cpp
@@ -1084,4 +1084,85 @@
   }
 }
 
+TEST_P(CompositedLayerMappingTest, AncestorClippingMaskLayerUpdates) {
+  setBodyInnerHTML(
+      "<style>"
+      "#ancestor { width: 100px; height: 100px; overflow: hidden; }"
+      "#child { width: 120px; height: 120px; background-color: green; }"
+      "</style>"
+      "<div id='ancestor'><div id='child'></div></div>");
+  document().view()->updateAllLifecyclePhases();
+
+  Element* ancestor = document().getElementById("ancestor");
+  ASSERT_TRUE(ancestor);
+  PaintLayer* ancestorPaintLayer =
+      toLayoutBoxModelObject(ancestor->layoutObject())->layer();
+  ASSERT_TRUE(ancestorPaintLayer);
+
+  CompositedLayerMapping* ancestorMapping =
+      ancestorPaintLayer->compositedLayerMapping();
+  ASSERT_FALSE(ancestorMapping);
+
+  Element* child = document().getElementById("child");
+  ASSERT_TRUE(child);
+  PaintLayer* childPaintLayer =
+      toLayoutBoxModelObject(child->layoutObject())->layer();
+  ASSERT_FALSE(childPaintLayer);
+
+  // Making the child conposited causes creation of an AncestorClippingLayer.
+  child->setAttribute(HTMLNames::styleAttr, "will-change: transform");
+  document().view()->updateAllLifecyclePhases();
+
+  childPaintLayer = toLayoutBoxModelObject(child->layoutObject())->layer();
+  ASSERT_TRUE(childPaintLayer);
+  CompositedLayerMapping* childMapping =
+      childPaintLayer->compositedLayerMapping();
+  ASSERT_TRUE(childMapping);
+  EXPECT_TRUE(childMapping->ancestorClippingLayer());
+  EXPECT_FALSE(childMapping->ancestorClippingLayer()->maskLayer());
+  EXPECT_FALSE(childMapping->ancestorClippingMaskLayer());
+
+  // Adding border radius to the ancestor requires an
+  // ancestorClippingMaskLayer for the child
+  ancestor->setAttribute(HTMLNames::styleAttr, "border-radius: 40px;");
+  document().view()->updateAllLifecyclePhases();
+
+  childPaintLayer = toLayoutBoxModelObject(child->layoutObject())->layer();
+  ASSERT_TRUE(childPaintLayer);
+  childMapping = childPaintLayer->compositedLayerMapping();
+  ASSERT_TRUE(childMapping);
+  EXPECT_TRUE(childMapping->ancestorClippingLayer());
+  EXPECT_TRUE(childMapping->ancestorClippingLayer()->maskLayer());
+  EXPECT_TRUE(childMapping->ancestorClippingMaskLayer());
+
+  // Removing the border radius should remove the ancestorClippingMaskLayer
+  // for the child
+  ancestor->setAttribute(HTMLNames::styleAttr, "border-radius: 0px;");
+  document().view()->updateAllLifecyclePhases();
+
+  childPaintLayer = toLayoutBoxModelObject(child->layoutObject())->layer();
+  ASSERT_TRUE(childPaintLayer);
+  childMapping = childPaintLayer->compositedLayerMapping();
+  ASSERT_TRUE(childMapping);
+  EXPECT_TRUE(childMapping->ancestorClippingLayer());
+  EXPECT_FALSE(childMapping->ancestorClippingLayer()->maskLayer());
+  EXPECT_FALSE(childMapping->ancestorClippingMaskLayer());
+
+  // Add border radius back so we can test one more case
+  ancestor->setAttribute(HTMLNames::styleAttr, "border-radius: 40px;");
+  document().view()->updateAllLifecyclePhases();
+
+  // Now change the overflow to remove the need for an ancestor clip
+  // on the child
+  ancestor->setAttribute(HTMLNames::styleAttr, "overflow: visible");
+  document().view()->updateAllLifecyclePhases();
+
+  childPaintLayer = toLayoutBoxModelObject(child->layoutObject())->layer();
+  ASSERT_TRUE(childPaintLayer);
+  childMapping = childPaintLayer->compositedLayerMapping();
+  ASSERT_TRUE(childMapping);
+  EXPECT_FALSE(childMapping->ancestorClippingLayer());
+  EXPECT_FALSE(childMapping->ancestorClippingMaskLayer());
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceMarker.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceMarker.cpp
index b314112..38e0dc2 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceMarker.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceMarker.cpp
@@ -27,7 +27,7 @@
 namespace blink {
 
 LayoutSVGResourceMarker::LayoutSVGResourceMarker(SVGMarkerElement* node)
-    : LayoutSVGResourceContainer(node) {}
+    : LayoutSVGResourceContainer(node), m_needsTransformUpdate(true) {}
 
 LayoutSVGResourceMarker::~LayoutSVGResourceMarker() {}
 
@@ -72,10 +72,6 @@
   return markerTransformation.mapRect(coordinates);
 }
 
-AffineTransform LayoutSVGResourceMarker::localToSVGParentTransform() const {
-  return viewportTransform();
-}
-
 FloatPoint LayoutSVGResourceMarker::referencePoint() const {
   SVGMarkerElement* marker = toSVGMarkerElement(element());
   ASSERT(marker);
@@ -119,7 +115,7 @@
   // The reference point (refX, refY) is in the coordinate space of the marker's
   // contents so we include the value in each marker's transform.
   FloatPoint mappedReferencePoint =
-      viewportTransform().mapPoint(referencePoint());
+      localToSVGParentTransform().mapPoint(referencePoint());
   transform.translate(-mappedReferencePoint.x(), -mappedReferencePoint.y());
   return transform;
 }
@@ -133,17 +129,19 @@
          !marker->viewBox()->currentValue()->value().isEmpty();
 }
 
-AffineTransform LayoutSVGResourceMarker::viewportTransform() const {
-  SVGMarkerElement* marker = toSVGMarkerElement(element());
-  ASSERT(marker);
-
-  return marker->viewBoxToViewTransform(m_viewportSize.width(),
-                                        m_viewportSize.height());
+void LayoutSVGResourceMarker::setNeedsTransformUpdate() {
+  setMayNeedPaintInvalidationSubtree();
+  if (RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled()) {
+    // The transform paint property relies on the SVG transform being up-to-date
+    // (see: PaintPropertyTreeBuilder::updateTransformForNonRootSVG).
+    setNeedsPaintPropertyUpdate();
+  }
+  m_needsTransformUpdate = true;
 }
 
-void LayoutSVGResourceMarker::calcViewport() {
-  if (!selfNeedsLayout())
-    return;
+SVGTransformChange LayoutSVGResourceMarker::calculateLocalTransform() {
+  if (!m_needsTransformUpdate)
+    return SVGTransformChange::None;
 
   SVGMarkerElement* marker = toSVGMarkerElement(element());
   ASSERT(marker);
@@ -152,14 +150,13 @@
   float width = marker->markerWidth()->currentValue()->value(lengthContext);
   float height = marker->markerHeight()->currentValue()->value(lengthContext);
   m_viewportSize = FloatSize(width, height);
-}
 
-SVGTransformChange LayoutSVGResourceMarker::calculateLocalTransform() {
-  // TODO(fs): Temporarily, needing a layout implies that the local transform
-  // has changed. This should be updated to be more precise and factor in the
-  // actual (relevant) changes to the computed user-space transform.
-  return selfNeedsLayout() ? SVGTransformChange::Full
-                           : SVGTransformChange::None;
+  SVGTransformChangeDetector changeDetector(m_localToParentTransform);
+  m_localToParentTransform = marker->viewBoxToViewTransform(
+      m_viewportSize.width(), m_viewportSize.height());
+
+  m_needsTransformUpdate = false;
+  return changeDetector.computeChange(m_localToParentTransform);
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceMarker.h b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceMarker.h
index 63fe310..bf5def6 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceMarker.h
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceMarker.h
@@ -42,11 +42,19 @@
   // Calculates marker boundaries, mapped to the target element's coordinate
   // space.
   FloatRect markerBoundaries(const AffineTransform& markerTransformation) const;
-
-  AffineTransform localToSVGParentTransform() const override;
   AffineTransform markerTransformation(const FloatPoint& origin,
                                        float angle,
                                        float strokeWidth) const;
+
+  AffineTransform localToSVGParentTransform() const final {
+    return m_localToParentTransform;
+  }
+  void setNeedsTransformUpdate() final;
+
+  // The viewport origin is (0,0) and not the reference point because each
+  // marker instance includes the reference in markerTransformation().
+  FloatRect viewport() const { return FloatRect(FloatPoint(), m_viewportSize); }
+
   bool shouldPaint() const;
 
   FloatPoint referencePoint() const;
@@ -54,21 +62,16 @@
   SVGMarkerUnitsType markerUnits() const;
   SVGMarkerOrientType orientType() const;
 
-  // The viewport origin is (0,0) and not the reference point because each
-  // marker instance includes the reference in markerTransformation().
-  FloatRect viewport() const { return FloatRect(FloatPoint(), m_viewportSize); }
-
   static const LayoutSVGResourceType s_resourceType = MarkerResourceType;
   LayoutSVGResourceType resourceType() const override { return s_resourceType; }
 
  private:
   void layout() override;
-  void calcViewport() override;
-  SVGTransformChange calculateLocalTransform() override;
+  SVGTransformChange calculateLocalTransform() final;
 
-  AffineTransform viewportTransform() const;
-
+  AffineTransform m_localToParentTransform;
   FloatSize m_viewportSize;
+  bool m_needsTransformUpdate;
 };
 
 DEFINE_LAYOUT_SVG_RESOURCE_TYPE_CASTS(LayoutSVGResourceMarker,
diff --git a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
index cd0ad37..359afdc 100644
--- a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
@@ -38,6 +38,7 @@
 #include "core/fetch/ImageResource.h"
 #include "core/fetch/MemoryCache.h"
 #include "core/fetch/ResourceFetcher.h"
+#include "core/frame/Deprecation.h"
 #include "core/frame/FrameHost.h"
 #include "core/frame/LocalDOMWindow.h"
 #include "core/frame/LocalFrame.h"
@@ -148,6 +149,10 @@
   return m_mainResource ? m_mainResource->identifier() : 0;
 }
 
+ResourceTimingInfo* DocumentLoader::getNavigationTimingInfo() const {
+  return fetcher()->getNavigationTimingInfo();
+}
+
 const ResourceRequest& DocumentLoader::originalRequest() const {
   return m_originalRequest;
 }
@@ -317,6 +322,19 @@
   if (m_state < MainResourceDone)
     m_state = MainResourceDone;
   clearMainResourceHandle();
+
+  // Shows the deprecation message and measures the impact of the new security
+  // restriction which disallows responding to navigation requests with
+  // redirected responses in the service worker.
+  // TODO(horo): Remove this when we actually introduce the restriction in
+  // RespondWithObserver.
+  if (m_response.wasFetchedViaServiceWorker() &&
+      m_response.urlListViaServiceWorker().size() > 1) {
+    Deprecation::countDeprecation(
+        m_frame,
+        UseCounter::
+            ServiceWorkerRespondToNavigationRequestWithRedirectedResponse);
+  }
 }
 
 bool DocumentLoader::redirectReceived(
@@ -764,8 +782,7 @@
   if (!init.shouldReuseDefaultView())
     frame->setDOMWindow(LocalDOMWindow::create(*frame));
 
-  Document* document =
-      frame->localDOMWindow()->installNewDocument(mimeType, init);
+  Document* document = frame->domWindow()->installNewDocument(mimeType, init);
 
   if (!init.shouldReuseDefaultView())
     frame->page()->chromeClient().installSupplements(*frame);
diff --git a/third_party/WebKit/Source/core/loader/DocumentLoader.h b/third_party/WebKit/Source/core/loader/DocumentLoader.h
index fd1ebf4..c36f01a 100644
--- a/third_party/WebKit/Source/core/loader/DocumentLoader.h
+++ b/third_party/WebKit/Source/core/loader/DocumentLoader.h
@@ -60,6 +60,7 @@
 class DocumentInit;
 class LocalFrame;
 class FrameLoader;
+class ResourceTimingInfo;
 class WebDocumentSubresourceFilter;
 struct ViewportDescriptionWrapper;
 
@@ -79,6 +80,8 @@
 
   LocalFrame* frame() const { return m_frame; }
 
+  ResourceTimingInfo* getNavigationTimingInfo() const;
+
   virtual void detachFromFrame();
 
   unsigned long mainResourceIdentifier() const;
@@ -135,8 +138,6 @@
     m_navigationType = navigationType;
   }
 
-  void upgradeInsecureRequest();
-
   void startLoadingMainResource();
 
   DocumentLoadTiming& timing() { return m_documentLoadTiming; }
diff --git a/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp b/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp
index 928aa32..e6aa7c4 100644
--- a/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp
@@ -322,9 +322,7 @@
     InspectorInstrumentation::
         documentThreadableLoaderFailedToStartLoadingForClient(m_document,
                                                               m_client);
-    ThreadableLoaderClient* client = m_client;
-    clear();
-    client->didFailAccessControlCheck(ResourceError(
+    dispatchDidFailAccessControlCheck(ResourceError(
         errorDomainBlinkInternal, 0, request.url().getString(),
         "Cross origin requests are only supported for protocol schemes: " +
             SchemeRegistry::listOfCORSEnabledURLSchemes() + "."));
@@ -334,9 +332,7 @@
   // Non-secure origins may not make "external requests":
   // https://mikewest.github.io/cors-rfc1918/#integration-fetch
   if (!document().isSecureContext() && request.isExternalRequest()) {
-    ThreadableLoaderClient* client = m_client;
-    clear();
-    client->didFailAccessControlCheck(
+    dispatchDidFailAccessControlCheck(
         ResourceError(errorDomainBlinkInternal, 0, request.url().getString(),
                       "Requests to internal network resources are not allowed "
                       "from non-secure contexts (see https://goo.gl/Y0ZkNV). "
@@ -439,29 +435,20 @@
 }
 
 void DocumentThreadableLoader::cancel() {
-  cancelWithError(ResourceError());
-}
-
-void DocumentThreadableLoader::cancelWithError(const ResourceError& error) {
-  // Cancel can re-enter and m_resource might be null here as a result.
+  // Cancel can re-enter, and therefore |resource()| might be null here as a
+  // result.
   if (!m_client || !resource()) {
     clear();
     return;
   }
 
-  ResourceError errorForCallback = error;
-  if (errorForCallback.isNull()) {
-    // FIXME: This error is sent to the client in didFail(), so it should not be
-    // an internal one. Use FrameLoaderClient::cancelledError() instead.
-    errorForCallback =
-        ResourceError(errorDomainBlinkInternal, 0,
-                      resource()->url().getString(), "Load cancelled");
-    errorForCallback.setIsCancellation(true);
-  }
+  // FIXME: This error is sent to the client in didFail(), so it should not be
+  // an internal one. Use FrameLoaderClient::cancelledError() instead.
+  ResourceError error(errorDomainBlinkInternal, 0, resource()->url(),
+                      "Load cancelled");
+  error.setIsCancellation(true);
 
-  ThreadableLoaderClient* client = m_client;
-  clear();
-  client->didFail(errorForCallback);
+  dispatchDidFail(error);
 }
 
 void DocumentThreadableLoader::setDefersLoading(bool value) {
@@ -580,9 +567,7 @@
   }
 
   if (!allowRedirect) {
-    ThreadableLoaderClient* client = m_client;
-    clear();
-    client->didFailAccessControlCheck(ResourceError(
+    dispatchDidFailAccessControlCheck(ResourceError(
         errorDomainBlinkInternal, 0, redirectResponse.url().getString(),
         accessControlErrorDescription));
     return false;
@@ -809,9 +794,7 @@
             accessControlErrorDescription, m_requestContext)) {
       reportResponseReceived(identifier, response);
 
-      ThreadableLoaderClient* client = m_client;
-      clear();
-      client->didFailAccessControlCheck(
+      dispatchDidFailAccessControlCheck(
           ResourceError(errorDomainBlinkInternal, 0, response.url().getString(),
                         accessControlErrorDescription));
       return;
@@ -868,7 +851,7 @@
   m_checker.notifyFinished(resource);
 
   if (resource->errorOccurred()) {
-    handleError(resource->resourceError());
+    dispatchDidFail(resource->resourceError());
   } else {
     handleSuccessfulFinish(resource->identifier(), resource->loadFinishTime());
   }
@@ -897,7 +880,16 @@
 }
 
 void DocumentThreadableLoader::didTimeout(TimerBase* timer) {
+  DCHECK(m_async);
   DCHECK_EQ(timer, &m_timeoutTimer);
+  // clearResource() may be called in clear() and some other places. clear()
+  // calls stop() on |m_timeoutTimer|. In the other places, the resource is set
+  // again. If the creation fails, clear() is called. So, here, resource() is
+  // always non-nullptr.
+  DCHECK(resource());
+  // When |m_client| is set to nullptr only in clear() where |m_timeoutTimer|
+  // is stopped. So, |m_client| is always non-nullptr here.
+  DCHECK(m_client);
 
   // Using values from net/base/net_error_list.h ERR_TIMED_OUT, Same as existing
   // FIXME above - this error should be coming from FrameLoaderClient to be
@@ -905,7 +897,8 @@
   static const int timeoutError = -7;
   ResourceError error("net", timeoutError, resource()->url(), String());
   error.setIsTimeout(true);
-  cancelWithError(error);
+
+  dispatchDidFail(error);
 }
 
 void DocumentThreadableLoader::loadFallbackRequestForServiceWorker() {
@@ -941,12 +934,17 @@
   // Prevent handleSuccessfulFinish() from bypassing access check.
   m_actualRequest = ResourceRequest();
 
+  dispatchDidFailAccessControlCheck(error);
+}
+
+void DocumentThreadableLoader::dispatchDidFailAccessControlCheck(
+    const ResourceError& error) {
   ThreadableLoaderClient* client = m_client;
   clear();
   client->didFailAccessControlCheck(error);
 }
 
-void DocumentThreadableLoader::handleError(const ResourceError& error) {
+void DocumentThreadableLoader::dispatchDidFail(const ResourceError& error) {
   ThreadableLoaderClient* client = m_client;
   clear();
   client->didFail(error);
diff --git a/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.h b/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.h
index 8af7fc9..bf1fb5c 100644
--- a/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.h
+++ b/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.h
@@ -110,8 +110,6 @@
   void dataDownloaded(Resource*, int) override;
   void didReceiveResourceTiming(Resource*, const ResourceTimingInfo&) override;
 
-  void cancelWithError(const ResourceError&);
-
   // Notify Inspector and log to console about resource response. Use this
   // method if response is not going to be finished normally.
   void reportResponseReceived(unsigned long identifier,
@@ -142,7 +140,9 @@
   // Investigates the response for the preflight request. If successful,
   // the actual request will be made later in handleSuccessfulFinish().
   void handlePreflightResponse(const ResourceResponse&);
-  void handleError(const ResourceError&);
+
+  void dispatchDidFailAccessControlCheck(const ResourceError&);
+  void dispatchDidFail(const ResourceError&);
 
   void loadRequestAsync(const ResourceRequest&, ResourceLoaderOptions);
   void loadRequestSync(const ResourceRequest&, ResourceLoaderOptions);
diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.cpp b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
index 4cbd51b..4ecd86a 100644
--- a/third_party/WebKit/Source/core/loader/FrameLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
@@ -515,7 +515,7 @@
 
   if (m_provisionalItem && isBackForwardLoadType(m_loadType)) {
     m_frame->document()->setStateForNewFormElements(
-        m_provisionalItem->documentState());
+        m_provisionalItem->getDocumentState());
   }
 }
 
@@ -747,7 +747,7 @@
     restoreScrollPositionAndViewState();
 
     m_loadType = FrameLoadTypeStandard;
-    m_frame->localDOMWindow()->finishedLoading();
+    m_frame->domWindow()->finishedLoading();
   }
 
   Frame* parent = m_frame->tree().parent();
@@ -870,7 +870,7 @@
     // If we were in the autoscroll/middleClickAutoscroll mode we want to stop
     // it before following the link to the anchor
     m_frame->eventHandler().stopAutoscroll();
-    m_frame->localDOMWindow()->enqueueHashchangeEvent(oldURL, url);
+    m_frame->domWindow()->enqueueHashchangeEvent(oldURL, url);
   }
   m_documentLoader->setIsClientRedirect(clientRedirect ==
                                         ClientRedirectPolicy::ClientRedirect);
@@ -882,9 +882,9 @@
 
   checkCompleted();
 
-  m_frame->localDOMWindow()->statePopped(
-      stateObject ? std::move(stateObject)
-                  : SerializedScriptValue::nullValue());
+  m_frame->domWindow()->statePopped(stateObject
+                                        ? std::move(stateObject)
+                                        : SerializedScriptValue::nullValue());
 
   if (historyLoadType == HistorySameDocumentLoad)
     restoreScrollPositionAndViewState();
diff --git a/third_party/WebKit/Source/core/loader/FrameLoaderClient.h b/third_party/WebKit/Source/core/loader/FrameLoaderClient.h
index 79694244..c445ac17 100644
--- a/third_party/WebKit/Source/core/loader/FrameLoaderClient.h
+++ b/third_party/WebKit/Source/core/loader/FrameLoaderClient.h
@@ -342,6 +342,8 @@
   // Overwrites the given URL to use an HTML5 embed if possible. An empty URL is
   // returned if the URL is not overriden.
   virtual KURL overrideFlashEmbedWithHTML(const KURL&) { return KURL(); }
+
+  virtual BlameContext* frameBlameContext() { return nullptr; }
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/HistoryItem.cpp b/third_party/WebKit/Source/core/loader/HistoryItem.cpp
index 872b52e2..28340e4 100644
--- a/third_party/WebKit/Source/core/loader/HistoryItem.cpp
+++ b/third_party/WebKit/Source/core/loader/HistoryItem.cpp
@@ -118,14 +118,14 @@
   m_documentState = state;
 }
 
-const Vector<String>& HistoryItem::documentState() {
+const Vector<String>& HistoryItem::getDocumentState() {
   if (m_documentState)
     m_documentStateVector = m_documentState->toStateVector();
   return m_documentStateVector;
 }
 
 Vector<String> HistoryItem::getReferencedFilePaths() {
-  return FormController::getReferencedFilePaths(documentState());
+  return FormController::getReferencedFilePaths(getDocumentState());
 }
 
 void HistoryItem::clearDocumentState() {
diff --git a/third_party/WebKit/Source/core/loader/HistoryItem.h b/third_party/WebKit/Source/core/loader/HistoryItem.h
index a231512..35ca7fa 100644
--- a/third_party/WebKit/Source/core/loader/HistoryItem.h
+++ b/third_party/WebKit/Source/core/loader/HistoryItem.h
@@ -69,7 +69,7 @@
   void setPageScaleFactor(float);
 
   Vector<String> getReferencedFilePaths();
-  const Vector<String>& documentState();
+  const Vector<String>& getDocumentState();
   void setDocumentState(const Vector<String>&);
   void setDocumentState(DocumentState*);
   void clearDocumentState();
diff --git a/third_party/WebKit/Source/core/loader/PingLoader.cpp b/third_party/WebKit/Source/core/loader/PingLoader.cpp
index d32a134..956cc97 100644
--- a/third_party/WebKit/Source/core/loader/PingLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/PingLoader.cpp
@@ -187,9 +187,7 @@
 };
 
 class PingLoaderImpl : public GarbageCollectedFinalized<PingLoaderImpl>,
-                       public DOMWindowProperty,
                        private WebURLLoaderClient {
-  USING_GARBAGE_COLLECTED_MIXIN(PingLoaderImpl);
   WTF_MAKE_NONCOPYABLE(PingLoaderImpl);
 
  public:
@@ -216,6 +214,7 @@
 
   void didFailLoading(LocalFrame*);
 
+  WeakMember<LocalFrame> m_frame;
   std::unique_ptr<WebURLLoader> m_loader;
   Timer<PingLoaderImpl> m_timeout;
   String m_url;
@@ -233,7 +232,7 @@
                                const AtomicString& initiator,
                                StoredCredentials credentialsAllowed,
                                bool isBeacon)
-    : DOMWindowProperty(frame),
+    : m_frame(frame),
       m_timeout(this, &PingLoaderImpl::timeout),
       m_url(request.url()),
       m_identifier(createUniqueIdentifier()),
@@ -313,9 +312,9 @@
   if (!CrossOriginAccessControl::handleRedirect(
           m_origin, newRequest, redirectResponse, AllowStoredCredentials,
           options, errorDescription)) {
-    if (LocalFrame* localFrame = frame()) {
-      if (localFrame->document()) {
-        localFrame->document()->addConsoleMessage(ConsoleMessage::create(
+    if (m_frame) {
+      if (m_frame->document()) {
+        m_frame->document()->addConsoleMessage(ConsoleMessage::create(
             JSMessageSource, ErrorMessageLevel, errorDescription));
       }
     }
@@ -331,31 +330,31 @@
 }
 
 void PingLoaderImpl::didReceiveResponse(const WebURLResponse& response) {
-  if (LocalFrame* frame = this->frame()) {
+  if (m_frame) {
     TRACE_EVENT1("devtools.timeline", "ResourceFinish", "data",
                  InspectorResourceFinishEvent::data(m_identifier, 0, true));
     const ResourceResponse& resourceResponse = response.toResourceResponse();
-    InspectorInstrumentation::didReceiveResourceResponse(frame, m_identifier, 0,
-                                                         resourceResponse, 0);
-    didFailLoading(frame);
+    InspectorInstrumentation::didReceiveResourceResponse(
+        m_frame, m_identifier, 0, resourceResponse, 0);
+    didFailLoading(m_frame);
   }
   dispose();
 }
 
 void PingLoaderImpl::didReceiveData(const char*, int) {
-  if (LocalFrame* frame = this->frame()) {
+  if (m_frame) {
     TRACE_EVENT1("devtools.timeline", "ResourceFinish", "data",
                  InspectorResourceFinishEvent::data(m_identifier, 0, true));
-    didFailLoading(frame);
+    didFailLoading(m_frame);
   }
   dispose();
 }
 
 void PingLoaderImpl::didFinishLoading(double, int64_t, int64_t) {
-  if (LocalFrame* frame = this->frame()) {
+  if (m_frame) {
     TRACE_EVENT1("devtools.timeline", "ResourceFinish", "data",
                  InspectorResourceFinishEvent::data(m_identifier, 0, true));
-    didFailLoading(frame);
+    didFailLoading(m_frame);
   }
   dispose();
 }
@@ -363,19 +362,19 @@
 void PingLoaderImpl::didFail(const WebURLError& resourceError,
                              int64_t,
                              int64_t) {
-  if (LocalFrame* frame = this->frame()) {
+  if (m_frame) {
     TRACE_EVENT1("devtools.timeline", "ResourceFinish", "data",
                  InspectorResourceFinishEvent::data(m_identifier, 0, true));
-    didFailLoading(frame);
+    didFailLoading(m_frame);
   }
   dispose();
 }
 
 void PingLoaderImpl::timeout(TimerBase*) {
-  if (LocalFrame* frame = this->frame()) {
+  if (m_frame) {
     TRACE_EVENT1("devtools.timeline", "ResourceFinish", "data",
                  InspectorResourceFinishEvent::data(m_identifier, 0, true));
-    didFailLoading(frame);
+    didFailLoading(m_frame);
   }
   dispose();
 }
@@ -388,7 +387,7 @@
 }
 
 DEFINE_TRACE(PingLoaderImpl) {
-  DOMWindowProperty::trace(visitor);
+  visitor->trace(m_frame);
 }
 
 void finishPingRequestInitialization(
diff --git a/third_party/WebKit/Source/core/loader/PingLoader.h b/third_party/WebKit/Source/core/loader/PingLoader.h
index ae6d269..8b8dd8e 100644
--- a/third_party/WebKit/Source/core/loader/PingLoader.h
+++ b/third_party/WebKit/Source/core/loader/PingLoader.h
@@ -34,7 +34,6 @@
 
 #include "core/CoreExport.h"
 #include "core/fetch/ResourceLoaderOptions.h"
-#include "core/frame/DOMWindowProperty.h"
 #include "platform/Timer.h"
 #include "platform/heap/Handle.h"
 #include "platform/heap/SelfKeepAlive.h"
diff --git a/third_party/WebKit/Source/core/page/Page.cpp b/third_party/WebKit/Source/core/page/Page.cpp
index 0fb7492..c16fb04 100644
--- a/third_party/WebKit/Source/core/page/Page.cpp
+++ b/third_party/WebKit/Source/core/page/Page.cpp
@@ -481,7 +481,7 @@
   }
 
   for (unsigned i = 0; i < frames.size(); ++i)
-    frames[i]->localDOMWindow()->acceptLanguagesChanged();
+    frames[i]->domWindow()->acceptLanguagesChanged();
 }
 
 DEFINE_TRACE(Page) {
diff --git a/third_party/WebKit/Source/core/paint/FilterPainter.cpp b/third_party/WebKit/Source/core/paint/FilterPainter.cpp
index 46e28f27..5646e1a 100644
--- a/third_party/WebKit/Source/core/paint/FilterPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/FilterPainter.cpp
@@ -56,7 +56,7 @@
   if (clipRect.rect() != paintingInfo.paintDirtyRect || clipRect.hasRadius()) {
     m_clipRecorder = WTF::wrapUnique(new LayerClipRecorder(
         context, *layer.layoutObject(), DisplayItem::kClipLayerFilter, clipRect,
-        &paintingInfo, LayoutPoint(), paintFlags));
+        paintingInfo.rootLayer, LayoutPoint(), paintFlags));
   }
 
   if (!context.getPaintController().displayItemConstructionIsDisabled()) {
diff --git a/third_party/WebKit/Source/core/paint/LayerClipRecorder.cpp b/third_party/WebKit/Source/core/paint/LayerClipRecorder.cpp
index bd8878a30..3d85217 100644
--- a/third_party/WebKit/Source/core/paint/LayerClipRecorder.cpp
+++ b/third_party/WebKit/Source/core/paint/LayerClipRecorder.cpp
@@ -15,24 +15,22 @@
 
 namespace blink {
 
-LayerClipRecorder::LayerClipRecorder(
-    GraphicsContext& graphicsContext,
-    const LayoutBoxModelObject& layoutObject,
-    DisplayItem::Type clipType,
-    const ClipRect& clipRect,
-    const PaintLayerPaintingInfo* localPaintingInfo,
-    const LayoutPoint& fragmentOffset,
-    PaintLayerFlags paintFlags,
-    BorderRadiusClippingRule rule)
+LayerClipRecorder::LayerClipRecorder(GraphicsContext& graphicsContext,
+                                     const LayoutBoxModelObject& layoutObject,
+                                     DisplayItem::Type clipType,
+                                     const ClipRect& clipRect,
+                                     const PaintLayer* clipRoot,
+                                     const LayoutPoint& fragmentOffset,
+                                     PaintLayerFlags paintFlags,
+                                     BorderRadiusClippingRule rule)
     : m_graphicsContext(graphicsContext),
       m_layoutObject(layoutObject),
       m_clipType(clipType) {
   IntRect snappedClipRect = pixelSnappedIntRect(clipRect.rect());
   Vector<FloatRoundedRect> roundedRects;
-  if (localPaintingInfo && clipRect.hasRadius()) {
-    collectRoundedRectClips(*layoutObject.layer(), *localPaintingInfo,
-                            graphicsContext, fragmentOffset, paintFlags, rule,
-                            roundedRects);
+  if (clipRoot && clipRect.hasRadius()) {
+    collectRoundedRectClips(*layoutObject.layer(), clipRoot, graphicsContext,
+                            fragmentOffset, paintFlags, rule, roundedRects);
   }
 
   m_graphicsContext.getPaintController().createAndAppend<ClipDisplayItem>(
@@ -58,7 +56,7 @@
 
 void LayerClipRecorder::collectRoundedRectClips(
     PaintLayer& paintLayer,
-    const PaintLayerPaintingInfo& localPaintingInfo,
+    const PaintLayer* clipRoot,
     GraphicsContext& context,
     const LayoutPoint& fragmentOffset,
     PaintLayerFlags paintFlags,
@@ -79,14 +77,15 @@
     // is properly clipped so that it can in turn clip the scrolled contents in
     // the compositor.
     if (layer->needsCompositedScrolling() &&
-        !(paintFlags & PaintLayerPaintingChildClippingMaskPhase))
+        !(paintFlags & PaintLayerPaintingChildClippingMaskPhase ||
+          paintFlags & PaintLayerPaintingAncestorClippingMaskPhase))
       break;
 
     if (layer->layoutObject()->hasOverflowClip() &&
         layer->layoutObject()->style()->hasBorderRadius() &&
         inContainingBlockChain(&paintLayer, layer)) {
       LayoutPoint delta(fragmentOffset);
-      layer->convertToLayerCoords(localPaintingInfo.rootLayer, delta);
+      layer->convertToLayerCoords(clipRoot, delta);
 
       // The PaintLayer's size is pixel-snapped if it is a LayoutBox. We can't
       // use a pre-snapped border rect for clipping, since
@@ -99,7 +98,7 @@
               LayoutRect(delta, size)));
     }
 
-    if (layer == localPaintingInfo.rootLayer)
+    if (layer == clipRoot)
       break;
   }
 }
diff --git a/third_party/WebKit/Source/core/paint/LayerClipRecorder.h b/third_party/WebKit/Source/core/paint/LayerClipRecorder.h
index b8e3aca..7601ca2a0 100644
--- a/third_party/WebKit/Source/core/paint/LayerClipRecorder.h
+++ b/third_party/WebKit/Source/core/paint/LayerClipRecorder.h
@@ -46,7 +46,7 @@
       const LayoutBoxModelObject&,
       DisplayItem::Type,
       const ClipRect&,
-      const PaintLayerPaintingInfo* localPaintingInfo,
+      const PaintLayer* clipRoot,
       const LayoutPoint& fragmentOffset,
       PaintLayerFlags,
       BorderRadiusClippingRule = IncludeSelfForBorderRadius);
@@ -55,7 +55,7 @@
 
  private:
   void collectRoundedRectClips(PaintLayer&,
-                               const PaintLayerPaintingInfo& localPaintingInfo,
+                               const PaintLayer* clipRoot,
                                GraphicsContext&,
                                const LayoutPoint& fragmentOffset,
                                PaintLayerFlags,
diff --git a/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.cpp b/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.cpp
index abca3af..256584c 100644
--- a/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.cpp
@@ -32,17 +32,26 @@
       *toLayoutText(div.firstChild()->layoutObject())->firstTextBox();
 
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
-    EXPECT_DISPLAY_LIST(
-        rootPaintController().getDisplayItemList(), 6,
-        TestDisplayItem(layoutView(),
-                        DisplayItem::kClipFrameToVisibleContentRect),
-        TestDisplayItem(*layoutView().layer(), DisplayItem::kSubsequence),
-        TestDisplayItem(layoutView(), documentBackgroundType),
-        TestDisplayItem(textInlineBox, foregroundType),
-        TestDisplayItem(*layoutView().layer(), DisplayItem::kEndSubsequence),
-        TestDisplayItem(layoutView(),
-                        DisplayItem::clipTypeToEndClipType(
-                            DisplayItem::kClipFrameToVisibleContentRect)));
+    if (RuntimeEnabledFeatures::rootLayerScrollingEnabled()) {
+      EXPECT_DISPLAY_LIST(
+          rootPaintController().getDisplayItemList(), 4,
+          TestDisplayItem(*layoutView().layer(), DisplayItem::kSubsequence),
+          TestDisplayItem(layoutView(), documentBackgroundType),
+          TestDisplayItem(textInlineBox, foregroundType),
+          TestDisplayItem(*layoutView().layer(), DisplayItem::kEndSubsequence));
+    } else {
+      EXPECT_DISPLAY_LIST(
+          rootPaintController().getDisplayItemList(), 6,
+          TestDisplayItem(layoutView(),
+                          DisplayItem::kClipFrameToVisibleContentRect),
+          TestDisplayItem(*layoutView().layer(), DisplayItem::kSubsequence),
+          TestDisplayItem(layoutView(), documentBackgroundType),
+          TestDisplayItem(textInlineBox, foregroundType),
+          TestDisplayItem(*layoutView().layer(), DisplayItem::kEndSubsequence),
+          TestDisplayItem(layoutView(),
+                          DisplayItem::clipTypeToEndClipType(
+                              DisplayItem::kClipFrameToVisibleContentRect)));
+    }
   } else {
     EXPECT_DISPLAY_LIST(rootPaintController().getDisplayItemList(), 2,
                         TestDisplayItem(layoutView(), documentBackgroundType),
@@ -53,19 +62,30 @@
   document().view()->updateAllLifecyclePhases();
 
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
-    EXPECT_DISPLAY_LIST(
-        rootPaintController().getDisplayItemList(), 7,
-        TestDisplayItem(layoutView(),
-                        DisplayItem::kClipFrameToVisibleContentRect),
-        TestDisplayItem(*layoutView().layer(), DisplayItem::kSubsequence),
-        TestDisplayItem(layoutView(), documentBackgroundType),
-        TestDisplayItem(textInlineBox, foregroundType),
-        TestDisplayItem(*document().frame()->selection().m_frameCaret,
-                        DisplayItem::kCaret),  // New!
-        TestDisplayItem(*layoutView().layer(), DisplayItem::kEndSubsequence),
-        TestDisplayItem(layoutView(),
-                        DisplayItem::clipTypeToEndClipType(
-                            DisplayItem::kClipFrameToVisibleContentRect)));
+    if (RuntimeEnabledFeatures::rootLayerScrollingEnabled()) {
+      EXPECT_DISPLAY_LIST(
+          rootPaintController().getDisplayItemList(), 5,
+          TestDisplayItem(*layoutView().layer(), DisplayItem::kSubsequence),
+          TestDisplayItem(layoutView(), documentBackgroundType),
+          TestDisplayItem(textInlineBox, foregroundType),
+          TestDisplayItem(*document().frame()->selection().m_frameCaret,
+                          DisplayItem::kCaret),  // New!
+          TestDisplayItem(*layoutView().layer(), DisplayItem::kEndSubsequence));
+    } else {
+      EXPECT_DISPLAY_LIST(
+          rootPaintController().getDisplayItemList(), 7,
+          TestDisplayItem(layoutView(),
+                          DisplayItem::kClipFrameToVisibleContentRect),
+          TestDisplayItem(*layoutView().layer(), DisplayItem::kSubsequence),
+          TestDisplayItem(layoutView(), documentBackgroundType),
+          TestDisplayItem(textInlineBox, foregroundType),
+          TestDisplayItem(*document().frame()->selection().m_frameCaret,
+                          DisplayItem::kCaret),  // New!
+          TestDisplayItem(*layoutView().layer(), DisplayItem::kEndSubsequence),
+          TestDisplayItem(layoutView(),
+                          DisplayItem::clipTypeToEndClipType(
+                              DisplayItem::kClipFrameToVisibleContentRect)));
+    }
   } else {
     EXPECT_DISPLAY_LIST(
         rootPaintController().getDisplayItemList(), 3,
@@ -87,17 +107,26 @@
   InlineTextBox& firstTextBox = *text.firstTextBox();
 
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
-    EXPECT_DISPLAY_LIST(
-        rootPaintController().getDisplayItemList(), 6,
-        TestDisplayItem(layoutView(),
-                        DisplayItem::kClipFrameToVisibleContentRect),
-        TestDisplayItem(*layoutView().layer(), DisplayItem::kSubsequence),
-        TestDisplayItem(layoutView(), documentBackgroundType),
-        TestDisplayItem(firstTextBox, foregroundType),
-        TestDisplayItem(*layoutView().layer(), DisplayItem::kEndSubsequence),
-        TestDisplayItem(layoutView(),
-                        DisplayItem::clipTypeToEndClipType(
-                            DisplayItem::kClipFrameToVisibleContentRect)));
+    if (RuntimeEnabledFeatures::rootLayerScrollingEnabled()) {
+      EXPECT_DISPLAY_LIST(
+          rootPaintController().getDisplayItemList(), 4,
+          TestDisplayItem(*layoutView().layer(), DisplayItem::kSubsequence),
+          TestDisplayItem(layoutView(), documentBackgroundType),
+          TestDisplayItem(firstTextBox, foregroundType),
+          TestDisplayItem(*layoutView().layer(), DisplayItem::kEndSubsequence));
+    } else {
+      EXPECT_DISPLAY_LIST(
+          rootPaintController().getDisplayItemList(), 6,
+          TestDisplayItem(layoutView(),
+                          DisplayItem::kClipFrameToVisibleContentRect),
+          TestDisplayItem(*layoutView().layer(), DisplayItem::kSubsequence),
+          TestDisplayItem(layoutView(), documentBackgroundType),
+          TestDisplayItem(firstTextBox, foregroundType),
+          TestDisplayItem(*layoutView().layer(), DisplayItem::kEndSubsequence),
+          TestDisplayItem(layoutView(),
+                          DisplayItem::clipTypeToEndClipType(
+                              DisplayItem::kClipFrameToVisibleContentRect)));
+    }
   } else {
     EXPECT_DISPLAY_LIST(rootPaintController().getDisplayItemList(), 2,
                         TestDisplayItem(layoutView(), documentBackgroundType),
@@ -112,18 +141,28 @@
   InlineTextBox& secondTextBox = *newText.firstTextBox()->nextTextBox();
 
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
-    EXPECT_DISPLAY_LIST(
-        rootPaintController().getDisplayItemList(), 7,
-        TestDisplayItem(layoutView(),
-                        DisplayItem::kClipFrameToVisibleContentRect),
-        TestDisplayItem(*layoutView().layer(), DisplayItem::kSubsequence),
-        TestDisplayItem(layoutView(), documentBackgroundType),
-        TestDisplayItem(newFirstTextBox, foregroundType),
-        TestDisplayItem(secondTextBox, foregroundType),
-        TestDisplayItem(*layoutView().layer(), DisplayItem::kEndSubsequence),
-        TestDisplayItem(layoutView(),
-                        DisplayItem::clipTypeToEndClipType(
-                            DisplayItem::kClipFrameToVisibleContentRect)));
+    if (RuntimeEnabledFeatures::rootLayerScrollingEnabled()) {
+      EXPECT_DISPLAY_LIST(
+          rootPaintController().getDisplayItemList(), 5,
+          TestDisplayItem(*layoutView().layer(), DisplayItem::kSubsequence),
+          TestDisplayItem(layoutView(), documentBackgroundType),
+          TestDisplayItem(newFirstTextBox, foregroundType),
+          TestDisplayItem(secondTextBox, foregroundType),
+          TestDisplayItem(*layoutView().layer(), DisplayItem::kEndSubsequence));
+    } else {
+      EXPECT_DISPLAY_LIST(
+          rootPaintController().getDisplayItemList(), 7,
+          TestDisplayItem(layoutView(),
+                          DisplayItem::kClipFrameToVisibleContentRect),
+          TestDisplayItem(*layoutView().layer(), DisplayItem::kSubsequence),
+          TestDisplayItem(layoutView(), documentBackgroundType),
+          TestDisplayItem(newFirstTextBox, foregroundType),
+          TestDisplayItem(secondTextBox, foregroundType),
+          TestDisplayItem(*layoutView().layer(), DisplayItem::kEndSubsequence),
+          TestDisplayItem(layoutView(),
+                          DisplayItem::clipTypeToEndClipType(
+                              DisplayItem::kClipFrameToVisibleContentRect)));
+    }
   } else {
     EXPECT_DISPLAY_LIST(rootPaintController().getDisplayItemList(), 3,
                         TestDisplayItem(layoutView(), documentBackgroundType),
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerClipper.h b/third_party/WebKit/Source/core/paint/PaintLayerClipper.h
index 51232a6..df71e64 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerClipper.h
+++ b/third_party/WebKit/Source/core/paint/PaintLayerClipper.h
@@ -182,7 +182,7 @@
   LayoutRect localClipRect(const PaintLayer* ancestorLayer) const;
 
   // Computes the same thing as backgroundRect in calculateRects(), but skips
-  // apllying CSS clip and the visualOverflowRect() of |m_layer|.
+  // applying CSS clip and the visualOverflowRect() of |m_layer|.
   ClipRect backgroundClipRect(const ClipRectsContext&) const;
 
   // This method figures out our layerBounds in coordinates relative to
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
index 18d5d0ad..e5cafe6 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
@@ -371,7 +371,8 @@
   // scrolling contents and scrollbars.
   if (m_paintLayer.layoutObject()->hasClipPath() &&
       (!m_paintLayer.needsCompositedScrolling() ||
-       (paintFlags & PaintLayerPaintingChildClippingMaskPhase))) {
+       (paintFlags & (PaintLayerPaintingChildClippingMaskPhase |
+                      PaintLayerPaintingAncestorClippingMaskPhase)))) {
     paintingInfo.ancestorHasClipPathClipping = true;
 
     LayoutRect referenceBox(m_paintLayer.boxForClipPath());
@@ -427,22 +428,51 @@
     ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects)
                                        ? UncachedClipRects
                                        : PaintingClipRects;
+    LayoutPoint offsetToClipper;
+    PaintLayer* paintLayerForFragments = &m_paintLayer;
+    if (paintFlags & PaintLayerPaintingAncestorClippingMaskPhase) {
+      // Compute fragments and their clips with respect to the clipping
+      // container. The paint rect is in this layer's space, so convert it
+      // to the clipper's layer's space. The rootLayer is also changed to
+      // the clipper's layer to simplify coordinate system adjustments.
+      // The change to rootLayer must persist to correctly record the clips.
+      paintLayerForFragments =
+          m_paintLayer.clippingContainer()->enclosingLayer();
+      localPaintingInfo.rootLayer = paintLayerForFragments;
+      m_paintLayer.convertToLayerCoords(localPaintingInfo.rootLayer,
+                                        offsetToClipper);
+      localPaintingInfo.paintDirtyRect.moveBy(offsetToClipper);
+    }
+
     // TODO(trchen): We haven't decided how to handle visual fragmentation with
     // SPv2.  Related thread
     // https://groups.google.com/a/chromium.org/forum/#!topic/graphics-dev/81XuWFf-mxM
     if (fragmentPolicy == ForceSingleFragment ||
-        RuntimeEnabledFeatures::slimmingPaintV2Enabled())
-      m_paintLayer.appendSingleFragmentIgnoringPagination(
+        RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
+      paintLayerForFragments->appendSingleFragmentIgnoringPagination(
           layerFragments, localPaintingInfo.rootLayer,
           localPaintingInfo.paintDirtyRect, cacheSlot,
           IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot,
           localPaintingInfo.subPixelAccumulation);
-    else
-      m_paintLayer.collectFragments(layerFragments, localPaintingInfo.rootLayer,
-                                    localPaintingInfo.paintDirtyRect, cacheSlot,
-                                    IgnoreOverlayScrollbarSize,
-                                    respectOverflowClip, &offsetFromRoot,
-                                    localPaintingInfo.subPixelAccumulation);
+    } else {
+      paintLayerForFragments->collectFragments(
+          layerFragments, localPaintingInfo.rootLayer,
+          localPaintingInfo.paintDirtyRect, cacheSlot,
+          IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot,
+          localPaintingInfo.subPixelAccumulation);
+    }
+
+    if (paintFlags & PaintLayerPaintingAncestorClippingMaskPhase) {
+      // Fragment offsets have been computed in the clipping container's
+      // layer's coordinate system, but for the rest of painting we need
+      // them in the layer coordinate. So move them and the foreground rect
+      // that is also in the clipper's space.
+      LayoutSize negativeOffset(-offsetToClipper.x(), -offsetToClipper.y());
+      for (auto& fragment : layerFragments) {
+        fragment.foregroundRect.move(negativeOffset);
+        fragment.paginationOffset.move(negativeOffset);
+      }
+    }
 
     if (shouldPaintContent) {
       // TODO(wangxianzhu): This is for old slow scrolling. Implement similar
@@ -546,7 +576,8 @@
       shouldPaintContent && m_paintLayer.layoutObject()->hasMask() &&
       !selectionOnly;
   bool shouldPaintClippingMask =
-      (paintFlags & PaintLayerPaintingChildClippingMaskPhase) &&
+      (paintFlags & (PaintLayerPaintingChildClippingMaskPhase |
+                     PaintLayerPaintingAncestorClippingMaskPhase)) &&
       shouldPaintContent && !selectionOnly;
 
   if (shouldPaintMask)
@@ -721,7 +752,7 @@
                             UseCounter::ClipCssOfFixedPositionElement);
         clipRecorder.emplace(context, *parentLayer->layoutObject(),
                              DisplayItem::kClipLayerParent, clipRectForFragment,
-                             &paintingInfo, fragment.paginationOffset,
+                             paintingInfo.rootLayer, fragment.paginationOffset,
                              paintFlags);
       }
     }
@@ -859,7 +890,7 @@
     if (needsToClip(localPaintingInfo, fragment.backgroundRect)) {
       clipRecorder.emplace(context, *m_paintLayer.layoutObject(),
                            DisplayItem::kClipLayerOverflowControls,
-                           fragment.backgroundRect, &localPaintingInfo,
+                           fragment.backgroundRect, localPaintingInfo.rootLayer,
                            fragment.paginationOffset, paintFlags);
     }
 
@@ -909,9 +940,12 @@
         break;
     }
 
+    // TODO(schenney): Nested border-radius clips are not applied to composited
+    // children, probably due to an incorrect clipRoot.
+    // https://bugs.chromium.org/p/chromium/issues/detail?id=672561
     clipRecorder.emplace(context, *m_paintLayer.layoutObject(), clipType,
-                         clipRect, &paintingInfo, fragment.paginationOffset,
-                         paintFlags, clippingRule);
+                         clipRect, paintingInfo.rootLayer,
+                         fragment.paginationOffset, paintFlags, clippingRule);
   }
 
   LayoutRect newCullRect(clipRect.rect());
@@ -983,7 +1017,8 @@
       needsToClip(localPaintingInfo, layerFragments[0].foregroundRect)) {
     clipRecorder.emplace(context, *m_paintLayer.layoutObject(),
                          DisplayItem::kClipLayerForeground,
-                         layerFragments[0].foregroundRect, &localPaintingInfo,
+                         layerFragments[0].foregroundRect,
+                         localPaintingInfo.rootLayer,
                          layerFragments[0].paginationOffset, paintFlags);
     clipState = HasClipped;
   }
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerPaintingInfo.h b/third_party/WebKit/Source/core/paint/PaintLayerPaintingInfo.h
index d907091e..f0980bc 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerPaintingInfo.h
+++ b/third_party/WebKit/Source/core/paint/PaintLayerPaintingInfo.h
@@ -67,8 +67,9 @@
   PaintLayerPaintingRootBackgroundOnly = 1 << 9,
   PaintLayerPaintingSkipRootBackground = 1 << 10,
   PaintLayerPaintingChildClippingMaskPhase = 1 << 11,
-  PaintLayerPaintingRenderingClipPathAsMask = 1 << 12,
-  PaintLayerPaintingCompositingDecorationPhase = 1 << 13,
+  PaintLayerPaintingAncestorClippingMaskPhase = 1 << 12,
+  PaintLayerPaintingRenderingClipPathAsMask = 1 << 13,
+  PaintLayerPaintingCompositingDecorationPhase = 1 << 14,
   PaintLayerPaintingCompositingAllPhases =
       (PaintLayerPaintingCompositingBackgroundPhase |
        PaintLayerPaintingCompositingForegroundPhase |
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
index a6adbe3..e50d441 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
@@ -849,7 +849,7 @@
 bool PaintLayerScrollableArea::shouldPerformScrollAnchoring() const {
   return RuntimeEnabledFeatures::scrollAnchoringEnabled() &&
          m_scrollAnchor.hasScroller() &&
-         layoutBox()->style()->overflowAnchor() != AnchorNone &&
+         layoutBox()->style()->overflowAnchor() != EOverflowAnchor::None &&
          !box().document().finishingOrIsPrinting();
 }
 
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
index d54efdb..bd9a0b02 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
@@ -3138,4 +3138,15 @@
               !div->layoutObject()->paintProperties()->overflowClip());
 }
 
+// A basic sanity check for over-invalidation of paint properties.
+TEST_P(PaintPropertyTreeBuilderTest, NoPaintPropertyUpdateOnBackgroundChange) {
+  setBodyInnerHTML("<div id='div' style='background-color: blue'>DIV</div>");
+  auto* div = document().getElementById("div");
+
+  document().view()->updateAllLifecyclePhases();
+  div->setAttribute(HTMLNames::styleAttr, "background-color: green");
+  document().view()->updateLifecycleToLayoutClean();
+  EXPECT_FALSE(div->layoutObject()->needsPaintPropertyUpdate());
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/TableSectionPainter.cpp b/third_party/WebKit/Source/core/paint/TableSectionPainter.cpp
index 877fbd9b..4b8f039 100644
--- a/third_party/WebKit/Source/core/paint/TableSectionPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/TableSectionPainter.cpp
@@ -81,14 +81,12 @@
                paintOffset.y() + totalHeightOfRows);
 
   while (paginationOffset.y() < bottomBound) {
-    LayoutPoint nestedOffset =
-        paginationOffset +
-        LayoutPoint(LayoutUnit(),
-                    m_layoutTableSection.offsetForRepeatingHeader());
-    if (itemToPaint == PaintCollapsedBorders)
-      paintCollapsedSectionBorders(paintInfo, nestedOffset, currentBorderValue);
-    else
-      paintSection(paintInfo, nestedOffset);
+    if (itemToPaint == PaintCollapsedBorders) {
+      paintCollapsedSectionBorders(paintInfo, paginationOffset,
+                                   currentBorderValue);
+    } else {
+      paintSection(paintInfo, paginationOffset);
+    }
     paginationOffset.move(0, pageHeight.toInt());
   }
 }
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.cpp b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
index a83f2f2..f3b61cc 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.cpp
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
@@ -594,8 +594,12 @@
 
   updatePropertySpecificDifferences(other, diff);
 
+  // The following conditions need to be at last, because they may depend on
+  // conditions in diff computed above.
   if (scrollAnchorDisablingPropertyChanged(other, diff))
     diff.setScrollAnchorDisablingPropertyChanged();
+  if (diffNeedsPaintPropertyUpdate(other, diff))
+    diff.setNeedsPaintPropertyUpdate();
 
   // Cursors are not checked, since they will be set appropriately in response
   // to mouse events, so they don't need to cause any paint invalidation or
@@ -610,7 +614,7 @@
 
 bool ComputedStyle::scrollAnchorDisablingPropertyChanged(
     const ComputedStyle& other,
-    StyleDifference& diff) const {
+    const StyleDifference& diff) const {
   if (m_nonInheritedData.m_position != other.m_nonInheritedData.m_position)
     return true;
 
@@ -932,11 +936,6 @@
 
 bool ComputedStyle::diffNeedsPaintInvalidationSubtree(
     const ComputedStyle& other) const {
-  if (position() != StaticPosition &&
-      (m_visual->clip != other.m_visual->clip ||
-       m_visual->hasAutoClip != other.m_visual->hasAutoClip))
-    return true;
-
   if (m_rareNonInheritedData.get() != other.m_rareNonInheritedData.get()) {
     if (m_rareNonInheritedData->m_effectiveBlendMode !=
             other.m_rareNonInheritedData->m_effectiveBlendMode ||
@@ -1132,6 +1131,24 @@
       diff.setTextDecorationOrColorChanged();
     }
   }
+
+  bool hasClip = hasOutOfFlowPosition() && !m_visual->hasAutoClip;
+  bool otherHasClip =
+      other.hasOutOfFlowPosition() && !other.m_visual->hasAutoClip;
+  if (hasClip != otherHasClip ||
+      (hasClip && m_visual->clip != other.m_visual->clip))
+    diff.setCSSClipChanged();
+}
+
+bool ComputedStyle::diffNeedsPaintPropertyUpdate(
+    const ComputedStyle& other,
+    const StyleDifference& diff) const {
+  if (diff.transformChanged() || diff.opacityChanged() ||
+      diff.zIndexChanged() || diff.filterChanged() ||
+      diff.backdropFilterChanged() || diff.cssClipChanged())
+    return true;
+
+  return false;
 }
 
 void ComputedStyle::addPaintImage(StyleImage* image) {
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.h b/third_party/WebKit/Source/core/style/ComputedStyle.h
index 225dcbb..865c8cbe 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.h
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.h
@@ -373,7 +373,8 @@
     m_nonInheritedData.m_effectiveDisplay =
         m_nonInheritedData.m_originalDisplay =
             static_cast<unsigned>(initialDisplay());
-    m_nonInheritedData.m_overflowAnchor = initialOverflowAnchor();
+    m_nonInheritedData.m_overflowAnchor =
+        static_cast<unsigned>(initialOverflowAnchor());
     m_nonInheritedData.m_overflowX = initialOverflowX();
     m_nonInheritedData.m_overflowY = initialOverflowY();
     m_nonInheritedData.m_verticalAlign = initialVerticalAlign();
@@ -1544,12 +1545,14 @@
 
   // Overflow properties.
   // overflow-anchor
-  static EOverflowAnchor initialOverflowAnchor() { return AnchorAuto; }
+  static EOverflowAnchor initialOverflowAnchor() {
+    return EOverflowAnchor::Auto;
+  }
   EOverflowAnchor overflowAnchor() const {
     return static_cast<EOverflowAnchor>(m_nonInheritedData.m_overflowAnchor);
   }
   void setOverflowAnchor(EOverflowAnchor v) {
-    m_nonInheritedData.m_overflowAnchor = v;
+    m_nonInheritedData.m_overflowAnchor = static_cast<unsigned>(v);
   }
 
   // overflow-x
@@ -3971,7 +3974,7 @@
                                 TransformationMatrix&) const;
 
   bool scrollAnchorDisablingPropertyChanged(const ComputedStyle& other,
-                                            StyleDifference&) const;
+                                            const StyleDifference&) const;
   bool diffNeedsFullLayoutAndPaintInvalidation(
       const ComputedStyle& other) const;
   bool diffNeedsFullLayout(const ComputedStyle& other) const;
@@ -3982,6 +3985,8 @@
       const ComputedStyle& other) const;
   void updatePropertySpecificDifferences(const ComputedStyle& other,
                                          StyleDifference&) const;
+  bool diffNeedsPaintPropertyUpdate(const ComputedStyle& other,
+                                    const StyleDifference&) const;
 
   bool requireTransformOrigin(ApplyTransformOrigin applyOrigin,
                               ApplyMotionPath) const;
diff --git a/third_party/WebKit/Source/core/style/ComputedStyleConstants.h b/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
index f387ebd..58221fe7 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
+++ b/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
@@ -146,7 +146,7 @@
 
 // Random visual rendering model attributes. Not inherited.
 
-enum EOverflowAnchor { AnchorVisible, AnchorNone, AnchorAuto };
+enum class EOverflowAnchor : unsigned { Visible, None, Auto };
 
 enum EOverflow {
   OverflowVisible,
diff --git a/third_party/WebKit/Source/core/style/StyleDifference.h b/third_party/WebKit/Source/core/style/StyleDifference.h
index 232831f5a..ed12f68 100644
--- a/third_party/WebKit/Source/core/style/StyleDifference.h
+++ b/third_party/WebKit/Source/core/style/StyleDifference.h
@@ -20,9 +20,10 @@
     ZIndexChanged = 1 << 2,
     FilterChanged = 1 << 3,
     BackdropFilterChanged = 1 << 4,
+    CSSClipChanged = 1 << 5,
     // The object needs to issue paint invalidations if it is affected by text
     // decorations or properties dependent on color (e.g., border or outline).
-    TextDecorationOrColorChanged = 1 << 5,
+    TextDecorationOrColorChanged = 1 << 6,
     // If you add a value here, be sure to update the number of bits on
     // m_propertySpecificDifferences.
   };
@@ -32,11 +33,18 @@
         m_layoutType(NoLayout),
         m_recomputeOverflow(false),
         m_propertySpecificDifferences(0),
-        m_scrollAnchorDisablingPropertyChanged(false) {}
+        m_scrollAnchorDisablingPropertyChanged(false),
+        m_needsPaintPropertyUpdate(false) {}
 
   bool hasDifference() const {
-    return m_paintInvalidationType || m_layoutType ||
-           m_propertySpecificDifferences;
+    bool result = m_paintInvalidationType || m_layoutType ||
+                  m_propertySpecificDifferences;
+    // m_recomputeOverflow, m_scrollAnchorDisablingPropertyChanged and
+    // m_needsPaintPropertyUpdate are never set without other flags set.
+    DCHECK(result ||
+           (!m_recomputeOverflow && !m_scrollAnchorDisablingPropertyChanged &&
+            !m_needsPaintPropertyUpdate));
+    return result;
   }
 
   bool hasAtMostPropertySpecificDifferences(
@@ -113,6 +121,11 @@
     m_propertySpecificDifferences |= BackdropFilterChanged;
   }
 
+  bool cssClipChanged() const {
+    return m_propertySpecificDifferences & CSSClipChanged;
+  }
+  void setCSSClipChanged() { m_propertySpecificDifferences |= CSSClipChanged; }
+
   bool textDecorationOrColorChanged() const {
     return m_propertySpecificDifferences & TextDecorationOrColorChanged;
   }
@@ -127,6 +140,9 @@
     m_scrollAnchorDisablingPropertyChanged = true;
   }
 
+  bool needsPaintPropertyUpdate() const { return m_needsPaintPropertyUpdate; }
+  void setNeedsPaintPropertyUpdate() { m_needsPaintPropertyUpdate = true; }
+
  private:
   enum PaintInvalidationType {
     NoPaintInvalidation = 0,
@@ -138,8 +154,9 @@
   enum LayoutType { NoLayout = 0, PositionedMovement, FullLayout };
   unsigned m_layoutType : 2;
   unsigned m_recomputeOverflow : 1;
-  unsigned m_propertySpecificDifferences : 6;
+  unsigned m_propertySpecificDifferences : 7;
   unsigned m_scrollAnchorDisablingPropertyChanged : 1;
+  unsigned m_needsPaintPropertyUpdate : 1;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGElement.cpp b/third_party/WebKit/Source/core/svg/SVGElement.cpp
index 41faa266..967313ce 100644
--- a/third_party/WebKit/Source/core/svg/SVGElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGElement.cpp
@@ -331,42 +331,40 @@
     TransformationMatrix transform;
     float zoom = style->effectiveZoom();
 
+    FloatRect boundingBox = layoutObject()->objectBoundingBox();
+    ComputedStyle::ApplyTransformOrigin applyTransformOrigin =
+        ComputedStyle::IncludeTransformOrigin;
     // SVGTextElements need special handling for the text positioning code.
     if (isSVGTextElement(this)) {
-      // Do not take into account SVG's zoom rules, transform-origin, or
-      // percentage values.
+      // Do not take into account transform-origin, or percentage values.
+      boundingBox = FloatRect();
+      applyTransformOrigin = ComputedStyle::ExcludeTransformOrigin;
+    }
+
+    // CSS transforms operate with pre-scaled lengths. To make this work with
+    // SVG (which applies the zoom factor globally, at the root level) we
+    //
+    //   * pre-scale the bounding box (to bring it into the same space as the
+    //     other CSS values)
+    //   * invert the zoom factor (to effectively compute the CSS transform
+    //     under a 1.0 zoom)
+    //
+    // Note: objectBoundingBox is an emptyRect for elements like pattern or
+    // clipPath. See the "Object bounding box units" section of
+    // http://dev.w3.org/csswg/css3-transforms/
+    if (zoom != 1) {
+      boundingBox.scale(zoom);
+      transform.scale(1 / zoom);
       style->applyTransform(
-          transform, LayoutSize(0, 0), ComputedStyle::ExcludeTransformOrigin,
+          transform, boundingBox, applyTransformOrigin,
           ComputedStyle::IncludeMotionPath,
           ComputedStyle::IncludeIndependentTransformProperties);
+      transform.scale(zoom);
     } else {
-      // CSS transforms operate with pre-scaled lengths. To make this work with
-      // SVG (which applies the zoom factor globally, at the root level) we
-      //
-      //   * pre-scale the bounding box (to bring it into the same space as the
-      //     other CSS values)
-      //   * invert the zoom factor (to effectively compute the CSS transform
-      //     under a 1.0 zoom)
-      //
-      // Note: objectBoundingBox is an emptyRect for elements like pattern or
-      // clipPath.  See the "Object bounding box units" section of
-      // http://dev.w3.org/csswg/css3-transforms/
-      if (zoom != 1) {
-        FloatRect scaledBBox = layoutObject()->objectBoundingBox();
-        scaledBBox.scale(zoom);
-        transform.scale(1 / zoom);
-        style->applyTransform(
-            transform, scaledBBox, ComputedStyle::IncludeTransformOrigin,
-            ComputedStyle::IncludeMotionPath,
-            ComputedStyle::IncludeIndependentTransformProperties);
-        transform.scale(zoom);
-      } else {
-        style->applyTransform(
-            transform, layoutObject()->objectBoundingBox(),
-            ComputedStyle::IncludeTransformOrigin,
-            ComputedStyle::IncludeMotionPath,
-            ComputedStyle::IncludeIndependentTransformProperties);
-      }
+      style->applyTransform(
+          transform, boundingBox, applyTransformOrigin,
+          ComputedStyle::IncludeMotionPath,
+          ComputedStyle::IncludeIndependentTransformProperties);
     }
     // Flatten any 3D transform.
     matrix = transform.toAffineTransform();
diff --git a/third_party/WebKit/Source/core/svg/SVGMarkerElement.cpp b/third_party/WebKit/Source/core/svg/SVGMarkerElement.cpp
index 55a4970..06e7d146 100644
--- a/third_party/WebKit/Source/core/svg/SVGMarkerElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGMarkerElement.cpp
@@ -99,22 +99,26 @@
 }
 
 void SVGMarkerElement::svgAttributeChanged(const QualifiedName& attrName) {
-  bool isLengthAttr = attrName == SVGNames::refXAttr ||
-                      attrName == SVGNames::refYAttr ||
-                      attrName == SVGNames::markerWidthAttr ||
-                      attrName == SVGNames::markerHeightAttr;
-
-  if (isLengthAttr)
+  bool viewboxAttributeChanged = SVGFitToViewBox::isKnownAttribute(attrName);
+  bool lengthAttributeChanged = attrName == SVGNames::refXAttr ||
+                                attrName == SVGNames::refYAttr ||
+                                attrName == SVGNames::markerWidthAttr ||
+                                attrName == SVGNames::markerHeightAttr;
+  if (lengthAttributeChanged)
     updateRelativeLengthsInformation();
 
-  if (isLengthAttr || attrName == SVGNames::markerUnitsAttr ||
-      attrName == SVGNames::orientAttr ||
-      SVGFitToViewBox::isKnownAttribute(attrName)) {
+  if (viewboxAttributeChanged || lengthAttributeChanged ||
+      attrName == SVGNames::markerUnitsAttr ||
+      attrName == SVGNames::orientAttr) {
     SVGElement::InvalidationGuard invalidationGuard(this);
-    LayoutSVGResourceContainer* layoutObject =
-        toLayoutSVGResourceContainer(this->layoutObject());
-    if (layoutObject)
-      layoutObject->invalidateCacheAndMarkForLayout();
+    auto* resourceContainer = toLayoutSVGResourceContainer(layoutObject());
+    if (resourceContainer) {
+      // The marker transform depends on both viewbox attributes, and the marker
+      // size attributes (width, height).
+      if (viewboxAttributeChanged || lengthAttributeChanged)
+        resourceContainer->setNeedsTransformUpdate();
+      resourceContainer->invalidateCacheAndMarkForLayout();
+    }
 
     return;
   }
diff --git a/third_party/WebKit/Source/core/testing/Internals.cpp b/third_party/WebKit/Source/core/testing/Internals.cpp
index 3c842d1..4fc499f 100644
--- a/third_party/WebKit/Source/core/testing/Internals.cpp
+++ b/third_party/WebKit/Source/core/testing/Internals.cpp
@@ -869,7 +869,7 @@
                                      "No history item is available.");
     return Vector<String>();
   }
-  return mainItem->documentState();
+  return mainItem->getDocumentState();
 }
 
 void Internals::setFormControlStateOfHistoryItem(
diff --git a/third_party/WebKit/Source/core/timing/PerformanceBase.cpp b/third_party/WebKit/Source/core/timing/PerformanceBase.cpp
index 39a7e30..2b8ea03 100644
--- a/third_party/WebKit/Source/core/timing/PerformanceBase.cpp
+++ b/third_party/WebKit/Source/core/timing/PerformanceBase.cpp
@@ -50,6 +50,16 @@
 
 namespace blink {
 
+namespace {
+
+SecurityOrigin* getSecurityOrigin(ExecutionContext* context) {
+  if (context)
+    return context->getSecurityOrigin();
+  return nullptr;
+}
+
+}  // namespace
+
 using PerformanceObserverVector = HeapVector<Member<PerformanceObserver>>;
 
 static const size_t defaultResourceTimingBufferSize = 150;
@@ -225,7 +235,7 @@
     dispatchEvent(Event::create(EventTypeNames::frametimingbufferfull));
 }
 
-static bool passesTimingAllowCheck(
+bool PerformanceBase::passesTimingAllowCheck(
     const ResourceResponse& response,
     const SecurityOrigin& initiatorSecurityOrigin,
     const AtomicString& originalTimingAllowOrigin,
@@ -263,10 +273,11 @@
   return false;
 }
 
-static bool allowsTimingRedirect(const Vector<ResourceResponse>& redirectChain,
-                                 const ResourceResponse& finalResponse,
-                                 const SecurityOrigin& initiatorSecurityOrigin,
-                                 ExecutionContext* context) {
+bool PerformanceBase::allowsTimingRedirect(
+    const Vector<ResourceResponse>& redirectChain,
+    const ResourceResponse& finalResponse,
+    const SecurityOrigin& initiatorSecurityOrigin,
+    ExecutionContext* context) {
   if (!passesTimingAllowCheck(finalResponse, initiatorSecurityOrigin,
                               AtomicString(), context))
     return false;
@@ -284,10 +295,8 @@
   if (isResourceTimingBufferFull() &&
       !hasObserverFor(PerformanceEntry::Resource))
     return;
-  SecurityOrigin* securityOrigin = nullptr;
   ExecutionContext* context = getExecutionContext();
-  if (context)
-    securityOrigin = context->getSecurityOrigin();
+  SecurityOrigin* securityOrigin = getSecurityOrigin(context);
   if (!securityOrigin)
     return;
 
@@ -336,12 +345,17 @@
   DCHECK(frame);
   const DocumentLoader* documentLoader = frame->loader().documentLoader();
   DCHECK(documentLoader);
+
   const DocumentLoadTiming& documentLoadTiming = documentLoader->timing();
 
   const DocumentTiming* documentTiming =
       frame->document() ? &(frame->document()->timing()) : nullptr;
 
   const ResourceResponse& finalResponse = documentLoader->response();
+  ResourceTimingInfo* navigationTimingInfo =
+      documentLoader->getNavigationTimingInfo();
+  if (!navigationTimingInfo)
+    return;
 
   ResourceLoadTiming* resourceLoadTiming = finalResponse.resourceLoadTiming();
   // Don't create a navigation timing instance when
@@ -352,8 +366,16 @@
   double lastRedirectEndTime = documentLoadTiming.redirectEnd();
   double finishTime = documentLoadTiming.loadEventEnd();
 
-  // TODO(sunjian) Implement transfer size. crbug/663187
-  unsigned long long transferSize = 0;
+  ExecutionContext* context = getExecutionContext();
+  SecurityOrigin* securityOrigin = getSecurityOrigin(context);
+  if (!securityOrigin)
+    return;
+
+  bool allowRedirectDetails =
+      allowsTimingRedirect(navigationTimingInfo->redirectChain(), finalResponse,
+                           *securityOrigin, context);
+
+  unsigned long long transferSize = navigationTimingInfo->transferSize();
   unsigned long long encodedBodyLength = finalResponse.encodedBodyLength();
   unsigned long long decodedBodyLength = finalResponse.decodedBodyLength();
   bool didReuseConnection = finalResponse.connectionReused();
@@ -370,7 +392,7 @@
       documentTiming ? documentTiming->domComplete() : 0, type,
       documentLoadTiming.redirectStart(), documentLoadTiming.redirectEnd(),
       documentLoadTiming.fetchStart(), documentLoadTiming.responseEnd(),
-      documentLoadTiming.hasCrossOriginRedirect(),
+      allowRedirectDetails,
       documentLoadTiming.hasSameOriginAsPreviousDocument(), resourceLoadTiming,
       lastRedirectEndTime, finishTime, transferSize, encodedBodyLength,
       decodedBodyLength, didReuseConnection);
diff --git a/third_party/WebKit/Source/core/timing/PerformanceBase.h b/third_party/WebKit/Source/core/timing/PerformanceBase.h
index a66931b3..2418bd6 100644
--- a/third_party/WebKit/Source/core/timing/PerformanceBase.h
+++ b/third_party/WebKit/Source/core/timing/PerformanceBase.h
@@ -132,6 +132,16 @@
       NavigationType,
       const Document*);
 
+  static bool allowsTimingRedirect(const Vector<ResourceResponse>&,
+                                   const ResourceResponse&,
+                                   const SecurityOrigin&,
+                                   ExecutionContext*);
+
+  static bool passesTimingAllowCheck(const ResourceResponse&,
+                                     const SecurityOrigin&,
+                                     const AtomicString&,
+                                     ExecutionContext*);
+
  protected:
   explicit PerformanceBase(double timeOrigin);
 
diff --git a/third_party/WebKit/Source/core/timing/PerformanceBaseTest.cpp b/third_party/WebKit/Source/core/timing/PerformanceBaseTest.cpp
index 1ff271cd..08ae8d8 100644
--- a/third_party/WebKit/Source/core/timing/PerformanceBaseTest.cpp
+++ b/third_party/WebKit/Source/core/timing/PerformanceBaseTest.cpp
@@ -7,10 +7,12 @@
 #include "bindings/core/v8/PerformanceObserverCallback.h"
 #include "bindings/core/v8/V8BindingForTesting.h"
 #include "core/testing/DummyPageHolder.h"
+#include "core/testing/NullExecutionContext.h"
 #include "core/timing/PerformanceBase.h"
 #include "core/timing/PerformanceLongTaskTiming.h"
 #include "core/timing/PerformanceObserver.h"
 #include "core/timing/PerformanceObserverInit.h"
+#include "platform/network/ResourceResponse.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace blink {
@@ -46,8 +48,11 @@
 
   void SetUp() override {
     m_pageHolder = DummyPageHolder::create(IntSize(800, 600));
+    m_executionContext = new NullExecutionContext();
   }
 
+  ExecutionContext* getExecutionContext() { return m_executionContext.get(); }
+
   int numPerformanceEntriesInObserver() {
     return m_observer->m_performanceEntries.size();
   }
@@ -58,7 +63,17 @@
     return PerformanceBase::getNavigationType(type, document);
   }
 
+  static bool allowsTimingRedirect(
+      const Vector<ResourceResponse>& redirectChain,
+      const ResourceResponse& finalResponse,
+      const SecurityOrigin& initiatorSecurityOrigin,
+      ExecutionContext* context) {
+    return PerformanceBase::allowsTimingRedirect(
+        redirectChain, finalResponse, initiatorSecurityOrigin, context);
+  }
+
   Persistent<TestPerformanceBase> m_base;
+  Persistent<ExecutionContext> m_executionContext;
   Persistent<PerformanceObserver> m_observer;
   std::unique_ptr<DummyPageHolder> m_pageHolder;
   Persistent<PerformanceObserverCallback> m_cb;
@@ -144,4 +159,40 @@
   EXPECT_EQ(returnedType,
             PerformanceNavigationTiming::NavigationType::Navigate);
 }
+
+TEST_F(PerformanceBaseTest, AllowsTimingRedirect) {
+  // When there are no cross-origin redirects.
+  AtomicString originDomain = "http://127.0.0.1:8000";
+  Vector<ResourceResponse> redirectChain;
+  KURL url(ParsedURLString, originDomain + "/foo.html");
+  ResourceResponse finalResponse;
+  finalResponse.setURL(url);
+  ResourceResponse redirectResponse1;
+  redirectResponse1.setURL(url);
+  ResourceResponse redirectResponse2;
+  redirectResponse2.setURL(url);
+  redirectChain.append(redirectResponse1);
+  redirectChain.append(redirectResponse2);
+  RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::create(url);
+  EXPECT_TRUE(allowsTimingRedirect(redirectChain, finalResponse,
+                                   *securityOrigin.get(),
+                                   getExecutionContext()));
+  // When there exist cross-origin redirects.
+  AtomicString crossOriginDomain = "http://126.0.0.1:8000";
+  KURL redirectUrl(ParsedURLString, crossOriginDomain + "/bar.html");
+  ResourceResponse redirectResponse3;
+  redirectResponse3.setURL(redirectUrl);
+  redirectChain.append(redirectResponse3);
+  EXPECT_FALSE(allowsTimingRedirect(redirectChain, finalResponse,
+                                    *securityOrigin.get(),
+                                    getExecutionContext()));
+
+  // When cross-origin redirect opts in.
+  redirectChain.back().setHTTPHeaderField(HTTPNames::Timing_Allow_Origin,
+                                          originDomain);
+  EXPECT_TRUE(allowsTimingRedirect(redirectChain, finalResponse,
+                                   *securityOrigin.get(),
+                                   getExecutionContext()));
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/timing/PerformanceNavigationTiming.cpp b/third_party/WebKit/Source/core/timing/PerformanceNavigationTiming.cpp
index b61a635a..5580c3a3 100644
--- a/third_party/WebKit/Source/core/timing/PerformanceNavigationTiming.cpp
+++ b/third_party/WebKit/Source/core/timing/PerformanceNavigationTiming.cpp
@@ -36,7 +36,7 @@
     double redirectEnd,
     double fetchStart,
     double responseEnd,
-    bool hasCrossOriginRedirect,
+    bool allowRedirectDetails,
     bool hasSameOriginAsPreviousDocument,
     ResourceLoadTiming* timing,
     double lastRedirectEndTime,
@@ -57,7 +57,7 @@
                                 true /*allowTimingDetails*/,  // TODO(sunjian):
                                                               // Create an enum
                                                               // for this.
-                                !hasCrossOriginRedirect,
+                                allowRedirectDetails,
                                 "document",
                                 "navigation",
                                 timeOrigin),
@@ -76,19 +76,19 @@
       m_redirectEnd(redirectEnd),
       m_fetchStart(fetchStart),
       m_responseEnd(responseEnd),
-      m_hasCrossOriginRedirect(hasCrossOriginRedirect),
+      m_allowRedirectDetails(allowRedirectDetails),
       m_hasSameOriginAsPreviousDocument(hasSameOriginAsPreviousDocument) {}
 
 PerformanceNavigationTiming::~PerformanceNavigationTiming() {}
 
 double PerformanceNavigationTiming::unloadEventStart() const {
-  if (m_hasCrossOriginRedirect || !m_hasSameOriginAsPreviousDocument)
+  if (!m_allowRedirectDetails || !m_hasSameOriginAsPreviousDocument)
     return 0;
   return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_unloadEventStart);
 }
 
 double PerformanceNavigationTiming::unloadEventEnd() const {
-  if (m_hasCrossOriginRedirect || !m_hasSameOriginAsPreviousDocument)
+  if (!m_allowRedirectDetails || !m_hasSameOriginAsPreviousDocument)
     return 0;
 
   return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_unloadEventEnd);
@@ -136,8 +136,7 @@
 }
 
 unsigned short PerformanceNavigationTiming::redirectCount() const {
-  // TODO(sunjian): Also check response headers to allow opt-in crbugs/665160
-  if (m_hasCrossOriginRedirect)
+  if (!m_allowRedirectDetails)
     return 0;
   return m_redirectCount;
 }
@@ -147,13 +146,13 @@
 }
 
 double PerformanceNavigationTiming::redirectStart() const {
-  if (m_hasCrossOriginRedirect)
+  if (!m_allowRedirectDetails)
     return 0;
   return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_redirectStart);
 }
 
 double PerformanceNavigationTiming::redirectEnd() const {
-  if (m_hasCrossOriginRedirect)
+  if (!m_allowRedirectDetails)
     return 0;
   return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_redirectEnd);
 }
diff --git a/third_party/WebKit/Source/core/timing/PerformanceNavigationTiming.h b/third_party/WebKit/Source/core/timing/PerformanceNavigationTiming.h
index 02249c0f..64e54fa 100644
--- a/third_party/WebKit/Source/core/timing/PerformanceNavigationTiming.h
+++ b/third_party/WebKit/Source/core/timing/PerformanceNavigationTiming.h
@@ -32,7 +32,7 @@
                               double redirectEnd,
                               double fetchStart,
                               double responseEnd,
-                              bool hasCrossOriginRedirect,
+                              bool allowRedirectDetails,
                               bool hasSameOriginAsPreviousDocument,
                               ResourceLoadTiming*,
                               double lastRedirectEndTime,
@@ -80,7 +80,7 @@
   double m_redirectEnd;
   double m_fetchStart;
   double m_responseEnd;
-  bool m_hasCrossOriginRedirect;
+  bool m_allowRedirectDetails;
   bool m_hasSameOriginAsPreviousDocument;
 };
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/xml/XSLTProcessor.cpp b/third_party/WebKit/Source/core/xml/XSLTProcessor.cpp
index b8fb6995..c2aaba3 100644
--- a/third_party/WebKit/Source/core/xml/XSLTProcessor.cpp
+++ b/third_party/WebKit/Source/core/xml/XSLTProcessor.cpp
@@ -84,8 +84,8 @@
     // Re-create the FrameView if needed.
     if (hasView)
       frame->loader().client()->transitionToCommittedForNewPage();
-    result = frame->localDOMWindow()->installNewDocument(sourceMIMEType, init,
-                                                         forceXHTML);
+    result = frame->domWindow()->installNewDocument(sourceMIMEType, init,
+                                                    forceXHTML);
 
     if (oldDocument) {
       DocumentXSLT::from(*result).setTransformSourceDocument(oldDocument);
diff --git a/third_party/WebKit/Source/devtools/.eslintignore b/third_party/WebKit/Source/devtools/.eslintignore
index 1df83afc..0f522c2 100644
--- a/third_party/WebKit/Source/devtools/.eslintignore
+++ b/third_party/WebKit/Source/devtools/.eslintignore
@@ -9,3 +9,4 @@
 front_end/InspectorBackendCommands.js
 front_end/SupportedCSSProperties.js
 front_end/terminal/xterm.js/**
+front_end/protocol_externs.js
diff --git a/third_party/WebKit/Source/devtools/BUILD.gn b/third_party/WebKit/Source/devtools/BUILD.gn
index 5df7907..dcc99075 100644
--- a/third_party/WebKit/Source/devtools/BUILD.gn
+++ b/third_party/WebKit/Source/devtools/BUILD.gn
@@ -512,7 +512,6 @@
   "front_end/heap_snapshot_worker/HeapSnapshotLoader.js",
   "front_end/heap_snapshot_worker/HeapSnapshotWorker.js",
   "front_end/heap_snapshot_worker/HeapSnapshotWorkerDispatcher.js",
-  "front_end/heap_snapshot_worker/JSHeapSnapshot.js",
   "front_end/platform/utilities.js",
   "front_end/profiler/HeapSnapshotCommon.js",
 ]
@@ -738,6 +737,7 @@
 devtools_timeline_js_files = [
   "front_end/timeline/invalidationsTree.css",
   "front_end/timeline/timelineFlamechartPopover.css",
+  "front_end/timeline/timelineLandingPage.css",
   "front_end/timeline/timelinePaintProfiler.css",
   "front_end/timeline/timelinePanel.css",
   "front_end/timeline/timelineStatusDialog.css",
@@ -748,6 +748,7 @@
   "front_end/timeline/TimelineFlameChart.js",
   "front_end/timeline/TimelineFlameChartView.js",
   "front_end/timeline/TimelineNetworkFlameChart.js",
+  "front_end/timeline/TimelineLandingPage.js",
   "front_end/timeline/TimelineLayersView.js",
   "front_end/timeline/TimelineLoader.js",
   "front_end/timeline/TimelinePaintProfilerView.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js b/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js
index 643e914..fc102c3 100644
--- a/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js
+++ b/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js
@@ -112,12 +112,12 @@
     var toolbarContainer = this.contentElement.createChild('div', 'animation-timeline-toolbar-container');
     var topToolbar = new UI.Toolbar('animation-timeline-toolbar', toolbarContainer);
     var clearButton = new UI.ToolbarButton(Common.UIString('Clear all'), 'largeicon-clear');
-    clearButton.addEventListener('click', this._reset.bind(this));
+    clearButton.addEventListener(UI.ToolbarButton.Events.Click, this._reset.bind(this));
     topToolbar.appendToolbarItem(clearButton);
     topToolbar.appendSeparator();
 
     this._pauseButton = new UI.ToolbarToggle(Common.UIString('Pause all'), 'largeicon-pause', 'largeicon-resume');
-    this._pauseButton.addEventListener('click', this._togglePauseAll.bind(this));
+    this._pauseButton.addEventListener(UI.ToolbarButton.Events.Click, this._togglePauseAll.bind(this));
     topToolbar.appendToolbarItem(this._pauseButton);
 
     var playbackRateControl = toolbarContainer.createChild('div', 'animation-playback-rate-control');
@@ -147,7 +147,7 @@
     this._controlButton = new UI.ToolbarToggle(Common.UIString('Replay timeline'), 'largeicon-replay-animation');
     this._controlState = Animation.AnimationTimeline._ControlState.Replay;
     this._controlButton.setToggled(true);
-    this._controlButton.addEventListener('click', this._controlButtonToggle.bind(this));
+    this._controlButton.addEventListener(UI.ToolbarButton.Events.Click, this._controlButtonToggle.bind(this));
     toolbar.appendToolbarItem(this._controlButton);
 
     var gridHeader = container.createChild('div', 'animation-grid-header');
diff --git a/third_party/WebKit/Source/devtools/front_end/bindings/DebuggerWorkspaceBinding.js b/third_party/WebKit/Source/devtools/front_end/bindings/DebuggerWorkspaceBinding.js
index 72c0494..5d5080c9 100644
--- a/third_party/WebKit/Source/devtools/front_end/bindings/DebuggerWorkspaceBinding.js
+++ b/third_party/WebKit/Source/devtools/front_end/bindings/DebuggerWorkspaceBinding.js
@@ -21,8 +21,6 @@
     targetManager.addModelListener(
         SDK.DebuggerModel, SDK.DebuggerModel.Events.GlobalObjectCleared, this._globalObjectCleared, this);
     targetManager.addModelListener(
-        SDK.DebuggerModel, SDK.DebuggerModel.Events.BeforeDebuggerPaused, this._beforeDebuggerPaused, this);
-    targetManager.addModelListener(
         SDK.DebuggerModel, SDK.DebuggerModel.Events.DebuggerResumed, this._debuggerResumed, this);
     workspace.addEventListener(Workspace.Workspace.Events.UISourceCodeRemoved, this._uiSourceCodeRemoved, this);
     workspace.addEventListener(Workspace.Workspace.Events.ProjectRemoved, this._projectRemoved, this);
@@ -327,18 +325,6 @@
     var debuggerModel = /** @type {!SDK.DebuggerModel} */ (event.target);
     this._reset(debuggerModel.target());
   }
-
-  /**
-   * @param {!Common.Event} event
-   */
-  _beforeDebuggerPaused(event) {
-    var rawLocation = event.data.callFrames[0].location();
-    var targetData = this._targetToData.get(rawLocation.target());
-    if (!targetData._compilerMapping.mapsToSourceCode(rawLocation)) {
-      event.stopPropagation();
-      event.preventDefault();
-    }
-  }
 };
 
 /**
@@ -350,7 +336,7 @@
    * @param {!Bindings.DebuggerWorkspaceBinding} debuggerWorkspaceBinding
    */
   constructor(debuggerModel, debuggerWorkspaceBinding) {
-    this._target = debuggerModel.target();
+    this._debuggerModel = debuggerModel;
 
     /** @type {!Map.<string, !Bindings.DebuggerWorkspaceBinding.ScriptInfo>} */
     this.scriptDataMap = new Map();
@@ -363,11 +349,13 @@
     this._defaultMapping = new Bindings.DefaultScriptMapping(debuggerModel, workspace, debuggerWorkspaceBinding);
     this._resourceMapping = new Bindings.ResourceScriptMapping(debuggerModel, workspace, debuggerWorkspaceBinding);
     this._compilerMapping = new Bindings.CompilerScriptMapping(
-        debuggerModel, workspace, Bindings.NetworkProject.forTarget(this._target), debuggerWorkspaceBinding);
+        debuggerModel, workspace, Bindings.NetworkProject.forTarget(this._debuggerModel.target()),
+        debuggerWorkspaceBinding);
 
     /** @type {!Map.<!Workspace.UISourceCode, !Bindings.DebuggerSourceMapping>} */
     this._uiSourceCodeToSourceMapping = new Map();
 
+    debuggerModel.setBeforePausedCallback(this._beforePaused.bind(this));
     this._eventListeners = [
       debuggerModel.addEventListener(SDK.DebuggerModel.Events.ParsedScriptSource, this._parsedScriptSource, this),
       debuggerModel.addEventListener(SDK.DebuggerModel.Events.FailedToParseScriptSource, this._parsedScriptSource, this)
@@ -375,6 +363,14 @@
   }
 
   /**
+   * @param {!SDK.DebuggerPausedDetails} debuggerPausedDetails
+   * @return {boolean}
+   */
+  _beforePaused(debuggerPausedDetails) {
+    return !!this._compilerMapping.mapsToSourceCode(debuggerPausedDetails.callFrames[0].location());
+  }
+
+  /**
    * @param {!Common.Event} event
    */
   _parsedScriptSource(event) {
@@ -401,7 +397,7 @@
 
     uiSourceCode.dispatchEventToListeners(
         Workspace.UISourceCode.Events.SourceMappingChanged,
-        {target: this._target, isIdentity: sourceMapping ? sourceMapping.isIdentity() : false});
+        {target: this._debuggerModel.target(), isIdentity: sourceMapping ? sourceMapping.isIdentity() : false});
   }
 
   /**
@@ -433,6 +429,7 @@
   }
 
   _dispose() {
+    this._debuggerModel.setBeforePausedCallback(null);
     Common.EventTarget.removeEventListeners(this._eventListeners);
     this._compilerMapping.dispose();
     this._resourceMapping.dispose();
diff --git a/third_party/WebKit/Source/devtools/front_end/common/Object.js b/third_party/WebKit/Source/devtools/front_end/common/Object.js
index 8a308d9..fe01dd3 100644
--- a/third_party/WebKit/Source/devtools/front_end/common/Object.js
+++ b/third_party/WebKit/Source/devtools/front_end/common/Object.js
@@ -87,21 +87,15 @@
    * @override
    * @param {symbol} eventType
    * @param {*=} eventData
-   * @return {boolean}
    */
   dispatchEventToListeners(eventType, eventData) {
     if (!this._listeners || !this._listeners.has(eventType))
-      return false;
+      return;
 
-    var event = new Common.Event(this, eventType, eventData);
+    var event = new Common.Event(this, eventData);
     var listeners = this._listeners.get(eventType).slice(0);
-    for (var i = 0; i < listeners.length; ++i) {
+    for (var i = 0; i < listeners.length; ++i)
       listeners[i].listener.call(listeners[i].thisObject, event);
-      if (event._stoppedPropagation)
-        break;
-    }
-
-    return event.defaultPrevented;
   }
 };
 
@@ -111,32 +105,11 @@
 Common.Event = class {
   /**
    * @param {!Common.EventTarget} target
-   * @param {symbol} type
    * @param {*=} data
    */
-  constructor(target, type, data) {
+  constructor(target, data) {
     this.target = target;
-    this.type = type;
     this.data = data;
-    this.defaultPrevented = false;
-    this._stoppedPropagation = false;
-  }
-
-  stopPropagation() {
-    this._stoppedPropagation = true;
-  }
-
-  preventDefault() {
-    this.defaultPrevented = true;
-  }
-
-  /**
-   * @param {boolean=} preventDefault
-   */
-  consume(preventDefault) {
-    this.stopPropagation();
-    if (preventDefault)
-      this.preventDefault();
   }
 };
 
@@ -184,7 +157,6 @@
   /**
    * @param {symbol} eventType
    * @param {*=} eventData
-   * @return {boolean}
    */
   dispatchEventToListeners(eventType, eventData) {},
 };
diff --git a/third_party/WebKit/Source/devtools/front_end/components/DockController.js b/third_party/WebKit/Source/devtools/front_end/components/DockController.js
index c4dfab20..0a1eab69 100644
--- a/third_party/WebKit/Source/devtools/front_end/components/DockController.js
+++ b/third_party/WebKit/Source/devtools/front_end/components/DockController.js
@@ -40,7 +40,8 @@
     this._canDock = canDock;
 
     this._closeButton = new UI.ToolbarButton(Common.UIString('Close'), 'largeicon-delete');
-    this._closeButton.addEventListener('click', InspectorFrontendHost.closeWindow.bind(InspectorFrontendHost));
+    this._closeButton.addEventListener(
+        UI.ToolbarButton.Events.Click, InspectorFrontendHost.closeWindow.bind(InspectorFrontendHost));
 
     if (!canDock) {
       this._dockSide = Components.DockController.State.Undocked;
diff --git a/third_party/WebKit/Source/devtools/front_end/components/EventListenersView.js b/third_party/WebKit/Source/devtools/front_end/components/EventListenersView.js
index 8f57990..ac68183 100644
--- a/third_party/WebKit/Source/devtools/front_end/components/EventListenersView.js
+++ b/third_party/WebKit/Source/devtools/front_end/components/EventListenersView.js
@@ -304,7 +304,7 @@
     }
 
     /**
-     * @param {!Common.Event} event
+     * @param {!Event} event
      * @this {Components.ObjectEventListenerBar}
      */
     function removeListener(event) {
@@ -314,7 +314,7 @@
     }
 
     /**
-     * @param {!Common.Event} event
+     * @param {!Event} event
      * @this {Components.ObjectEventListenerBar}
      */
     function togglePassiveListener(event) {
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 abbcb82..f892558 100644
--- a/third_party/WebKit/Source/devtools/front_end/components/ObjectPopoverHelper.js
+++ b/third_party/WebKit/Source/devtools/front_end/components/ObjectPopoverHelper.js
@@ -98,7 +98,7 @@
       if (rawLocation && Runtime.experiments.isEnabled('continueToFirstInvocation')) {
         var sectionToolbar = new UI.Toolbar('function-location-step-into', linkContainer);
         var stepInto = new UI.ToolbarButton(Common.UIString('Continue to first invocation'), 'largeicon-step-in');
-        stepInto.addEventListener('click', () => rawLocation.continueToLocation());
+        stepInto.addEventListener(UI.ToolbarButton.Events.Click, () => rawLocation.continueToLocation());
         sectionToolbar.appendToolbarItem(stepInto);
       }
       var sourceURL = rawLocation && rawLocation.script() ? rawLocation.script().sourceURL : null;
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 910d6a8..830e921 100644
--- a/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js
+++ b/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js
@@ -101,6 +101,14 @@
       return 1;
     if (b === '__proto__')
       return -1;
+    if (!propertyA.enumerable && propertyB.enumerable)
+      return 1;
+    if (!propertyB.enumerable && propertyA.enumerable)
+      return -1;
+    if (a.startsWith('_') && !b.startsWith('_'))
+      return 1;
+    if (b.startsWith('_') && !a.startsWith('_'))
+      return -1;
     if (propertyA.symbol && !propertyB.symbol)
       return 1;
     if (propertyB.symbol && !propertyA.symbol)
@@ -341,7 +349,8 @@
       var defaultName = includePreview ? '' : 'anonymous';
       if (response && response.functionName)
         defaultName = response.functionName;
-      var valueElement = Components.ObjectPropertiesSection.valueElementForFunctionDescription(func.description, includePreview, defaultName);
+      var valueElement = Components.ObjectPropertiesSection.valueElementForFunctionDescription(
+          func.description, includePreview, defaultName);
       element.appendChild(valueElement);
     }
   }
diff --git a/third_party/WebKit/Source/devtools/front_end/components/Spectrum.js b/third_party/WebKit/Source/devtools/front_end/components/Spectrum.js
index 30a63a34..c714b4a8 100644
--- a/third_party/WebKit/Source/devtools/front_end/components/Spectrum.js
+++ b/third_party/WebKit/Source/devtools/front_end/components/Spectrum.js
@@ -58,7 +58,8 @@
     var toolbar = new UI.Toolbar('spectrum-eye-dropper', this.contentElement);
     this._colorPickerButton = new UI.ToolbarToggle(Common.UIString('Toggle color picker'), 'largeicon-eyedropper');
     this._colorPickerButton.setToggled(true);
-    this._colorPickerButton.addEventListener('click', this._toggleColorPicker.bind(this, undefined));
+    this._colorPickerButton.addEventListener(
+        UI.ToolbarButton.Events.Click, this._toggleColorPicker.bind(this, undefined));
     toolbar.appendToolbarItem(this._colorPickerButton);
 
     var swatchElement = this.contentElement.createChild('span', 'swatch');
@@ -136,7 +137,7 @@
 
     this._addColorToolbar = new UI.Toolbar('add-color-toolbar');
     var addColorButton = new UI.ToolbarButton(Common.UIString('Add to palette'), 'largeicon-add');
-    addColorButton.addEventListener('click', this._addColorToCustomPalette.bind(this));
+    addColorButton.addEventListener(UI.ToolbarButton.Events.Click, this._addColorToCustomPalette, this);
     this._addColorToolbar.appendToolbarItem(addColorButton);
 
     this._loadPalettes();
@@ -208,7 +209,7 @@
     title.textContent = Common.UIString('Color Palettes');
     var toolbar = new UI.Toolbar('', this._palettePanel);
     var closeButton = new UI.ToolbarButton('Return to color picker', 'largeicon-delete');
-    closeButton.addEventListener('click', this._togglePalettePanel.bind(this, false));
+    closeButton.addEventListener(UI.ToolbarButton.Events.Click, this._togglePalettePanel.bind(this, false));
     toolbar.appendToolbarItem(closeButton);
     for (var palette of this._palettes.values())
       this._palettePanel.appendChild(this._createPreviewPaletteElement(palette));
@@ -524,7 +525,10 @@
         Components.Spectrum._ChangeSource.Other);
   }
 
-  _addColorToCustomPalette() {
+  /**
+   * @param {!Common.Event} event
+   */
+  _addColorToCustomPalette(event) {
     var palette = this._customPaletteSetting.get();
     palette.colors.push(this.colorString());
     this._customPaletteSetting.set(palette);
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js b/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js
index c996dae..1b430f9 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js
@@ -184,7 +184,7 @@
     this._button = new UI.ToolbarToggle(Common.UIString('Element Classes'), '');
     this._button.setText('.cls');
     this._button.element.classList.add('monospace');
-    this._button.addEventListener('click', this._clicked, this);
+    this._button.addEventListener(UI.ToolbarButton.Events.Click, this._clicked, this);
     this._view = new Elements.ClassesPaneWidget();
   }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementStatePaneWidget.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementStatePaneWidget.js
index 77efe65..10c8b9f 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/ElementStatePaneWidget.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementStatePaneWidget.js
@@ -108,7 +108,7 @@
   constructor() {
     this._button = new UI.ToolbarToggle(Common.UIString('Toggle Element State'), '');
     this._button.setText(Common.UIString(':hov'));
-    this._button.addEventListener('click', this._clicked, this);
+    this._button.addEventListener(UI.ToolbarButton.Events.Click, this._clicked, this);
     this._button.element.classList.add('monospace');
     this._view = new Elements.ElementStatePaneWidget();
   }
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/EventListenersWidget.js b/third_party/WebKit/Source/devtools/front_end/elements/EventListenersWidget.js
index 464cab1d..bd334a8 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/EventListenersWidget.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/EventListenersWidget.js
@@ -48,7 +48,7 @@
     this._eventListenersView = new Components.EventListenersView(this.element, this.update.bind(this));
 
     var refreshButton = new UI.ToolbarButton(Common.UIString('Refresh'), 'largeicon-refresh');
-    refreshButton.addEventListener('click', this.update.bind(this));
+    refreshButton.addEventListener(UI.ToolbarButton.Events.Click, this.update.bind(this));
     this._toolbarItems.push(refreshButton);
     this._toolbarItems.push(new UI.ToolbarCheckbox(
         Common.UIString('Ancestors'), Common.UIString('Show listeners on the ancestors'),
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 628d1132..2f41c11 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
@@ -719,25 +719,27 @@
     var items = [];
 
     var textShadowButton = new UI.ToolbarButton(Common.UIString('Add text-shadow'), 'largeicon-text-shadow');
-    textShadowButton.addEventListener('click', this._onInsertShadowPropertyClick.bind(this, 'text-shadow'));
+    textShadowButton.addEventListener(
+        UI.ToolbarButton.Events.Click, this._onInsertShadowPropertyClick.bind(this, 'text-shadow'));
     items.push(textShadowButton);
 
     var boxShadowButton = new UI.ToolbarButton(Common.UIString('Add box-shadow'), 'largeicon-box-shadow');
-    boxShadowButton.addEventListener('click', this._onInsertShadowPropertyClick.bind(this, 'box-shadow'));
+    boxShadowButton.addEventListener(
+        UI.ToolbarButton.Events.Click, this._onInsertShadowPropertyClick.bind(this, 'box-shadow'));
     items.push(boxShadowButton);
 
     var colorButton = new UI.ToolbarButton(Common.UIString('Add color'), 'largeicon-foreground-color');
-    colorButton.addEventListener('click', this._onInsertColorPropertyClick.bind(this));
+    colorButton.addEventListener(UI.ToolbarButton.Events.Click, this._onInsertColorPropertyClick, this);
     items.push(colorButton);
 
     var backgroundButton = new UI.ToolbarButton(Common.UIString('Add background-color'), 'largeicon-background-color');
-    backgroundButton.addEventListener('click', this._onInsertBackgroundColorPropertyClick.bind(this));
+    backgroundButton.addEventListener(UI.ToolbarButton.Events.Click, this._onInsertBackgroundColorPropertyClick, this);
     items.push(backgroundButton);
 
     var newRuleButton = null;
     if (this._style.parentRule) {
       newRuleButton = new UI.ToolbarButton(Common.UIString('Insert Style Rule Below'), 'largeicon-add');
-      newRuleButton.addEventListener('click', this._onNewRuleClick.bind(this));
+      newRuleButton.addEventListener(UI.ToolbarButton.Events.Click, this._onNewRuleClick, this);
       items.push(newRuleButton);
     }
 
@@ -880,7 +882,7 @@
    * @param {!Common.Event} event
    */
   _onNewRuleClick(event) {
-    event.consume();
+    event.data.consume();
     var rule = this._style.parentRule;
     var range = Common.TextRange.createFromLocation(rule.style.range.endLine, rule.style.range.endColumn + 1);
     this._parentPane._addBlankSection(this, /** @type {string} */ (rule.styleSheetId), range);
@@ -891,7 +893,7 @@
    * @param {!Common.Event} event
    */
   _onInsertShadowPropertyClick(propertyName, event) {
-    event.consume(true);
+    event.data.consume(true);
     var treeElement = this.addNewBlankProperty();
     treeElement.property.name = propertyName;
     treeElement.property.value = '0 0 black';
@@ -905,7 +907,7 @@
    * @param {!Common.Event} event
    */
   _onInsertColorPropertyClick(event) {
-    event.consume(true);
+    event.data.consume(true);
     var treeElement = this.addNewBlankProperty();
     treeElement.property.name = 'color';
     treeElement.property.value = 'black';
@@ -919,7 +921,7 @@
    * @param {!Common.Event} event
    */
   _onInsertBackgroundColorPropertyClick(event) {
-    event.consume(true);
+    event.data.consume(true);
     var treeElement = this.addNewBlankProperty();
     treeElement.property.name = 'background-color';
     treeElement.property.value = 'white';
@@ -3016,7 +3018,7 @@
 Elements.StylesSidebarPane.ButtonProvider = class {
   constructor() {
     this._button = new UI.ToolbarButton(Common.UIString('New Style Rule'), 'largeicon-add');
-    this._button.addEventListener('click', this._clicked, this);
+    this._button.addEventListener(UI.ToolbarButton.Events.Click, this._clicked, this);
     var longclickTriangle = UI.Icon.create('largeicon-longclick-triangle', 'long-click-glyph');
     this._button.element.appendChild(longclickTriangle);
 
@@ -3034,7 +3036,10 @@
     }
   }
 
-  _clicked() {
+  /**
+   * @param {!Common.Event} event
+   */
+  _clicked(event) {
     Elements.StylesSidebarPane._instance._createNewRuleInViaInspectorStyleSheet();
   }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeToolbar.js b/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeToolbar.js
index a658424..b7dec58 100644
--- a/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeToolbar.js
+++ b/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeToolbar.js
@@ -170,7 +170,7 @@
     toolbar.appendToolbarItem(
         this._wrapToolbarItem(createElementWithClass('div', 'device-mode-empty-toolbar-element')));
     this._modeButton = new UI.ToolbarButton('', 'largeicon-rotate-screen');
-    this._modeButton.addEventListener('click', this._modeMenuClicked, this);
+    this._modeButton.addEventListener(UI.ToolbarButton.Events.Click, this._modeMenuClicked, this);
     toolbar.appendToolbarItem(this._modeButton);
   }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/extensions/ExtensionPanel.js b/third_party/WebKit/Source/devtools/front_end/extensions/ExtensionPanel.js
index fc6ceb4..87c5b1b 100644
--- a/third_party/WebKit/Source/devtools/front_end/extensions/ExtensionPanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/extensions/ExtensionPanel.js
@@ -133,7 +133,8 @@
     this._id = id;
 
     this._toolbarButton = new UI.ToolbarButton('', '');
-    this._toolbarButton.addEventListener('click', server.notifyButtonClicked.bind(server, this._id));
+    this._toolbarButton.addEventListener(
+        UI.ToolbarButton.Events.Click, server.notifyButtonClicked.bind(server, this._id));
     this.update(iconURL, tooltip, disabled);
   }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/heap_snapshot_worker/HeapSnapshot.js b/third_party/WebKit/Source/devtools/front_end/heap_snapshot_worker/HeapSnapshot.js
index be90fc7e..b9209dd 100644
--- a/third_party/WebKit/Source/devtools/front_end/heap_snapshot_worker/HeapSnapshot.js
+++ b/third_party/WebKit/Source/devtools/front_end/heap_snapshot_worker/HeapSnapshot.js
@@ -2399,3 +2399,815 @@
         this._buildCompareFunction(comparator), leftBound, rightBound, windowLeft, windowRight);
   }
 };
+
+/**
+ * @unrestricted
+ */
+HeapSnapshotWorker.JSHeapSnapshot = class extends HeapSnapshotWorker.HeapSnapshot {
+  /**
+   * @param {!Object} profile
+   * @param {!HeapSnapshotWorker.HeapSnapshotProgress} progress
+   */
+  constructor(profile, progress) {
+    super(profile, progress);
+    this._nodeFlags = {
+      // bit flags
+      canBeQueried: 1,
+      detachedDOMTreeNode: 2,
+      pageObject: 4  // The idea is to track separately the objects owned by the page and the objects owned by debugger.
+    };
+    this.initialize();
+    this._lazyStringCache = {};
+  }
+
+  /**
+   * @override
+   * @param {number=} nodeIndex
+   * @return {!HeapSnapshotWorker.JSHeapSnapshotNode}
+   */
+  createNode(nodeIndex) {
+    return new HeapSnapshotWorker.JSHeapSnapshotNode(this, nodeIndex === undefined ? -1 : nodeIndex);
+  }
+
+  /**
+   * @override
+   * @param {number} edgeIndex
+   * @return {!HeapSnapshotWorker.JSHeapSnapshotEdge}
+   */
+  createEdge(edgeIndex) {
+    return new HeapSnapshotWorker.JSHeapSnapshotEdge(this, edgeIndex);
+  }
+
+  /**
+   * @override
+   * @param {number} retainerIndex
+   * @return {!HeapSnapshotWorker.JSHeapSnapshotRetainerEdge}
+   */
+  createRetainingEdge(retainerIndex) {
+    return new HeapSnapshotWorker.JSHeapSnapshotRetainerEdge(this, retainerIndex);
+  }
+
+  /**
+   * @override
+   * @return {?function(!HeapSnapshotWorker.HeapSnapshotNode):boolean}
+   */
+  classNodesFilter() {
+    var mapAndFlag = this.userObjectsMapAndFlag();
+    if (!mapAndFlag)
+      return null;
+    var map = mapAndFlag.map;
+    var flag = mapAndFlag.flag;
+    /**
+     * @param {!HeapSnapshotWorker.HeapSnapshotNode} node
+     * @return {boolean}
+     */
+    function filter(node) {
+      return !!(map[node.ordinal()] & flag);
+    }
+    return filter;
+  }
+
+  /**
+   * @override
+   * @return {function(!HeapSnapshotWorker.HeapSnapshotEdge):boolean}
+   */
+  containmentEdgesFilter() {
+    return edge => !edge.isInvisible();
+  }
+
+  /**
+   * @override
+   * @return {function(!HeapSnapshotWorker.HeapSnapshotEdge):boolean}
+   */
+  retainingEdgesFilter() {
+    var containmentEdgesFilter = this.containmentEdgesFilter();
+    function filter(edge) {
+      return containmentEdgesFilter(edge) && !edge.node().isRoot() && !edge.isWeak();
+    }
+    return filter;
+  }
+
+  /**
+   * @override
+   */
+  calculateFlags() {
+    this._flags = new Uint32Array(this.nodeCount);
+    this._markDetachedDOMTreeNodes();
+    this._markQueriableHeapObjects();
+    this._markPageOwnedNodes();
+  }
+
+  /**
+   * @override
+   */
+  calculateDistances() {
+    /**
+     * @param {!HeapSnapshotWorker.HeapSnapshotNode} node
+     * @param {!HeapSnapshotWorker.HeapSnapshotEdge} edge
+     * @return {boolean}
+     */
+    function filter(node, edge) {
+      if (node.isHidden())
+        return edge.name() !== 'sloppy_function_map' || node.rawName() !== 'system / NativeContext';
+      if (node.isArray()) {
+        // DescriptorArrays are fixed arrays used to hold instance descriptors.
+        // The format of the these objects is:
+        //   [0]: Number of descriptors
+        //   [1]: Either Smi(0) if uninitialized, or a pointer to small fixed array:
+        //          [0]: pointer to fixed array with enum cache
+        //          [1]: either Smi(0) or pointer to fixed array with indices
+        //   [i*3+2]: i-th key
+        //   [i*3+3]: i-th type
+        //   [i*3+4]: i-th descriptor
+        // As long as maps may share descriptor arrays some of the descriptor
+        // links may not be valid for all the maps. We just skip
+        // all the descriptor links when calculating distances.
+        // For more details see http://crbug.com/413608
+        if (node.rawName() !== '(map descriptors)')
+          return true;
+        var index = edge.name();
+        return index < 2 || (index % 3) !== 1;
+      }
+      return true;
+    }
+    super.calculateDistances(filter);
+  }
+
+  /**
+   * @override
+   * @protected
+   * @param {!HeapSnapshotWorker.HeapSnapshotNode} node
+   * @return {boolean}
+   */
+  isUserRoot(node) {
+    return node.isUserRoot() || node.isDocumentDOMTreesRoot();
+  }
+
+  /**
+   * @override
+   * @param {function(!HeapSnapshotWorker.HeapSnapshotNode)} action
+   * @param {boolean=} userRootsOnly
+   */
+  forEachRoot(action, userRootsOnly) {
+    /**
+     * @param {!HeapSnapshotWorker.HeapSnapshotNode} node
+     * @param {string} name
+     * @return {?HeapSnapshotWorker.HeapSnapshotNode}
+     */
+    function getChildNodeByName(node, name) {
+      for (var iter = node.edges(); iter.hasNext(); iter.next()) {
+        var child = iter.edge.node();
+        if (child.name() === name)
+          return child;
+      }
+      return null;
+    }
+
+    var visitedNodes = {};
+    /**
+     * @param {!HeapSnapshotWorker.HeapSnapshotNode} node
+     */
+    function doAction(node) {
+      var ordinal = node.ordinal();
+      if (!visitedNodes[ordinal]) {
+        action(node);
+        visitedNodes[ordinal] = true;
+      }
+    }
+
+    var gcRoots = getChildNodeByName(this.rootNode(), '(GC roots)');
+    if (!gcRoots)
+      return;
+
+    if (userRootsOnly) {
+      for (var iter = this.rootNode().edges(); iter.hasNext(); iter.next()) {
+        var node = iter.edge.node();
+        if (this.isUserRoot(node))
+          doAction(node);
+      }
+    } else {
+      for (var iter = gcRoots.edges(); iter.hasNext(); iter.next()) {
+        var subRoot = iter.edge.node();
+        for (var iter2 = subRoot.edges(); iter2.hasNext(); iter2.next())
+          doAction(iter2.edge.node());
+        doAction(subRoot);
+      }
+      for (var iter = this.rootNode().edges(); iter.hasNext(); iter.next())
+        doAction(iter.edge.node());
+    }
+  }
+
+  /**
+   * @override
+   * @return {?{map: !Uint32Array, flag: number}}
+   */
+  userObjectsMapAndFlag() {
+    return {map: this._flags, flag: this._nodeFlags.pageObject};
+  }
+
+  /**
+   * @param {!HeapSnapshotWorker.HeapSnapshotNode} node
+   * @return {number}
+   */
+  _flagsOfNode(node) {
+    return this._flags[node.nodeIndex / this._nodeFieldCount];
+  }
+
+  _markDetachedDOMTreeNodes() {
+    var flag = this._nodeFlags.detachedDOMTreeNode;
+    var detachedDOMTreesRoot;
+    for (var iter = this.rootNode().edges(); iter.hasNext(); iter.next()) {
+      var node = iter.edge.node();
+      if (node.name() === '(Detached DOM trees)') {
+        detachedDOMTreesRoot = node;
+        break;
+      }
+    }
+
+    if (!detachedDOMTreesRoot)
+      return;
+
+    var detachedDOMTreeRE = /^Detached DOM tree/;
+    for (var iter = detachedDOMTreesRoot.edges(); iter.hasNext(); iter.next()) {
+      var node = iter.edge.node();
+      if (detachedDOMTreeRE.test(node.className())) {
+        for (var edgesIter = node.edges(); edgesIter.hasNext(); edgesIter.next())
+          this._flags[edgesIter.edge.node().nodeIndex / this._nodeFieldCount] |= flag;
+      }
+    }
+  }
+
+  _markQueriableHeapObjects() {
+    // Allow runtime properties query for objects accessible from Window objects
+    // via regular properties, and for DOM wrappers. Trying to access random objects
+    // can cause a crash due to insonsistent state of internal properties of wrappers.
+    var flag = this._nodeFlags.canBeQueried;
+    var hiddenEdgeType = this._edgeHiddenType;
+    var internalEdgeType = this._edgeInternalType;
+    var invisibleEdgeType = this._edgeInvisibleType;
+    var weakEdgeType = this._edgeWeakType;
+    var edgeToNodeOffset = this._edgeToNodeOffset;
+    var edgeTypeOffset = this._edgeTypeOffset;
+    var edgeFieldsCount = this._edgeFieldsCount;
+    var containmentEdges = this.containmentEdges;
+    var nodeFieldCount = this._nodeFieldCount;
+    var firstEdgeIndexes = this._firstEdgeIndexes;
+
+    var flags = this._flags;
+    var list = [];
+
+    for (var iter = this.rootNode().edges(); iter.hasNext(); iter.next()) {
+      if (iter.edge.node().isUserRoot())
+        list.push(iter.edge.node().nodeIndex / nodeFieldCount);
+    }
+
+    while (list.length) {
+      var nodeOrdinal = list.pop();
+      if (flags[nodeOrdinal] & flag)
+        continue;
+      flags[nodeOrdinal] |= flag;
+      var beginEdgeIndex = firstEdgeIndexes[nodeOrdinal];
+      var endEdgeIndex = firstEdgeIndexes[nodeOrdinal + 1];
+      for (var edgeIndex = beginEdgeIndex; edgeIndex < endEdgeIndex; edgeIndex += edgeFieldsCount) {
+        var childNodeIndex = containmentEdges[edgeIndex + edgeToNodeOffset];
+        var childNodeOrdinal = childNodeIndex / nodeFieldCount;
+        if (flags[childNodeOrdinal] & flag)
+          continue;
+        var type = containmentEdges[edgeIndex + edgeTypeOffset];
+        if (type === hiddenEdgeType || type === invisibleEdgeType || type === internalEdgeType || type === weakEdgeType)
+          continue;
+        list.push(childNodeOrdinal);
+      }
+    }
+  }
+
+  _markPageOwnedNodes() {
+    var edgeShortcutType = this._edgeShortcutType;
+    var edgeElementType = this._edgeElementType;
+    var edgeToNodeOffset = this._edgeToNodeOffset;
+    var edgeTypeOffset = this._edgeTypeOffset;
+    var edgeFieldsCount = this._edgeFieldsCount;
+    var edgeWeakType = this._edgeWeakType;
+    var firstEdgeIndexes = this._firstEdgeIndexes;
+    var containmentEdges = this.containmentEdges;
+    var nodeFieldCount = this._nodeFieldCount;
+    var nodesCount = this.nodeCount;
+
+    var flags = this._flags;
+    var pageObjectFlag = this._nodeFlags.pageObject;
+
+    var nodesToVisit = new Uint32Array(nodesCount);
+    var nodesToVisitLength = 0;
+
+    var rootNodeOrdinal = this._rootNodeIndex / nodeFieldCount;
+    var node = this.rootNode();
+
+    // Populate the entry points. They are Window objects and DOM Tree Roots.
+    for (var edgeIndex = firstEdgeIndexes[rootNodeOrdinal], endEdgeIndex = firstEdgeIndexes[rootNodeOrdinal + 1];
+         edgeIndex < endEdgeIndex; edgeIndex += edgeFieldsCount) {
+      var edgeType = containmentEdges[edgeIndex + edgeTypeOffset];
+      var nodeIndex = containmentEdges[edgeIndex + edgeToNodeOffset];
+      if (edgeType === edgeElementType) {
+        node.nodeIndex = nodeIndex;
+        if (!node.isDocumentDOMTreesRoot())
+          continue;
+      } else if (edgeType !== edgeShortcutType) {
+        continue;
+      }
+      var nodeOrdinal = nodeIndex / nodeFieldCount;
+      nodesToVisit[nodesToVisitLength++] = nodeOrdinal;
+      flags[nodeOrdinal] |= pageObjectFlag;
+    }
+
+    // Mark everything reachable with the pageObject flag.
+    while (nodesToVisitLength) {
+      var nodeOrdinal = nodesToVisit[--nodesToVisitLength];
+      var beginEdgeIndex = firstEdgeIndexes[nodeOrdinal];
+      var endEdgeIndex = firstEdgeIndexes[nodeOrdinal + 1];
+      for (var edgeIndex = beginEdgeIndex; edgeIndex < endEdgeIndex; edgeIndex += edgeFieldsCount) {
+        var childNodeIndex = containmentEdges[edgeIndex + edgeToNodeOffset];
+        var childNodeOrdinal = childNodeIndex / nodeFieldCount;
+        if (flags[childNodeOrdinal] & pageObjectFlag)
+          continue;
+        var type = containmentEdges[edgeIndex + edgeTypeOffset];
+        if (type === edgeWeakType)
+          continue;
+        nodesToVisit[nodesToVisitLength++] = childNodeOrdinal;
+        flags[childNodeOrdinal] |= pageObjectFlag;
+      }
+    }
+  }
+
+  /**
+   * @override
+   */
+  calculateStatistics() {
+    var nodeFieldCount = this._nodeFieldCount;
+    var nodes = this.nodes;
+    var nodesLength = nodes.length;
+    var nodeTypeOffset = this._nodeTypeOffset;
+    var nodeSizeOffset = this._nodeSelfSizeOffset;
+    var nodeNativeType = this._nodeNativeType;
+    var nodeCodeType = this._nodeCodeType;
+    var nodeConsStringType = this._nodeConsStringType;
+    var nodeSlicedStringType = this._nodeSlicedStringType;
+    var distances = this._nodeDistances;
+    var sizeNative = 0;
+    var sizeCode = 0;
+    var sizeStrings = 0;
+    var sizeJSArrays = 0;
+    var sizeSystem = 0;
+    var node = this.rootNode();
+    for (var nodeIndex = 0; nodeIndex < nodesLength; nodeIndex += nodeFieldCount) {
+      var nodeSize = nodes[nodeIndex + nodeSizeOffset];
+      var ordinal = nodeIndex / nodeFieldCount;
+      if (distances[ordinal] >= Profiler.HeapSnapshotCommon.baseSystemDistance) {
+        sizeSystem += nodeSize;
+        continue;
+      }
+      var nodeType = nodes[nodeIndex + nodeTypeOffset];
+      node.nodeIndex = nodeIndex;
+      if (nodeType === nodeNativeType)
+        sizeNative += nodeSize;
+      else if (nodeType === nodeCodeType)
+        sizeCode += nodeSize;
+      else if (nodeType === nodeConsStringType || nodeType === nodeSlicedStringType || node.type() === 'string')
+        sizeStrings += nodeSize;
+      else if (node.name() === 'Array')
+        sizeJSArrays += this._calculateArraySize(node);
+    }
+    this._statistics = new Profiler.HeapSnapshotCommon.Statistics();
+    this._statistics.total = this.totalSize;
+    this._statistics.v8heap = this.totalSize - sizeNative;
+    this._statistics.native = sizeNative;
+    this._statistics.code = sizeCode;
+    this._statistics.jsArrays = sizeJSArrays;
+    this._statistics.strings = sizeStrings;
+    this._statistics.system = sizeSystem;
+  }
+
+  /**
+   * @param {!HeapSnapshotWorker.HeapSnapshotNode} node
+   * @return {number}
+   */
+  _calculateArraySize(node) {
+    var size = node.selfSize();
+    var beginEdgeIndex = node.edgeIndexesStart();
+    var endEdgeIndex = node.edgeIndexesEnd();
+    var containmentEdges = this.containmentEdges;
+    var strings = this.strings;
+    var edgeToNodeOffset = this._edgeToNodeOffset;
+    var edgeTypeOffset = this._edgeTypeOffset;
+    var edgeNameOffset = this._edgeNameOffset;
+    var edgeFieldsCount = this._edgeFieldsCount;
+    var edgeInternalType = this._edgeInternalType;
+    for (var edgeIndex = beginEdgeIndex; edgeIndex < endEdgeIndex; edgeIndex += edgeFieldsCount) {
+      var edgeType = containmentEdges[edgeIndex + edgeTypeOffset];
+      if (edgeType !== edgeInternalType)
+        continue;
+      var edgeName = strings[containmentEdges[edgeIndex + edgeNameOffset]];
+      if (edgeName !== 'elements')
+        continue;
+      var elementsNodeIndex = containmentEdges[edgeIndex + edgeToNodeOffset];
+      node.nodeIndex = elementsNodeIndex;
+      if (node.retainersCount() === 1)
+        size += node.selfSize();
+      break;
+    }
+    return size;
+  }
+
+  /**
+   * @return {!Profiler.HeapSnapshotCommon.Statistics}
+   */
+  getStatistics() {
+    return this._statistics;
+  }
+};
+
+/**
+ * @unrestricted
+ */
+HeapSnapshotWorker.JSHeapSnapshotNode = class extends HeapSnapshotWorker.HeapSnapshotNode {
+  /**
+   * @param {!HeapSnapshotWorker.JSHeapSnapshot} snapshot
+   * @param {number=} nodeIndex
+   */
+  constructor(snapshot, nodeIndex) {
+    super(snapshot, nodeIndex);
+  }
+
+  /**
+   * @return {boolean}
+   */
+  canBeQueried() {
+    var flags = this._snapshot._flagsOfNode(this);
+    return !!(flags & this._snapshot._nodeFlags.canBeQueried);
+  }
+
+  /**
+   * @return {string}
+   */
+  rawName() {
+    return super.name();
+  }
+
+  /**
+   * @override
+   * @return {string}
+   */
+  name() {
+    var snapshot = this._snapshot;
+    if (this.rawType() === snapshot._nodeConsStringType) {
+      var string = snapshot._lazyStringCache[this.nodeIndex];
+      if (typeof string === 'undefined') {
+        string = this._consStringName();
+        snapshot._lazyStringCache[this.nodeIndex] = string;
+      }
+      return string;
+    }
+    return this.rawName();
+  }
+
+  /**
+   * @return {string}
+   */
+  _consStringName() {
+    var snapshot = this._snapshot;
+    var consStringType = snapshot._nodeConsStringType;
+    var edgeInternalType = snapshot._edgeInternalType;
+    var edgeFieldsCount = snapshot._edgeFieldsCount;
+    var edgeToNodeOffset = snapshot._edgeToNodeOffset;
+    var edgeTypeOffset = snapshot._edgeTypeOffset;
+    var edgeNameOffset = snapshot._edgeNameOffset;
+    var strings = snapshot.strings;
+    var edges = snapshot.containmentEdges;
+    var firstEdgeIndexes = snapshot._firstEdgeIndexes;
+    var nodeFieldCount = snapshot._nodeFieldCount;
+    var nodeTypeOffset = snapshot._nodeTypeOffset;
+    var nodeNameOffset = snapshot._nodeNameOffset;
+    var nodes = snapshot.nodes;
+    var nodesStack = [];
+    nodesStack.push(this.nodeIndex);
+    var name = '';
+
+    while (nodesStack.length && name.length < 1024) {
+      var nodeIndex = nodesStack.pop();
+      if (nodes[nodeIndex + nodeTypeOffset] !== consStringType) {
+        name += strings[nodes[nodeIndex + nodeNameOffset]];
+        continue;
+      }
+      var nodeOrdinal = nodeIndex / nodeFieldCount;
+      var beginEdgeIndex = firstEdgeIndexes[nodeOrdinal];
+      var endEdgeIndex = firstEdgeIndexes[nodeOrdinal + 1];
+      var firstNodeIndex = 0;
+      var secondNodeIndex = 0;
+      for (var edgeIndex = beginEdgeIndex; edgeIndex < endEdgeIndex && (!firstNodeIndex || !secondNodeIndex);
+           edgeIndex += edgeFieldsCount) {
+        var edgeType = edges[edgeIndex + edgeTypeOffset];
+        if (edgeType === edgeInternalType) {
+          var edgeName = strings[edges[edgeIndex + edgeNameOffset]];
+          if (edgeName === 'first')
+            firstNodeIndex = edges[edgeIndex + edgeToNodeOffset];
+          else if (edgeName === 'second')
+            secondNodeIndex = edges[edgeIndex + edgeToNodeOffset];
+        }
+      }
+      nodesStack.push(secondNodeIndex);
+      nodesStack.push(firstNodeIndex);
+    }
+    return name;
+  }
+
+  /**
+   * @override
+   * @return {string}
+   */
+  className() {
+    var type = this.type();
+    switch (type) {
+      case 'hidden':
+        return '(system)';
+      case 'object':
+      case 'native':
+        return this.name();
+      case 'code':
+        return '(compiled code)';
+      default:
+        return '(' + type + ')';
+    }
+  }
+
+  /**
+   * @override
+   * @return {number}
+   */
+  classIndex() {
+    var snapshot = this._snapshot;
+    var nodes = snapshot.nodes;
+    var type = nodes[this.nodeIndex + snapshot._nodeTypeOffset];
+    if (type === snapshot._nodeObjectType || type === snapshot._nodeNativeType)
+      return nodes[this.nodeIndex + snapshot._nodeNameOffset];
+    return -1 - type;
+  }
+
+  /**
+   * @override
+   * @return {number}
+   */
+  id() {
+    var snapshot = this._snapshot;
+    return snapshot.nodes[this.nodeIndex + snapshot._nodeIdOffset];
+  }
+
+  /**
+   * @return {boolean}
+   */
+  isHidden() {
+    return this.rawType() === this._snapshot._nodeHiddenType;
+  }
+
+  /**
+   * @return {boolean}
+   */
+  isArray() {
+    return this.rawType() === this._snapshot._nodeArrayType;
+  }
+
+  /**
+   * @return {boolean}
+   */
+  isSynthetic() {
+    return this.rawType() === this._snapshot._nodeSyntheticType;
+  }
+
+  /**
+   * @return {boolean}
+   */
+  isUserRoot() {
+    return !this.isSynthetic();
+  }
+
+  /**
+   * @return {boolean}
+   */
+  isDocumentDOMTreesRoot() {
+    return this.isSynthetic() && this.name() === '(Document DOM trees)';
+  }
+
+  /**
+   * @override
+   * @return {!Profiler.HeapSnapshotCommon.Node}
+   */
+  serialize() {
+    var result = super.serialize();
+    var flags = this._snapshot._flagsOfNode(this);
+    if (flags & this._snapshot._nodeFlags.canBeQueried)
+      result.canBeQueried = true;
+    if (flags & this._snapshot._nodeFlags.detachedDOMTreeNode)
+      result.detachedDOMTreeNode = true;
+    return result;
+  }
+};
+
+/**
+ * @unrestricted
+ */
+HeapSnapshotWorker.JSHeapSnapshotEdge = class extends HeapSnapshotWorker.HeapSnapshotEdge {
+  /**
+   * @param {!HeapSnapshotWorker.JSHeapSnapshot} snapshot
+   * @param {number=} edgeIndex
+   */
+  constructor(snapshot, edgeIndex) {
+    super(snapshot, edgeIndex);
+  }
+
+  /**
+   * @override
+   * @return {!HeapSnapshotWorker.JSHeapSnapshotEdge}
+   */
+  clone() {
+    var snapshot = /** @type {!HeapSnapshotWorker.JSHeapSnapshot} */ (this._snapshot);
+    return new HeapSnapshotWorker.JSHeapSnapshotEdge(snapshot, this.edgeIndex);
+  }
+
+  /**
+   * @override
+   * @return {boolean}
+   */
+  hasStringName() {
+    if (!this.isShortcut())
+      return this._hasStringName();
+    return isNaN(parseInt(this._name(), 10));
+  }
+
+  /**
+   * @return {boolean}
+   */
+  isElement() {
+    return this.rawType() === this._snapshot._edgeElementType;
+  }
+
+  /**
+   * @return {boolean}
+   */
+  isHidden() {
+    return this.rawType() === this._snapshot._edgeHiddenType;
+  }
+
+  /**
+   * @return {boolean}
+   */
+  isWeak() {
+    return this.rawType() === this._snapshot._edgeWeakType;
+  }
+
+  /**
+   * @return {boolean}
+   */
+  isInternal() {
+    return this.rawType() === this._snapshot._edgeInternalType;
+  }
+
+  /**
+   * @return {boolean}
+   */
+  isInvisible() {
+    return this.rawType() === this._snapshot._edgeInvisibleType;
+  }
+
+  /**
+   * @return {boolean}
+   */
+  isShortcut() {
+    return this.rawType() === this._snapshot._edgeShortcutType;
+  }
+
+  /**
+   * @override
+   * @return {string}
+   */
+  name() {
+    var name = this._name();
+    if (!this.isShortcut())
+      return String(name);
+    var numName = parseInt(name, 10);
+    return String(isNaN(numName) ? name : numName);
+  }
+
+  /**
+   * @override
+   * @return {string}
+   */
+  toString() {
+    var name = this.name();
+    switch (this.type()) {
+      case 'context':
+        return '->' + name;
+      case 'element':
+        return '[' + name + ']';
+      case 'weak':
+        return '[[' + name + ']]';
+      case 'property':
+        return name.indexOf(' ') === -1 ? '.' + name : '["' + name + '"]';
+      case 'shortcut':
+        if (typeof name === 'string')
+          return name.indexOf(' ') === -1 ? '.' + name : '["' + name + '"]';
+        else
+          return '[' + name + ']';
+      case 'internal':
+      case 'hidden':
+      case 'invisible':
+        return '{' + name + '}';
+    }
+    return '?' + name + '?';
+  }
+
+  /**
+   * @return {boolean}
+   */
+  _hasStringName() {
+    var type = this.rawType();
+    var snapshot = this._snapshot;
+    return type !== snapshot._edgeElementType && type !== snapshot._edgeHiddenType;
+  }
+
+  /**
+   * @return {string|number}
+   */
+  _name() {
+    return this._hasStringName() ? this._snapshot.strings[this._nameOrIndex()] : this._nameOrIndex();
+  }
+
+  /**
+   * @return {number}
+   */
+  _nameOrIndex() {
+    return this._edges[this.edgeIndex + this._snapshot._edgeNameOffset];
+  }
+
+  /**
+   * @override
+   * @return {number}
+   */
+  rawType() {
+    return this._edges[this.edgeIndex + this._snapshot._edgeTypeOffset];
+  }
+};
+
+/**
+ * @unrestricted
+ */
+HeapSnapshotWorker.JSHeapSnapshotRetainerEdge = class extends HeapSnapshotWorker.HeapSnapshotRetainerEdge {
+  /**
+   * @param {!HeapSnapshotWorker.JSHeapSnapshot} snapshot
+   * @param {number} retainerIndex
+   */
+  constructor(snapshot, retainerIndex) {
+    super(snapshot, retainerIndex);
+  }
+
+  /**
+   * @override
+   * @return {!HeapSnapshotWorker.JSHeapSnapshotRetainerEdge}
+   */
+  clone() {
+    var snapshot = /** @type {!HeapSnapshotWorker.JSHeapSnapshot} */ (this._snapshot);
+    return new HeapSnapshotWorker.JSHeapSnapshotRetainerEdge(snapshot, this.retainerIndex());
+  }
+
+  /**
+   * @return {boolean}
+   */
+  isHidden() {
+    return this._edge().isHidden();
+  }
+
+  /**
+   * @return {boolean}
+   */
+  isInternal() {
+    return this._edge().isInternal();
+  }
+
+  /**
+   * @return {boolean}
+   */
+  isInvisible() {
+    return this._edge().isInvisible();
+  }
+
+  /**
+   * @return {boolean}
+   */
+  isShortcut() {
+    return this._edge().isShortcut();
+  }
+
+  /**
+   * @return {boolean}
+   */
+  isWeak() {
+    return this._edge().isWeak();
+  }
+};
diff --git a/third_party/WebKit/Source/devtools/front_end/heap_snapshot_worker/JSHeapSnapshot.js b/third_party/WebKit/Source/devtools/front_end/heap_snapshot_worker/JSHeapSnapshot.js
deleted file mode 100644
index b957343..0000000
--- a/third_party/WebKit/Source/devtools/front_end/heap_snapshot_worker/JSHeapSnapshot.js
+++ /dev/null
@@ -1,841 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-/**
- * @unrestricted
- */
-HeapSnapshotWorker.JSHeapSnapshot = class extends HeapSnapshotWorker.HeapSnapshot {
-  /**
-   * @param {!Object} profile
-   * @param {!HeapSnapshotWorker.HeapSnapshotProgress} progress
-   */
-  constructor(profile, progress) {
-    super(profile, progress);
-    this._nodeFlags = {
-      // bit flags
-      canBeQueried: 1,
-      detachedDOMTreeNode: 2,
-      pageObject: 4  // The idea is to track separately the objects owned by the page and the objects owned by debugger.
-    };
-    this.initialize();
-    this._lazyStringCache = {};
-  }
-
-  /**
-   * @override
-   * @param {number=} nodeIndex
-   * @return {!HeapSnapshotWorker.JSHeapSnapshotNode}
-   */
-  createNode(nodeIndex) {
-    return new HeapSnapshotWorker.JSHeapSnapshotNode(this, nodeIndex === undefined ? -1 : nodeIndex);
-  }
-
-  /**
-   * @override
-   * @param {number} edgeIndex
-   * @return {!HeapSnapshotWorker.JSHeapSnapshotEdge}
-   */
-  createEdge(edgeIndex) {
-    return new HeapSnapshotWorker.JSHeapSnapshotEdge(this, edgeIndex);
-  }
-
-  /**
-   * @override
-   * @param {number} retainerIndex
-   * @return {!HeapSnapshotWorker.JSHeapSnapshotRetainerEdge}
-   */
-  createRetainingEdge(retainerIndex) {
-    return new HeapSnapshotWorker.JSHeapSnapshotRetainerEdge(this, retainerIndex);
-  }
-
-  /**
-   * @override
-   * @return {?function(!HeapSnapshotWorker.HeapSnapshotNode):boolean}
-   */
-  classNodesFilter() {
-    var mapAndFlag = this.userObjectsMapAndFlag();
-    if (!mapAndFlag)
-      return null;
-    var map = mapAndFlag.map;
-    var flag = mapAndFlag.flag;
-    /**
-     * @param {!HeapSnapshotWorker.HeapSnapshotNode} node
-     * @return {boolean}
-     */
-    function filter(node) {
-      return !!(map[node.ordinal()] & flag);
-    }
-    return filter;
-  }
-
-  /**
-   * @override
-   * @return {function(!HeapSnapshotWorker.HeapSnapshotEdge):boolean}
-   */
-  containmentEdgesFilter() {
-    return edge => !edge.isInvisible();
-  }
-
-  /**
-   * @override
-   * @return {function(!HeapSnapshotWorker.HeapSnapshotEdge):boolean}
-   */
-  retainingEdgesFilter() {
-    var containmentEdgesFilter = this.containmentEdgesFilter();
-    function filter(edge) {
-      return containmentEdgesFilter(edge) && !edge.node().isRoot() && !edge.isWeak();
-    }
-    return filter;
-  }
-
-  /**
-   * @override
-   */
-  calculateFlags() {
-    this._flags = new Uint32Array(this.nodeCount);
-    this._markDetachedDOMTreeNodes();
-    this._markQueriableHeapObjects();
-    this._markPageOwnedNodes();
-  }
-
-  /**
-   * @override
-   */
-  calculateDistances() {
-    /**
-     * @param {!HeapSnapshotWorker.HeapSnapshotNode} node
-     * @param {!HeapSnapshotWorker.HeapSnapshotEdge} edge
-     * @return {boolean}
-     */
-    function filter(node, edge) {
-      if (node.isHidden())
-        return edge.name() !== 'sloppy_function_map' || node.rawName() !== 'system / NativeContext';
-      if (node.isArray()) {
-        // DescriptorArrays are fixed arrays used to hold instance descriptors.
-        // The format of the these objects is:
-        //   [0]: Number of descriptors
-        //   [1]: Either Smi(0) if uninitialized, or a pointer to small fixed array:
-        //          [0]: pointer to fixed array with enum cache
-        //          [1]: either Smi(0) or pointer to fixed array with indices
-        //   [i*3+2]: i-th key
-        //   [i*3+3]: i-th type
-        //   [i*3+4]: i-th descriptor
-        // As long as maps may share descriptor arrays some of the descriptor
-        // links may not be valid for all the maps. We just skip
-        // all the descriptor links when calculating distances.
-        // For more details see http://crbug.com/413608
-        if (node.rawName() !== '(map descriptors)')
-          return true;
-        var index = edge.name();
-        return index < 2 || (index % 3) !== 1;
-      }
-      return true;
-    }
-    super.calculateDistances(filter);
-  }
-
-  /**
-   * @override
-   * @protected
-   * @param {!HeapSnapshotWorker.HeapSnapshotNode} node
-   * @return {boolean}
-   */
-  isUserRoot(node) {
-    return node.isUserRoot() || node.isDocumentDOMTreesRoot();
-  }
-
-  /**
-   * @override
-   * @param {function(!HeapSnapshotWorker.HeapSnapshotNode)} action
-   * @param {boolean=} userRootsOnly
-   */
-  forEachRoot(action, userRootsOnly) {
-    /**
-     * @param {!HeapSnapshotWorker.HeapSnapshotNode} node
-     * @param {string} name
-     * @return {?HeapSnapshotWorker.HeapSnapshotNode}
-     */
-    function getChildNodeByName(node, name) {
-      for (var iter = node.edges(); iter.hasNext(); iter.next()) {
-        var child = iter.edge.node();
-        if (child.name() === name)
-          return child;
-      }
-      return null;
-    }
-
-    var visitedNodes = {};
-    /**
-     * @param {!HeapSnapshotWorker.HeapSnapshotNode} node
-     */
-    function doAction(node) {
-      var ordinal = node.ordinal();
-      if (!visitedNodes[ordinal]) {
-        action(node);
-        visitedNodes[ordinal] = true;
-      }
-    }
-
-    var gcRoots = getChildNodeByName(this.rootNode(), '(GC roots)');
-    if (!gcRoots)
-      return;
-
-    if (userRootsOnly) {
-      for (var iter = this.rootNode().edges(); iter.hasNext(); iter.next()) {
-        var node = iter.edge.node();
-        if (this.isUserRoot(node))
-          doAction(node);
-      }
-    } else {
-      for (var iter = gcRoots.edges(); iter.hasNext(); iter.next()) {
-        var subRoot = iter.edge.node();
-        for (var iter2 = subRoot.edges(); iter2.hasNext(); iter2.next())
-          doAction(iter2.edge.node());
-        doAction(subRoot);
-      }
-      for (var iter = this.rootNode().edges(); iter.hasNext(); iter.next())
-        doAction(iter.edge.node());
-    }
-  }
-
-  /**
-   * @override
-   * @return {?{map: !Uint32Array, flag: number}}
-   */
-  userObjectsMapAndFlag() {
-    return {map: this._flags, flag: this._nodeFlags.pageObject};
-  }
-
-  /**
-   * @param {!HeapSnapshotWorker.HeapSnapshotNode} node
-   * @return {number}
-   */
-  _flagsOfNode(node) {
-    return this._flags[node.nodeIndex / this._nodeFieldCount];
-  }
-
-  _markDetachedDOMTreeNodes() {
-    var flag = this._nodeFlags.detachedDOMTreeNode;
-    var detachedDOMTreesRoot;
-    for (var iter = this.rootNode().edges(); iter.hasNext(); iter.next()) {
-      var node = iter.edge.node();
-      if (node.name() === '(Detached DOM trees)') {
-        detachedDOMTreesRoot = node;
-        break;
-      }
-    }
-
-    if (!detachedDOMTreesRoot)
-      return;
-
-    var detachedDOMTreeRE = /^Detached DOM tree/;
-    for (var iter = detachedDOMTreesRoot.edges(); iter.hasNext(); iter.next()) {
-      var node = iter.edge.node();
-      if (detachedDOMTreeRE.test(node.className())) {
-        for (var edgesIter = node.edges(); edgesIter.hasNext(); edgesIter.next())
-          this._flags[edgesIter.edge.node().nodeIndex / this._nodeFieldCount] |= flag;
-      }
-    }
-  }
-
-  _markQueriableHeapObjects() {
-    // Allow runtime properties query for objects accessible from Window objects
-    // via regular properties, and for DOM wrappers. Trying to access random objects
-    // can cause a crash due to insonsistent state of internal properties of wrappers.
-    var flag = this._nodeFlags.canBeQueried;
-    var hiddenEdgeType = this._edgeHiddenType;
-    var internalEdgeType = this._edgeInternalType;
-    var invisibleEdgeType = this._edgeInvisibleType;
-    var weakEdgeType = this._edgeWeakType;
-    var edgeToNodeOffset = this._edgeToNodeOffset;
-    var edgeTypeOffset = this._edgeTypeOffset;
-    var edgeFieldsCount = this._edgeFieldsCount;
-    var containmentEdges = this.containmentEdges;
-    var nodeFieldCount = this._nodeFieldCount;
-    var firstEdgeIndexes = this._firstEdgeIndexes;
-
-    var flags = this._flags;
-    var list = [];
-
-    for (var iter = this.rootNode().edges(); iter.hasNext(); iter.next()) {
-      if (iter.edge.node().isUserRoot())
-        list.push(iter.edge.node().nodeIndex / nodeFieldCount);
-    }
-
-    while (list.length) {
-      var nodeOrdinal = list.pop();
-      if (flags[nodeOrdinal] & flag)
-        continue;
-      flags[nodeOrdinal] |= flag;
-      var beginEdgeIndex = firstEdgeIndexes[nodeOrdinal];
-      var endEdgeIndex = firstEdgeIndexes[nodeOrdinal + 1];
-      for (var edgeIndex = beginEdgeIndex; edgeIndex < endEdgeIndex; edgeIndex += edgeFieldsCount) {
-        var childNodeIndex = containmentEdges[edgeIndex + edgeToNodeOffset];
-        var childNodeOrdinal = childNodeIndex / nodeFieldCount;
-        if (flags[childNodeOrdinal] & flag)
-          continue;
-        var type = containmentEdges[edgeIndex + edgeTypeOffset];
-        if (type === hiddenEdgeType || type === invisibleEdgeType || type === internalEdgeType || type === weakEdgeType)
-          continue;
-        list.push(childNodeOrdinal);
-      }
-    }
-  }
-
-  _markPageOwnedNodes() {
-    var edgeShortcutType = this._edgeShortcutType;
-    var edgeElementType = this._edgeElementType;
-    var edgeToNodeOffset = this._edgeToNodeOffset;
-    var edgeTypeOffset = this._edgeTypeOffset;
-    var edgeFieldsCount = this._edgeFieldsCount;
-    var edgeWeakType = this._edgeWeakType;
-    var firstEdgeIndexes = this._firstEdgeIndexes;
-    var containmentEdges = this.containmentEdges;
-    var nodeFieldCount = this._nodeFieldCount;
-    var nodesCount = this.nodeCount;
-
-    var flags = this._flags;
-    var pageObjectFlag = this._nodeFlags.pageObject;
-
-    var nodesToVisit = new Uint32Array(nodesCount);
-    var nodesToVisitLength = 0;
-
-    var rootNodeOrdinal = this._rootNodeIndex / nodeFieldCount;
-    var node = this.rootNode();
-
-    // Populate the entry points. They are Window objects and DOM Tree Roots.
-    for (var edgeIndex = firstEdgeIndexes[rootNodeOrdinal], endEdgeIndex = firstEdgeIndexes[rootNodeOrdinal + 1];
-         edgeIndex < endEdgeIndex; edgeIndex += edgeFieldsCount) {
-      var edgeType = containmentEdges[edgeIndex + edgeTypeOffset];
-      var nodeIndex = containmentEdges[edgeIndex + edgeToNodeOffset];
-      if (edgeType === edgeElementType) {
-        node.nodeIndex = nodeIndex;
-        if (!node.isDocumentDOMTreesRoot())
-          continue;
-      } else if (edgeType !== edgeShortcutType) {
-        continue;
-      }
-      var nodeOrdinal = nodeIndex / nodeFieldCount;
-      nodesToVisit[nodesToVisitLength++] = nodeOrdinal;
-      flags[nodeOrdinal] |= pageObjectFlag;
-    }
-
-    // Mark everything reachable with the pageObject flag.
-    while (nodesToVisitLength) {
-      var nodeOrdinal = nodesToVisit[--nodesToVisitLength];
-      var beginEdgeIndex = firstEdgeIndexes[nodeOrdinal];
-      var endEdgeIndex = firstEdgeIndexes[nodeOrdinal + 1];
-      for (var edgeIndex = beginEdgeIndex; edgeIndex < endEdgeIndex; edgeIndex += edgeFieldsCount) {
-        var childNodeIndex = containmentEdges[edgeIndex + edgeToNodeOffset];
-        var childNodeOrdinal = childNodeIndex / nodeFieldCount;
-        if (flags[childNodeOrdinal] & pageObjectFlag)
-          continue;
-        var type = containmentEdges[edgeIndex + edgeTypeOffset];
-        if (type === edgeWeakType)
-          continue;
-        nodesToVisit[nodesToVisitLength++] = childNodeOrdinal;
-        flags[childNodeOrdinal] |= pageObjectFlag;
-      }
-    }
-  }
-
-  /**
-   * @override
-   */
-  calculateStatistics() {
-    var nodeFieldCount = this._nodeFieldCount;
-    var nodes = this.nodes;
-    var nodesLength = nodes.length;
-    var nodeTypeOffset = this._nodeTypeOffset;
-    var nodeSizeOffset = this._nodeSelfSizeOffset;
-    var nodeNativeType = this._nodeNativeType;
-    var nodeCodeType = this._nodeCodeType;
-    var nodeConsStringType = this._nodeConsStringType;
-    var nodeSlicedStringType = this._nodeSlicedStringType;
-    var distances = this._nodeDistances;
-    var sizeNative = 0;
-    var sizeCode = 0;
-    var sizeStrings = 0;
-    var sizeJSArrays = 0;
-    var sizeSystem = 0;
-    var node = this.rootNode();
-    for (var nodeIndex = 0; nodeIndex < nodesLength; nodeIndex += nodeFieldCount) {
-      var nodeSize = nodes[nodeIndex + nodeSizeOffset];
-      var ordinal = nodeIndex / nodeFieldCount;
-      if (distances[ordinal] >= Profiler.HeapSnapshotCommon.baseSystemDistance) {
-        sizeSystem += nodeSize;
-        continue;
-      }
-      var nodeType = nodes[nodeIndex + nodeTypeOffset];
-      node.nodeIndex = nodeIndex;
-      if (nodeType === nodeNativeType)
-        sizeNative += nodeSize;
-      else if (nodeType === nodeCodeType)
-        sizeCode += nodeSize;
-      else if (nodeType === nodeConsStringType || nodeType === nodeSlicedStringType || node.type() === 'string')
-        sizeStrings += nodeSize;
-      else if (node.name() === 'Array')
-        sizeJSArrays += this._calculateArraySize(node);
-    }
-    this._statistics = new Profiler.HeapSnapshotCommon.Statistics();
-    this._statistics.total = this.totalSize;
-    this._statistics.v8heap = this.totalSize - sizeNative;
-    this._statistics.native = sizeNative;
-    this._statistics.code = sizeCode;
-    this._statistics.jsArrays = sizeJSArrays;
-    this._statistics.strings = sizeStrings;
-    this._statistics.system = sizeSystem;
-  }
-
-  /**
-   * @param {!HeapSnapshotWorker.HeapSnapshotNode} node
-   * @return {number}
-   */
-  _calculateArraySize(node) {
-    var size = node.selfSize();
-    var beginEdgeIndex = node.edgeIndexesStart();
-    var endEdgeIndex = node.edgeIndexesEnd();
-    var containmentEdges = this.containmentEdges;
-    var strings = this.strings;
-    var edgeToNodeOffset = this._edgeToNodeOffset;
-    var edgeTypeOffset = this._edgeTypeOffset;
-    var edgeNameOffset = this._edgeNameOffset;
-    var edgeFieldsCount = this._edgeFieldsCount;
-    var edgeInternalType = this._edgeInternalType;
-    for (var edgeIndex = beginEdgeIndex; edgeIndex < endEdgeIndex; edgeIndex += edgeFieldsCount) {
-      var edgeType = containmentEdges[edgeIndex + edgeTypeOffset];
-      if (edgeType !== edgeInternalType)
-        continue;
-      var edgeName = strings[containmentEdges[edgeIndex + edgeNameOffset]];
-      if (edgeName !== 'elements')
-        continue;
-      var elementsNodeIndex = containmentEdges[edgeIndex + edgeToNodeOffset];
-      node.nodeIndex = elementsNodeIndex;
-      if (node.retainersCount() === 1)
-        size += node.selfSize();
-      break;
-    }
-    return size;
-  }
-
-  /**
-   * @return {!Profiler.HeapSnapshotCommon.Statistics}
-   */
-  getStatistics() {
-    return this._statistics;
-  }
-};
-
-/**
- * @unrestricted
- */
-HeapSnapshotWorker.JSHeapSnapshotNode = class extends HeapSnapshotWorker.HeapSnapshotNode {
-  /**
-   * @param {!HeapSnapshotWorker.JSHeapSnapshot} snapshot
-   * @param {number=} nodeIndex
-   */
-  constructor(snapshot, nodeIndex) {
-    super(snapshot, nodeIndex);
-  }
-
-  /**
-   * @return {boolean}
-   */
-  canBeQueried() {
-    var flags = this._snapshot._flagsOfNode(this);
-    return !!(flags & this._snapshot._nodeFlags.canBeQueried);
-  }
-
-  /**
-   * @return {string}
-   */
-  rawName() {
-    return super.name();
-  }
-
-  /**
-   * @override
-   * @return {string}
-   */
-  name() {
-    var snapshot = this._snapshot;
-    if (this.rawType() === snapshot._nodeConsStringType) {
-      var string = snapshot._lazyStringCache[this.nodeIndex];
-      if (typeof string === 'undefined') {
-        string = this._consStringName();
-        snapshot._lazyStringCache[this.nodeIndex] = string;
-      }
-      return string;
-    }
-    return this.rawName();
-  }
-
-  /**
-   * @return {string}
-   */
-  _consStringName() {
-    var snapshot = this._snapshot;
-    var consStringType = snapshot._nodeConsStringType;
-    var edgeInternalType = snapshot._edgeInternalType;
-    var edgeFieldsCount = snapshot._edgeFieldsCount;
-    var edgeToNodeOffset = snapshot._edgeToNodeOffset;
-    var edgeTypeOffset = snapshot._edgeTypeOffset;
-    var edgeNameOffset = snapshot._edgeNameOffset;
-    var strings = snapshot.strings;
-    var edges = snapshot.containmentEdges;
-    var firstEdgeIndexes = snapshot._firstEdgeIndexes;
-    var nodeFieldCount = snapshot._nodeFieldCount;
-    var nodeTypeOffset = snapshot._nodeTypeOffset;
-    var nodeNameOffset = snapshot._nodeNameOffset;
-    var nodes = snapshot.nodes;
-    var nodesStack = [];
-    nodesStack.push(this.nodeIndex);
-    var name = '';
-
-    while (nodesStack.length && name.length < 1024) {
-      var nodeIndex = nodesStack.pop();
-      if (nodes[nodeIndex + nodeTypeOffset] !== consStringType) {
-        name += strings[nodes[nodeIndex + nodeNameOffset]];
-        continue;
-      }
-      var nodeOrdinal = nodeIndex / nodeFieldCount;
-      var beginEdgeIndex = firstEdgeIndexes[nodeOrdinal];
-      var endEdgeIndex = firstEdgeIndexes[nodeOrdinal + 1];
-      var firstNodeIndex = 0;
-      var secondNodeIndex = 0;
-      for (var edgeIndex = beginEdgeIndex; edgeIndex < endEdgeIndex && (!firstNodeIndex || !secondNodeIndex);
-           edgeIndex += edgeFieldsCount) {
-        var edgeType = edges[edgeIndex + edgeTypeOffset];
-        if (edgeType === edgeInternalType) {
-          var edgeName = strings[edges[edgeIndex + edgeNameOffset]];
-          if (edgeName === 'first')
-            firstNodeIndex = edges[edgeIndex + edgeToNodeOffset];
-          else if (edgeName === 'second')
-            secondNodeIndex = edges[edgeIndex + edgeToNodeOffset];
-        }
-      }
-      nodesStack.push(secondNodeIndex);
-      nodesStack.push(firstNodeIndex);
-    }
-    return name;
-  }
-
-  /**
-   * @override
-   * @return {string}
-   */
-  className() {
-    var type = this.type();
-    switch (type) {
-      case 'hidden':
-        return '(system)';
-      case 'object':
-      case 'native':
-        return this.name();
-      case 'code':
-        return '(compiled code)';
-      default:
-        return '(' + type + ')';
-    }
-  }
-
-  /**
-   * @override
-   * @return {number}
-   */
-  classIndex() {
-    var snapshot = this._snapshot;
-    var nodes = snapshot.nodes;
-    var type = nodes[this.nodeIndex + snapshot._nodeTypeOffset];
-    if (type === snapshot._nodeObjectType || type === snapshot._nodeNativeType)
-      return nodes[this.nodeIndex + snapshot._nodeNameOffset];
-    return -1 - type;
-  }
-
-  /**
-   * @override
-   * @return {number}
-   */
-  id() {
-    var snapshot = this._snapshot;
-    return snapshot.nodes[this.nodeIndex + snapshot._nodeIdOffset];
-  }
-
-  /**
-   * @return {boolean}
-   */
-  isHidden() {
-    return this.rawType() === this._snapshot._nodeHiddenType;
-  }
-
-  /**
-   * @return {boolean}
-   */
-  isArray() {
-    return this.rawType() === this._snapshot._nodeArrayType;
-  }
-
-  /**
-   * @return {boolean}
-   */
-  isSynthetic() {
-    return this.rawType() === this._snapshot._nodeSyntheticType;
-  }
-
-  /**
-   * @return {boolean}
-   */
-  isUserRoot() {
-    return !this.isSynthetic();
-  }
-
-  /**
-   * @return {boolean}
-   */
-  isDocumentDOMTreesRoot() {
-    return this.isSynthetic() && this.name() === '(Document DOM trees)';
-  }
-
-  /**
-   * @override
-   * @return {!Profiler.HeapSnapshotCommon.Node}
-   */
-  serialize() {
-    var result = super.serialize();
-    var flags = this._snapshot._flagsOfNode(this);
-    if (flags & this._snapshot._nodeFlags.canBeQueried)
-      result.canBeQueried = true;
-    if (flags & this._snapshot._nodeFlags.detachedDOMTreeNode)
-      result.detachedDOMTreeNode = true;
-    return result;
-  }
-};
-
-/**
- * @unrestricted
- */
-HeapSnapshotWorker.JSHeapSnapshotEdge = class extends HeapSnapshotWorker.HeapSnapshotEdge {
-  /**
-   * @param {!HeapSnapshotWorker.JSHeapSnapshot} snapshot
-   * @param {number=} edgeIndex
-   */
-  constructor(snapshot, edgeIndex) {
-    super(snapshot, edgeIndex);
-  }
-
-  /**
-   * @override
-   * @return {!HeapSnapshotWorker.JSHeapSnapshotEdge}
-   */
-  clone() {
-    var snapshot = /** @type {!HeapSnapshotWorker.JSHeapSnapshot} */ (this._snapshot);
-    return new HeapSnapshotWorker.JSHeapSnapshotEdge(snapshot, this.edgeIndex);
-  }
-
-  /**
-   * @override
-   * @return {boolean}
-   */
-  hasStringName() {
-    if (!this.isShortcut())
-      return this._hasStringName();
-    return isNaN(parseInt(this._name(), 10));
-  }
-
-  /**
-   * @return {boolean}
-   */
-  isElement() {
-    return this.rawType() === this._snapshot._edgeElementType;
-  }
-
-  /**
-   * @return {boolean}
-   */
-  isHidden() {
-    return this.rawType() === this._snapshot._edgeHiddenType;
-  }
-
-  /**
-   * @return {boolean}
-   */
-  isWeak() {
-    return this.rawType() === this._snapshot._edgeWeakType;
-  }
-
-  /**
-   * @return {boolean}
-   */
-  isInternal() {
-    return this.rawType() === this._snapshot._edgeInternalType;
-  }
-
-  /**
-   * @return {boolean}
-   */
-  isInvisible() {
-    return this.rawType() === this._snapshot._edgeInvisibleType;
-  }
-
-  /**
-   * @return {boolean}
-   */
-  isShortcut() {
-    return this.rawType() === this._snapshot._edgeShortcutType;
-  }
-
-  /**
-   * @override
-   * @return {string}
-   */
-  name() {
-    var name = this._name();
-    if (!this.isShortcut())
-      return String(name);
-    var numName = parseInt(name, 10);
-    return String(isNaN(numName) ? name : numName);
-  }
-
-  /**
-   * @override
-   * @return {string}
-   */
-  toString() {
-    var name = this.name();
-    switch (this.type()) {
-      case 'context':
-        return '->' + name;
-      case 'element':
-        return '[' + name + ']';
-      case 'weak':
-        return '[[' + name + ']]';
-      case 'property':
-        return name.indexOf(' ') === -1 ? '.' + name : '["' + name + '"]';
-      case 'shortcut':
-        if (typeof name === 'string')
-          return name.indexOf(' ') === -1 ? '.' + name : '["' + name + '"]';
-        else
-          return '[' + name + ']';
-      case 'internal':
-      case 'hidden':
-      case 'invisible':
-        return '{' + name + '}';
-    }
-    return '?' + name + '?';
-  }
-
-  /**
-   * @return {boolean}
-   */
-  _hasStringName() {
-    var type = this.rawType();
-    var snapshot = this._snapshot;
-    return type !== snapshot._edgeElementType && type !== snapshot._edgeHiddenType;
-  }
-
-  /**
-   * @return {string|number}
-   */
-  _name() {
-    return this._hasStringName() ? this._snapshot.strings[this._nameOrIndex()] : this._nameOrIndex();
-  }
-
-  /**
-   * @return {number}
-   */
-  _nameOrIndex() {
-    return this._edges[this.edgeIndex + this._snapshot._edgeNameOffset];
-  }
-
-  /**
-   * @override
-   * @return {number}
-   */
-  rawType() {
-    return this._edges[this.edgeIndex + this._snapshot._edgeTypeOffset];
-  }
-};
-
-/**
- * @unrestricted
- */
-HeapSnapshotWorker.JSHeapSnapshotRetainerEdge = class extends HeapSnapshotWorker.HeapSnapshotRetainerEdge {
-  /**
-   * @param {!HeapSnapshotWorker.JSHeapSnapshot} snapshot
-   * @param {number} retainerIndex
-   */
-  constructor(snapshot, retainerIndex) {
-    super(snapshot, retainerIndex);
-  }
-
-  /**
-   * @override
-   * @return {!HeapSnapshotWorker.JSHeapSnapshotRetainerEdge}
-   */
-  clone() {
-    var snapshot = /** @type {!HeapSnapshotWorker.JSHeapSnapshot} */ (this._snapshot);
-    return new HeapSnapshotWorker.JSHeapSnapshotRetainerEdge(snapshot, this.retainerIndex());
-  }
-
-  /**
-   * @return {boolean}
-   */
-  isHidden() {
-    return this._edge().isHidden();
-  }
-
-  /**
-   * @return {boolean}
-   */
-  isInternal() {
-    return this._edge().isInternal();
-  }
-
-  /**
-   * @return {boolean}
-   */
-  isInvisible() {
-    return this._edge().isInvisible();
-  }
-
-  /**
-   * @return {boolean}
-   */
-  isShortcut() {
-    return this._edge().isShortcut();
-  }
-
-  /**
-   * @return {boolean}
-   */
-  isWeak() {
-    return this._edge().isWeak();
-  }
-};
diff --git a/third_party/WebKit/Source/devtools/front_end/heap_snapshot_worker/module.json b/third_party/WebKit/Source/devtools/front_end/heap_snapshot_worker/module.json
index 51358cc..3322c42 100644
--- a/third_party/WebKit/Source/devtools/front_end/heap_snapshot_worker/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/heap_snapshot_worker/module.json
@@ -8,7 +8,6 @@
         "HeapSnapshot.js",
         "HeapSnapshotLoader.js",
         "HeapSnapshotWorkerDispatcher.js",
-        "JSHeapSnapshot.js",
         "HeapSnapshotWorker.js"
     ]
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/layer_viewer/TransformController.js b/third_party/WebKit/Source/devtools/front_end/layer_viewer/TransformController.js
index 821e50a..b7e5b80 100644
--- a/third_party/WebKit/Source/devtools/front_end/layer_viewer/TransformController.js
+++ b/third_party/WebKit/Source/devtools/front_end/layer_viewer/TransformController.js
@@ -33,19 +33,20 @@
     this._modeButtons = {};
     if (!disableRotate) {
       var panModeButton = new UI.ToolbarToggle(Common.UIString('Pan mode (X)'), 'largeicon-pan');
-      panModeButton.addEventListener('click', this._setMode.bind(this, LayerViewer.TransformController.Modes.Pan));
+      panModeButton.addEventListener(
+          UI.ToolbarButton.Events.Click, this._setMode.bind(this, LayerViewer.TransformController.Modes.Pan));
       this._modeButtons[LayerViewer.TransformController.Modes.Pan] = panModeButton;
       this._controlPanelToolbar.appendToolbarItem(panModeButton);
       var rotateModeButton = new UI.ToolbarToggle(Common.UIString('Rotate mode (V)'), 'largeicon-rotate');
       rotateModeButton.addEventListener(
-          'click', this._setMode.bind(this, LayerViewer.TransformController.Modes.Rotate));
+          UI.ToolbarButton.Events.Click, this._setMode.bind(this, LayerViewer.TransformController.Modes.Rotate));
       this._modeButtons[LayerViewer.TransformController.Modes.Rotate] = rotateModeButton;
       this._controlPanelToolbar.appendToolbarItem(rotateModeButton);
     }
     this._setMode(LayerViewer.TransformController.Modes.Pan);
 
     var resetButton = new UI.ToolbarButton(Common.UIString('Reset transform (0)'), 'largeicon-center');
-    resetButton.addEventListener('click', this.resetAndNotify.bind(this, undefined));
+    resetButton.addEventListener(UI.ToolbarButton.Events.Click, this.resetAndNotify.bind(this, undefined));
     this._controlPanelToolbar.appendToolbarItem(resetButton);
 
     this._reset();
diff --git a/third_party/WebKit/Source/devtools/front_end/main/Main.js b/third_party/WebKit/Source/devtools/front_end/main/Main.js
index c7e58b5b..5a877b01 100644
--- a/third_party/WebKit/Source/devtools/front_end/main/Main.js
+++ b/third_party/WebKit/Source/devtools/front_end/main/Main.js
@@ -112,6 +112,7 @@
     Runtime.experiments.register('sourceDiff', 'Source diff');
     Runtime.experiments.register('terminalInDrawer', 'Terminal in drawer', true);
     Runtime.experiments.register('timelineInvalidationTracking', 'Timeline invalidation tracking', true);
+    Runtime.experiments.register('timelineLandingPage', 'Timeline landing page', true);
     Runtime.experiments.register('timelineRecordingPerspectives', 'Timeline recording perspectives UI');
     Runtime.experiments.register('timelineTracingJSProfile', 'Timeline tracing based JS profiler', true);
     Runtime.experiments.register('timelineV8RuntimeCallStats', 'V8 Runtime Call Stats on Timeline', true);
@@ -675,7 +676,7 @@
 Main.Main.MainMenuItem = class {
   constructor() {
     this._item = new UI.ToolbarButton(Common.UIString('Customize and control DevTools'), 'largeicon-menu');
-    this._item.addEventListener('mousedown', this._mouseDown, this);
+    this._item.addEventListener(UI.ToolbarButton.Events.MouseDown, this._mouseDown, this);
   }
 
   /**
@@ -707,9 +708,12 @@
       var undock = new UI.ToolbarToggle(Common.UIString('Undock into separate window'), 'largeicon-undock');
       var bottom = new UI.ToolbarToggle(Common.UIString('Dock to bottom'), 'largeicon-dock-to-bottom');
       var right = new UI.ToolbarToggle(Common.UIString('Dock to right'), 'largeicon-dock-to-right');
-      undock.addEventListener('mouseup', setDockSide.bind(null, Components.DockController.State.Undocked));
-      bottom.addEventListener('mouseup', setDockSide.bind(null, Components.DockController.State.DockedToBottom));
-      right.addEventListener('mouseup', setDockSide.bind(null, Components.DockController.State.DockedToRight));
+      undock.addEventListener(
+          UI.ToolbarButton.Events.MouseUp, setDockSide.bind(null, Components.DockController.State.Undocked));
+      bottom.addEventListener(
+          UI.ToolbarButton.Events.MouseUp, setDockSide.bind(null, Components.DockController.State.DockedToBottom));
+      right.addEventListener(
+          UI.ToolbarButton.Events.MouseUp, setDockSide.bind(null, Components.DockController.State.DockedToRight));
       undock.setToggled(Components.dockController.dockSide() === Components.DockController.State.Undocked);
       bottom.setToggled(Components.dockController.dockSide() === Components.DockController.State.DockedToBottom);
       right.setToggled(Components.dockController.dockSide() === Components.DockController.State.DockedToRight);
diff --git a/third_party/WebKit/Source/devtools/front_end/network/BlockedURLsPane.js b/third_party/WebKit/Source/devtools/front_end/network/BlockedURLsPane.js
index 5e3690c..200b2994 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/BlockedURLsPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/network/BlockedURLsPane.js
@@ -18,10 +18,10 @@
     this._toolbar = new UI.Toolbar('', this.contentElement);
     this._toolbar.element.addEventListener('click', (e) => e.consume());
     var addButton = new UI.ToolbarButton(Common.UIString('Add pattern'), 'largeicon-add');
-    addButton.addEventListener('click', this._addButtonClicked.bind(this));
+    addButton.addEventListener(UI.ToolbarButton.Events.Click, this._addButtonClicked, this);
     this._toolbar.appendToolbarItem(addButton);
     var clearButton = new UI.ToolbarButton(Common.UIString('Remove all'), 'largeicon-clear');
-    clearButton.addEventListener('click', this._removeAll.bind(this));
+    clearButton.addEventListener(UI.ToolbarButton.Events.Click, this._removeAll, this);
     this._toolbar.appendToolbarItem(clearButton);
 
     this._emptyElement = this.contentElement.createChild('div', 'no-blocked-urls');
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js
index ebf5b7a0..e62d3fb 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js
+++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js
@@ -287,14 +287,15 @@
 
   /**
    * @override
+   * @param {!Element} element
    */
-  createCells() {
+  createCells(element) {
     this._nameCell = null;
     this._initiatorCell = null;
 
-    this._element.classList.toggle('network-error-row', this._isFailed());
-    this._element.classList.toggle('network-navigation-row', this._isNavigationRequest);
-    super.createCells();
+    element.classList.toggle('network-error-row', this._isFailed());
+    element.classList.toggle('network-navigation-row', this._isNavigationRequest);
+    super.createCells(element);
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkOverview.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkOverview.js
index 017d02c..5b53515 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/NetworkOverview.js
+++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkOverview.js
@@ -19,10 +19,6 @@
     this._restoringWindow = false;
     /** @type {boolean} */
     this._updateScheduled = false;
-    /** @type {number} */
-    this._canvasWidth = 0;
-    /** @type {number} */
-    this._canvasHeight = 0;
 
     SDK.targetManager.addModelListener(
         SDK.ResourceTreeModel, SDK.ResourceTreeModel.Events.Load, this._loadEventFired, this);
@@ -111,7 +107,7 @@
   onResize() {
     var width = this.element.offsetWidth;
     var height = this.element.offsetHeight;
-    this._calculator.setDisplayWindow(width);
+    this.calculator().setDisplayWindow(width);
     this.resetCanvas();
     var numBands = (((height - 1) / Network.NetworkOverview._bandHeight) - 1) | 0;
     this._numBands = (numBands > 0) ? numBands : 1;
@@ -164,27 +160,26 @@
   update() {
     this._updateScheduled = false;
 
-    var newBoundary =
-        new Network.NetworkTimeBoundary(this._calculator.minimumBoundary(), this._calculator.maximumBoundary());
+    var calculator = this.calculator();
+
+    var newBoundary = new Network.NetworkTimeBoundary(calculator.minimumBoundary(), calculator.maximumBoundary());
     if (!this._lastBoundary || !newBoundary.equals(this._lastBoundary)) {
-      var span = this._calculator.boundarySpan();
+      var span = calculator.boundarySpan();
       while (this._span < span)
         this._span *= 1.25;
-      this._calculator.setBounds(this._calculator.minimumBoundary(), this._calculator.minimumBoundary() + this._span);
-      this._lastBoundary =
-          new Network.NetworkTimeBoundary(this._calculator.minimumBoundary(), this._calculator.maximumBoundary());
+      calculator.setBounds(calculator.minimumBoundary(), calculator.minimumBoundary() + this._span);
+      this._lastBoundary = new Network.NetworkTimeBoundary(calculator.minimumBoundary(), calculator.maximumBoundary());
       if (this._windowStart || this._windowEnd) {
         this._restoringWindow = true;
-        var startTime = this._calculator.minimumBoundary();
-        var totalTime = this._calculator.boundarySpan();
+        var startTime = calculator.minimumBoundary();
+        var totalTime = calculator.boundarySpan();
         var left = (this._windowStart - startTime) / totalTime;
         var right = (this._windowEnd - startTime) / totalTime;
         this._restoringWindow = false;
       }
     }
 
-    var context = this._canvas.getContext('2d');
-    var calculator = this._calculator;
+    var context = this.context();
     var linesByType = {};
     var paddingTop = 2;
 
@@ -233,7 +228,7 @@
       var band = this._bandId(request.connectionId);
       var y = (band === -1) ? 0 : (band % this._numBands + 1);
       var timeRanges =
-          Network.RequestTimingView.calculateRequestTimeRanges(request, this._calculator.minimumBoundary());
+          Network.RequestTimingView.calculateRequestTimeRanges(request, this.calculator().minimumBoundary());
       for (var j = 0; j < timeRanges.length; ++j) {
         var type = timeRanges[j].name;
         if (band !== -1 || type === Network.RequestTimeRangeNames.Total)
@@ -241,7 +236,7 @@
       }
     }
 
-    context.clearRect(0, 0, this._canvas.width, this._canvas.height);
+    context.clearRect(0, 0, this.width(), this.height());
     context.save();
     context.scale(window.devicePixelRatio, window.devicePixelRatio);
     context.lineWidth = 2;
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkPanel.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkPanel.js
index 93f2900..2f78bf4c 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/NetworkPanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkPanel.js
@@ -140,7 +140,7 @@
     this._panelToolbar.appendToolbarItem(UI.Toolbar.createActionButton(this._toggleRecordAction));
 
     this._clearButton = new UI.ToolbarButton(Common.UIString('Clear'), 'largeicon-clear');
-    this._clearButton.addEventListener('click', this._onClearButtonClicked, this);
+    this._clearButton.addEventListener(UI.ToolbarButton.Events.Click, this._onClearButtonClicked, this);
     this._panelToolbar.appendToolbarItem(this._clearButton);
     this._panelToolbar.appendSeparator();
     var recordFilmStripButton = new UI.ToolbarSettingToggle(
diff --git a/third_party/WebKit/Source/devtools/front_end/network/ResourceWebSocketFrameView.js b/third_party/WebKit/Source/devtools/front_end/network/ResourceWebSocketFrameView.js
index dc001513..f7a634ae 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/ResourceWebSocketFrameView.js
+++ b/third_party/WebKit/Source/devtools/front_end/network/ResourceWebSocketFrameView.js
@@ -212,15 +212,15 @@
 
   /**
    * @override
+   * @param {!Element} element
    */
-  createCells() {
-    var element = this._element;
+  createCells(element) {
     element.classList.toggle(
         'websocket-frame-view-row-error', this._frame.type === SDK.NetworkRequest.WebSocketFrameType.Error);
     element.classList.toggle(
         'websocket-frame-view-row-outcoming', this._frame.type === SDK.NetworkRequest.WebSocketFrameType.Send);
     element.classList.toggle('websocket-frame-view-row-opcode', !this._isTextFrame);
-    super.createCells();
+    super.createCells(element);
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/BottomUpProfileDataGrid.js b/third_party/WebKit/Source/devtools/front_end/profiler/BottomUpProfileDataGrid.js
index b94e7260..c1752f4 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/BottomUpProfileDataGrid.js
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/BottomUpProfileDataGrid.js
@@ -175,6 +175,7 @@
    */
   constructor(formatter, searchableView, rootProfileNode, total) {
     super(formatter, searchableView, total);
+    this.deepSearch = false;
 
     // Iterate each node in pre-order.
     var profileNodeUIDs = 0;
@@ -291,28 +292,6 @@
 
   /**
    * @override
-   * @param {!UI.SearchableView.SearchConfig} searchConfig
-   * @param {boolean} shouldJump
-   * @param {boolean=} jumpBackwards
-   */
-  performSearch(searchConfig, shouldJump, jumpBackwards) {
-    this.searchCanceled();
-    var matchesQuery = this._matchFunction(searchConfig);
-    if (!matchesQuery)
-      return;
-
-    this._searchResults = [];
-    for (var current = this.children[0]; current; current = current.traverseNextNode(true, null, true)) {
-      if (matchesQuery(current))
-        this._searchResults.push({profileNode: current});
-    }
-    this._searchResultIndex = jumpBackwards ? 0 : this._searchResults.length - 1;
-    this._searchableView.updateSearchMatchesCount(this._searchResults.length);
-    this._searchableView.updateCurrentMatchIndex(this._searchResultIndex);
-  }
-
-  /**
-   * @override
    */
   populateChildren() {
     Profiler.BottomUpProfileDataGridNode._sharedPopulate(this);
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/CPUProfileFlameChart.js b/third_party/WebKit/Source/devtools/front_end/profiler/CPUProfileFlameChart.js
index d489167..7577cb7 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/CPUProfileFlameChart.js
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/CPUProfileFlameChart.js
@@ -33,12 +33,8 @@
  * @unrestricted
  */
 Profiler.ProfileFlameChartDataProvider = class {
-  /**
-   * @param {?SDK.Target} target
-   */
-  constructor(target) {
+  constructor() {
     UI.FlameChartDataProvider.call(this);
-    this._target = target;
     this._colorGenerator = Profiler.ProfileFlameChartDataProvider.colorGenerator();
   }
 
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 010d83c..657eb562 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/CPUProfileView.js
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/CPUProfileView.js
@@ -190,7 +190,7 @@
 
   startRecordingProfile() {
     var target = UI.context.flavor(SDK.Target);
-    if (this._profileBeingRecorded || !target)
+    if (this.profileBeingRecorded() || !target)
       return;
     var profile = new Profiler.CPUProfileHeader(target, this);
     this.setProfileBeingRecorded(profile);
@@ -203,7 +203,7 @@
 
   stopRecordingProfile() {
     this._recording = false;
-    if (!this._profileBeingRecorded || !this._profileBeingRecorded.target())
+    if (!this.profileBeingRecorded() || !this.profileBeingRecorded().target())
       return;
 
     var recordedProfile;
@@ -213,12 +213,12 @@
      * @this {Profiler.CPUProfileType}
      */
     function didStopProfiling(profile) {
-      if (!this._profileBeingRecorded)
+      if (!this.profileBeingRecorded())
         return;
       console.assert(profile);
-      this._profileBeingRecorded.setProtocolProfile(profile);
-      this._profileBeingRecorded.updateStatus('');
-      recordedProfile = this._profileBeingRecorded;
+      this.profileBeingRecorded().setProtocolProfile(profile);
+      this.profileBeingRecorded().updateStatus('');
+      recordedProfile = this.profileBeingRecorded();
       this.setProfileBeingRecorded(null);
     }
 
@@ -229,7 +229,7 @@
       this.dispatchEventToListeners(Profiler.ProfileType.Events.ProfileComplete, recordedProfile);
     }
 
-    this._profileBeingRecorded.target()
+    this.profileBeingRecorded().target()
         .cpuProfilerModel.stopRecording()
         .then(didStopProfiling.bind(this))
         .then(SDK.targetManager.resumeAllTargets.bind(SDK.targetManager))
@@ -332,8 +332,9 @@
    * @param {?SDK.Target} target
    */
   constructor(cpuProfile, target) {
-    super(target);
+    super();
     this._cpuProfile = cpuProfile;
+    this._target = target;
   }
 
   /**
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 e10fb662..bcfb271a 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/HeapProfileView.js
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/HeapProfileView.js
@@ -97,7 +97,7 @@
 
   startRecordingProfile() {
     var target = UI.context.flavor(SDK.Target);
-    if (this._profileBeingRecorded || !target)
+    if (this.profileBeingRecorded() || !target)
       return;
     var profile = new Profiler.SamplingHeapProfileHeader(target, this);
     this.setProfileBeingRecorded(profile);
@@ -110,7 +110,7 @@
 
   stopRecordingProfile() {
     this._recording = false;
-    if (!this._profileBeingRecorded || !this._profileBeingRecorded.target())
+    if (!this.profileBeingRecorded() || !this.profileBeingRecorded().target())
       return;
 
     var recordedProfile;
@@ -120,12 +120,12 @@
      * @this {Profiler.SamplingHeapProfileType}
      */
     function didStopProfiling(profile) {
-      if (!this._profileBeingRecorded)
+      if (!this.profileBeingRecorded())
         return;
       console.assert(profile);
-      this._profileBeingRecorded.setProtocolProfile(profile);
-      this._profileBeingRecorded.updateStatus('');
-      recordedProfile = this._profileBeingRecorded;
+      this.profileBeingRecorded().setProtocolProfile(profile);
+      this.profileBeingRecorded().updateStatus('');
+      recordedProfile = this.profileBeingRecorded();
       this.setProfileBeingRecorded(null);
     }
 
@@ -136,7 +136,7 @@
       this.dispatchEventToListeners(Profiler.ProfileType.Events.ProfileComplete, recordedProfile);
     }
 
-    this._profileBeingRecorded.target()
+    this.profileBeingRecorded().target()
         .heapProfilerModel.stopSampling()
         .then(didStopProfiling.bind(this))
         .then(SDK.targetManager.resumeAllTargets.bind(SDK.targetManager))
@@ -294,8 +294,9 @@
    * @param {?SDK.Target} target
    */
   constructor(profile, target) {
-    super(target);
+    super();
     this._profile = profile;
+    this._target = target;
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotProxy.js b/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotProxy.js
index a6ab8de1..0005305 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotProxy.js
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotProxy.js
@@ -157,7 +157,7 @@
         this._previousCallbacks.delete(callId);
     }
     var hasLongRunningCalls = !!this._previousCallbacks.size;
-    this.dispatchEventToListeners('wait', hasLongRunningCalls);
+    this.dispatchEventToListeners(Profiler.HeapSnapshotWorkerProxy.Events.Wait, hasLongRunningCalls);
     for (var callId of this._callbacks.keysArray())
       this._previousCallbacks.add(callId);
   }
@@ -193,6 +193,10 @@
   }
 };
 
+Profiler.HeapSnapshotWorkerProxy.Events = {
+  Wait: Symbol('Wait')
+};
+
 /**
  * @unrestricted
  */
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotView.js b/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotView.js
index 11f37c8..0c66cf8 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotView.js
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotView.js
@@ -1036,7 +1036,7 @@
      * @this {Profiler.HeapSnapshotProfileType}
      */
     function didTakeHeapSnapshot(error) {
-      var profile = this._profileBeingRecorded;
+      var profile = this.profileBeingRecorded();
       profile.title = Common.UIString('Snapshot %d', profile.uid);
       profile._finishLoad();
       this.setProfileBeingRecorded(null);
@@ -1070,11 +1070,11 @@
   }
 
   _resetProfiles() {
-    this._reset();
+    this.reset();
   }
 
   _snapshotReceived(profile) {
-    if (this._profileBeingRecorded === profile)
+    if (this.profileBeingRecorded() === profile)
       this.setProfileBeingRecorded(null);
     this.dispatchEventToListeners(Profiler.HeapSnapshotProfileType.SnapshotReceived, profile);
   }
@@ -1150,7 +1150,7 @@
     if (profileSamples.totalTime < data.timestamp - profileSamples.timestamps[0])
       profileSamples.totalTime *= 2;
     this.dispatchEventToListeners(Profiler.TrackingHeapSnapshotProfileType.HeapStatsUpdate, this._profileSamples);
-    this._profileBeingRecorded.updateStatus(null, true);
+    this.profileBeingRecorded().updateStatus(null, true);
   }
 
   /**
@@ -1194,15 +1194,15 @@
     var target = UI.context.flavor(SDK.Target);
     this.setProfileBeingRecorded(new Profiler.HeapProfileHeader(target, this, undefined));
     this._profileSamples = new Profiler.TrackingHeapSnapshotProfileType.Samples();
-    this._profileBeingRecorded._profileSamples = this._profileSamples;
+    this.profileBeingRecorded()._profileSamples = this._profileSamples;
     this._recording = true;
-    this.addProfile(this._profileBeingRecorded);
-    this._profileBeingRecorded.updateStatus(Common.UIString('Recording\u2026'));
+    this.addProfile(/** @type {!Profiler.ProfileHeader} */ (this.profileBeingRecorded()));
+    this.profileBeingRecorded().updateStatus(Common.UIString('Recording\u2026'));
     this.dispatchEventToListeners(Profiler.TrackingHeapSnapshotProfileType.TrackingStarted);
   }
 
   _stopRecordingProfile() {
-    this._profileBeingRecorded.updateStatus(Common.UIString('Snapshotting\u2026'));
+    this.profileBeingRecorded().updateStatus(Common.UIString('Snapshotting\u2026'));
     /**
      * @param {?string} error
      * @this {Profiler.HeapSnapshotProfileType}
@@ -1217,7 +1217,7 @@
       this.dispatchEventToListeners(Profiler.ProfileType.Events.ProfileComplete, profile);
     }
 
-    this._profileBeingRecorded.target().heapProfilerAgent().stopTrackingHeapObjects(
+    this.profileBeingRecorded().target().heapProfilerAgent().stopTrackingHeapObjects(
         true, didTakeHeapSnapshot.bind(this));
     this._recording = false;
     this.dispatchEventToListeners(Profiler.TrackingHeapSnapshotProfileType.TrackingStopped);
@@ -1391,7 +1391,7 @@
     }
     console.assert(!this._workerProxy, 'HeapSnapshotWorkerProxy already exists');
     this._workerProxy = new Profiler.HeapSnapshotWorkerProxy(this._handleWorkerEvent.bind(this));
-    this._workerProxy.addEventListener('wait', setProfileWait, this);
+    this._workerProxy.addEventListener(Profiler.HeapSnapshotWorkerProxy.Events.Wait, setProfileWait, this);
     this._receiver = this._workerProxy.createLoader(this.uid, this._snapshotReceived.bind(this));
   }
 
@@ -1453,7 +1453,7 @@
 
   notifySnapshotReceived() {
     this._fulfillLoad(this._snapshotProxy);
-    this._profileType._snapshotReceived(this);
+    this.profileType()._snapshotReceived(this);
     if (this.canSaveToFile())
       this.dispatchEventToListeners(Profiler.ProfileHeader.Events.ProfileReceived);
   }
@@ -1494,7 +1494,7 @@
         this._updateSaveProgress(0, 1);
       }
     }
-    this._fileName = this._fileName || 'Heap-' + new Date().toISO8601Compact() + this._profileType.fileExtension();
+    this._fileName = this._fileName || 'Heap-' + new Date().toISO8601Compact() + this.profileType().fileExtension();
     fileOutputStream.open(this._fileName, onOpen.bind(this));
   }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/ProfileDataGrid.js b/third_party/WebKit/Source/devtools/front_end/profiler/ProfileDataGrid.js
index 9c50155..bd6cb3f 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/ProfileDataGrid.js
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/ProfileDataGrid.js
@@ -332,6 +332,7 @@
     this.total = total;
     this.lastComparator = null;
     this.childrenByCallUID = new Map();
+    this.deepSearch = true;
   }
 
   /**
@@ -547,7 +548,8 @@
       return;
 
     this._searchResults = [];
-    for (var current = this.children[0]; current; current = current.traverseNextNode(false, null, false)) {
+    const deepSearch = this.deepSearch;
+    for (var current = this.children[0]; current; current = current.traverseNextNode(!deepSearch, null, !deepSearch)) {
       if (matchesQuery(current))
         this._searchResults.push({profileNode: current});
     }
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/ProfileView.js b/third_party/WebKit/Source/devtools/front_end/profiler/ProfileView.js
index c30218d..e4d927c 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/ProfileView.js
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/ProfileView.js
@@ -34,15 +34,15 @@
 
     this.focusButton = new UI.ToolbarButton(Common.UIString('Focus selected function'), 'largeicon-visibility');
     this.focusButton.setEnabled(false);
-    this.focusButton.addEventListener('click', this._focusClicked, this);
+    this.focusButton.addEventListener(UI.ToolbarButton.Events.Click, this._focusClicked, this);
 
     this.excludeButton = new UI.ToolbarButton(Common.UIString('Exclude selected function'), 'largeicon-delete');
     this.excludeButton.setEnabled(false);
-    this.excludeButton.addEventListener('click', this._excludeClicked, this);
+    this.excludeButton.addEventListener(UI.ToolbarButton.Events.Click, this._excludeClicked, this);
 
     this.resetButton = new UI.ToolbarButton(Common.UIString('Restore all functions'), 'largeicon-refresh');
     this.resetButton.setEnabled(false);
-    this.resetButton.addEventListener('click', this._resetClicked, this);
+    this.resetButton.addEventListener(UI.ToolbarButton.Events.Click, this._resetClicked, this);
 
     this._linkifier = new Components.Linkifier(Profiler.ProfileView._maxLinkLength);
   }
@@ -325,6 +325,9 @@
     this.excludeButton.setEnabled(selected);
   }
 
+  /**
+   * @param {!Common.Event} event
+   */
   _focusClicked(event) {
     if (!this.dataGrid.selectedNode)
       return;
@@ -335,6 +338,9 @@
     this.refreshVisibleData();
   }
 
+  /**
+   * @param {!Common.Event} event
+   */
   _excludeClicked(event) {
     var selectedNode = this.dataGrid.selectedNode;
 
@@ -349,6 +355,9 @@
     this.refreshVisibleData();
   }
 
+  /**
+   * @param {!Common.Event} event
+   */
   _resetClicked(event) {
     this.resetButton.setEnabled(false);
     this.profileDataGridTree.restore();
@@ -419,8 +428,8 @@
     this._jsonifiedProfile = null;
     this.updateStatus(Common.UIString('Loaded'), false);
 
-    if (this._profileType.profileBeingRecorded() === this)
-      this._profileType.setProfileBeingRecorded(null);
+    if (this.profileType().profileBeingRecorded() === this)
+      this.profileType().setProfileBeingRecorded(null);
   }
 
   /**
@@ -512,7 +521,7 @@
       }
     }
     this._fileName = this._fileName ||
-        `${this._profileType.typeName()}-${new Date().toISO8601Compact()}${this._profileType.fileExtension()}`;
+        `${this.profileType().typeName()}-${new Date().toISO8601Compact()}${this.profileType().fileExtension()}`;
     fileOutputStream.open(this._fileName, onOpenForSave.bind(this));
   }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/ProfilesPanel.js b/third_party/WebKit/Source/devtools/front_end/profiler/ProfilesPanel.js
index d30c0f9..96d66d1 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/ProfilesPanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/ProfilesPanel.js
@@ -220,12 +220,9 @@
   profileBeingRecordedRemoved() {
   }
 
-  _reset() {
-    var profiles = this._profiles.slice(0);
-    for (var i = 0; i < profiles.length; ++i)
-      this._disposeProfile(profiles[i]);
+  reset() {
+    this._profiles.slice(0).forEach(this._disposeProfile.bind(this));
     this._profiles = [];
-
     this._nextProfileUid = 1;
   }
 
@@ -429,7 +426,7 @@
     toolbar.appendToolbarItem(this._toggleRecordButton);
 
     this.clearResultsButton = new UI.ToolbarButton(Common.UIString('Clear all profiles'), 'largeicon-clear');
-    this.clearResultsButton.addEventListener('click', this._reset, this);
+    this.clearResultsButton.addEventListener(UI.ToolbarButton.Events.Click, this._reset, this);
     toolbar.appendToolbarItem(this.clearResultsButton);
     toolbar.appendSeparator();
     toolbar.appendToolbarItem(
@@ -598,9 +595,7 @@
   }
 
   _reset() {
-    var types = Profiler.ProfileTypeRegistry.instance.profileTypes();
-    for (var i = 0; i < types.length; i++)
-      types[i]._reset();
+    Profiler.ProfileTypeRegistry.instance.profileTypes().forEach(type => type.reset());
 
     delete this.visibleView;
 
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/AppManifestView.js b/third_party/WebKit/Source/devtools/front_end/resources/AppManifestView.js
index 97f7c84..c99bed20c 100644
--- a/third_party/WebKit/Source/devtools/front_end/resources/AppManifestView.js
+++ b/third_party/WebKit/Source/devtools/front_end/resources/AppManifestView.js
@@ -19,7 +19,7 @@
     toolbar.renderAsLinks();
     var addToHomeScreen =
         new UI.ToolbarButton(Common.UIString('Add to homescreen'), undefined, Common.UIString('Add to homescreen'));
-    addToHomeScreen.addEventListener('click', this._addToHomescreen.bind(this));
+    addToHomeScreen.addEventListener(UI.ToolbarButton.Events.Click, this._addToHomescreen, this);
     toolbar.appendToolbarItem(addToHomeScreen);
 
     this._presentationSection = this._reportView.appendSection(Common.UIString('Presentation'));
@@ -136,7 +136,10 @@
     }
   }
 
-  _addToHomescreen() {
+  /**
+   * @param {!Common.Event} event
+   */
+  _addToHomescreen(event) {
     var target = SDK.targetManager.mainTarget();
     if (target && target.hasBrowserCapability()) {
       target.pageAgent().requestAppBanner();
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/ApplicationCacheItemsView.js b/third_party/WebKit/Source/devtools/front_end/resources/ApplicationCacheItemsView.js
index fbe91d08..f154fd65 100644
--- a/third_party/WebKit/Source/devtools/front_end/resources/ApplicationCacheItemsView.js
+++ b/third_party/WebKit/Source/devtools/front_end/resources/ApplicationCacheItemsView.js
@@ -36,7 +36,7 @@
 
     this._deleteButton = new UI.ToolbarButton(Common.UIString('Delete'), 'largeicon-delete');
     this._deleteButton.setVisible(false);
-    this._deleteButton.addEventListener('click', this._deleteButtonClicked, this);
+    this._deleteButton.addEventListener(UI.ToolbarButton.Events.Click, this._deleteButtonClicked, this);
 
     this._connectivityIcon = createElement('label', 'dt-icon-label');
     this._connectivityIcon.style.margin = '0 2px 0 5px';
@@ -239,6 +239,9 @@
       this._dataGrid.rootNode().children[0].selected = true;
   }
 
+  /**
+   * @param {!Common.Event} event
+   */
   _deleteButtonClicked(event) {
     if (!this._dataGrid || !this._dataGrid.selectedNode)
       return;
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/CookieItemsView.js b/third_party/WebKit/Source/devtools/front_end/resources/CookieItemsView.js
index c334644..42c424c 100644
--- a/third_party/WebKit/Source/devtools/front_end/resources/CookieItemsView.js
+++ b/third_party/WebKit/Source/devtools/front_end/resources/CookieItemsView.js
@@ -38,14 +38,14 @@
 
     this._deleteButton = new UI.ToolbarButton(Common.UIString('Delete'), 'largeicon-delete');
     this._deleteButton.setVisible(false);
-    this._deleteButton.addEventListener('click', this._deleteButtonClicked, this);
+    this._deleteButton.addEventListener(UI.ToolbarButton.Events.Click, this._deleteButtonClicked, this);
 
     this._clearButton = new UI.ToolbarButton(Common.UIString('Clear'), 'largeicon-clear');
     this._clearButton.setVisible(false);
-    this._clearButton.addEventListener('click', this._clearButtonClicked, this);
+    this._clearButton.addEventListener(UI.ToolbarButton.Events.Click, this._clearButtonClicked, this);
 
     this._refreshButton = new UI.ToolbarButton(Common.UIString('Refresh'), 'largeicon-refresh');
-    this._refreshButton.addEventListener('click', this._refreshButtonClicked, this);
+    this._refreshButton.addEventListener(UI.ToolbarButton.Events.Click, this._refreshButtonClicked, this);
 
     this._treeElement = treeElement;
     this._cookieDomain = cookieDomain;
@@ -156,7 +156,10 @@
     this._update();
   }
 
-  _clearButtonClicked() {
+  /**
+   * @param {!Common.Event} event
+   */
+  _clearButtonClicked(event) {
     this.clear();
   }
 
@@ -164,7 +167,10 @@
     this._deleteButton.setVisible(true);
   }
 
-  _deleteButtonClicked() {
+  /**
+   * @param {!Common.Event} event
+   */
+  _deleteButtonClicked(event) {
     var selectedCookie = this._cookiesTable.selectedCookie();
     if (selectedCookie) {
       selectedCookie.remove();
@@ -172,6 +178,9 @@
     }
   }
 
+  /**
+   * @param {!Common.Event} event
+   */
   _refreshButtonClicked(event) {
     this._update();
   }
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/DOMStorageItemsView.js b/third_party/WebKit/Source/devtools/front_end/resources/DOMStorageItemsView.js
index 303f117..f4814b0 100644
--- a/third_party/WebKit/Source/devtools/front_end/resources/DOMStorageItemsView.js
+++ b/third_party/WebKit/Source/devtools/front_end/resources/DOMStorageItemsView.js
@@ -37,10 +37,10 @@
 
     this.deleteButton = new UI.ToolbarButton(Common.UIString('Delete'), 'largeicon-delete');
     this.deleteButton.setVisible(false);
-    this.deleteButton.addEventListener('click', this._deleteButtonClicked, this);
+    this.deleteButton.addEventListener(UI.ToolbarButton.Events.Click, this._deleteButtonClicked, this);
 
     this.refreshButton = new UI.ToolbarButton(Common.UIString('Refresh'), 'largeicon-refresh');
-    this.refreshButton.addEventListener('click', this._refreshButtonClicked, this);
+    this.refreshButton.addEventListener(UI.ToolbarButton.Events.Click, this._refreshButtonClicked, this);
 
     this.domStorage.addEventListener(
         Resources.DOMStorage.Events.DOMStorageItemsCleared, this._domStorageItemsCleared, this);
@@ -83,7 +83,6 @@
     this._dataGrid.rootNode().removeChildren();
     this._dataGrid.addCreationNode(false);
     this.deleteButton.setVisible(false);
-    event.consume(true);
   }
 
   /**
@@ -97,8 +96,6 @@
     var rootNode = this._dataGrid.rootNode();
     var children = rootNode.children;
 
-    event.consume(true);
-
     for (var i = 0; i < children.length; ++i) {
       var childNode = children[i];
       if (childNode.data.key === storageData.key) {
@@ -120,7 +117,6 @@
     var rootNode = this._dataGrid.rootNode();
     var children = rootNode.children;
 
-    event.consume(true);
     this.deleteButton.setVisible(true);
 
     for (var i = 0; i < children.length; ++i) {
@@ -143,8 +139,6 @@
     var rootNode = this._dataGrid.rootNode();
     var children = rootNode.children;
 
-    event.consume(true);
-
     var keyFound = false;
     for (var i = 0; i < children.length; ++i) {
       var childNode = children[i];
@@ -209,6 +203,9 @@
     return dataGrid;
   }
 
+  /**
+   * @param {!Common.Event} event
+   */
   _deleteButtonClicked(event) {
     if (!this._dataGrid || !this._dataGrid.selectedNode)
       return;
@@ -216,6 +213,9 @@
     this._deleteCallback(this._dataGrid.selectedNode);
   }
 
+  /**
+   * @param {!Common.Event} event
+   */
   _refreshButtonClicked(event) {
     this._update();
   }
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/DatabaseTableView.js b/third_party/WebKit/Source/devtools/front_end/resources/DatabaseTableView.js
index 6b98450e..ce6f2629 100644
--- a/third_party/WebKit/Source/devtools/front_end/resources/DatabaseTableView.js
+++ b/third_party/WebKit/Source/devtools/front_end/resources/DatabaseTableView.js
@@ -38,7 +38,7 @@
     this._visibleColumnsSetting = Common.settings.createSetting('databaseTableViewVisibleColumns', {});
 
     this.refreshButton = new UI.ToolbarButton(Common.UIString('Refresh'), 'largeicon-refresh');
-    this.refreshButton.addEventListener('click', this._refreshButtonClicked, this);
+    this.refreshButton.addEventListener(UI.ToolbarButton.Events.Click, this._refreshButtonClicked, this);
     this._visibleColumnsInput = new UI.ToolbarInput(Common.UIString('Visible columns'), 1);
     this._visibleColumnsInput.addEventListener(UI.ToolbarInput.Event.TextChanged, this._onVisibleColumnsChanged, this);
   }
@@ -134,6 +134,9 @@
     this.element.appendChild(errorMsgElement);
   }
 
+  /**
+   * @param {!Common.Event} event
+   */
   _refreshButtonClicked(event) {
     this.update();
   }
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/IndexedDBViews.js b/third_party/WebKit/Source/devtools/front_end/resources/IndexedDBViews.js
index 0b4a589..b68d654 100644
--- a/third_party/WebKit/Source/devtools/front_end/resources/IndexedDBViews.js
+++ b/third_party/WebKit/Source/devtools/front_end/resources/IndexedDBViews.js
@@ -99,10 +99,10 @@
     this._createEditorToolbar();
 
     this._refreshButton = new UI.ToolbarButton(Common.UIString('Refresh'), 'largeicon-refresh');
-    this._refreshButton.addEventListener('click', this._refreshButtonClicked, this);
+    this._refreshButton.addEventListener(UI.ToolbarButton.Events.Click, this._refreshButtonClicked, this);
 
     this._clearButton = new UI.ToolbarButton(Common.UIString('Clear object store'), 'largeicon-clear');
-    this._clearButton.addEventListener('click', this._clearButtonClicked, this);
+    this._clearButton.addEventListener(UI.ToolbarButton.Events.Click, this._clearButtonClicked, this);
 
     this._pageSize = 50;
     this._skipCount = 0;
@@ -179,12 +179,12 @@
     var editorToolbar = new UI.Toolbar('data-view-toolbar', this.element);
 
     this._pageBackButton = new UI.ToolbarButton(Common.UIString('Show previous page'), 'largeicon-play-back');
-    this._pageBackButton.addEventListener('click', this._pageBackButtonClicked, this);
+    this._pageBackButton.addEventListener(UI.ToolbarButton.Events.Click, this._pageBackButtonClicked, this);
     editorToolbar.appendToolbarItem(this._pageBackButton);
 
     this._pageForwardButton = new UI.ToolbarButton(Common.UIString('Show next page'), 'largeicon-play');
     this._pageForwardButton.setEnabled(false);
-    this._pageForwardButton.addEventListener('click', this._pageForwardButtonClicked, this);
+    this._pageForwardButton.addEventListener(UI.ToolbarButton.Events.Click, this._pageForwardButtonClicked, this);
     editorToolbar.appendToolbarItem(this._pageForwardButton);
 
     this._keyInputElement = editorToolbar.element.createChild('input', 'key-input');
@@ -195,12 +195,18 @@
     this._keyInputElement.addEventListener('keydown', this._keyInputChanged.bind(this), false);
   }
 
-  _pageBackButtonClicked() {
+  /**
+   * @param {!Common.Event} event
+   */
+  _pageBackButtonClicked(event) {
     this._skipCount = Math.max(0, this._skipCount - this._pageSize);
     this._updateData(false);
   }
 
-  _pageForwardButtonClicked() {
+  /**
+   * @param {!Common.Event} event
+   */
+  _pageForwardButtonClicked(event) {
     this._skipCount = this._skipCount + this._pageSize;
     this._updateData(false);
   }
@@ -295,10 +301,16 @@
     }
   }
 
+  /**
+   * @param {!Common.Event} event
+   */
   _refreshButtonClicked(event) {
     this._updateData(true);
   }
 
+  /**
+   * @param {!Common.Event} event
+   */
   _clearButtonClicked(event) {
     /**
      * @this {Resources.IDBDataView}
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/ServiceWorkerCacheViews.js b/third_party/WebKit/Source/devtools/front_end/resources/ServiceWorkerCacheViews.js
index d688bee..40124cf 100644
--- a/third_party/WebKit/Source/devtools/front_end/resources/ServiceWorkerCacheViews.js
+++ b/third_party/WebKit/Source/devtools/front_end/resources/ServiceWorkerCacheViews.js
@@ -21,7 +21,7 @@
     this._createEditorToolbar();
 
     this._refreshButton = new UI.ToolbarButton(Common.UIString('Refresh'), 'largeicon-refresh');
-    this._refreshButton.addEventListener('click', this._refreshButtonClicked, this);
+    this._refreshButton.addEventListener(UI.ToolbarButton.Events.Click, this._refreshButtonClicked, this);
 
     this._pageSize = 50;
     this._skipCount = 0;
@@ -45,21 +45,27 @@
     var editorToolbar = new UI.Toolbar('data-view-toolbar', this.element);
 
     this._pageBackButton = new UI.ToolbarButton(Common.UIString('Show previous page'), 'largeicon-play-back');
-    this._pageBackButton.addEventListener('click', this._pageBackButtonClicked, this);
+    this._pageBackButton.addEventListener(UI.ToolbarButton.Events.Click, this._pageBackButtonClicked, this);
     editorToolbar.appendToolbarItem(this._pageBackButton);
 
     this._pageForwardButton = new UI.ToolbarButton(Common.UIString('Show next page'), 'largeicon-play');
     this._pageForwardButton.setEnabled(false);
-    this._pageForwardButton.addEventListener('click', this._pageForwardButtonClicked, this);
+    this._pageForwardButton.addEventListener(UI.ToolbarButton.Events.Click, this._pageForwardButtonClicked, this);
     editorToolbar.appendToolbarItem(this._pageForwardButton);
   }
 
-  _pageBackButtonClicked() {
+  /**
+   * @param {!Common.Event} event
+   */
+  _pageBackButtonClicked(event) {
     this._skipCount = Math.max(0, this._skipCount - this._pageSize);
     this._updateData(false);
   }
 
-  _pageForwardButtonClicked() {
+  /**
+   * @param {!Common.Event} event
+   */
+  _pageForwardButtonClicked(event) {
     this._skipCount = this._skipCount + this._pageSize;
     this._updateData(false);
   }
@@ -128,6 +134,9 @@
     this._model.loadCacheData(this._cache, skipCount, pageSize, this._updateDataCallback.bind(this, skipCount));
   }
 
+  /**
+   * @param {!Common.Event} event
+   */
   _refreshButtonClicked(event) {
     this._updateData(true);
   }
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/ServiceWorkersView.js b/third_party/WebKit/Source/devtools/front_end/resources/ServiceWorkersView.js
index c7ca8771..bbd952e1 100644
--- a/third_party/WebKit/Source/devtools/front_end/resources/ServiceWorkersView.js
+++ b/third_party/WebKit/Source/devtools/front_end/resources/ServiceWorkersView.js
@@ -154,18 +154,18 @@
     this._toolbar = section.createToolbar();
     this._toolbar.renderAsLinks();
     this._updateButton = new UI.ToolbarButton(Common.UIString('Update'), undefined, Common.UIString('Update'));
-    this._updateButton.addEventListener('click', this._updateButtonClicked.bind(this));
+    this._updateButton.addEventListener(UI.ToolbarButton.Events.Click, this._updateButtonClicked, this);
     this._toolbar.appendToolbarItem(this._updateButton);
     this._pushButton = new UI.ToolbarButton(Common.UIString('Emulate push event'), undefined, Common.UIString('Push'));
-    this._pushButton.addEventListener('click', this._pushButtonClicked.bind(this));
+    this._pushButton.addEventListener(UI.ToolbarButton.Events.Click, this._pushButtonClicked, this);
     this._toolbar.appendToolbarItem(this._pushButton);
     this._syncButton =
         new UI.ToolbarButton(Common.UIString('Emulate background sync event'), undefined, Common.UIString('Sync'));
-    this._syncButton.addEventListener('click', this._syncButtonClicked.bind(this));
+    this._syncButton.addEventListener(UI.ToolbarButton.Events.Click, this._syncButtonClicked, this);
     this._toolbar.appendToolbarItem(this._syncButton);
     this._deleteButton =
         new UI.ToolbarButton(Common.UIString('Unregister service worker'), undefined, Common.UIString('Unregister'));
-    this._deleteButton.addEventListener('click', this._unregisterButtonClicked.bind(this));
+    this._deleteButton.addEventListener(UI.ToolbarButton.Events.Click, this._unregisterButtonClicked, this);
     this._toolbar.appendToolbarItem(this._deleteButton);
 
     // Preserve the order.
@@ -318,20 +318,32 @@
     message.appendChild(createLabel('#' + error.versionId + ': ' + error.errorMessage, 'smallicon-error'));
   }
 
-  _unregisterButtonClicked() {
+  /**
+   * @param {!Common.Event} event
+   */
+  _unregisterButtonClicked(event) {
     this._manager.deleteRegistration(this._registration.id);
   }
 
-  _updateButtonClicked() {
+  /**
+   * @param {!Common.Event} event
+   */
+  _updateButtonClicked(event) {
     this._manager.updateRegistration(this._registration.id);
   }
 
-  _pushButtonClicked() {
+  /**
+   * @param {!Common.Event} event
+   */
+  _pushButtonClicked(event) {
     var data = 'Test push message from DevTools.';
     this._manager.deliverPushMessage(this._registration.id, data);
   }
 
-  _syncButtonClicked() {
+  /**
+   * @param {!Common.Event} event
+   */
+  _syncButtonClicked(event) {
     var tag = 'test-tag-from-devtools';
     var lastChance = true;
     this._manager.dispatchSyncEvent(this._registration.id, tag, lastChance);
diff --git a/third_party/WebKit/Source/devtools/front_end/screencast/ScreencastApp.js b/third_party/WebKit/Source/devtools/front_end/screencast/ScreencastApp.js
index 25f1ac0..6946291 100644
--- a/third_party/WebKit/Source/devtools/front_end/screencast/ScreencastApp.js
+++ b/third_party/WebKit/Source/devtools/front_end/screencast/ScreencastApp.js
@@ -11,7 +11,7 @@
     this._enabledSetting = Common.settings.createSetting('screencastEnabled', true);
     this._toggleButton = new UI.ToolbarToggle(Common.UIString('Toggle screencast'), 'largeicon-phone');
     this._toggleButton.setToggled(this._enabledSetting.get());
-    this._toggleButton.addEventListener('click', this._toggleButtonClicked, this);
+    this._toggleButton.addEventListener(UI.ToolbarButton.Events.Click, this._toggleButtonClicked, this);
     SDK.targetManager.observeTargets(this);
   }
 
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 60fcf43..4c0c485 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js
@@ -411,8 +411,8 @@
     this._isPausing = false;
     this._debuggerPausedDetails = debuggerPausedDetails;
     if (this._debuggerPausedDetails) {
-      if (Runtime.experiments.isEnabled('emptySourceMapAutoStepping')) {
-        if (this.dispatchEventToListeners(SDK.DebuggerModel.Events.BeforeDebuggerPaused, this._debuggerPausedDetails))
+      if (Runtime.experiments.isEnabled('emptySourceMapAutoStepping') && this._beforePausedCallback) {
+        if (!this._beforePausedCallback.call(null, this._debuggerPausedDetails))
           return false;
       }
       this.dispatchEventToListeners(SDK.DebuggerModel.Events.DebuggerPaused, this._debuggerPausedDetails);
@@ -425,6 +425,13 @@
   }
 
   /**
+   * @param {?function(!SDK.DebuggerPausedDetails):boolean} callback
+   */
+  setBeforePausedCallback(callback) {
+    this._beforePausedCallback = callback;
+  }
+
+  /**
    * @param {!Array.<!Protocol.Debugger.CallFrame>} callFrames
    * @param {string} reason
    * @param {!Object|undefined} auxData
@@ -807,7 +814,6 @@
 SDK.DebuggerModel.Events = {
   DebuggerWasEnabled: Symbol('DebuggerWasEnabled'),
   DebuggerWasDisabled: Symbol('DebuggerWasDisabled'),
-  BeforeDebuggerPaused: Symbol('BeforeDebuggerPaused'),
   DebuggerPaused: Symbol('DebuggerPaused'),
   DebuggerResumed: Symbol('DebuggerResumed'),
   ParsedScriptSource: Symbol('ParsedScriptSource'),
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/InspectorBackend.js b/third_party/WebKit/Source/devtools/front_end/sdk/InspectorBackend.js
index 3b03735e..d9bef3c 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/InspectorBackend.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/InspectorBackend.js
@@ -175,7 +175,7 @@
   }
 };
 
-InspectorBackendClass._DevToolsErrorCode = -32000;
+InspectorBackendClass._ConnectionClosedErrorCode = -32000;
 InspectorBackendClass.DevToolsStubErrorCode = -32015;
 
 
@@ -457,7 +457,7 @@
   _dispatchConnectionErrorResponse(domain, methodName, callback) {
     var error = {
       message: 'Connection is closed, can\'t dispatch pending ' + methodName,
-      code: InspectorBackendClass._DevToolsErrorCode,
+      code: InspectorBackendClass._ConnectionClosedErrorCode,
       data: null
     };
     var messageObject = {error: error};
@@ -634,7 +634,7 @@
    * @param {function(*)|function(?Protocol.Error, ?Object)} callback
    */
   dispatchResponse(messageObject, methodName, callback) {
-    if (messageObject.error && messageObject.error.code !== InspectorBackendClass._DevToolsErrorCode &&
+    if (messageObject.error && messageObject.error.code !== InspectorBackendClass._ConnectionClosedErrorCode &&
         messageObject.error.code !== InspectorBackendClass.DevToolsStubErrorCode &&
         !InspectorBackendClass.Options.suppressRequestErrors) {
       var id = InspectorBackendClass.Options.dumpInspectorProtocolMessages ? ' with id = ' + messageObject.id : '';
diff --git a/third_party/WebKit/Source/devtools/front_end/settings/SettingsScreen.js b/third_party/WebKit/Source/devtools/front_end/settings/SettingsScreen.js
index 85c68583..37d4a3b 100644
--- a/third_party/WebKit/Source/devtools/front_end/settings/SettingsScreen.js
+++ b/third_party/WebKit/Source/devtools/front_end/settings/SettingsScreen.js
@@ -368,7 +368,7 @@
 
     var toolbar = new UI.Toolbar('');
     var button = new UI.ToolbarButton(Common.UIString('Remove'), 'largeicon-delete');
-    button.addEventListener('click', this._removeFileSystemClicked.bind(this, fileSystem));
+    button.addEventListener(UI.ToolbarButton.Events.Click, this._removeFileSystemClicked.bind(this, fileSystem));
     toolbar.appendToolbarItem(button);
     header.appendChild(toolbar.element);
 
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/InplaceFormatterEditorAction.js b/third_party/WebKit/Source/devtools/front_end/sources/InplaceFormatterEditorAction.js
index 7e8a6aa85..036a6fc8e 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/InplaceFormatterEditorAction.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/InplaceFormatterEditorAction.js
@@ -44,7 +44,7 @@
     this._sourcesView.addEventListener(Sources.SourcesView.Events.EditorClosed, this._editorClosed.bind(this));
 
     this._button = new UI.ToolbarButton(Common.UIString('Format'), 'largeicon-pretty-print');
-    this._button.addEventListener('click', this._formatSourceInPlace, this);
+    this._button.addEventListener(UI.ToolbarButton.Events.Click, this._formatSourceInPlace, this);
     this._updateButton(sourcesView.currentUISourceCode());
 
     return this._button;
@@ -64,7 +64,10 @@
     return uiSourceCode.contentType().isStyleSheet();
   }
 
-  _formatSourceInPlace() {
+  /**
+   * @param {!Common.Event} event
+   */
+  _formatSourceInPlace(event) {
     var uiSourceCode = this._sourcesView.currentUISourceCode();
     if (!this._isFormattable(uiSourceCode))
       return;
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/NavigatorView.js b/third_party/WebKit/Source/devtools/front_end/sources/NavigatorView.js
index 3180034..e11f4e8 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/NavigatorView.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/NavigatorView.js
@@ -40,7 +40,7 @@
     this.element.appendChild(this._scriptsTree.element);
     this.setDefaultFocusedElement(this._scriptsTree.element);
 
-    /** @type {!Map.<!Workspace.UISourceCode, !Sources.NavigatorUISourceCodeTreeNode>} */
+    /** @type {!Map.<!Workspace.UISourceCode, !Array<!Sources.NavigatorUISourceCodeTreeNode>>} */
     this._uiSourceCodeNodes = new Map();
     /** @type {!Map.<string, !Sources.NavigatorFolderTreeNode>} */
     this._subfolderNodes = new Map();
@@ -188,11 +188,11 @@
     var binding = /** @type {!Persistence.PersistenceBinding} */ (event.data);
 
     // Update UISourceCode titles.
-    var networkNode = this._uiSourceCodeNodes.get(binding.network);
-    if (networkNode)
+    var networkNodes = this._uiSourceCodeNodes.get(binding.network) || [];
+    for (var networkNode of networkNodes)
       networkNode.updateTitle();
-    var fileSystemNode = this._uiSourceCodeNodes.get(binding.fileSystem);
-    if (fileSystemNode)
+    var fileSystemNodes = this._uiSourceCodeNodes.get(binding.fileSystem) || [];
+    for (var fileSystemNode of fileSystemNodes)
       fileSystemNode.updateTitle();
 
     // Update folder titles.
@@ -232,6 +232,14 @@
   }
 
   /**
+   * @return {!Workspace.Workspace}
+   * @protected
+   */
+  workspace() {
+    return this._workspace;
+  }
+
+  /**
    * @param {!Workspace.UISourceCode} uiSourceCode
    * @return {boolean}
    */
@@ -278,7 +286,7 @@
     var folderNode =
         this._folderNode(uiSourceCode, project, target, frame, uiSourceCode.origin(), path, isFromSourceMap);
     var uiSourceCodeNode = new Sources.NavigatorUISourceCodeTreeNode(this, uiSourceCode);
-    this._uiSourceCodeNodes.set(uiSourceCode, uiSourceCodeNode);
+    this._uiSourceCodeNodes.set(uiSourceCode, [uiSourceCodeNode]);
     folderNode.appendChild(uiSourceCodeNode);
     this.uiSourceCodeAdded(uiSourceCode);
   }
@@ -290,13 +298,6 @@
   }
 
   /**
-   * @return {!Array<!Sources.NavigatorUISourceCodeTreeNode>}
-   */
-  uiSourceCodeNodes() {
-    return this._uiSourceCodeNodes.valuesArray();
-  }
-
-  /**
    * @param {!Common.Event} event
    */
   _uiSourceCodeAdded(event) {
@@ -496,15 +497,18 @@
   /**
    * @param {!Workspace.UISourceCode} uiSourceCode
    * @param {boolean=} select
+   * @return {?Sources.NavigatorUISourceCodeTreeNode}
    */
   revealUISourceCode(uiSourceCode, select) {
-    var node = this._uiSourceCodeNodes.get(uiSourceCode);
-    if (!node)
-      return;
+    var nodes = this._uiSourceCodeNodes.get(uiSourceCode);
+    if (!nodes)
+      return null;
     if (this._scriptsTree.selectedTreeElement)
       this._scriptsTree.selectedTreeElement.deselect();
     this._lastSelectedUISourceCode = uiSourceCode;
-    node.reveal(select);
+    // TODO(dgozman): figure out revealing multiple.
+    nodes[0].reveal(select);
+    return nodes[0];
   }
 
   /**
@@ -526,39 +530,42 @@
    * @param {!Workspace.UISourceCode} uiSourceCode
    */
   _removeUISourceCode(uiSourceCode) {
-    var node = this._uiSourceCodeNodes.get(uiSourceCode);
-    if (!node)
-      return;
+    var nodes = this._uiSourceCodeNodes.get(uiSourceCode) || [];
+    for (var i = 0; i < nodes.length; i++) {
+      var node = nodes[i];
 
-    var project = uiSourceCode.project();
-    var target = Bindings.NetworkProject.targetForUISourceCode(uiSourceCode);
-    var frame = this._uiSourceCodeFrame(uiSourceCode);
+      var project = uiSourceCode.project();
+      var target = Bindings.NetworkProject.targetForUISourceCode(uiSourceCode);
+      var frame = this._uiSourceCodeFrame(uiSourceCode);
 
-    var parentNode = node.parent;
-    this._uiSourceCodeNodes.delete(uiSourceCode);
-    parentNode.removeChild(node);
-    node = parentNode;
-
-    while (node) {
-      parentNode = node.parent;
-      if (!parentNode || !node.isEmpty())
-        break;
-      if (!(node instanceof Sources.NavigatorGroupTreeNode || node instanceof Sources.NavigatorFolderTreeNode))
-        break;
-      if (node._type === Sources.NavigatorView.Types.Frame)
-        break;
-
-      var folderId = this._folderNodeId(project, target, frame, uiSourceCode.origin(), node._folderPath);
-      this._subfolderNodes.delete(folderId);
+      var parentNode = node.parent;
       parentNode.removeChild(node);
       node = parentNode;
+
+      while (node) {
+        parentNode = node.parent;
+        if (!parentNode || !node.isEmpty())
+          break;
+        if (!(node instanceof Sources.NavigatorGroupTreeNode || node instanceof Sources.NavigatorFolderTreeNode))
+          break;
+        if (node._type === Sources.NavigatorView.Types.Frame)
+          break;
+
+        var folderId = this._folderNodeId(project, target, frame, uiSourceCode.origin(), node._folderPath);
+        this._subfolderNodes.delete(folderId);
+        parentNode.removeChild(node);
+        node = parentNode;
+      }
     }
+    this._uiSourceCodeNodes.delete(uiSourceCode);
   }
 
   reset() {
-    var nodes = this._uiSourceCodeNodes.valuesArray();
-    for (var i = 0; i < nodes.length; ++i)
-      nodes[i].dispose();
+    for (var entry of this._uiSourceCodeNodes) {
+      var nodes = /** @type {!Array<!Sources.NavigatorUISourceCodeTreeNode>} */ (entry[1]);
+      for (var i = 0; i < nodes.length; i++)
+        nodes[i].dispose();
+    }
 
     this._scriptsTree.removeChildren();
     this._uiSourceCodeNodes.clear();
@@ -583,10 +590,10 @@
   }
 
   /**
-   * @param {!Workspace.UISourceCode} uiSourceCode
+   * @param {!Sources.NavigatorUISourceCodeTreeNode} node
    */
-  _handleContextMenuRename(uiSourceCode) {
-    this.rename(uiSourceCode, false);
+  _handleContextMenuRename(node) {
+    this.rename(node, false);
   }
 
   /**
@@ -613,9 +620,10 @@
 
   /**
    * @param {!Event} event
-   * @param {!Workspace.UISourceCode} uiSourceCode
+   * @param {!Sources.NavigatorUISourceCodeTreeNode} node
    */
-  handleFileContextMenu(event, uiSourceCode) {
+  handleFileContextMenu(event, node) {
+    var uiSourceCode = node.uiSourceCode();
     var contextMenu = new UI.ContextMenu(event);
     contextMenu.appendApplicableItems(uiSourceCode);
     contextMenu.appendSeparator();
@@ -623,7 +631,7 @@
     var project = uiSourceCode.project();
     if (project.type() === Workspace.projectTypes.FileSystem) {
       var parentURL = uiSourceCode.parentURL();
-      contextMenu.appendItem(Common.UIString('Rename\u2026'), this._handleContextMenuRename.bind(this, uiSourceCode));
+      contextMenu.appendItem(Common.UIString('Rename\u2026'), this._handleContextMenuRename.bind(this, node));
       contextMenu.appendItem(
           Common.UIString('Make a copy\u2026'),
           this._handleContextMenuCreate.bind(this, project, parentURL, uiSourceCode));
@@ -668,12 +676,12 @@
   }
 
   /**
-   * @param {!Workspace.UISourceCode} uiSourceCode
+   * @param {!Sources.NavigatorUISourceCodeTreeNode} node
    * @param {boolean} deleteIfCanceled
+   * @protected
    */
-  rename(uiSourceCode, deleteIfCanceled) {
-    var node = this._uiSourceCodeNodes.get(uiSourceCode);
-    console.assert(node);
+  rename(node, deleteIfCanceled) {
+    var uiSourceCode = node.uiSourceCode();
     node.rename(callback.bind(this));
 
     /**
@@ -729,8 +737,9 @@
       if (!uiSourceCode)
         return;
       this._sourceSelected(uiSourceCode, false);
-      this.revealUISourceCode(uiSourceCode, true);
-      this.rename(uiSourceCode, true);
+      var node = this.revealUISourceCode(uiSourceCode, true);
+      if (node)
+        this.rename(node, true);
     }
   }
 
@@ -922,10 +931,12 @@
    * @param {!Sources.NavigatorView} navigatorView
    * @param {!Workspace.UISourceCode} uiSourceCode
    * @param {string} title
+   * @param {!Sources.NavigatorUISourceCodeTreeNode} node
    */
-  constructor(navigatorView, uiSourceCode, title) {
+  constructor(navigatorView, uiSourceCode, title, node) {
     super('', false);
     this._nodeType = Sources.NavigatorView.Types.File;
+    this._node = node;
     this.title = title;
     this.listItemElement.classList.add(
         'navigator-' + uiSourceCode.contentType().name() + '-tree-item', 'navigator-file-tree-item');
@@ -950,22 +961,9 @@
     this.listItemElement.draggable = true;
     this.listItemElement.addEventListener('click', this._onclick.bind(this), false);
     this.listItemElement.addEventListener('contextmenu', this._handleContextMenuEvent.bind(this), false);
-    this.listItemElement.addEventListener('mousedown', this._onmousedown.bind(this), false);
     this.listItemElement.addEventListener('dragstart', this._ondragstart.bind(this), false);
   }
 
-  _onmousedown(event) {
-    if (event.which === 1)  // Warm-up data for drag'n'drop
-      this._uiSourceCode.requestContent().then(callback.bind(this));
-    /**
-     * @param {?string} content
-     * @this {Sources.NavigatorSourceTreeElement}
-     */
-    function callback(content) {
-      this._warmedUpContent = content;
-    }
-  }
-
   _shouldRenameOnMouseDown() {
     if (!this._uiSourceCode.canRename())
       return false;
@@ -988,14 +986,16 @@
      */
     function rename() {
       if (this._shouldRenameOnMouseDown())
-        this._navigatorView.rename(this.uiSourceCode, false);
+        this._navigatorView.rename(this._node, false);
     }
   }
 
+  /**
+   * @param {!DragEvent} event
+   */
   _ondragstart(event) {
-    event.dataTransfer.setData('text/plain', this._warmedUpContent);
+    event.dataTransfer.setData('text/plain', this._uiSourceCode.url());
     event.dataTransfer.effectAllowed = 'copy';
-    return true;
   }
 
   /**
@@ -1047,7 +1047,7 @@
    */
   _handleContextMenuEvent(event) {
     this.select();
-    this._navigatorView.handleFileContextMenu(event, this._uiSourceCode);
+    this._navigatorView.handleFileContextMenu(event, this._node);
   }
 };
 
@@ -1244,7 +1244,7 @@
     if (this._treeElement)
       return this._treeElement;
 
-    this._treeElement = new Sources.NavigatorSourceTreeElement(this._navigatorView, this._uiSourceCode, '');
+    this._treeElement = new Sources.NavigatorSourceTreeElement(this._navigatorView, this._uiSourceCode, '', this);
     this.updateTitle();
 
     var updateTitleBound = this.updateTitle.bind(this, undefined);
@@ -1268,16 +1268,15 @@
         (this._uiSourceCode.isDirty() || Persistence.persistence.hasUnsavedCommittedChanges(this._uiSourceCode)))
       titleText = '*' + titleText;
 
+    this._treeElement.title = titleText;
+
     var binding = Persistence.persistence.binding(this._uiSourceCode);
     if (binding && Runtime.experiments.isEnabled('persistence2')) {
-      var titleElement = createElement('span');
-      titleElement.textContent = titleText;
-      var icon = UI.Icon.create('smallicon-checkmark', 'mapped-file-checkmark');
+      var icon = UI.Icon.create('smallicon-green-checkmark');
       icon.title = Persistence.PersistenceUtils.tooltipForUISourceCode(this._uiSourceCode);
-      titleElement.appendChild(icon);
-      this._treeElement.title = titleElement;
+      this._treeElement.setTrailingIcons([icon]);
     } else {
-      this._treeElement.title = titleText;
+      this._treeElement.setTrailingIcons([]);
     }
 
     var tooltip = this._uiSourceCode.url();
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/ObjectEventListenersSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/sources/ObjectEventListenersSidebarPane.js
index db31f97..e1ba2fc 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/ObjectEventListenersSidebarPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/ObjectEventListenersSidebarPane.js
@@ -11,7 +11,7 @@
     this.element.classList.add('event-listeners-sidebar-pane');
 
     this._refreshButton = new UI.ToolbarButton(Common.UIString('Refresh'), 'largeicon-refresh');
-    this._refreshButton.addEventListener('click', this._refreshClick.bind(this));
+    this._refreshButton.addEventListener(UI.ToolbarButton.Events.Click, this._refreshClick, this);
     this._refreshButton.setEnabled(false);
 
     this._eventListenersView = new Components.EventListenersView(this.element, this.update.bind(this));
@@ -91,7 +91,7 @@
    * @param {!Common.Event} event
    */
   _refreshClick(event) {
-    event.consume();
+    event.data.consume();
     this.update();
   }
 };
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/ScriptFormatterEditorAction.js b/third_party/WebKit/Source/devtools/front_end/sources/ScriptFormatterEditorAction.js
index 1576286..402627f 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/ScriptFormatterEditorAction.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/ScriptFormatterEditorAction.js
@@ -194,7 +194,7 @@
     this._sourcesView.addEventListener(Sources.SourcesView.Events.EditorClosed, this._editorClosed.bind(this));
 
     this._button = new UI.ToolbarButton(Common.UIString('Pretty print'), 'largeicon-pretty-print');
-    this._button.addEventListener('click', this._toggleFormatScriptSource, this);
+    this._button.addEventListener(UI.ToolbarButton.Events.Click, this._toggleFormatScriptSource, this);
     this._updateButton(sourcesView.currentUISourceCode());
 
     return this._button;
@@ -216,7 +216,10 @@
     return uiSourceCode.contentType().hasScripts();
   }
 
-  _toggleFormatScriptSource() {
+  /**
+   * @param {!Common.Event} event
+   */
+  _toggleFormatScriptSource(event) {
     var uiSourceCode = this._sourcesView.currentUISourceCode();
     if (this._isFormatableScript(uiSourceCode))
       this._formatUISourceCodeScript(uiSourceCode);
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/SourcesNavigator.js b/third_party/WebKit/Source/devtools/front_end/sources/SourcesNavigator.js
index 0b8dbf6..6d1ac998 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/SourcesNavigator.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/SourcesNavigator.js
@@ -57,9 +57,8 @@
     var inspectedURL = mainTarget && mainTarget.inspectedURL();
     if (!inspectedURL)
       return;
-    for (var node of this.uiSourceCodeNodes()) {
-      var uiSourceCode = node.uiSourceCode();
-      if (uiSourceCode.url() === inspectedURL)
+    for (var uiSourceCode of this.workspace().uiSourceCodes()) {
+      if (this.accept(uiSourceCode) && uiSourceCode.url() === inspectedURL)
         this.revealUISourceCode(uiSourceCode, true);
     }
   }
@@ -116,9 +115,8 @@
     var inspectedURL = mainTarget && mainTarget.inspectedURL();
     if (!inspectedURL)
       return;
-    for (var node of this.uiSourceCodeNodes()) {
-      var uiSourceCode = node.uiSourceCode();
-      if (uiSourceCode.url() === inspectedURL)
+    for (var uiSourceCode of this.workspace().uiSourceCodes()) {
+      if (this.accept(uiSourceCode) && uiSourceCode.url() === inspectedURL)
         this.revealUISourceCode(uiSourceCode, true);
     }
   }
@@ -146,7 +144,8 @@
     var toolbar = new UI.Toolbar('navigator-toolbar');
     var title = Common.UIString('Add folder to workspace');
     var addButton = new UI.ToolbarButton(title, 'largeicon-add', title);
-    addButton.addEventListener('click', () => Workspace.isolatedFileSystemManager.addFileSystem());
+    addButton.addEventListener(
+        UI.ToolbarButton.Events.Click, () => Workspace.isolatedFileSystemManager.addFileSystem());
     toolbar.appendToolbarItem(addButton);
     this.element.insertBefore(toolbar.element, this.element.firstChild);
   }
@@ -197,7 +196,7 @@
     super();
     var toolbar = new UI.Toolbar('navigator-toolbar');
     var newButton = new UI.ToolbarButton('', 'largeicon-add', Common.UIString('New Snippet'));
-    newButton.addEventListener('click', this._handleCreateSnippet.bind(this));
+    newButton.addEventListener(UI.ToolbarButton.Events.Click, this._handleCreateSnippet.bind(this));
     toolbar.appendToolbarItem(newButton);
     this.element.insertBefore(toolbar.element, this.element.firstChild);
   }
@@ -224,12 +223,13 @@
   /**
    * @override
    * @param {!Event} event
-   * @param {!Workspace.UISourceCode} uiSourceCode
+   * @param {!Sources.NavigatorUISourceCodeTreeNode} node
    */
-  handleFileContextMenu(event, uiSourceCode) {
+  handleFileContextMenu(event, node) {
+    var uiSourceCode = node.uiSourceCode();
     var contextMenu = new UI.ContextMenu(event);
     contextMenu.appendItem(Common.UIString('Run'), this._handleEvaluateSnippet.bind(this, uiSourceCode));
-    contextMenu.appendItem(Common.UIString('Rename'), this.rename.bind(this, uiSourceCode));
+    contextMenu.appendItem(Common.UIString('Rename'), this.rename.bind(this, node));
     contextMenu.appendItem(Common.UIString('Remove'), this._handleRemoveSnippet.bind(this, uiSourceCode));
     contextMenu.appendSeparator();
     contextMenu.appendItem(Common.UIString('New'), this._handleCreateSnippet.bind(this));
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 9e93907c..fc305dd 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js
@@ -595,16 +595,15 @@
   }
 
   /**
-   * @return {boolean}
+   * @param {!Common.Event} event
    */
-  _longResume() {
+  _longResume(event) {
     var debuggerModel = this._prepareToResume();
     if (!debuggerModel)
-      return true;
+      return;
 
     debuggerModel.skipAllPausesUntilReloadOrTimeout(500);
     debuggerModel.resume();
-    return true;
   }
 
   /**
@@ -681,7 +680,7 @@
 
     var longResumeButton =
         new UI.ToolbarButton(Common.UIString('Resume with all pauses blocked for 500 ms'), 'largeicon-play');
-    longResumeButton.addEventListener('click', this._longResume.bind(this), this);
+    longResumeButton.addEventListener(UI.ToolbarButton.Events.Click, this._longResume, this);
     debugToolbar.appendToolbarItem(UI.Toolbar.createActionButton(this._togglePauseAction, [longResumeButton], []));
 
     debugToolbar.appendToolbarItem(UI.Toolbar.createActionButton(this._stepOverAction));
@@ -691,7 +690,7 @@
     debugToolbar.appendToolbarItem(UI.Toolbar.createActionButton(this._toggleBreakpointsActiveAction));
 
     this._pauseOnExceptionButton = new UI.ToolbarToggle('', 'largeicon-pause-on-exceptions');
-    this._pauseOnExceptionButton.addEventListener('click', this._togglePauseOnExceptions, this);
+    this._pauseOnExceptionButton.addEventListener(UI.ToolbarButton.Events.Click, this._togglePauseOnExceptions, this);
     debugToolbar.appendToolbarItem(this._pauseOnExceptionButton);
 
     debugToolbar.appendSeparator();
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/WatchExpressionsSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/sources/WatchExpressionsSidebarPane.js
index 6385a2a..fd34603 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/WatchExpressionsSidebarPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/WatchExpressionsSidebarPane.js
@@ -43,9 +43,9 @@
     this._watchExpressionsSetting = Common.settings.createLocalSetting('watchExpressions', []);
 
     this._addButton = new UI.ToolbarButton(Common.UIString('Add expression'), 'largeicon-add');
-    this._addButton.addEventListener('click', this._addButtonClicked.bind(this));
+    this._addButton.addEventListener(UI.ToolbarButton.Events.Click, this._addButtonClicked.bind(this));
     this._refreshButton = new UI.ToolbarButton(Common.UIString('Refresh'), 'largeicon-refresh');
-    this._refreshButton.addEventListener('click', this._refreshButtonClicked.bind(this));
+    this._refreshButton.addEventListener(UI.ToolbarButton.Events.Click, this.update, this);
 
     this._bodyElement = this.element.createChild('div', 'vbox watch-expressions');
     this._bodyElement.addEventListener('contextmenu', this._contextMenu.bind(this), false);
@@ -82,25 +82,12 @@
     this._watchExpressionsSetting.set(toSave);
   }
 
-  /**
-   * @param {!Common.Event=} event
-   */
-  _addButtonClicked(event) {
-    if (event)
-      event.consume(true);
+  _addButtonClicked() {
     UI.viewManager.showView('sources.watch');
     this._createWatchExpression(null).startEditing();
   }
 
   /**
-   * @param {!Common.Event} event
-   */
-  _refreshButtonClicked(event) {
-    event.consume();
-    this.update();
-  }
-
-  /**
    * @override
    * @return {!Promise.<?>}
    */
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/XHRBreakpointsSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/sources/XHRBreakpointsSidebarPane.js
index 69b130b..d21e644 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/XHRBreakpointsSidebarPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/XHRBreakpointsSidebarPane.js
@@ -16,7 +16,7 @@
     this._breakpointElements = new Map();
 
     this._addButton = new UI.ToolbarButton(Common.UIString('Add breakpoint'), 'largeicon-add');
-    this._addButton.addEventListener('click', this._addButtonClicked.bind(this));
+    this._addButton.addEventListener(UI.ToolbarButton.Events.Click, this._addButtonClicked.bind(this));
 
     this.emptyElement.addEventListener('contextmenu', this._emptyElementContextMenu.bind(this), true);
     SDK.targetManager.observeTargets(this, SDK.Target.Capability.Browser);
@@ -52,10 +52,7 @@
     contextMenu.show();
   }
 
-  _addButtonClicked(event) {
-    if (event)
-      event.consume();
-
+  _addButtonClicked() {
     UI.viewManager.showView('sources.xhrBreakpoints');
 
     var inputElementContainer = createElementWithClass('p', 'breakpoint-condition');
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/navigatorTree.css b/third_party/WebKit/Source/devtools/front_end/sources/navigatorTree.css
index b4418f4..e7a45e3b 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/navigatorTree.css
+++ b/third_party/WebKit/Source/devtools/front_end/sources/navigatorTree.css
@@ -52,15 +52,6 @@
     opacity: 0.5;
 }
 
-.mapped-file-checkmark {
-    background: #009802;
-    margin-left: 3px;
-}
-
-:focus .navigator-file-tree-item.selected .mapped-file-checkmark {
-    background: white !important;
-}
-
 :focus .navigator-file-tree-item.selected .icon {
     background: white !important;
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/text_editor/CodeMirrorTextEditor.js b/third_party/WebKit/Source/devtools/front_end/text_editor/CodeMirrorTextEditor.js
index acd1700..0310ab6 100644
--- a/third_party/WebKit/Source/devtools/front_end/text_editor/CodeMirrorTextEditor.js
+++ b/third_party/WebKit/Source/devtools/front_end/text_editor/CodeMirrorTextEditor.js
@@ -172,6 +172,8 @@
 
     this._needsRefresh = true;
 
+    this._readOnly = false;
+
     this._mimeType = '';
     if (options.mimeType)
       this.setMimeType(options.mimeType);
@@ -711,6 +713,10 @@
    * @param {boolean} readOnly
    */
   setReadOnly(readOnly) {
+    if (this._readOnly === readOnly)
+      return;
+    this.clearPositionHighlight();
+    this._readOnly = readOnly;
     this.element.classList.toggle('CodeMirror-readonly', readOnly);
     this._codeMirror.setOption('readOnly', readOnly);
   }
@@ -903,8 +909,10 @@
       return;
     this.scrollLineIntoView(lineNumber);
     if (shouldHighlight) {
-      this._codeMirror.addLineClass(this._highlightedLine, null, 'cm-highlight');
-      this._clearHighlightTimeout = setTimeout(this.clearPositionHighlight.bind(this), 2000);
+      this._codeMirror.addLineClass(
+          this._highlightedLine, null, this._readOnly ? 'cm-readonly-highlight' : 'cm-highlight');
+      if (!this._readOnly)
+        this._clearHighlightTimeout = setTimeout(this.clearPositionHighlight.bind(this), 2000);
     }
     this.setSelection(Common.TextRange.createFromLocation(lineNumber, columnNumber));
   }
@@ -914,8 +922,10 @@
       clearTimeout(this._clearHighlightTimeout);
     delete this._clearHighlightTimeout;
 
-    if (this._highlightedLine)
-      this._codeMirror.removeLineClass(this._highlightedLine, null, 'cm-highlight');
+    if (this._highlightedLine) {
+      this._codeMirror.removeLineClass(
+          this._highlightedLine, null, this._readOnly ? 'cm-readonly-highlight' : 'cm-highlight');
+    }
     delete this._highlightedLine;
   }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/text_editor/cmdevtools.css b/third_party/WebKit/Source/devtools/front_end/text_editor/cmdevtools.css
index 969daea..c143868 100644
--- a/third_party/WebKit/Source/devtools/front_end/text_editor/cmdevtools.css
+++ b/third_party/WebKit/Source/devtools/front_end/text_editor/cmdevtools.css
@@ -70,6 +70,14 @@
     to { background-color: transparent; }
 }
 
+.cm-readonly-highlight {
+    background-color: rgb(255, 255, 120);
+}
+
+.-theme-with-dark-background .cm-readonly-highlight {
+    background-color: hsla(133, 100%, 30%, 0.5);
+}
+
 .cm-highlight.cm-execution-line {
     -webkit-animation: fadeout-execution-line 1s 0s;
 }
@@ -378,11 +386,11 @@
     top: -9px;
 }
 
-.CodeMirror .text-editor-line-with-warning:not(.cm-execution-line) {
+.CodeMirror .text-editor-line-with-warning:not(.cm-execution-line):not(.cm-readonly-highlight) {
     background-color: rgba(241, 230, 0, 0.1);
 }
 
-.CodeMirror .text-editor-line-with-error:not(.cm-execution-line) {
+.CodeMirror .text-editor-line-with-error:not(.cm-execution-line):not(.cm-readonly-highlight) {
     background-color: rgba(255, 0, 0, 0.05);
 }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/CountersGraph.js b/third_party/WebKit/Source/devtools/front_end/timeline/CountersGraph.js
index 9fd19ae..b48a7cf 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/CountersGraph.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/CountersGraph.js
@@ -103,6 +103,14 @@
   }
 
   /**
+   * @protected
+   * @return {!TimelineModel.TimelineModel}
+   */
+  model() {
+    return this._model;
+  }
+
+  /**
    * @override
    */
   dispose() {
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/MemoryCountersGraph.js b/third_party/WebKit/Source/devtools/front_end/timeline/MemoryCountersGraph.js
index c1a1ce6..99878329 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/MemoryCountersGraph.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/MemoryCountersGraph.js
@@ -59,7 +59,7 @@
    */
   refreshRecords() {
     this.reset();
-    var events = this._model.mainThreadEvents();
+    var events = this.model().mainThreadEvents();
     for (var i = 0; i < events.length; ++i) {
       var event = events[i];
       if (event.name !== TimelineModel.TimelineModel.RecordType.UpdateCounters)
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineEventOverview.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineEventOverview.js
index 45b18d3..5408a32c 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineEventOverview.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineEventOverview.js
@@ -528,7 +528,7 @@
     if (!this._filmStripModel.frames().length)
       return Promise.resolve(/** @type {?Element} */ (null));
 
-    var time = this._calculator.positionToTime(x);
+    var time = this.calculator().positionToTime(x);
     var frame = this._filmStripModel.frameByTimestamp(time);
     if (frame === this._lastFrame)
       return Promise.resolve(this._lastElement);
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineLandingPage.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineLandingPage.js
new file mode 100644
index 0000000..559a97c
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineLandingPage.js
@@ -0,0 +1,172 @@
+// 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.
+
+Timeline.TimelineLandingPage = class extends UI.VBox {
+  constructor() {
+    super(true);
+    this.registerRequiredCSS('timeline/timelineLandingPage.css');
+    this.contentElement.classList.add('timeline-landing-page', 'fill');
+    const perspectives = Timeline.TimelinePanel.Perspectives;
+    const config = Timeline.TimelineLandingPage.RecordingConfig;
+    this._tabbedPane = new UI.TabbedPane();
+    this._tabbedPane.setTabSlider(true);
+    this._tabbedPane.renderWithNoHeaderBackground();
+
+    var tab = new Timeline.TimelineLandingPage.PerspectiveTabWidget();
+    tab.setDescription(Common.UIString(
+        'Page Load mode allows you to analyze how fast the page is loaded and becomes responsive.\n' +
+        'In this mode the page is automatically reloaded right after the recording has started. ' +
+        'During recording it collects information about network requests, screen state updates, ' +
+        'and CPU threads acivity along with JavaScript stacks. ' +
+        'Recording is stopped automatically shortly after the page processes load event.'));
+    tab.setAction(recordAndReload);
+    tab.appendOption(config.network, false, true);
+    tab.appendOption(config.screenshots, true, true);
+    this._tabbedPane.appendTab(perspectives.Load, Common.UIString('Page Load'), tab);
+
+    tab = new Timeline.TimelineLandingPage.PerspectiveTabWidget();
+    tab.setDescription(Common.UIString('Record page responsiveness.'));
+    tab.setAction(record);
+    tab.appendOption(config.network, false, true);
+    tab.appendOption(config.screenshots, true, false);
+    this._tabbedPane.appendTab(perspectives.Responsiveness, Common.UIString('Responsiveness'), tab);
+
+    tab = new Timeline.TimelineLandingPage.PerspectiveTabWidget();
+    tab.setDescription(Common.UIString(
+        'This mode is useful when you want to focus on JavaScript performance. ' +
+        'All the options besides sampling CPU profiler are turned off to minimize measurement errors.'));
+    tab.setAction(record);
+    this._tabbedPane.appendTab(perspectives.JavaScript, Common.UIString('JavaScript'), tab);
+
+    tab = new Timeline.TimelineLandingPage.PerspectiveTabWidget();
+    tab.setDescription(Common.UIString('Advanced mode that allows you to customize recording options.'));
+    tab.setAction(record);
+    tab.appendOption(config.network, true, true);
+    tab.appendOption(config.javascript, true, true);
+    tab.appendOption(config.screenshots, true, true);
+    tab.appendOption(config.memory, true, false);
+    tab.appendOption(config.paints, true, false);
+    this._tabbedPane.appendTab(perspectives.Custom, Common.UIString('Custom'), tab);
+
+    this._tabbedPane.addEventListener(UI.TabbedPane.Events.TabSelected, this._tabSelected, this);
+    this._tabbedPane.show(this.contentElement);
+    this._perspectiveSetting =
+        Common.settings.createSetting('timelinePerspective', Timeline.TimelinePanel.Perspectives.Load);
+    this._perspectiveSetting.addChangeListener(this._perspectiveChanged, this);
+
+    function record() {
+      UI.actionRegistry.action('timeline.toggle-recording').execute();
+    }
+
+    function recordAndReload() {
+      SDK.targetManager.reloadPage();
+    }
+  }
+
+  /**
+   * @param {!Common.Event} event
+   */
+  _tabSelected(event) {
+    if (this._perspectiveSetting.get() !== event.data.tabId)
+      this._perspectiveSetting.set(event.data.tabId);
+  }
+
+  _perspectiveChanged() {
+    this._tabbedPane.selectTab(this._perspectiveSetting.get());
+    const tabWidget = /** @type {!Timeline.TimelineLandingPage.PerspectiveTabWidget} */ (this._tabbedPane.visibleView);
+    tabWidget.activate();
+  }
+};
+
+/** @typedef {!{id: string, title: string, description: string, setting: string}} */
+Timeline.TimelineLandingPage.RecordingOption;
+
+/** @type {!Object<string, !Timeline.TimelineLandingPage.RecordingOption>} */
+Timeline.TimelineLandingPage.RecordingConfig = {
+  network: {
+    id: 'network',
+    title: Common.UIString('Network'),
+    description: Common.UIString('Capture network requests information.'),
+    setting: 'timelineCaptureNetwork'
+  },
+  javascript: {
+    id: 'javascript',
+    title: Common.UIString('JavaScript'),
+    description: Common.UIString('Use sampling CPU profiler to collect JavaScript stacks.'),
+    setting: 'timelineEnableJSSampling'
+  },
+  screenshots: {
+    id: 'screenshots',
+    title: Common.UIString('Screenshots'),
+    description:
+        Common.UIString('Collect page screenshots, so you can observe how the page was evolving during recording.'),
+    setting: 'timelineCaptureFilmStrip'
+  },
+  paints: {
+    id: 'paints',
+    title: Common.UIString('Paints'),
+    description: Common.UIString(
+        'Capture graphics layer positions and rasterization draw calls (moderate performance overhead).'),
+    setting: 'timelineCaptureLayersAndPictures'
+  },
+  memory: {
+    id: 'memory',
+    title: Common.UIString('Memory'),
+    description: Common.UIString('Capture memory statistics on every timeline event.'),
+    setting: 'timelineCaptureMemory'
+  }
+};
+
+Timeline.TimelineLandingPage.PerspectiveTabWidget = class extends UI.VBox {
+  constructor() {
+    super(false);
+    this.contentElement.classList.add('timeline-perspective-body');
+    this._enabledOptions = new Set([Timeline.TimelineLandingPage.RecordingConfig.javascript.id]);
+    this._descriptionDiv = this.contentElement.createChild('div', 'timeline-perspective-description');
+    this._actionButton = createTextButton(Common.UIString('Start'));
+    this._actionButtonDiv = this.contentElement.createChild('div');
+    this._actionButtonDiv.appendChild(this._actionButton);
+  }
+
+  /**
+   * @param {string} text
+   */
+  setDescription(text) {
+    this._descriptionDiv.textContent = text;
+  }
+
+  /**
+   * @param {function()} action
+   */
+  setAction(action) {
+    this._actionButton.addEventListener('click', action);
+  }
+
+  /**
+   * @param {!Timeline.TimelineLandingPage.RecordingOption} option
+   * @param {boolean} visible
+   * @param {boolean} enabled
+   */
+  appendOption(option, visible, enabled) {
+    if (enabled)
+      this._enabledOptions.add(option.id);
+    if (!visible)
+      return;
+    const div = createElementWithClass('div', 'recording-setting');
+    const value = this._enabledOptions.has(option.id);
+    const setting = Common.settings.createSetting(option.setting, value);
+    div.appendChild(UI.SettingsUI.createSettingCheckbox(option.title, setting, true));
+    if (option.description)
+      div.createChild('div', 'recording-setting-description').textContent = option.description;
+    this.contentElement.insertBefore(div, this._actionButtonDiv);
+  }
+
+  activate() {
+    for (const id in Timeline.TimelineLandingPage.RecordingConfig) {
+      const config = Timeline.TimelineLandingPage.RecordingConfig[id];
+      const setting = Common.settings.createSetting(config.setting, false);
+      setting.set(this._enabledOptions.has(id));
+    }
+  }
+};
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineNetworkFlameChart.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineNetworkFlameChart.js
index a6c73d3..a87831d86 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineNetworkFlameChart.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineNetworkFlameChart.js
@@ -23,7 +23,7 @@
       height: 17,
       collapsible: true,
       color: UI.themeSupport.patchColor('#222', UI.ThemeSupport.ColorUsage.Foreground),
-      font: this._font,
+      font: this.font(),
       backgroundColor: UI.themeSupport.patchColor('white', UI.ThemeSupport.ColorUsage.Background),
       nestingLevel: 0,
       useFirstLineForOverview: false,
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js
index 3b0192f..1d7c854 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js
@@ -83,16 +83,16 @@
 
     this._panelToolbar = new UI.Toolbar('', this.element);
 
-    var timelinePane = new UI.VBox();
-    timelinePane.show(this.element);
-    var topPaneElement = timelinePane.element.createChild('div', 'hbox');
+    this._timelinePane = new UI.VBox();
+    this._timelinePane.show(this.element);
+    var topPaneElement = this._timelinePane.element.createChild('div', 'hbox');
     topPaneElement.id = 'timeline-overview-panel';
 
     // Create top overview component.
     this._overviewPane = new UI.TimelineOverviewPane('timeline');
     this._overviewPane.addEventListener(UI.TimelineOverviewPane.Events.WindowChanged, this._onWindowChanged.bind(this));
     this._overviewPane.show(topPaneElement);
-    this._statusPaneContainer = timelinePane.element.createChild('div', 'status-pane-container fill');
+    this._statusPaneContainer = this._timelinePane.element.createChild('div', 'status-pane-container fill');
 
     this._createFileSelector();
 
@@ -122,7 +122,7 @@
     this._captureMemorySetting.addChangeListener(this._onModeChanged, this);
     this._captureFilmStripSetting.addChangeListener(this._onModeChanged, this);
 
-    this._detailsSplitWidget.show(timelinePane.element);
+    this._detailsSplitWidget.show(this._timelinePane.element);
     this._detailsSplitWidget.hideSidebar();
     SDK.targetManager.addEventListener(SDK.TargetManager.Events.SuspendStateChanged, this._onSuspendStateChanged, this);
     this._showRecordingHelpMessage();
@@ -282,7 +282,7 @@
     if (Runtime.experiments.isEnabled('timelineRecordingPerspectives') &&
         perspectiveSetting.get() === Timeline.TimelinePanel.Perspectives.Load) {
       this._reloadButton = new UI.ToolbarButton(Common.UIString('Record & Reload'), 'largeicon-refresh');
-      this._reloadButton.addEventListener('click', () => SDK.targetManager.reloadPage());
+      this._reloadButton.addEventListener(UI.ToolbarButton.Events.Click, () => SDK.targetManager.reloadPage());
       this._panelToolbar.appendToolbarItem(this._reloadButton);
     } else {
       this._panelToolbar.appendToolbarItem(UI.Toolbar.createActionButton(this._toggleRecordAction));
@@ -290,7 +290,7 @@
 
     // Clear
     var clearButton = new UI.ToolbarButton(Common.UIString('Clear recording'), 'largeicon-clear');
-    clearButton.addEventListener('click', this._clear, this);
+    clearButton.addEventListener(UI.ToolbarButton.Events.Click, this._clear, this);
     this._panelToolbar.appendToolbarItem(clearButton);
 
     this._panelToolbar.appendSeparator();
@@ -410,7 +410,7 @@
      * @param {string} name
      * @param {number} value
      */
-    function addGroupingOption(name, value) {
+    function addOption(name, value) {
       var option = cpuThrottlingCombobox.createOption(name, '', String(value));
       cpuThrottlingCombobox.addOption(option);
       if (hasSelection || (value && value !== currentRate))
@@ -418,13 +418,9 @@
       cpuThrottlingCombobox.select(option);
       hasSelection = true;
     }
-    var predefinedRates = new Map([
-      [1, Common.UIString('No CPU throttling')], [2, Common.UIString('2\xD7 slowdown')],
-      [5, Common.UIString('5\xD7 slowdown')], [10, Common.UIString('10\xD7 slowdown')],
-      [20, Common.UIString('20\xD7 slowdown')]
-    ]);
-    for (var rate of predefinedRates)
-      addGroupingOption(rate[1], rate[0]);
+    addOption(Common.UIString('No CPU throttling'), 1);
+    for (const rate of [2, 5, 10, 20])
+      addOption(Common.UIString('%d\xD7 slowdown', rate), rate);
   }
 
   _prepareToLoadTimeline() {
@@ -633,32 +629,34 @@
   }
 
   _clear() {
+    this._showRecordingHelpMessage();
+    this._detailsSplitWidget.hideSidebar();
+    this._reset();
+  }
+
+  _reset() {
     if (Runtime.experiments.isEnabled('timelineRuleUsageRecording') && this._markUnusedCSS.get())
       Components.CoverageProfile.instance().reset();
 
     Components.LineLevelProfile.instance().reset();
     this._tracingModel.reset();
     this._model.reset();
-    this._showRecordingHelpMessage();
 
     this.requestWindowTimes(0, Infinity);
     delete this._selection;
     this._frameModel.reset();
     this._filmStripModel.reset(this._tracingModel);
     this._overviewPane.reset();
-    for (var i = 0; i < this._currentViews.length; ++i)
-      this._currentViews[i].reset();
-    for (var i = 0; i < this._overviewControls.length; ++i)
-      this._overviewControls[i].reset();
+    this._currentViews.forEach(view => view.reset());
+    this._overviewControls.forEach(overview => overview.reset());
     this.select(null);
-    this._detailsSplitWidget.hideSidebar();
   }
 
   /**
    * @override
    */
   recordingStarted() {
-    this._clear();
+    this._reset();
     this._setState(Timeline.TimelinePanel.State.Recording);
     this._showRecordingStarted();
     this._statusPane.updateStatus(Common.UIString('Recording\u2026'));
@@ -676,6 +674,11 @@
   }
 
   _showRecordingHelpMessage() {
+    if (Runtime.experiments.isEnabled('timelineLandingPage')) {
+      this._showLandingPage();
+      return;
+    }
+
     /**
      * @param {string} tagName
      * @param {string} contents
@@ -710,11 +713,31 @@
   }
 
   _hideRecordingHelpMessage() {
+    if (Runtime.experiments.isEnabled('timelineLandingPage')) {
+      this._hideLandingPage();
+      return;
+    }
     if (this._helpMessageElement)
       this._helpMessageElement.remove();
     delete this._helpMessageElement;
   }
 
+  _showLandingPage() {
+    if (this._landingPage)
+      return;
+    this._timelinePane.detach();
+    this._landingPage = new Timeline.TimelineLandingPage();
+    this._landingPage.show(this.element);
+  }
+
+  _hideLandingPage() {
+    if (!this._landingPage)
+      return;
+    this._landingPage.detach();
+    this._landingPage = null;
+    this._timelinePane.show(this.element);
+  }
+
   /**
    * @override
    */
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/module.json b/third_party/WebKit/Source/devtools/front_end/timeline/module.json
index 4e31b04..205c09a 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/module.json
@@ -131,6 +131,7 @@
         "TimelineFlameChart.js",
         "TimelineNetworkFlameChart.js",
         "TimelineTreeView.js",
+        "TimelineLandingPage.js",
         "TimelineUIUtils.js",
         "TimelineLayersView.js",
         "TimelinePaintProfilerView.js",
@@ -139,6 +140,7 @@
     "resources": [
         "invalidationsTree.css",
         "timelineFlamechartPopover.css",
+        "timelineLandingPage.css",
         "timelinePanel.css",
         "timelinePaintProfiler.css",
         "timelineStatusDialog.css"
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/timelineLandingPage.css b/third_party/WebKit/Source/devtools/front_end/timeline/timelineLandingPage.css
new file mode 100644
index 0000000..d6a652f1
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/timelineLandingPage.css
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+.timeline-landing-page {
+    align-self: center;
+    max-width: 500px;
+    font-size: 13px;
+}
+
+.timeline-landing-page .tabbed-pane {
+    padding: 10px 0 0 0;
+}
+
+.timeline-landing-page .timeline-perspective-body {
+    align-items: stretch;
+    line-height: 1.5;
+    padding: 12px;
+    white-space: pre-line;
+    width: 100%;
+    font-size: 12px;
+}
+
+.timeline-landing-page .timeline-perspective-body > div {
+    margin-bottom: 12px;
+    flex-shrink: 0;
+}
+
+.timeline-landing-page button {
+    min-width: 90px;
+    min-height: 26px;
+    margin: 10px 0 0 0;
+}
+
+.timeline-landing-page .recording-setting {
+    display: flex;
+    align-items: flex-start;
+    margin-bottom: 2px !important;
+}
+
+.timeline-landing-page .recording-setting label {
+    flex: 0 0 100px;
+}
+
+.timeline-landing-page .recording-setting-description {
+    color: #999;
+}
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/FilterBar.js b/third_party/WebKit/Source/devtools/front_end/ui/FilterBar.js
index 34afd71e..75225cf 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/FilterBar.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/FilterBar.js
@@ -44,7 +44,7 @@
     this.element.classList.add('filter-bar');
 
     this._filterButton = new UI.ToolbarToggle(Common.UIString('Filter'), 'largeicon-filter');
-    this._filterButton.addEventListener('click', this._handleFilterButtonClick, this);
+    this._filterButton.addEventListener(UI.ToolbarButton.Events.Click, this._handleFilterButtonClick, this);
 
     this._filters = [];
 
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/InspectorView.js b/third_party/WebKit/Source/devtools/front_end/ui/InspectorView.js
index 95178e7d..5e83c12 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/InspectorView.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/InspectorView.js
@@ -51,7 +51,7 @@
     this._drawerTabbedPane = this._drawerTabbedLocation.tabbedPane();
     this._drawerTabbedPane.setMinimumSize(0, 27);
     var closeDrawerButton = new UI.ToolbarButton(Common.UIString('Close drawer'), 'largeicon-delete');
-    closeDrawerButton.addEventListener('click', this._closeDrawer.bind(this));
+    closeDrawerButton.addEventListener(UI.ToolbarButton.Events.Click, this._closeDrawer, this);
     this._drawerTabbedPane.rightToolbar().appendToolbarItem(closeDrawerButton);
     this._drawerSplitWidget.installResizer(this._drawerTabbedPane.headerElement());
     this._drawerSplitWidget.setSidebarWidget(this._drawerTabbedPane);
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/SearchableView.js b/third_party/WebKit/Source/devtools/front_end/ui/SearchableView.js
index d7f95e81..9edae2f 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/SearchableView.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/SearchableView.js
@@ -54,14 +54,14 @@
     if (this._searchProvider.supportsCaseSensitiveSearch()) {
       this._caseSensitiveButton = new UI.ToolbarToggle(Common.UIString('Case sensitive'), '');
       this._caseSensitiveButton.setText('Aa');
-      this._caseSensitiveButton.addEventListener('click', this._toggleCaseSensitiveSearch, this);
+      this._caseSensitiveButton.addEventListener(UI.ToolbarButton.Events.Click, this._toggleCaseSensitiveSearch, this);
       toolbar.appendToolbarItem(this._caseSensitiveButton);
     }
 
     if (this._searchProvider.supportsRegexSearch()) {
       this._regexButton = new UI.ToolbarToggle(Common.UIString('Regex'), '');
       this._regexButton.setText('.*');
-      this._regexButton.addEventListener('click', this._toggleRegexSearch, this);
+      this._regexButton.addEventListener(UI.ToolbarButton.Events.Click, this._toggleRegexSearch, this);
       toolbar.appendToolbarItem(this._regexButton);
     }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/SplitWidget.js b/third_party/WebKit/Source/devtools/front_end/ui/SplitWidget.js
index ea73d19..72d4fe4 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/SplitWidget.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/SplitWidget.js
@@ -832,7 +832,7 @@
   createShowHideSidebarButton(title) {
     this._showHideSidebarButtonTitle = Common.UIString(title);
     this._showHideSidebarButton = new UI.ToolbarButton('', '');
-    this._showHideSidebarButton.addEventListener('click', buttonClicked.bind(this));
+    this._showHideSidebarButton.addEventListener(UI.ToolbarButton.Events.Click, buttonClicked, this);
     this._updateShowHideSidebarButton();
 
     /**
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/TabbedPane.js b/third_party/WebKit/Source/devtools/front_end/ui/TabbedPane.js
index 3616263..d9ad72f 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/TabbedPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/TabbedPane.js
@@ -455,6 +455,7 @@
   setTabSlider(enable) {
     this._sliderEnabled = enable;
     this._tabSlider.classList.toggle('enabled', enable);
+    this._headerElement.classList.add('tabbed-pane-no-tab-borders');
   }
 
   /**
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 29a80f9..62958369 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/Toolbar.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/Toolbar.js
@@ -57,7 +57,7 @@
   static createActionButton(action, toggledOptions, untoggledOptions) {
     var button = new UI.ToolbarToggle(action.title(), action.icon(), action.toggledIcon());
     button.setToggleWithRedColor(action.toggleWithRedColor());
-    button.addEventListener('click', action.execute, action);
+    button.addEventListener(UI.ToolbarButton.Events.Click, action.execute, action);
     action.addEventListener(UI.Action.Events.Enabled, enabledChanged);
     action.addEventListener(UI.Action.Events.Toggled, toggled);
     /** @type {?UI.LongClickController} */
@@ -107,7 +107,7 @@
     function showOptions() {
       var buttons = longClickButtons.slice();
       var mainButtonClone = new UI.ToolbarToggle(action.title(), action.icon(), action.toggledIcon());
-      mainButtonClone.addEventListener('click', clicked);
+      mainButtonClone.addEventListener(UI.ToolbarButton.Events.Click, clicked);
 
       /**
        * @param {!Common.Event} event
@@ -511,25 +511,30 @@
    * @param {!Event} event
    */
   _clicked(event) {
-    var defaultPrevented = this.dispatchEventToListeners('click', event);
-    event.consume(defaultPrevented);
+    this.dispatchEventToListeners(UI.ToolbarButton.Events.Click, event);
   }
 
   /**
    * @param {!Event} event
    */
   _mouseDown(event) {
-    this.dispatchEventToListeners('mousedown', event);
+    this.dispatchEventToListeners(UI.ToolbarButton.Events.MouseDown, event);
   }
 
   /**
    * @param {!Event} event
    */
   _mouseUp(event) {
-    this.dispatchEventToListeners('mouseup', event);
+    this.dispatchEventToListeners(UI.ToolbarButton.Events.MouseUp, event);
   }
 };
 
+UI.ToolbarButton.Events = {
+  Click: Symbol('Click'),
+  MouseDown: Symbol('MouseDown'),
+  MouseUp: Symbol('MouseUp')
+};
+
 /**
  * @unrestricted
  */
@@ -569,7 +574,7 @@
 };
 
 UI.ToolbarInput.Event = {
-  TextChanged: 'TextChanged'
+  TextChanged: Symbol('TextChanged')
 };
 
 /**
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/tabbedPane.css b/third_party/WebKit/Source/devtools/front_end/ui/tabbedPane.css
index 2d72edb..ee8aacf 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/tabbedPane.css
+++ b/third_party/WebKit/Source/devtools/front_end/ui/tabbedPane.css
@@ -269,6 +269,15 @@
     background-color: transparent;
 }
 
+.tabbed-pane-no-tab-borders .tabbed-pane-header-tab {
+    border: none;
+    padding: 2px 10px;
+}
+
+.tabbed-pane-no-tab-borders .tabbed-pane-header-contents {
+    margin-left: 0;
+}
+
 .tabbed-pane-left-toolbar {
     margin-right: -4px;
     flex: none;
diff --git a/third_party/WebKit/Source/devtools/front_end/ui_lazy/DataGrid.js b/third_party/WebKit/Source/devtools/front_end/ui_lazy/DataGrid.js
index 3e67015d..9534f7f 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui_lazy/DataGrid.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui_lazy/DataGrid.js
@@ -1255,14 +1255,15 @@
    */
   element() {
     if (!this._element) {
-      this.createElement();
-      this.createCells();
+      var element = this.createElement();
+      this.createCells(element);
     }
     return /** @type {!Element} */ (this._element);
   }
 
   /**
    * @protected
+   * @return {!Element}
    */
   createElement() {
     this._element = createElement('tr');
@@ -1276,17 +1277,33 @@
       this._element.classList.add('selected');
     if (this.revealed)
       this._element.classList.add('revealed');
+    return this._element;
+  }
+
+  /**
+   * @return {?Element}
+   */
+  existingElement() {
+    return this._element || null;
   }
 
   /**
    * @protected
    */
-  createCells() {
-    this._element.removeChildren();
+  resetElement() {
+    this._element = null;
+  }
+
+  /**
+   * @param {!Element} element
+   * @protected
+   */
+  createCells(element) {
+    element.removeChildren();
     var columnsArray = this.dataGrid._visibleColumnsArray;
     for (var i = 0; i < columnsArray.length; ++i)
-      this._element.appendChild(this.createCell(columnsArray[i].id));
-    this._element.appendChild(this._createTDWithClass('corner'));
+      element.appendChild(this.createCell(columnsArray[i].id));
+    element.appendChild(this._createTDWithClass('corner'));
   }
 
   /**
@@ -1439,7 +1456,7 @@
       this._element = null;
     if (!this._element)
       return;
-    this.createCells();
+    this.createCells(this._element);
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/ui_lazy/OverviewGrid.js b/third_party/WebKit/Source/devtools/front_end/ui_lazy/OverviewGrid.js
index 90c5f20..856470c 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui_lazy/OverviewGrid.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui_lazy/OverviewGrid.js
@@ -110,6 +110,13 @@
   }
 
   /**
+   * @param {?function(!Event):boolean} clickHandler
+   */
+  setClickHandler(clickHandler) {
+    this._window.setClickHandler(clickHandler);
+  }
+
+  /**
    * @param {number} zoomFactor
    * @param {number} referencePoint
    */
@@ -185,6 +192,13 @@
   }
 
   /**
+   * @param {?function(!Event):boolean} clickHandler
+   */
+  setClickHandler(clickHandler) {
+    this._clickHandler = clickHandler;
+  }
+
+  /**
    * @param {!Event} event
    */
   _resizerElementStartDragging(event) {
@@ -240,7 +254,7 @@
     delete this._overviewWindowSelector;
     var clickThreshold = 3;
     if (window.end - window.start < clickThreshold) {
-      if (this.dispatchEventToListeners(UI.OverviewGrid.Events.Click, event))
+      if (this._clickHandler && this._clickHandler.call(null, event))
         return;
       var middle = window.end;
       window.start = Math.max(0, middle - UI.OverviewGrid.MinSelectableSize / 2);
@@ -405,8 +419,7 @@
 
 /** @enum {symbol} */
 UI.OverviewGrid.Events = {
-  WindowChanged: Symbol('WindowChanged'),
-  Click: Symbol('Click')
+  WindowChanged: Symbol('WindowChanged')
 };
 
 /**
diff --git a/third_party/WebKit/Source/devtools/front_end/ui_lazy/ShowMoreDataGridNode.js b/third_party/WebKit/Source/devtools/front_end/ui_lazy/ShowMoreDataGridNode.js
index 30c5bb3..0e4c57d 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui_lazy/ShowMoreDataGridNode.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui_lazy/ShowMoreDataGridNode.js
@@ -89,10 +89,11 @@
 
   /**
    * @override
+   * @param {!Element} element
    */
-  createCells() {
+  createCells(element) {
     this._hasCells = false;
-    super.createCells();
+    super.createCells(element);
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/ui_lazy/TimelineOverviewPane.js b/third_party/WebKit/Source/devtools/front_end/ui_lazy/TimelineOverviewPane.js
index 9daeb84..7b6de36 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui_lazy/TimelineOverviewPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui_lazy/TimelineOverviewPane.js
@@ -49,7 +49,7 @@
 
     this._overviewGrid.setResizeEnabled(false);
     this._overviewGrid.addEventListener(UI.OverviewGrid.Events.WindowChanged, this._onWindowChanged, this);
-    this._overviewGrid.addEventListener(UI.OverviewGrid.Events.Click, this._onClick, this);
+    this._overviewGrid.setClickHandler(this._onClick.bind(this));
     this._overviewControls = [];
     this._markers = new Map();
 
@@ -264,16 +264,15 @@
   }
 
   /**
-   * @param {!Common.Event} event
+   * @param {!Event} event
+   * @return {boolean}
    */
   _onClick(event) {
-    var domEvent = /** @type {!Event} */ (event.data);
     for (var overviewControl of this._overviewControls) {
-      if (overviewControl.onClick(domEvent)) {
-        event.preventDefault();
-        return;
-      }
+      if (overviewControl.onClick(event))
+        return true;
     }
+    return false;
   }
 
   /**
@@ -508,6 +507,14 @@
   }
 
   /**
+   * @protected
+   * @return {?UI.TimelineOverviewCalculator}
+   */
+  calculator() {
+    return this._calculator;
+  }
+
+  /**
    * @override
    */
   update() {
diff --git a/third_party/WebKit/Source/devtools/front_end/ui_lazy/ViewportDataGrid.js b/third_party/WebKit/Source/devtools/front_end/ui_lazy/ViewportDataGrid.js
index adf618e..7bbc2e1 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui_lazy/ViewportDataGrid.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui_lazy/ViewportDataGrid.js
@@ -221,7 +221,7 @@
     for (var i = 0; i < this._visibleNodes.length; ++i) {
       var oldNode = this._visibleNodes[i];
       if (!visibleNodesSet.has(oldNode) && oldNode.attached()) {
-        var element = oldNode._element;
+        var element = oldNode.existingElement();
         if (element === this._wheelTarget)
           this._hiddenWheelTarget = oldNode.abandonElement();
         else
@@ -306,18 +306,13 @@
    * @return {!Element}
    */
   element() {
-    if (!this._element) {
-      this.createElement();
-      this.createCells();
+    var existingElement = this.existingElement();
+    var element = existingElement || this.createElement();
+    if (!existingElement || this._stale) {
+      this.createCells(element);
       this._stale = false;
     }
-
-    if (this._stale) {
-      this.createCells();
-      this._stale = false;
-    }
-
-    return /** @type {!Element} */ (this._element);
+    return element;
   }
 
   /**
@@ -391,7 +386,7 @@
 
   _unlink() {
     if (this.attached()) {
-      this._element.remove();
+      this.existingElement().remove();
       this.wasDetached();
     }
     this.dataGrid = null;
@@ -407,8 +402,8 @@
     if (!this._expanded)
       return;
     this._expanded = false;
-    if (this._element)
-      this._element.classList.remove('expanded');
+    if (this.existingElement())
+      this.existingElement().classList.remove('expanded');
     this.dataGrid.scheduleUpdateStructure();
   }
 
@@ -433,7 +428,7 @@
    * @return {boolean}
    */
   attached() {
-    return !!(this.dataGrid && this._element && this._element.parentElement);
+    return !!(this.dataGrid && this.existingElement() && this.existingElement().parentElement);
   }
 
   /**
@@ -444,7 +439,7 @@
       this._stale = true;
       this.dataGrid.scheduleUpdate();
     } else {
-      this._element = null;
+      this.resetElement();
     }
   }
 
@@ -452,10 +447,10 @@
    * @return {?Element}
    */
   abandonElement() {
-    var result = this._element;
+    var result = this.existingElement();
     if (result)
       result.style.display = 'none';
-    this._element = null;
+    this.resetElement();
     return result;
   }
 
diff --git a/third_party/WebKit/Source/devtools/scripts/closure/closure_runner/closure_runner.jar b/third_party/WebKit/Source/devtools/scripts/closure/closure_runner/closure_runner.jar
index 6b249c1..21e5d197a 100644
--- a/third_party/WebKit/Source/devtools/scripts/closure/closure_runner/closure_runner.jar
+++ b/third_party/WebKit/Source/devtools/scripts/closure/closure_runner/closure_runner.jar
Binary files differ
diff --git a/third_party/WebKit/Source/devtools/scripts/closure/closure_runner/src/org/chromium/devtools/compiler/DevToolsCodingConvention.java b/third_party/WebKit/Source/devtools/scripts/closure/closure_runner/src/org/chromium/devtools/compiler/DevToolsCodingConvention.java
index 84288376..a238589 100644
--- a/third_party/WebKit/Source/devtools/scripts/closure/closure_runner/src/org/chromium/devtools/compiler/DevToolsCodingConvention.java
+++ b/third_party/WebKit/Source/devtools/scripts/closure/closure_runner/src/org/chromium/devtools/compiler/DevToolsCodingConvention.java
@@ -11,7 +11,7 @@
 
     @Override
     public boolean isPrivate(String name) {
-        return false; // name.length() > 1 && name.charAt(0) == '_' && name.charAt(1) != '_';
+        return name.length() > 1 && name.charAt(0) == '_' && name.charAt(1) != '_';
     }
 
     @Override
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTCharacteristic.cpp b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTCharacteristic.cpp
index 0d4f5a8d..f679ecb 100644
--- a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTCharacteristic.cpp
+++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTCharacteristic.cpp
@@ -368,14 +368,6 @@
 
 ScriptPromise BluetoothRemoteGATTCharacteristic::stopNotifications(
     ScriptState* scriptState) {
-#if OS(MACOSX)
-  // TODO(jlebel): Remove when stopNotifications is implemented.
-  return ScriptPromise::rejectWithDOMException(
-      scriptState, DOMException::create(NotSupportedError,
-                                        "stopNotifications is not implemented "
-                                        "yet. See https://goo.gl/J6ASzs"));
-#endif  // OS(MACOSX)
-
   if (!gatt()->connected()) {
     return ScriptPromise::rejectWithDOMException(
         scriptState,
diff --git a/third_party/WebKit/Source/modules/budget/BudgetService.cpp b/third_party/WebKit/Source/modules/budget/BudgetService.cpp
index afd12a2..fda4afeb 100644
--- a/third_party/WebKit/Source/modules/budget/BudgetService.cpp
+++ b/third_party/WebKit/Source/modules/budget/BudgetService.cpp
@@ -65,10 +65,7 @@
         scriptState, DOMException::create(SecurityError, errorMessage));
 
   mojom::blink::BudgetOperationType type = stringToOperationType(operation);
-  if (type == mojom::blink::BudgetOperationType::INVALID_OPERATION)
-    return ScriptPromise::rejectWithDOMException(
-        scriptState, DOMException::create(NotSupportedError,
-                                          "Invalid operation type specified"));
+  DCHECK_NE(type, mojom::blink::BudgetOperationType::INVALID_OPERATION);
 
   ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
   ScriptPromise promise = resolver->promise();
@@ -129,10 +126,7 @@
   DCHECK(m_service);
 
   mojom::blink::BudgetOperationType type = stringToOperationType(operation);
-  if (type == mojom::blink::BudgetOperationType::INVALID_OPERATION)
-    return ScriptPromise::rejectWithDOMException(
-        scriptState, DOMException::create(NotSupportedError,
-                                          "Invalid operation type specified"));
+  DCHECK_NE(type, mojom::blink::BudgetOperationType::INVALID_OPERATION);
 
   String errorMessage;
   if (!scriptState->getExecutionContext()->isSecureContext(errorMessage))
diff --git a/third_party/WebKit/Source/modules/csspaint/PaintWorkletTest.cpp b/third_party/WebKit/Source/modules/csspaint/PaintWorkletTest.cpp
index 56498780..4c8d400 100644
--- a/third_party/WebKit/Source/modules/csspaint/PaintWorkletTest.cpp
+++ b/third_party/WebKit/Source/modules/csspaint/PaintWorkletTest.cpp
@@ -22,7 +22,7 @@
   PaintWorkletTest() : m_page(DummyPageHolder::create()) {}
 
   PaintWorklet* paintWorklet() {
-    return WindowPaintWorklet::from(*m_page->frame().localDOMWindow())
+    return WindowPaintWorklet::from(*m_page->frame().domWindow())
         .paintWorklet();
   }
 
diff --git a/third_party/WebKit/Source/modules/device_orientation/DeviceMotionController.cpp b/third_party/WebKit/Source/modules/device_orientation/DeviceMotionController.cpp
index f204460..52d6e60 100644
--- a/third_party/WebKit/Source/modules/device_orientation/DeviceMotionController.cpp
+++ b/third_party/WebKit/Source/modules/device_orientation/DeviceMotionController.cpp
@@ -43,8 +43,7 @@
     return;
 
   if (document().frame()) {
-    String errorMessage;
-    if (document().isSecureContext(errorMessage)) {
+    if (document().isSecureContext()) {
       UseCounter::count(document().frame(),
                         UseCounter::DeviceMotionSecureOrigin);
     } else {
diff --git a/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationAbsoluteController.cpp b/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationAbsoluteController.cpp
index 4683ffa..7703574 100644
--- a/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationAbsoluteController.cpp
+++ b/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationAbsoluteController.cpp
@@ -42,8 +42,7 @@
     return;
 
   if (document().frame()) {
-    String errorMessage;
-    if (document().isSecureContext(errorMessage)) {
+    if (document().isSecureContext()) {
       UseCounter::count(document().frame(),
                         UseCounter::DeviceOrientationAbsoluteSecureOrigin);
     } else {
diff --git a/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationController.cpp b/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationController.cpp
index 7d39dab..0390ae3 100644
--- a/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationController.cpp
+++ b/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationController.cpp
@@ -52,8 +52,7 @@
     return;
 
   if (document().frame()) {
-    String errorMessage;
-    if (document().isSecureContext(errorMessage)) {
+    if (document().isSecureContext()) {
       UseCounter::count(document().frame(),
                         UseCounter::DeviceOrientationSecureOrigin);
     } else {
diff --git a/third_party/WebKit/Source/modules/encryptedmedia/NavigatorRequestMediaKeySystemAccess.cpp b/third_party/WebKit/Source/modules/encryptedmedia/NavigatorRequestMediaKeySystemAccess.cpp
index 7ba57ec0..76c9f5d 100644
--- a/third_party/WebKit/Source/modules/encryptedmedia/NavigatorRequestMediaKeySystemAccess.cpp
+++ b/third_party/WebKit/Source/modules/encryptedmedia/NavigatorRequestMediaKeySystemAccess.cpp
@@ -355,8 +355,7 @@
   // sites, we simply keep track of sites that aren't secure and output a
   // deprecation message.
   ExecutionContext* executionContext = scriptState->getExecutionContext();
-  String errorMessage;
-  if (executionContext->isSecureContext(errorMessage)) {
+  if (executionContext->isSecureContext()) {
     UseCounter::count(executionContext, UseCounter::EncryptedMediaSecureOrigin);
   } else {
     Deprecation::countDeprecation(executionContext,
diff --git a/third_party/WebKit/Source/modules/fetch/FetchManager.cpp b/third_party/WebKit/Source/modules/fetch/FetchManager.cpp
index 87f92a5..471c0a99 100644
--- a/third_party/WebKit/Source/modules/fetch/FetchManager.cpp
+++ b/third_party/WebKit/Source/modules/fetch/FetchManager.cpp
@@ -408,8 +408,8 @@
         tainting = FetchRequestData::OpaqueTainting;
         break;
       case WebServiceWorkerResponseTypeOpaqueRedirect:
-      // ServiceWorker can't respond to the request from fetch() with an
-      // opaque redirect response.
+        DCHECK(NetworkUtils::isRedirectResponseCode(m_responseHttpStatusCode));
+        break;  // The code below creates an opaque-redirect filtered response.
       case WebServiceWorkerResponseTypeError:
         LOG(FATAL) << "When ServiceWorker respond to the request from fetch() "
                       "with an error response, FetchManager::Loader::didFail() "
diff --git a/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.cpp b/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.cpp
index f99ab0b..546499b 100644
--- a/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.cpp
+++ b/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.cpp
@@ -174,7 +174,7 @@
           this,
           &NavigatorGamepad::dispatchOneEvent)) {
   if (frame)
-    frame->localDOMWindow()->registerEventListenerObserver(this);
+    frame->domWindow()->registerEventListenerObserver(this);
 }
 
 NavigatorGamepad::~NavigatorGamepad() {}
diff --git a/third_party/WebKit/Source/modules/notifications/Notification.cpp b/third_party/WebKit/Source/modules/notifications/Notification.cpp
index f2fa76b..ff8630b4 100644
--- a/third_party/WebKit/Source/modules/notifications/Notification.cpp
+++ b/third_party/WebKit/Source/modules/notifications/Notification.cpp
@@ -91,8 +91,7 @@
     return nullptr;
   }
 
-  String insecureOriginMessage;
-  if (context->isSecureContext(insecureOriginMessage)) {
+  if (context->isSecureContext()) {
     UseCounter::count(context, UseCounter::NotificationSecureOrigin);
     if (context->isDocument())
       UseCounter::countCrossOriginIframe(
diff --git a/third_party/WebKit/Source/modules/permissions/Permissions.cpp b/third_party/WebKit/Source/modules/permissions/Permissions.cpp
index 873b4452..0050013 100644
--- a/third_party/WebKit/Source/modules/permissions/Permissions.cpp
+++ b/third_party/WebKit/Source/modules/permissions/Permissions.cpp
@@ -156,7 +156,7 @@
   service->RequestPermission(
       std::move(descriptor),
       scriptState->getExecutionContext()->getSecurityOrigin(),
-      UserGestureIndicator::processingUserGesture(),
+      UserGestureIndicator::processingUserGestureThreadSafe(),
       convertToBaseCallback(WTF::bind(
           &Permissions::taskComplete, wrapPersistent(this),
           wrapPersistent(resolver), WTF::passed(std::move(descriptorCopy)))));
@@ -247,7 +247,7 @@
   service->RequestPermissions(
       std::move(internalPermissions),
       scriptState->getExecutionContext()->getSecurityOrigin(),
-      UserGestureIndicator::processingUserGesture(),
+      UserGestureIndicator::processingUserGestureThreadSafe(),
       convertToBaseCallback(
           WTF::bind(&Permissions::batchTaskComplete, wrapPersistent(this),
                     wrapPersistent(resolver),
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ForeignFetchRespondWithObserver.cpp b/third_party/WebKit/Source/modules/serviceworkers/ForeignFetchRespondWithObserver.cpp
index b0ade79..2fcc3e0 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ForeignFetchRespondWithObserver.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ForeignFetchRespondWithObserver.cpp
@@ -15,13 +15,14 @@
     int eventID,
     const KURL& requestURL,
     WebURLRequest::FetchRequestMode requestMode,
+    WebURLRequest::FetchRedirectMode redirectMode,
     WebURLRequest::FrameType frameType,
     WebURLRequest::RequestContext requestContext,
     PassRefPtr<SecurityOrigin> requestOrigin,
     WaitUntilObserver* observer) {
   return new ForeignFetchRespondWithObserver(
-      context, eventID, requestURL, requestMode, frameType, requestContext,
-      std::move(requestOrigin), observer);
+      context, eventID, requestURL, requestMode, redirectMode, frameType,
+      requestContext, std::move(requestOrigin), observer);
 }
 
 void ForeignFetchRespondWithObserver::responseWasFulfilled(
@@ -95,6 +96,7 @@
     int eventID,
     const KURL& requestURL,
     WebURLRequest::FetchRequestMode requestMode,
+    WebURLRequest::FetchRedirectMode redirectMode,
     WebURLRequest::FrameType frameType,
     WebURLRequest::RequestContext requestContext,
     PassRefPtr<SecurityOrigin> requestOrigin,
@@ -103,6 +105,7 @@
                           eventID,
                           requestURL,
                           requestMode,
+                          redirectMode,
                           frameType,
                           requestContext,
                           observer),
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ForeignFetchRespondWithObserver.h b/third_party/WebKit/Source/modules/serviceworkers/ForeignFetchRespondWithObserver.h
index 3c4b2b8..4489268 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ForeignFetchRespondWithObserver.h
+++ b/third_party/WebKit/Source/modules/serviceworkers/ForeignFetchRespondWithObserver.h
@@ -19,6 +19,7 @@
       int eventID,
       const KURL& requestURL,
       WebURLRequest::FetchRequestMode,
+      WebURLRequest::FetchRedirectMode,
       WebURLRequest::FrameType,
       WebURLRequest::RequestContext,
       PassRefPtr<SecurityOrigin>,
@@ -31,6 +32,7 @@
                                   int eventID,
                                   const KURL& requestURL,
                                   WebURLRequest::FetchRequestMode,
+                                  WebURLRequest::FetchRedirectMode,
                                   WebURLRequest::FrameType,
                                   WebURLRequest::RequestContext,
                                   PassRefPtr<SecurityOrigin>,
diff --git a/third_party/WebKit/Source/modules/serviceworkers/RespondWithObserver.cpp b/third_party/WebKit/Source/modules/serviceworkers/RespondWithObserver.cpp
index 0551f8b..4d4b53a 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/RespondWithObserver.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/RespondWithObserver.cpp
@@ -69,7 +69,7 @@
     case WebServiceWorkerResponseErrorResponseTypeOpaqueRedirect:
       errorMessage = errorMessage +
                      "an \"opaqueredirect\" type response was used for a "
-                     "request which is not a navigation request.";
+                     "request whose redirect mode is not \"manual\".";
       break;
     case WebServiceWorkerResponseErrorBodyLocked:
       errorMessage = errorMessage +
@@ -90,6 +90,11 @@
       errorMessage =
           errorMessage + "origin in response does not match origin of request.";
       break;
+    case WebServiceWorkerResponseErrorRedirectedResponseForNotFollowRequest:
+      errorMessage = errorMessage +
+                     "a redirected response was used for a request whose "
+                     "redirect mode is not \"follow\".";
+      break;
     case WebServiceWorkerResponseErrorUnknown:
     default:
       errorMessage = errorMessage + "an unexpected error occurred.";
@@ -98,6 +103,22 @@
   return errorMessage;
 }
 
+const String getErrorMessageForRedirectedResponseForNavigationRequest(
+    const KURL& requestURL,
+    const Vector<KURL>& responseURLList) {
+  String errorMessage =
+      "In Chrome 59, the navigation to \"" + requestURL.getString() + "\" " +
+      "will result in a network error, because FetchEvent.respondWith() was " +
+      "called with a redirected response. See https://crbug.com/658249. The " +
+      "url list of the response was: [\"" + responseURLList[0].getString() +
+      "\"";
+  for (size_t i = 1; i < responseURLList.size(); ++i) {
+    errorMessage =
+        errorMessage + ", \"" + responseURLList[i].getString() + "\"";
+  }
+  return errorMessage + "]";
+}
+
 bool isNavigationRequest(WebURLRequest::FrameType frameType) {
   return frameType != WebURLRequest::FrameTypeNone;
 }
@@ -177,11 +198,13 @@
     int fetchEventID,
     const KURL& requestURL,
     WebURLRequest::FetchRequestMode requestMode,
+    WebURLRequest::FetchRedirectMode redirectMode,
     WebURLRequest::FrameType frameType,
     WebURLRequest::RequestContext requestContext,
     WaitUntilObserver* observer) {
   return new RespondWithObserver(context, fetchEventID, requestURL, requestMode,
-                                 frameType, requestContext, observer);
+                                 redirectMode, frameType, requestContext,
+                                 observer);
 }
 
 void RespondWithObserver::contextDestroyed() {
@@ -284,12 +307,27 @@
       return;
     }
   }
-  if (!isNavigationRequest(m_frameType) &&
+  if (m_redirectMode != WebURLRequest::FetchRedirectModeManual &&
       responseType == FetchResponseData::OpaqueRedirectType) {
     responseWasRejected(
         WebServiceWorkerResponseErrorResponseTypeOpaqueRedirect);
     return;
   }
+  if (m_redirectMode != WebURLRequest::FetchRedirectModeFollow &&
+      response->redirected()) {
+    if (!isNavigationRequest(m_frameType)) {
+      responseWasRejected(
+          WebServiceWorkerResponseErrorRedirectedResponseForNotFollowRequest);
+      return;
+    }
+    // TODO(horo): We should just reject even if the request was a navigation.
+    // Currently we measure the impact of the restriction with the use counter
+    // in DocumentLoader.
+    getExecutionContext()->addConsoleMessage(ConsoleMessage::create(
+        JSMessageSource, ErrorMessageLevel,
+        getErrorMessageForRedirectedResponseForNavigationRequest(
+            m_requestURL, response->internalURLList())));
+  }
   if (response->isBodyLocked()) {
     responseWasRejected(WebServiceWorkerResponseErrorBodyLocked);
     return;
@@ -326,6 +364,7 @@
     int fetchEventID,
     const KURL& requestURL,
     WebURLRequest::FetchRequestMode requestMode,
+    WebURLRequest::FetchRedirectMode redirectMode,
     WebURLRequest::FrameType frameType,
     WebURLRequest::RequestContext requestContext,
     WaitUntilObserver* observer)
@@ -333,6 +372,7 @@
       m_fetchEventID(fetchEventID),
       m_requestURL(requestURL),
       m_requestMode(requestMode),
+      m_redirectMode(redirectMode),
       m_frameType(frameType),
       m_requestContext(requestContext),
       m_state(Initial),
diff --git a/third_party/WebKit/Source/modules/serviceworkers/RespondWithObserver.h b/third_party/WebKit/Source/modules/serviceworkers/RespondWithObserver.h
index 087d06b4..b7f049a 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/RespondWithObserver.h
+++ b/third_party/WebKit/Source/modules/serviceworkers/RespondWithObserver.h
@@ -35,6 +35,7 @@
                                      int fetchEventID,
                                      const KURL& requestURL,
                                      WebURLRequest::FetchRequestMode,
+                                     WebURLRequest::FetchRedirectMode,
                                      WebURLRequest::FrameType,
                                      WebURLRequest::RequestContext,
                                      WaitUntilObserver*);
@@ -58,6 +59,7 @@
                       int fetchEventID,
                       const KURL& requestURL,
                       WebURLRequest::FetchRequestMode,
+                      WebURLRequest::FetchRedirectMode,
                       WebURLRequest::FrameType,
                       WebURLRequest::RequestContext,
                       WaitUntilObserver*);
@@ -65,11 +67,12 @@
  private:
   class ThenFunction;
 
-  int m_fetchEventID;
-  KURL m_requestURL;
-  WebURLRequest::FetchRequestMode m_requestMode;
-  WebURLRequest::FrameType m_frameType;
-  WebURLRequest::RequestContext m_requestContext;
+  const int m_fetchEventID;
+  const KURL m_requestURL;
+  const WebURLRequest::FetchRequestMode m_requestMode;
+  const WebURLRequest::FetchRedirectMode m_redirectMode;
+  const WebURLRequest::FrameType m_frameType;
+  const WebURLRequest::RequestContext m_requestContext;
 
   double m_eventDispatchTime = 0;
 
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.cpp
index 29948f0d5..ca34c93 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.cpp
@@ -29,6 +29,7 @@
  */
 #include "modules/serviceworkers/ServiceWorkerContainer.h"
 
+#include "bindings/core/v8/CallbackPromiseAdapter.h"
 #include "bindings/core/v8/ScriptPromise.h"
 #include "bindings/core/v8/ScriptPromiseResolver.h"
 #include "bindings/core/v8/ScriptState.h"
@@ -62,41 +63,6 @@
 
 namespace blink {
 
-class RegistrationCallback
-    : public WebServiceWorkerProvider::WebServiceWorkerRegistrationCallbacks {
- public:
-  explicit RegistrationCallback(ScriptPromiseResolver* resolver)
-      : m_resolver(resolver) {}
-  ~RegistrationCallback() override {}
-
-  void onSuccess(
-      std::unique_ptr<WebServiceWorkerRegistration::Handle> handle) override {
-    if (!m_resolver->getExecutionContext() ||
-        m_resolver->getExecutionContext()->isContextDestroyed())
-      return;
-    m_resolver->resolve(ServiceWorkerRegistration::getOrCreate(
-        m_resolver->getExecutionContext(), WTF::wrapUnique(handle.release())));
-  }
-
-  void onError(const WebServiceWorkerError& error) override {
-    if (!m_resolver->getExecutionContext() ||
-        m_resolver->getExecutionContext()->isContextDestroyed())
-      return;
-    ScriptState::Scope scope(m_resolver->getScriptState());
-    if (error.errorType == WebServiceWorkerError::ErrorTypeType) {
-      m_resolver->reject(V8ThrowException::createTypeError(
-          m_resolver->getScriptState()->isolate(), error.message));
-    } else {
-      m_resolver->reject(
-          ServiceWorkerErrorForUpdate::take(m_resolver.get(), error));
-    }
-  }
-
- private:
-  Persistent<ScriptPromiseResolver> m_resolver;
-  WTF_MAKE_NONCOPYABLE(RegistrationCallback);
-};
-
 class GetRegistrationCallback : public WebServiceWorkerProvider::
                                     WebServiceWorkerGetRegistrationCallbacks {
  public:
@@ -132,42 +98,6 @@
   WTF_MAKE_NONCOPYABLE(GetRegistrationCallback);
 };
 
-class GetRegistrationsCallback : public WebServiceWorkerProvider::
-                                     WebServiceWorkerGetRegistrationsCallbacks {
- public:
-  explicit GetRegistrationsCallback(ScriptPromiseResolver* resolver)
-      : m_resolver(resolver) {}
-  ~GetRegistrationsCallback() override {}
-
-  void onSuccess(
-      std::unique_ptr<WebVector<WebServiceWorkerRegistration::Handle*>>
-          webPassRegistrations) override {
-    Vector<std::unique_ptr<WebServiceWorkerRegistration::Handle>> handles;
-    std::unique_ptr<WebVector<WebServiceWorkerRegistration::Handle*>>
-        webRegistrations = WTF::wrapUnique(webPassRegistrations.release());
-    for (auto& handle : *webRegistrations) {
-      handles.append(WTF::wrapUnique(handle));
-    }
-
-    if (!m_resolver->getExecutionContext() ||
-        m_resolver->getExecutionContext()->isContextDestroyed())
-      return;
-    m_resolver->resolve(
-        ServiceWorkerRegistrationArray::take(m_resolver.get(), &handles));
-  }
-
-  void onError(const WebServiceWorkerError& error) override {
-    if (!m_resolver->getExecutionContext() ||
-        m_resolver->getExecutionContext()->isContextDestroyed())
-      return;
-    m_resolver->reject(ServiceWorkerError::take(m_resolver.get(), error));
-  }
-
- private:
-  Persistent<ScriptPromiseResolver> m_resolver;
-  WTF_MAKE_NONCOPYABLE(GetRegistrationsCallback);
-};
-
 class ServiceWorkerContainer::GetRegistrationForReadyCallback
     : public WebServiceWorkerProvider::
           WebServiceWorkerGetRegistrationForReadyCallbacks {
@@ -358,8 +288,11 @@
     patternURL = enteredExecutionContext(scriptState->isolate())
                      ->completeURL(options.scope());
 
-  registerServiceWorkerImpl(executionContext, scriptURL, patternURL,
-                            WTF::makeUnique<RegistrationCallback>(resolver));
+  registerServiceWorkerImpl(
+      executionContext, scriptURL, patternURL,
+      WTF::makeUnique<CallbackPromiseAdapter<ServiceWorkerRegistration,
+                                             ServiceWorkerErrorForUpdate>>(
+          resolver));
 
   return promise;
 }
@@ -455,7 +388,8 @@
   }
 
   m_provider->getRegistrations(
-      WTF::makeUnique<GetRegistrationsCallback>(resolver));
+      WTF::makeUnique<CallbackPromiseAdapter<ServiceWorkerRegistrationArray,
+                                             ServiceWorkerError>>(resolver));
 
   return promise;
 }
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerError.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerError.cpp
index 93e1fdad..f197f17f 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerError.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerError.cpp
@@ -137,6 +137,9 @@
       // a TypeError.
       return V8ThrowException::createTypeError(
           scriptState->isolate(), getExceptionParams(webError).message);
+    case WebServiceWorkerError::ErrorTypeType:
+      return V8ThrowException::createTypeError(scriptState->isolate(),
+                                               webError.message);
     default:
       return toV8(ServiceWorkerError::take(resolver, webError),
                   scriptState->context()->Global(), scriptState->isolate());
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerRegistration.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerRegistration.cpp
index 01f905d8..80811fec 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerRegistration.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerRegistration.cpp
@@ -21,6 +21,12 @@
 
 namespace blink {
 
+ServiceWorkerRegistration* ServiceWorkerRegistration::take(
+    ScriptPromiseResolver* resolver,
+    std::unique_ptr<WebServiceWorkerRegistration::Handle> handle) {
+  return getOrCreate(resolver->getExecutionContext(), std::move(handle));
+}
+
 bool ServiceWorkerRegistration::hasPendingActivity() const {
   return !m_stopped;
 }
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerRegistration.h b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerRegistration.h
index b748839..3add8bbf 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerRegistration.h
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerRegistration.h
@@ -37,6 +37,12 @@
   USING_PRE_FINALIZER(ServiceWorkerRegistration, dispose);
 
  public:
+  // Called from CallbackPromiseAdapter.
+  using WebType = std::unique_ptr<WebServiceWorkerRegistration::Handle>;
+  static ServiceWorkerRegistration* take(
+      ScriptPromiseResolver*,
+      std::unique_ptr<WebServiceWorkerRegistration::Handle>);
+
   // ScriptWrappable overrides.
   bool hasPendingActivity() const final;
 
@@ -102,14 +108,17 @@
   STATIC_ONLY(ServiceWorkerRegistrationArray);
 
  public:
+  // Called from CallbackPromiseAdapter.
+  using WebType = std::unique_ptr<
+      WebVector<std::unique_ptr<WebServiceWorkerRegistration::Handle>>>;
   static HeapVector<Member<ServiceWorkerRegistration>> take(
       ScriptPromiseResolver* resolver,
-      Vector<std::unique_ptr<WebServiceWorkerRegistration::Handle>>*
-          webServiceWorkerRegistrations) {
+      WebType webServiceWorkerRegistrations) {
     HeapVector<Member<ServiceWorkerRegistration>> registrations;
-    for (auto& registration : *webServiceWorkerRegistrations)
-      registrations.append(ServiceWorkerRegistration::getOrCreate(
-          resolver->getExecutionContext(), std::move(registration)));
+    for (auto& registration : *webServiceWorkerRegistrations) {
+      registrations.append(
+          ServiceWorkerRegistration::take(resolver, std::move(registration)));
+    }
     return registrations;
   }
 };
diff --git a/third_party/WebKit/Source/modules/storage/StorageArea.cpp b/third_party/WebKit/Source/modules/storage/StorageArea.cpp
index 9e3bb551..3271d940 100644
--- a/third_party/WebKit/Source/modules/storage/StorageArea.cpp
+++ b/third_party/WebKit/Source/modules/storage/StorageArea.cpp
@@ -174,14 +174,14 @@
       if (!frame->isLocalFrame())
         continue;
       LocalFrame* localFrame = toLocalFrame(frame);
-      LocalDOMWindow* localWindow = localFrame->localDOMWindow();
+      LocalDOMWindow* localWindow = localFrame->domWindow();
       Storage* storage =
           DOMWindowStorage::from(*localWindow).optionalLocalStorage();
       if (storage &&
           localFrame->document()->getSecurityOrigin()->canAccess(
               securityOrigin) &&
           !isEventSource(storage, sourceAreaInstance))
-        localFrame->localDOMWindow()->enqueueWindowEvent(
+        localFrame->domWindow()->enqueueWindowEvent(
             StorageEvent::create(EventTypeNames::storage, key, oldValue,
                                  newValue, pageURL, storage));
     }
@@ -225,14 +225,14 @@
     if (!frame->isLocalFrame())
       continue;
     LocalFrame* localFrame = toLocalFrame(frame);
-    LocalDOMWindow* localWindow = localFrame->localDOMWindow();
+    LocalDOMWindow* localWindow = localFrame->domWindow();
     Storage* storage =
         DOMWindowStorage::from(*localWindow).optionalSessionStorage();
     if (storage &&
         localFrame->document()->getSecurityOrigin()->canAccess(
             securityOrigin) &&
         !isEventSource(storage, sourceAreaInstance))
-      localFrame->localDOMWindow()->enqueueWindowEvent(StorageEvent::create(
+      localFrame->domWindow()->enqueueWindowEvent(StorageEvent::create(
           EventTypeNames::storage, key, oldValue, newValue, pageURL, storage));
   }
   if (InspectorDOMStorageAgent* agent =
diff --git a/third_party/WebKit/Source/modules/vibration/NavigatorVibration.cpp b/third_party/WebKit/Source/modules/vibration/NavigatorVibration.cpp
index a932c52..95e5b353 100644
--- a/third_party/WebKit/Source/modules/vibration/NavigatorVibration.cpp
+++ b/third_party/WebKit/Source/modules/vibration/NavigatorVibration.cpp
@@ -82,11 +82,11 @@
   // runtime flag.
   if (!isFeatureEnabledInFrame(blink::kVibrateFeature, frame)) {
     if (RuntimeEnabledFeatures::featurePolicyEnabled()) {
-      frame->localDOMWindow()->printErrorMessage(
+      frame->domWindow()->printErrorMessage(
           "Navigator.vibrate() is not enabled in feature policy for this "
           "frame.");
     } else {
-      frame->localDOMWindow()->printErrorMessage(
+      frame->domWindow()->printErrorMessage(
           "A call of navigator.vibrate will be no-op inside cross-origin "
           "iframes: https://www.chromestatus.com/feature/5682658461876224.");
     }
diff --git a/third_party/WebKit/Source/modules/vr/NavigatorVR.cpp b/third_party/WebKit/Source/modules/vr/NavigatorVR.cpp
index 68a6c6b..1dfdcf8a 100644
--- a/third_party/WebKit/Source/modules/vr/NavigatorVR.cpp
+++ b/third_party/WebKit/Source/modules/vr/NavigatorVR.cpp
@@ -61,8 +61,7 @@
 
   UseCounter::count(*document, UseCounter::VRGetDisplays);
   ExecutionContext* executionContext = scriptState->getExecutionContext();
-  String errorMessage;
-  if (!executionContext->isSecureContext(errorMessage))
+  if (!executionContext->isSecureContext())
     UseCounter::count(*document, UseCounter::VRGetDisplaysInsecureOrigin);
 
   Platform::current()->recordRapporURL("VR.WebVR.GetDisplays", document->url());
@@ -97,7 +96,7 @@
 
 NavigatorVR::NavigatorVR(LocalFrame* frame)
     : DOMWindowProperty(frame), PageVisibilityObserver(frame->page()) {
-  frame->localDOMWindow()->registerEventListenerObserver(this);
+  frame->domWindow()->registerEventListenerObserver(this);
 }
 
 NavigatorVR::~NavigatorVR() {}
@@ -107,17 +106,19 @@
 }
 
 void NavigatorVR::enqueueVREvent(VRDisplayEvent* event) {
-  if (frame() && frame()->localDOMWindow()) {
-    frame()->localDOMWindow()->enqueueWindowEvent(event);
+  // TODO(dcheng): Why does this need to check both frame and domWindow?
+  if (frame() && frame()->domWindow()) {
+    frame()->domWindow()->enqueueWindowEvent(event);
   }
 }
 
 void NavigatorVR::dispatchVRGestureEvent(VRDisplayEvent* event) {
-  if (frame() && frame()->localDOMWindow()) {
+  // TODO(dcheng): Why does this need to check both frame and domWindow?
+  if (frame() && frame()->domWindow()) {
     UserGestureIndicator gestureIndicator(
         DocumentUserGestureToken::create(frame()->document()));
-    event->setTarget(frame()->localDOMWindow());
-    frame()->localDOMWindow()->dispatchEvent(event);
+    event->setTarget(frame()->domWindow());
+    frame()->domWindow()->dispatchEvent(event);
   }
 }
 
diff --git a/third_party/WebKit/Source/modules/vr/VRDisplay.cpp b/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
index debe0fb..f4ed320c 100644
--- a/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
+++ b/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
@@ -283,8 +283,7 @@
                                         const HeapVector<VRLayer>& layers) {
   ExecutionContext* executionContext = scriptState->getExecutionContext();
   UseCounter::count(executionContext, UseCounter::VRRequestPresent);
-  String errorMessage;
-  if (!executionContext->isSecureContext(errorMessage)) {
+  if (!executionContext->isSecureContext()) {
     UseCounter::count(executionContext,
                       UseCounter::VRRequestPresentInsecureOrigin);
   }
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn
index d43ec77..0a49563d 100644
--- a/third_party/WebKit/Source/platform/BUILD.gn
+++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -1606,6 +1606,7 @@
     "testing/MessageLoopForMojo.h",
     "testing/PaintPrinters.cpp",
     "testing/PaintPrinters.h",
+    "testing/PaintPropertyTestHelpers.h",
     "testing/PictureMatchers.cpp",
     "testing/PictureMatchers.h",
     "testing/PlatformTestPrinters.cpp",
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
index 33b67cc..127f6dc 100644
--- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
+++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
@@ -276,5 +276,5 @@
 LazyParseCSS status=experimental
 ParseHTMLOnMainThread status=test
 SendBeaconThrowForBlobWithNonSimpleType status=experimental
-PerformanceNavigationTiming2 status=test
+PerformanceNavigationTiming2 status=experimental
 BackgroundVideoTrackOptimization status=stable
diff --git a/third_party/WebKit/Source/platform/UserGestureIndicator.cpp b/third_party/WebKit/Source/platform/UserGestureIndicator.cpp
index 84433950..6311458 100644
--- a/third_party/WebKit/Source/platform/UserGestureIndicator.cpp
+++ b/third_party/WebKit/Source/platform/UserGestureIndicator.cpp
@@ -42,7 +42,7 @@
       m_timestamp(WTF::currentTime()),
       m_timeoutPolicy(Default),
       m_usageCallback(nullptr) {
-  if (status == NewGesture || !UserGestureIndicator::currentToken())
+  if (status == NewGesture || !UserGestureIndicator::currentTokenThreadSafe())
     m_consumableGestures++;
 }
 
@@ -151,18 +151,18 @@
 }
 
 bool UserGestureIndicator::processingUserGesture() {
-  if (auto* token = currentToken()) {
-    ASSERT(isMainThread());
+  if (auto* token = currentToken())
     return token->hasGestures();
-  }
-
   return false;
 }
 
+bool UserGestureIndicator::processingUserGestureThreadSafe() {
+  return isMainThread() && processingUserGesture();
+}
+
 // static
 bool UserGestureIndicator::consumeUserGesture() {
   if (auto* token = currentToken()) {
-    ASSERT(isMainThread());
     if (token->consumeGesture()) {
       token->userGestureUtilized();
       return true;
@@ -171,11 +171,17 @@
   return false;
 }
 
-// static
+bool UserGestureIndicator::consumeUserGestureThreadSafe() {
+  return isMainThread() && consumeUserGesture();
+}
+
 UserGestureToken* UserGestureIndicator::currentToken() {
-  if (!isMainThread() || !s_rootToken)
-    return nullptr;
+  DCHECK(isMainThread());
   return s_rootToken;
 }
 
+UserGestureToken* UserGestureIndicator::currentTokenThreadSafe() {
+  return isMainThread() ? currentToken() : nullptr;
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/UserGestureIndicator.h b/third_party/WebKit/Source/platform/UserGestureIndicator.h
index 5cab2e0..4e4cebe2 100644
--- a/third_party/WebKit/Source/platform/UserGestureIndicator.h
+++ b/third_party/WebKit/Source/platform/UserGestureIndicator.h
@@ -94,11 +94,17 @@
   WTF_MAKE_NONCOPYABLE(UserGestureIndicator);
 
  public:
+  // Note: All *ThreadSafe methods are safe to call from any thread. Their
+  // non-suffixed counterparts *must* be called on the main thread. Consider
+  // always using the non-suffixed one unless the code really
+  // needs to be thread-safe
+
   // Returns whether a user gesture is currently in progress.
   // Does not invoke the UserGestureUtilizedCallback.  Consider calling
   // utilizeUserGesture instead if you know for sure that the return value
   // will have an effect.
   static bool processingUserGesture();
+  static bool processingUserGestureThreadSafe();
 
   // Indicates that a user gesture (if any) is being used, without preventing it
   // from being used again.  Returns whether a user gesture is currently in
@@ -111,8 +117,10 @@
   // operations like creating a new process.
   // Like utilizeUserGesture, may invoke/clear any UserGestureUtilizedCallback.
   static bool consumeUserGesture();
+  static bool consumeUserGestureThreadSafe();
 
   static UserGestureToken* currentToken();
+  static UserGestureToken* currentTokenThreadSafe();
 
   explicit UserGestureIndicator(PassRefPtr<UserGestureToken>);
   ~UserGestureIndicator();
diff --git a/third_party/WebKit/Source/platform/WebTaskRunner.h b/third_party/WebKit/Source/platform/WebTaskRunner.h
index b6cf972f..073e1ee 100644
--- a/third_party/WebKit/Source/platform/WebTaskRunner.h
+++ b/third_party/WebKit/Source/platform/WebTaskRunner.h
@@ -60,22 +60,6 @@
  public:
   virtual ~WebTaskRunner() {}
 
-  class BLINK_PLATFORM_EXPORT Task {
-   public:
-    virtual ~Task() {}
-    virtual void run() = 0;
-  };
-
-  // Schedule a task to be run on the the associated WebThread.
-  // Takes ownership of |Task|. Can be called from any thread.
-  virtual void postTask(const WebTraceLocation&, Task*) = 0;
-
-  // Schedule a task to be run after |delayMs| on the the associated WebThread.
-  // Takes ownership of |Task|. Can be called from any thread.
-  virtual void postDelayedTask(const WebTraceLocation&,
-                               Task*,
-                               double delayMs) = 0;
-
   // Schedule a task to be run after |delayMs| on the the associated WebThread.
   // Can be called from any thread.
   virtual void postDelayedTask(const WebTraceLocation&,
diff --git a/third_party/WebKit/Source/platform/exported/WebSecurityOrigin.cpp b/third_party/WebKit/Source/platform/exported/WebSecurityOrigin.cpp
index bfaaaa1..a23adf014 100644
--- a/third_party/WebKit/Source/platform/exported/WebSecurityOrigin.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebSecurityOrigin.cpp
@@ -95,7 +95,8 @@
 
 WebString WebSecurityOrigin::suborigin() const {
   DCHECK(m_private);
-  return m_private->hasSuborigin() ? m_private->suborigin()->name() : "";
+  return m_private->hasSuborigin() ? WebString(m_private->suborigin()->name())
+                                   : WebString();
 }
 
 bool WebSecurityOrigin::isUnique() const {
diff --git a/third_party/WebKit/Source/platform/graphics/CompositingReasons.cpp b/third_party/WebKit/Source/platform/graphics/CompositingReasons.cpp
index b053de8..fdc3d2a 100644
--- a/third_party/WebKit/Source/platform/graphics/CompositingReasons.cpp
+++ b/third_party/WebKit/Source/platform/graphics/CompositingReasons.cpp
@@ -127,6 +127,10 @@
      "Secondary layer, to contain the mask contents"},
     {CompositingReasonLayerForClippingMask, "layerForClippingMask",
      "Secondary layer, for clipping mask"},
+    {CompositingReasonLayerForAncestorClippingMask,
+     "layerForAncestorClippingMask",
+     "Secondary layer, applies a clipping mask due to a sibling in the "
+     "composited layer tree"},
     {CompositingReasonLayerForScrollingBlockSelection,
      "layerForScrollingBlockSelection",
      "Secondary layer, to house block selection gaps for composited scrolling "
diff --git a/third_party/WebKit/Source/platform/graphics/CompositingReasons.h b/third_party/WebKit/Source/platform/graphics/CompositingReasons.h
index e0d8667..aff8adc 100644
--- a/third_party/WebKit/Source/platform/graphics/CompositingReasons.h
+++ b/third_party/WebKit/Source/platform/graphics/CompositingReasons.h
@@ -84,16 +84,18 @@
 const uint64_t CompositingReasonLayerForBackground = UINT64_C(1) << 44;
 const uint64_t CompositingReasonLayerForMask = UINT64_C(1) << 45;
 const uint64_t CompositingReasonLayerForClippingMask = UINT64_C(1) << 46;
+const uint64_t CompositingReasonLayerForAncestorClippingMask = UINT64_C(1)
+                                                               << 47;
 const uint64_t CompositingReasonLayerForScrollingBlockSelection = UINT64_C(1)
-                                                                  << 47;
+                                                                  << 48;
 // Composited layer painted on top of all other layers as decoration
-const uint64_t CompositingReasonLayerForDecoration = UINT64_C(1) << 48;
+const uint64_t CompositingReasonLayerForDecoration = UINT64_C(1) << 49;
 
 // Composited elements with inline transforms trigger assumed overlap so that
 // we can update their transforms quickly.
-const uint64_t CompositingReasonInlineTransform = UINT64_C(1) << 49;
+const uint64_t CompositingReasonInlineTransform = UINT64_C(1) << 50;
 
-const uint64_t CompositingReasonCompositorProxy = UINT64_C(1) << 50;
+const uint64_t CompositingReasonCompositorProxy = UINT64_C(1) << 51;
 
 // Various combinations of compositing reasons are defined here also, for more
 // intutive and faster bitwise logic.
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
index d2a9211..7816da4 100644
--- a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
@@ -738,6 +738,8 @@
       paintingPhasesJSON->pushString("GraphicsLayerPaintMask");
     if (m_paintingPhase & GraphicsLayerPaintChildClippingMask)
       paintingPhasesJSON->pushString("GraphicsLayerPaintChildClippingMask");
+    if (m_paintingPhase & GraphicsLayerPaintAncestorClippingMask)
+      paintingPhasesJSON->pushString("GraphicsLayerPaintAncestorClippingMask");
     if (m_paintingPhase & GraphicsLayerPaintOverflowContents)
       paintingPhasesJSON->pushString("GraphicsLayerPaintOverflowContents");
     if (m_paintingPhase & GraphicsLayerPaintCompositedScroll)
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayerClient.h b/third_party/WebKit/Source/platform/graphics/GraphicsLayerClient.h
index d5c81e5..c121f147 100644
--- a/third_party/WebKit/Source/platform/graphics/GraphicsLayerClient.h
+++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayerClient.h
@@ -43,7 +43,8 @@
   GraphicsLayerPaintOverflowContents = (1 << 3),
   GraphicsLayerPaintCompositedScroll = (1 << 4),
   GraphicsLayerPaintChildClippingMask = (1 << 5),
-  GraphicsLayerPaintDecoration = (1 << 6),
+  GraphicsLayerPaintAncestorClippingMask = (1 << 6),
+  GraphicsLayerPaintDecoration = (1 << 7),
   GraphicsLayerPaintAllWithOverflowClip =
       (GraphicsLayerPaintBackground | GraphicsLayerPaintForeground |
        GraphicsLayerPaintMask |
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp
index 9d23fbb..65f83f6 100644
--- a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp
@@ -19,6 +19,7 @@
 #include "platform/graphics/paint/EffectPaintPropertyNode.h"
 #include "platform/graphics/paint/PaintArtifact.h"
 #include "platform/graphics/paint/ScrollPaintPropertyNode.h"
+#include "platform/testing/PaintPropertyTestHelpers.h"
 #include "platform/testing/PictureMatchers.h"
 #include "platform/testing/TestPaintArtifact.h"
 #include "platform/testing/WebLayerTreeViewImplForTesting.h"
@@ -29,6 +30,7 @@
 namespace blink {
 namespace {
 
+using ::blink::testing::createOpacityOnlyEffect;
 using ::testing::Pointee;
 
 PaintChunkProperties defaultPaintChunkProperties() {
@@ -569,15 +571,12 @@
 }
 
 TEST_F(PaintArtifactCompositorTestWithPropertyTrees, EffectTreeConversion) {
-  RefPtr<EffectPaintPropertyNode> effect1 = EffectPaintPropertyNode::create(
-      EffectPaintPropertyNode::root(), TransformPaintPropertyNode::root(),
-      ClipPaintPropertyNode::root(), CompositorFilterOperations(), 0.5);
-  RefPtr<EffectPaintPropertyNode> effect2 = EffectPaintPropertyNode::create(
-      effect1, TransformPaintPropertyNode::root(),
-      ClipPaintPropertyNode::root(), CompositorFilterOperations(), 0.3);
-  RefPtr<EffectPaintPropertyNode> effect3 = EffectPaintPropertyNode::create(
-      EffectPaintPropertyNode::root(), TransformPaintPropertyNode::root(),
-      ClipPaintPropertyNode::root(), CompositorFilterOperations(), 0.2);
+  RefPtr<EffectPaintPropertyNode> effect1 =
+      createOpacityOnlyEffect(EffectPaintPropertyNode::root(), 0.5);
+  RefPtr<EffectPaintPropertyNode> effect2 =
+      createOpacityOnlyEffect(effect1, 0.3);
+  RefPtr<EffectPaintPropertyNode> effect3 =
+      createOpacityOnlyEffect(EffectPaintPropertyNode::root(), 0.2);
 
   TestPaintArtifact artifact;
   artifact
@@ -661,9 +660,8 @@
 }
 
 TEST_F(PaintArtifactCompositorTestWithPropertyTrees, NestedScrollNodes) {
-  RefPtr<EffectPaintPropertyNode> effect = EffectPaintPropertyNode::create(
-      EffectPaintPropertyNode::root(), TransformPaintPropertyNode::root(),
-      ClipPaintPropertyNode::root(), CompositorFilterOperations(), 0.5);
+  RefPtr<EffectPaintPropertyNode> effect =
+      createOpacityOnlyEffect(EffectPaintPropertyNode::root(), 0.5);
 
   RefPtr<TransformPaintPropertyNode> scrollTranslationA =
       TransformPaintPropertyNode::create(
diff --git a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTest.cpp
index 3f7d0e5..e9533d8 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTest.cpp
@@ -10,22 +10,19 @@
 #include "platform/graphics/paint/EffectPaintPropertyNode.h"
 #include "platform/graphics/paint/ScrollPaintPropertyNode.h"
 #include "platform/graphics/paint/TransformPaintPropertyNode.h"
+#include "platform/testing/PaintPropertyTestHelpers.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace blink {
 
 class GeometryMapperTest : public ::testing::Test {
  public:
-  RefPtr<TransformPaintPropertyNode> rootTransformNode;
-  RefPtr<ClipPaintPropertyNode> rootClipNode;
-  RefPtr<EffectPaintPropertyNode> rootEffectNode;
-  RefPtr<ScrollPaintPropertyNode> rootScrollNode;
-
   std::unique_ptr<GeometryMapper> geometryMapper;
 
   PropertyTreeState rootPropertyTreeState() {
-    PropertyTreeState state(rootTransformNode.get(), rootClipNode.get(),
-                            rootEffectNode.get(), rootScrollNode.get());
+    PropertyTreeState state(
+        TransformPaintPropertyNode::root(), ClipPaintPropertyNode::root(),
+        EffectPaintPropertyNode::root(), ScrollPaintPropertyNode::root());
     return state;
   }
 
@@ -42,16 +39,6 @@
 
  private:
   void SetUp() override {
-    rootTransformNode = TransformPaintPropertyNode::create(
-        nullptr, TransformationMatrix(), FloatPoint3D());
-    rootClipNode = ClipPaintPropertyNode::create(
-        nullptr, rootTransformNode,
-        FloatRoundedRect(LayoutRect::infiniteIntRect()));
-    rootEffectNode = EffectPaintPropertyNode::create(
-        nullptr, rootTransformNode, rootClipNode, CompositorFilterOperations(),
-        1.0);
-    rootScrollNode = ScrollPaintPropertyNode::create(
-        nullptr, rootTransformNode, IntSize(), IntSize(), false, false, 0);
     geometryMapper = WTF::makeUnique<GeometryMapper>();
   }
 
@@ -116,9 +103,10 @@
 TEST_F(GeometryMapperTest, Root) {
   FloatRect input(0, 0, 100, 100);
 
-  CHECK_MAPPINGS(input, input, input, rootTransformNode->matrix(),
-                 rootClipNode->clipRect().rect(), rootPropertyTreeState(),
-                 rootPropertyTreeState());
+  CHECK_MAPPINGS(input, input, input,
+                 TransformPaintPropertyNode::root()->matrix(),
+                 ClipPaintPropertyNode::root()->clipRect().rect(),
+                 rootPropertyTreeState(), rootPropertyTreeState());
 }
 
 TEST_F(GeometryMapperTest, IdentityTransform) {
@@ -132,7 +120,7 @@
   FloatRect input(0, 0, 100, 100);
 
   CHECK_MAPPINGS(input, input, input, transform->matrix(),
-                 rootClipNode->clipRect().rect(), localState,
+                 ClipPaintPropertyNode::root()->clipRect().rect(), localState,
                  rootPropertyTreeState());
 }
 
@@ -149,7 +137,7 @@
   FloatRect output = transformMatrix.mapRect(input);
 
   CHECK_MAPPINGS(input, output, output, transform->matrix(),
-                 rootClipNode->clipRect().rect(), localState,
+                 ClipPaintPropertyNode::root()->clipRect().rect(), localState,
                  rootPropertyTreeState());
 
   bool success = false;
@@ -174,7 +162,7 @@
   FloatRect output = transformMatrix.mapRect(input);
 
   CHECK_MAPPINGS(input, output, output, transformMatrix,
-                 rootClipNode->clipRect().rect(), localState,
+                 ClipPaintPropertyNode::root()->clipRect().rect(), localState,
                  rootPropertyTreeState());
 }
 
@@ -194,7 +182,7 @@
   FloatRect output = transformMatrix.mapRect(input);
 
   CHECK_MAPPINGS(input, output, output, transformMatrix,
-                 rootClipNode->clipRect().rect(), localState,
+                 ClipPaintPropertyNode::root()->clipRect().rect(), localState,
                  rootPropertyTreeState());
 }
 
@@ -218,8 +206,9 @@
   TransformationMatrix final = rotateTransform * scaleTransform;
   FloatRect output = final.mapRect(input);
 
-  CHECK_MAPPINGS(input, output, output, final, rootClipNode->clipRect().rect(),
-                 localState, rootPropertyTreeState());
+  CHECK_MAPPINGS(input, output, output, final,
+                 ClipPaintPropertyNode::root()->clipRect().rect(), localState,
+                 rootPropertyTreeState());
 
   // Check the cached matrix for the intermediate transform.
   EXPECT_EQ(rotateTransform,
@@ -249,8 +238,9 @@
   TransformationMatrix final = scaleTransform * translateTransform;
   FloatRect output = final.mapRect(input);
 
-  CHECK_MAPPINGS(input, output, output, final, rootClipNode->clipRect().rect(),
-                 localState, rootPropertyTreeState());
+  CHECK_MAPPINGS(input, output, output, final,
+                 ClipPaintPropertyNode::root()->clipRect().rect(), localState,
+                 rootPropertyTreeState());
 
   // Check the cached matrix for the intermediate transform.
   EXPECT_EQ(scaleTransform,
@@ -281,13 +271,14 @@
   FloatRect output = scaleTransform.mapRect(input);
 
   CHECK_MAPPINGS(input, output, output, scaleTransform,
-                 rootClipNode->clipRect().rect(), localState,
+                 ClipPaintPropertyNode::root()->clipRect().rect(), localState,
                  intermediateState);
 }
 
 TEST_F(GeometryMapperTest, SimpleClip) {
   RefPtr<ClipPaintPropertyNode> clip = ClipPaintPropertyNode::create(
-      rootClipNode, rootTransformNode, FloatRoundedRect(10, 10, 50, 50));
+      ClipPaintPropertyNode::root(), TransformPaintPropertyNode::root(),
+      FloatRoundedRect(10, 10, 50, 50));
 
   PropertyTreeState localState = rootPropertyTreeState();
   localState.setClip(clip.get());
@@ -295,13 +286,14 @@
   FloatRect input(0, 0, 100, 100);
   FloatRect output(10, 10, 50, 50);
 
-  CHECK_MAPPINGS(
-      input,                        // Input
-      output,                       // Visual rect
-      input,                        // Transformed rect (not clipped).
-      rootTransformNode->matrix(),  // Transform matrix to ancestor space
-      clip->clipRect().rect(),      // Clip rect in ancestor space
-      localState, rootPropertyTreeState());
+  CHECK_MAPPINGS(input,   // Input
+                 output,  // Visual rect
+                 input,   // Transformed rect (not clipped).
+                 TransformPaintPropertyNode::root()
+                     ->matrix(),           // Transform matrix to ancestor space
+                 clip->clipRect().rect(),  // Clip rect in ancestor space
+                 localState,
+                 rootPropertyTreeState());
 }
 
 TEST_F(GeometryMapperTest, ClipBeforeTransform) {
@@ -312,7 +304,8 @@
                                          rotateTransform, FloatPoint3D());
 
   RefPtr<ClipPaintPropertyNode> clip = ClipPaintPropertyNode::create(
-      rootClipNode, transform.get(), FloatRoundedRect(10, 10, 50, 50));
+      ClipPaintPropertyNode::root(), transform.get(),
+      FloatRoundedRect(10, 10, 50, 50));
 
   PropertyTreeState localState = rootPropertyTreeState();
   localState.setClip(clip.get());
@@ -341,9 +334,9 @@
       TransformPaintPropertyNode::create(rootPropertyTreeState().transform(),
                                          rotateTransform, FloatPoint3D());
 
-  RefPtr<ClipPaintPropertyNode> clip =
-      ClipPaintPropertyNode::create(rootClipNode, rootTransformNode.get(),
-                                    FloatRoundedRect(10, 10, 200, 200));
+  RefPtr<ClipPaintPropertyNode> clip = ClipPaintPropertyNode::create(
+      ClipPaintPropertyNode::root(), TransformPaintPropertyNode::root(),
+      FloatRoundedRect(10, 10, 200, 200));
 
   PropertyTreeState localState = rootPropertyTreeState();
   localState.setClip(clip.get());
@@ -364,9 +357,9 @@
 }
 
 TEST_F(GeometryMapperTest, TwoClipsWithTransformBetween) {
-  RefPtr<ClipPaintPropertyNode> clip1 =
-      ClipPaintPropertyNode::create(rootClipNode, rootTransformNode.get(),
-                                    FloatRoundedRect(10, 10, 200, 200));
+  RefPtr<ClipPaintPropertyNode> clip1 = ClipPaintPropertyNode::create(
+      ClipPaintPropertyNode::root(), TransformPaintPropertyNode::root(),
+      FloatRoundedRect(10, 10, 200, 200));
 
   TransformationMatrix rotateTransform;
   rotateTransform.rotate(45);
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintChunkerTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintChunkerTest.cpp
index 3704015..d1fd8e48 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintChunkerTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintChunkerTest.cpp
@@ -5,24 +5,18 @@
 #include "platform/graphics/paint/PaintChunker.h"
 
 #include "platform/RuntimeEnabledFeatures.h"
+#include "platform/testing/PaintPropertyTestHelpers.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using testing::ElementsAre;
+using ::blink::testing::createOpacityOnlyEffect;
+using ::blink::testing::defaultPaintChunkProperties;
+using ::testing::ElementsAre;
 
 namespace blink {
 namespace {
 
-PaintChunkProperties rootPaintChunkProperties() {
-  PaintChunkProperties rootProperties;
-  rootProperties.transform = TransformPaintPropertyNode::root();
-  rootProperties.clip = ClipPaintPropertyNode::root();
-  rootProperties.effect = EffectPaintPropertyNode::root();
-  rootProperties.scroll = ScrollPaintPropertyNode::root();
-  return rootProperties;
-}
-
-class PaintChunkerTest : public testing::Test {
+class PaintChunkerTest : public ::testing::Test {
  protected:
   void SetUp() override {
     RuntimeEnabledFeatures::setSlimmingPaintV2Enabled(true);
@@ -73,34 +67,34 @@
 TEST_F(PaintChunkerTest, SingleNonEmptyRange) {
   PaintChunker chunker;
   chunker.updateCurrentPaintChunkProperties(nullptr,
-                                            rootPaintChunkProperties());
+                                            defaultPaintChunkProperties());
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
   Vector<PaintChunk> chunks = chunker.releasePaintChunks();
 
   EXPECT_THAT(chunks, ElementsAre(PaintChunk(0, 2, nullptr,
-                                             rootPaintChunkProperties())));
+                                             defaultPaintChunkProperties())));
 }
 
 TEST_F(PaintChunkerTest, SamePropertiesTwiceCombineIntoOneChunk) {
   PaintChunker chunker;
   chunker.updateCurrentPaintChunkProperties(nullptr,
-                                            rootPaintChunkProperties());
+                                            defaultPaintChunkProperties());
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
   chunker.updateCurrentPaintChunkProperties(nullptr,
-                                            rootPaintChunkProperties());
+                                            defaultPaintChunkProperties());
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
   Vector<PaintChunk> chunks = chunker.releasePaintChunks();
 
   EXPECT_THAT(chunks, ElementsAre(PaintChunk(0, 3, nullptr,
-                                             rootPaintChunkProperties())));
+                                             defaultPaintChunkProperties())));
 }
 
 TEST_F(PaintChunkerTest, CanRewindDisplayItemIndex) {
   PaintChunker chunker;
   chunker.updateCurrentPaintChunkProperties(nullptr,
-                                            rootPaintChunkProperties());
+                                            defaultPaintChunkProperties());
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
   chunker.decrementDisplayItemIndex();
@@ -108,24 +102,24 @@
   Vector<PaintChunk> chunks = chunker.releasePaintChunks();
 
   EXPECT_THAT(chunks, ElementsAre(PaintChunk(0, 2, nullptr,
-                                             rootPaintChunkProperties())));
+                                             defaultPaintChunkProperties())));
 }
 
 TEST_F(PaintChunkerTest, BuildMultipleChunksWithSinglePropertyChanging) {
   PaintChunker chunker;
   chunker.updateCurrentPaintChunkProperties(nullptr,
-                                            rootPaintChunkProperties());
+                                            defaultPaintChunkProperties());
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
 
-  PaintChunkProperties simpleTransform = rootPaintChunkProperties();
+  PaintChunkProperties simpleTransform = defaultPaintChunkProperties();
   simpleTransform.transform = TransformPaintPropertyNode::create(
       nullptr, TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
 
   chunker.updateCurrentPaintChunkProperties(nullptr, simpleTransform);
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
 
-  PaintChunkProperties anotherTransform = rootPaintChunkProperties();
+  PaintChunkProperties anotherTransform = defaultPaintChunkProperties();
   anotherTransform.transform = TransformPaintPropertyNode::create(
       nullptr, TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
   chunker.updateCurrentPaintChunkProperties(nullptr, anotherTransform);
@@ -133,45 +127,42 @@
 
   Vector<PaintChunk> chunks = chunker.releasePaintChunks();
 
-  EXPECT_THAT(chunks,
-              ElementsAre(PaintChunk(0, 2, nullptr, rootPaintChunkProperties()),
-                          PaintChunk(2, 3, nullptr, simpleTransform),
-                          PaintChunk(3, 4, nullptr, anotherTransform)));
+  EXPECT_THAT(chunks, ElementsAre(PaintChunk(0, 2, nullptr,
+                                             defaultPaintChunkProperties()),
+                                  PaintChunk(2, 3, nullptr, simpleTransform),
+                                  PaintChunk(3, 4, nullptr, anotherTransform)));
 }
 
 TEST_F(PaintChunkerTest, BuildMultipleChunksWithDifferentPropertyChanges) {
   PaintChunker chunker;
   chunker.updateCurrentPaintChunkProperties(nullptr,
-                                            rootPaintChunkProperties());
+                                            defaultPaintChunkProperties());
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
 
-  PaintChunkProperties simpleTransform = rootPaintChunkProperties();
+  PaintChunkProperties simpleTransform = defaultPaintChunkProperties();
   simpleTransform.transform = TransformPaintPropertyNode::create(
       nullptr, TransformationMatrix(0, 0, 0, 0, 0, 0), FloatPoint3D(9, 8, 7));
   chunker.updateCurrentPaintChunkProperties(nullptr, simpleTransform);
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
 
-  PaintChunkProperties simpleTransformAndEffect = rootPaintChunkProperties();
+  PaintChunkProperties simpleTransformAndEffect = defaultPaintChunkProperties();
   simpleTransformAndEffect.transform = simpleTransform.transform;
-  simpleTransformAndEffect.effect = EffectPaintPropertyNode::create(
-      EffectPaintPropertyNode::root(), TransformPaintPropertyNode::root(),
-      ClipPaintPropertyNode::root(), CompositorFilterOperations(), 0.5f);
+  simpleTransformAndEffect.effect =
+      createOpacityOnlyEffect(EffectPaintPropertyNode::root(), 0.5f);
   chunker.updateCurrentPaintChunkProperties(nullptr, simpleTransformAndEffect);
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
 
   PaintChunkProperties simpleTransformAndEffectWithUpdatedTransform =
-      rootPaintChunkProperties();
+      defaultPaintChunkProperties();
   simpleTransformAndEffectWithUpdatedTransform.transform =
       TransformPaintPropertyNode::create(nullptr,
                                          TransformationMatrix(1, 1, 0, 0, 0, 0),
                                          FloatPoint3D(9, 8, 7));
   simpleTransformAndEffectWithUpdatedTransform.effect =
-      EffectPaintPropertyNode::create(
-          EffectPaintPropertyNode::root(), TransformPaintPropertyNode::root(),
-          ClipPaintPropertyNode::root(), CompositorFilterOperations(),
-          simpleTransformAndEffect.effect->opacity());
+      createOpacityOnlyEffect(EffectPaintPropertyNode::root(),
+                              simpleTransformAndEffect.effect->opacity());
   chunker.updateCurrentPaintChunkProperties(
       nullptr, simpleTransformAndEffectWithUpdatedTransform);
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
@@ -187,7 +178,7 @@
 
   EXPECT_THAT(
       chunks,
-      ElementsAre(PaintChunk(0, 1, nullptr, rootPaintChunkProperties()),
+      ElementsAre(PaintChunk(0, 1, nullptr, defaultPaintChunkProperties()),
                   PaintChunk(1, 3, nullptr, simpleTransform),
                   PaintChunk(3, 5, nullptr, simpleTransformAndEffect),
                   PaintChunk(5, 7, nullptr,
@@ -202,10 +193,10 @@
   // </root xform>
   PaintChunker chunker;
   chunker.updateCurrentPaintChunkProperties(nullptr,
-                                            rootPaintChunkProperties());
+                                            defaultPaintChunkProperties());
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
 
-  PaintChunkProperties simpleTransform = rootPaintChunkProperties();
+  PaintChunkProperties simpleTransform = defaultPaintChunkProperties();
   simpleTransform.transform = TransformPaintPropertyNode::create(
       nullptr, TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
   chunker.updateCurrentPaintChunkProperties(nullptr, simpleTransform);
@@ -213,31 +204,31 @@
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
 
   chunker.updateCurrentPaintChunkProperties(nullptr,
-                                            rootPaintChunkProperties());
+                                            defaultPaintChunkProperties());
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
 
   Vector<PaintChunk> chunks = chunker.releasePaintChunks();
 
   EXPECT_THAT(
       chunks,
-      ElementsAre(PaintChunk(0, 1, nullptr, rootPaintChunkProperties()),
+      ElementsAre(PaintChunk(0, 1, nullptr, defaultPaintChunkProperties()),
                   PaintChunk(1, 3, nullptr, simpleTransform),
-                  PaintChunk(3, 4, nullptr, rootPaintChunkProperties())));
+                  PaintChunk(3, 4, nullptr, defaultPaintChunkProperties())));
 }
 
 TEST_F(PaintChunkerTest, ChangingPropertiesWithoutItems) {
   // Test that properties can change without display items being generated.
   PaintChunker chunker;
   chunker.updateCurrentPaintChunkProperties(nullptr,
-                                            rootPaintChunkProperties());
+                                            defaultPaintChunkProperties());
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
 
-  PaintChunkProperties firstTransform = rootPaintChunkProperties();
+  PaintChunkProperties firstTransform = defaultPaintChunkProperties();
   firstTransform.transform = TransformPaintPropertyNode::create(
       nullptr, TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
   chunker.updateCurrentPaintChunkProperties(nullptr, firstTransform);
 
-  PaintChunkProperties secondTransform = rootPaintChunkProperties();
+  PaintChunkProperties secondTransform = defaultPaintChunkProperties();
   secondTransform.transform = TransformPaintPropertyNode::create(
       nullptr, TransformationMatrix(9, 8, 7, 6, 5, 4), FloatPoint3D(3, 2, 1));
   chunker.updateCurrentPaintChunkProperties(nullptr, secondTransform);
@@ -245,9 +236,9 @@
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
   Vector<PaintChunk> chunks = chunker.releasePaintChunks();
 
-  EXPECT_THAT(chunks,
-              ElementsAre(PaintChunk(0, 1, nullptr, rootPaintChunkProperties()),
-                          PaintChunk(1, 2, nullptr, secondTransform)));
+  EXPECT_THAT(chunks, ElementsAre(PaintChunk(0, 1, nullptr,
+                                             defaultPaintChunkProperties()),
+                                  PaintChunk(1, 2, nullptr, secondTransform)));
 }
 
 TEST_F(PaintChunkerTest, CreatesSeparateChunksWhenRequested) {
@@ -262,7 +253,7 @@
   TestDisplayItemRequiringSeparateChunk i6(m_client);
 
   chunker.updateCurrentPaintChunkProperties(nullptr,
-                                            rootPaintChunkProperties());
+                                            defaultPaintChunkProperties());
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
   chunker.incrementDisplayItemIndex(i1);
   chunker.incrementDisplayItemIndex(i2);
@@ -282,13 +273,14 @@
   DisplayItem::Id id3 = i3.getId();
   DisplayItem::Id id6 = i6.getId();
   Vector<PaintChunk> chunks = chunker.releasePaintChunks();
-  EXPECT_THAT(chunks,
-              ElementsAre(PaintChunk(0, 1, nullptr, rootPaintChunkProperties()),
-                          PaintChunk(1, 2, &id1, rootPaintChunkProperties()),
-                          PaintChunk(2, 3, &id2, rootPaintChunkProperties()),
-                          PaintChunk(3, 4, &id3, rootPaintChunkProperties()),
-                          PaintChunk(4, 6, nullptr, rootPaintChunkProperties()),
-                          PaintChunk(6, 7, &id6, rootPaintChunkProperties())));
+  EXPECT_THAT(
+      chunks,
+      ElementsAre(PaintChunk(0, 1, nullptr, defaultPaintChunkProperties()),
+                  PaintChunk(1, 2, &id1, defaultPaintChunkProperties()),
+                  PaintChunk(2, 3, &id2, defaultPaintChunkProperties()),
+                  PaintChunk(3, 4, &id3, defaultPaintChunkProperties()),
+                  PaintChunk(4, 6, nullptr, defaultPaintChunkProperties()),
+                  PaintChunk(6, 7, &id6, defaultPaintChunkProperties())));
 }
 
 TEST_F(PaintChunkerTest, ChunkIds) {
@@ -299,11 +291,11 @@
   DisplayItem::Id id2 = i2.getId();
 
   chunker.updateCurrentPaintChunkProperties(nullptr,
-                                            rootPaintChunkProperties());
+                                            defaultPaintChunkProperties());
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
 
-  PaintChunkProperties simpleTransform = rootPaintChunkProperties();
+  PaintChunkProperties simpleTransform = defaultPaintChunkProperties();
   simpleTransform.transform = TransformPaintPropertyNode::create(
       nullptr, TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
   chunker.updateCurrentPaintChunkProperties(&id1, simpleTransform);
@@ -314,17 +306,17 @@
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
 
   chunker.updateCurrentPaintChunkProperties(nullptr,
-                                            rootPaintChunkProperties());
+                                            defaultPaintChunkProperties());
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
 
   Vector<PaintChunk> chunks = chunker.releasePaintChunks();
   EXPECT_THAT(
       chunks,
-      ElementsAre(PaintChunk(0, 2, nullptr, rootPaintChunkProperties()),
+      ElementsAre(PaintChunk(0, 2, nullptr, defaultPaintChunkProperties()),
                   PaintChunk(2, 4, &id1, simpleTransform),
                   PaintChunk(4, 5, &id2, simpleTransform),
                   PaintChunk(5, 6, nullptr, simpleTransform),
-                  PaintChunk(6, 7, nullptr, rootPaintChunkProperties())));
+                  PaintChunk(6, 7, nullptr, defaultPaintChunkProperties())));
 }
 
 TEST_F(PaintChunkerTest, ChunkIdsSkippingCache) {
@@ -336,11 +328,11 @@
   i2.setSkippedCache();
 
   chunker.updateCurrentPaintChunkProperties(nullptr,
-                                            rootPaintChunkProperties());
+                                            defaultPaintChunkProperties());
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
 
-  PaintChunkProperties simpleTransform = rootPaintChunkProperties();
+  PaintChunkProperties simpleTransform = defaultPaintChunkProperties();
   simpleTransform.transform = TransformPaintPropertyNode::create(
       nullptr, TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
   chunker.updateCurrentPaintChunkProperties(&id1, simpleTransform);
@@ -351,17 +343,17 @@
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
 
   chunker.updateCurrentPaintChunkProperties(nullptr,
-                                            rootPaintChunkProperties());
+                                            defaultPaintChunkProperties());
   chunker.incrementDisplayItemIndex(NormalTestDisplayItem(m_client));
 
   Vector<PaintChunk> chunks = chunker.releasePaintChunks();
   EXPECT_THAT(
       chunks,
-      ElementsAre(PaintChunk(0, 2, nullptr, rootPaintChunkProperties()),
+      ElementsAre(PaintChunk(0, 2, nullptr, defaultPaintChunkProperties()),
                   PaintChunk(2, 4, nullptr, simpleTransform),
                   PaintChunk(4, 5, nullptr, simpleTransform),
                   PaintChunk(5, 6, nullptr, simpleTransform),
-                  PaintChunk(6, 7, nullptr, rootPaintChunkProperties())));
+                  PaintChunk(6, 7, nullptr, defaultPaintChunkProperties())));
 }
 
 }  // namespace
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp
index 870d850..90b33c04 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp
@@ -14,15 +14,18 @@
 #include "platform/graphics/paint/DrawingRecorder.h"
 #include "platform/graphics/paint/SubsequenceRecorder.h"
 #include "platform/testing/FakeDisplayItemClient.h"
+#include "platform/testing/PaintPropertyTestHelpers.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include <memory>
 
+using blink::testing::createOpacityOnlyEffect;
+using blink::testing::defaultPaintChunkProperties;
 using testing::UnorderedElementsAre;
 
 namespace blink {
 
-class PaintControllerTestBase : public testing::Test {
+class PaintControllerTestBase : public ::testing::Test {
  public:
   PaintControllerTestBase() : m_paintController(PaintController::create()) {}
 
@@ -54,15 +57,6 @@
   RuntimeEnabledFeatures::Backup m_featuresBackup;
 };
 
-PaintChunkProperties rootPaintChunkProperties() {
-  PaintChunkProperties rootProperties;
-  rootProperties.transform = TransformPaintPropertyNode::root();
-  rootProperties.clip = ClipPaintPropertyNode::root();
-  rootProperties.effect = EffectPaintPropertyNode::root();
-  rootProperties.scroll = ScrollPaintPropertyNode::root();
-  return rootProperties;
-}
-
 const DisplayItem::Type foregroundDrawingType =
     static_cast<DisplayItem::Type>(DisplayItem::kDrawingPaintPhaseFirst + 4);
 const DisplayItem::Type backgroundDrawingType =
@@ -136,7 +130,7 @@
 // enabled and disabled.
 class PaintControllerTest
     : public PaintControllerTestBase,
-      public testing::WithParamInterface<TestConfigurations> {
+      public ::testing::WithParamInterface<TestConfigurations> {
  public:
   PaintControllerTest()
       : m_rootPaintPropertyClient("root"),
@@ -177,7 +171,7 @@
   FakeDisplayItemClient client("client", LayoutRect(100, 100, 200, 200));
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
 
   drawClippedRect(context, client, clipType, backgroundDrawingType,
@@ -203,7 +197,7 @@
   GraphicsContext context(getPaintController());
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
 
   drawRect(context, first, backgroundDrawingType,
@@ -228,7 +222,7 @@
                 UnorderedElementsAre(FloatRect(LayoutRect::infiniteIntRect())));
 
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
 
   drawRect(context, first, backgroundDrawingType,
@@ -265,7 +259,7 @@
   GraphicsContext context(getPaintController());
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
 
   drawRect(context, first, backgroundDrawingType,
@@ -292,7 +286,7 @@
 
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
   drawRect(context, second, backgroundDrawingType,
            FloatRect(100, 100, 50, 200));
@@ -339,7 +333,7 @@
   GraphicsContext context(getPaintController());
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
 
   drawRect(context, first, backgroundDrawingType,
@@ -366,7 +360,7 @@
 
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
 
   first.setDisplayItemsUncached();
@@ -418,7 +412,7 @@
   GraphicsContext context(getPaintController());
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
 
   drawRect(context, first, backgroundDrawingType,
@@ -433,7 +427,7 @@
 
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
 
   drawRect(context, first, backgroundDrawingType,
@@ -472,7 +466,7 @@
   GraphicsContext context(getPaintController());
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
 
   drawRect(context, first, backgroundDrawingType,
@@ -497,7 +491,7 @@
 
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
 
   second.setDisplayItemsUncached();
@@ -544,7 +538,7 @@
   GraphicsContext context(getPaintController());
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
 
   drawRect(context, second, backgroundDrawingType, FloatRect(200, 200, 50, 50));
@@ -557,7 +551,7 @@
 
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
 
   first.setDisplayItemsUncached();
@@ -590,7 +584,7 @@
                     FloatRect(150, 150, 100, 100)));  // New bounds of |second|.
 
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
 
   drawRect(context, second, backgroundDrawingType,
@@ -626,7 +620,7 @@
   GraphicsContext context(getPaintController());
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
 
   drawRect(context, first, backgroundDrawingType,
@@ -641,7 +635,7 @@
 
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
 
   first.setDisplayItemsUncached();
@@ -672,7 +666,7 @@
                               50)));  // |second| newly appeared in the chunk.
 
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
 
   first.setDisplayItemsUncached();
@@ -708,7 +702,7 @@
   {
     if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
       PaintChunk::Id id(first, clipType);
-      PaintChunkProperties properties = rootPaintChunkProperties();
+      PaintChunkProperties properties = defaultPaintChunkProperties();
       properties.clip = ClipPaintPropertyNode::create(
           nullptr, nullptr, FloatRoundedRect(1, 1, 2, 2));
       getPaintController().updateCurrentPaintChunkProperties(&id, properties);
@@ -730,7 +724,7 @@
 
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
 
   first.setDisplayItemsUncached();
@@ -759,7 +753,7 @@
                     LayoutRect::infiniteIntRect())));  // This is a new chunk.
 
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
 
   second.setDisplayItemsUncached();
@@ -768,7 +762,7 @@
   {
     if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
       PaintChunk::Id id(second, clipType);
-      PaintChunkProperties properties = rootPaintChunkProperties();
+      PaintChunkProperties properties = defaultPaintChunkProperties();
       properties.clip = ClipPaintPropertyNode::create(
           nullptr, nullptr, FloatRoundedRect(1, 1, 2, 2));
       getPaintController().updateCurrentPaintChunkProperties(&id, properties);
@@ -804,7 +798,7 @@
   GraphicsContext context(getPaintController());
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
 
   drawRect(context, first, backgroundDrawingType,
@@ -833,7 +827,7 @@
 
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
   drawRect(context, first, backgroundDrawingType,
            FloatRect(100, 100, 150, 150));
@@ -871,7 +865,7 @@
   GraphicsContext context(getPaintController());
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
 
   drawRect(context, container1, backgroundDrawingType,
@@ -904,7 +898,7 @@
 
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
 
   // Simulate the situation when |container1| gets a z-index that is greater
@@ -959,7 +953,7 @@
   GraphicsContext context(getPaintController());
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
 
   drawRect(context, container1, backgroundDrawingType,
@@ -992,7 +986,7 @@
 
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
 
   // Simulate the situation when |container1| gets a z-index that is greater
@@ -1049,15 +1043,14 @@
   FakeDisplayItemClient content2("content2", LayoutRect(100, 200, 50, 200));
   GraphicsContext context(getPaintController());
 
-  PaintChunkProperties container1Properties = rootPaintChunkProperties();
-  PaintChunkProperties container2Properties = rootPaintChunkProperties();
+  PaintChunkProperties container1Properties = defaultPaintChunkProperties();
+  PaintChunkProperties container2Properties = defaultPaintChunkProperties();
 
   {
     if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
       PaintChunk::Id id(container1, backgroundDrawingType);
-      container1Properties.effect = EffectPaintPropertyNode::create(
-          EffectPaintPropertyNode::root(), TransformPaintPropertyNode::root(),
-          ClipPaintPropertyNode::root(), CompositorFilterOperations(), 0.5);
+      container1Properties.effect =
+          createOpacityOnlyEffect(EffectPaintPropertyNode::root(), 0.5);
       getPaintController().updateCurrentPaintChunkProperties(
           &id, container1Properties);
     }
@@ -1074,9 +1067,8 @@
   {
     if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
       PaintChunk::Id id(container2, backgroundDrawingType);
-      container2Properties.effect = EffectPaintPropertyNode::create(
-          EffectPaintPropertyNode::root(), TransformPaintPropertyNode::root(),
-          ClipPaintPropertyNode::root(), CompositorFilterOperations(), 0.5);
+      container2Properties.effect =
+          createOpacityOnlyEffect(EffectPaintPropertyNode::root(), 0.5);
       getPaintController().updateCurrentPaintChunkProperties(
           &id, container2Properties);
     }
@@ -1221,15 +1213,14 @@
   FakeDisplayItemClient content2("content2", LayoutRect(100, 200, 50, 200));
   GraphicsContext context(getPaintController());
 
-  PaintChunkProperties container1Properties = rootPaintChunkProperties();
-  PaintChunkProperties container2Properties = rootPaintChunkProperties();
+  PaintChunkProperties container1Properties = defaultPaintChunkProperties();
+  PaintChunkProperties container2Properties = defaultPaintChunkProperties();
 
   {
     if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
       PaintChunk::Id id(container1, backgroundDrawingType);
-      container1Properties.effect = EffectPaintPropertyNode::create(
-          EffectPaintPropertyNode::root(), TransformPaintPropertyNode::root(),
-          ClipPaintPropertyNode::root(), CompositorFilterOperations(), 0.5);
+      container1Properties.effect =
+          createOpacityOnlyEffect(EffectPaintPropertyNode::root(), 0.5);
       getPaintController().updateCurrentPaintChunkProperties(
           &id, container1Properties);
     }
@@ -1241,9 +1232,8 @@
   {
     if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
       PaintChunk::Id id(container2, backgroundDrawingType);
-      container2Properties.effect = EffectPaintPropertyNode::create(
-          EffectPaintPropertyNode::root(), TransformPaintPropertyNode::root(),
-          ClipPaintPropertyNode::root(), CompositorFilterOperations(), 0.5);
+      container2Properties.effect =
+          createOpacityOnlyEffect(EffectPaintPropertyNode::root(), 0.5);
       getPaintController().updateCurrentPaintChunkProperties(
           &id, container2Properties);
     }
@@ -1335,7 +1325,7 @@
 
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
   drawRect(context, client, type1, FloatRect(100, 100, 100, 100));
   drawRect(context, client, type2, FloatRect(100, 100, 50, 200));
@@ -1346,7 +1336,7 @@
 
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
   drawRect(context, client, type2, FloatRect(100, 100, 50, 200));
   drawRect(context, client, type3, FloatRect(100, 100, 50, 200));
@@ -1366,20 +1356,19 @@
   GraphicsContext context(getPaintController());
 
   PaintChunkProperties container1BackgroundProperties =
-      rootPaintChunkProperties();
-  PaintChunkProperties content1Properties = rootPaintChunkProperties();
+      defaultPaintChunkProperties();
+  PaintChunkProperties content1Properties = defaultPaintChunkProperties();
   PaintChunkProperties container1ForegroundProperties =
-      rootPaintChunkProperties();
+      defaultPaintChunkProperties();
   PaintChunkProperties container2BackgroundProperties =
-      rootPaintChunkProperties();
-  PaintChunkProperties content2Properties = rootPaintChunkProperties();
+      defaultPaintChunkProperties();
+  PaintChunkProperties content2Properties = defaultPaintChunkProperties();
 
   {
     if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
       PaintChunk::Id id(container1, backgroundDrawingType);
-      container1BackgroundProperties.effect = EffectPaintPropertyNode::create(
-          EffectPaintPropertyNode::root(), TransformPaintPropertyNode::root(),
-          ClipPaintPropertyNode::root(), CompositorFilterOperations(), 0.5);
+      container1BackgroundProperties.effect =
+          createOpacityOnlyEffect(EffectPaintPropertyNode::root(), 0.5);
       getPaintController().updateCurrentPaintChunkProperties(
           &id, container1BackgroundProperties);
     }
@@ -1389,9 +1378,8 @@
     {
       if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
         PaintChunk::Id id(content1, backgroundDrawingType);
-        content1Properties.effect = EffectPaintPropertyNode::create(
-            EffectPaintPropertyNode::root(), TransformPaintPropertyNode::root(),
-            ClipPaintPropertyNode::root(), CompositorFilterOperations(), 0.6);
+        content1Properties.effect =
+            createOpacityOnlyEffect(EffectPaintPropertyNode::root(), 0.6);
         getPaintController().updateCurrentPaintChunkProperties(
             &id, content1Properties);
       }
@@ -1403,9 +1391,8 @@
     }
     if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
       PaintChunk::Id id(container1, foregroundDrawingType);
-      container1ForegroundProperties.effect = EffectPaintPropertyNode::create(
-          EffectPaintPropertyNode::root(), TransformPaintPropertyNode::root(),
-          ClipPaintPropertyNode::root(), CompositorFilterOperations(), 0.5);
+      container1ForegroundProperties.effect =
+          createOpacityOnlyEffect(EffectPaintPropertyNode::root(), 0.5);
       getPaintController().updateCurrentPaintChunkProperties(
           &id, container1ForegroundProperties);
     }
@@ -1415,9 +1402,8 @@
   {
     if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
       PaintChunk::Id id(container2, backgroundDrawingType);
-      container2BackgroundProperties.effect = EffectPaintPropertyNode::create(
-          EffectPaintPropertyNode::root(), TransformPaintPropertyNode::root(),
-          ClipPaintPropertyNode::root(), CompositorFilterOperations(), 0.7);
+      container2BackgroundProperties.effect =
+          createOpacityOnlyEffect(EffectPaintPropertyNode::root(), 0.7);
       getPaintController().updateCurrentPaintChunkProperties(
           &id, container2BackgroundProperties);
     }
@@ -1427,9 +1413,8 @@
     {
       if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
         PaintChunk::Id id(content2, backgroundDrawingType);
-        content2Properties.effect = EffectPaintPropertyNode::create(
-            EffectPaintPropertyNode::root(), TransformPaintPropertyNode::root(),
-            ClipPaintPropertyNode::root(), CompositorFilterOperations(), 0.8);
+        content2Properties.effect =
+            createOpacityOnlyEffect(EffectPaintPropertyNode::root(), 0.8);
         getPaintController().updateCurrentPaintChunkProperties(
             &id, content2Properties);
       }
@@ -1596,7 +1581,7 @@
   GraphicsContext context(getPaintController());
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
 
   FloatRect rect1(100, 100, 50, 50);
@@ -1633,7 +1618,7 @@
                 UnorderedElementsAre(FloatRect(LayoutRect::infiniteIntRect())));
 
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
 
   // Draw again with nothing invalidated.
@@ -1675,7 +1660,7 @@
             FloatRect(100, 100, 100, 100)));  // New bounds of |content|.
 
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
 
   // Now the multicol becomes 3 columns and repaints.
@@ -1726,7 +1711,7 @@
 
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
   drawRect(context, content, backgroundDrawingType, rect1);
   getPaintController().beginSkippingCache();
@@ -1760,7 +1745,7 @@
 
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     getPaintController().updateCurrentPaintChunkProperties(
-        &m_rootPaintChunkId, rootPaintChunkProperties());
+        &m_rootPaintChunkId, defaultPaintChunkProperties());
   }
   // Draw again with nothing invalidated.
   drawRect(context, content, backgroundDrawingType, rect1);
@@ -1851,7 +1836,7 @@
 
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     getPaintController().updateCurrentPaintChunkProperties(
-        nullptr, rootPaintChunkProperties());
+        nullptr, defaultPaintChunkProperties());
   }
   GraphicsContext context(getPaintController());
   drawRect(context, client, backgroundDrawingType, FloatRect(0, 0, 100, 100));
diff --git a/third_party/WebKit/Source/platform/network/HTTPParsers.cpp b/third_party/WebKit/Source/platform/network/HTTPParsers.cpp
index bd5257d..948e932e 100644
--- a/third_party/WebKit/Source/platform/network/HTTPParsers.cpp
+++ b/third_party/WebKit/Source/platform/network/HTTPParsers.cpp
@@ -874,12 +874,9 @@
       new net::HttpResponseHeaders(
           net::HttpUtil::AssembleRawHeaders(headers.data(), headers.length()));
 
-  std::string mimeType;
-  responseHeaders->GetMimeType(&mimeType);
+  std::string mimeType, charset;
+  responseHeaders->GetMimeTypeAndCharset(&mimeType, &charset);
   response->setMimeType(WebString::fromUTF8(mimeType));
-
-  std::string charset;
-  responseHeaders->GetCharset(&charset);
   response->setTextEncodingName(WebString::fromUTF8(charset));
 
   // Copy headers listed in replaceHeaders to the response.
diff --git a/third_party/WebKit/Source/platform/scheduler/child/web_task_runner_impl.cc b/third_party/WebKit/Source/platform/scheduler/child/web_task_runner_impl.cc
index f767e1a..5d8d6c445 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/web_task_runner_impl.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/web_task_runner_impl.cc
@@ -19,24 +19,6 @@
 
 WebTaskRunnerImpl::~WebTaskRunnerImpl() {}
 
-void WebTaskRunnerImpl::postTask(const blink::WebTraceLocation& location,
-                                 blink::WebTaskRunner::Task* task) {
-  task_queue_->PostTask(location,
-                        base::Bind(&WebTaskRunnerImpl::runTask,
-                                   base::Passed(base::WrapUnique(task))));
-}
-
-void WebTaskRunnerImpl::postDelayedTask(const blink::WebTraceLocation& location,
-                                        blink::WebTaskRunner::Task* task,
-                                        double delayMs) {
-  DCHECK_GE(delayMs, 0.0) << location.function_name() << " "
-                          << location.file_name();
-  task_queue_->PostDelayedTask(location,
-                               base::Bind(&WebTaskRunnerImpl::runTask,
-                                          base::Passed(base::WrapUnique(task))),
-                               base::TimeDelta::FromMillisecondsD(delayMs));
-}
-
 void WebTaskRunnerImpl::postDelayedTask(const WebTraceLocation& location,
                                         const base::Closure& task,
                                         double delayMs) {
@@ -76,10 +58,5 @@
   return task_queue_.get();
 }
 
-void WebTaskRunnerImpl::runTask(
-    std::unique_ptr<blink::WebTaskRunner::Task> task) {
-  task->run();
-}
-
 }  // namespace scheduler
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/child/web_task_runner_impl.h b/third_party/WebKit/Source/platform/scheduler/child/web_task_runner_impl.h
index f8fa9c2..2eb7f11 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/web_task_runner_impl.h
+++ b/third_party/WebKit/Source/platform/scheduler/child/web_task_runner_impl.h
@@ -24,11 +24,6 @@
   ~WebTaskRunnerImpl() override;
 
   // WebTaskRunner implementation:
-  void postTask(const WebTraceLocation& web_location,
-                WebTaskRunner::Task* task) override;
-  void postDelayedTask(const WebTraceLocation& web_location,
-                       WebTaskRunner::Task* task,
-                       double delayMs) override;
   void postDelayedTask(const WebTraceLocation&,
                        const base::Closure&,
                        double delayMs) override;
@@ -38,14 +33,6 @@
   std::unique_ptr<WebTaskRunner> clone() override;
   base::SingleThreadTaskRunner* toSingleThreadTaskRunner() override;
 
-  // WebTaskRunner::Task should be wrapped by base::Passed() when
-  // used with base::Bind(). See https://crbug.com/551356.
-  // runTask() is a helper to call WebTaskRunner::Task::run from
-  // std::unique_ptr<WebTaskRunner::Task>.
-  // runTask() is placed here because std::unique_ptr<> cannot be used from
-  // Blink.
-  static void runTask(std::unique_ptr<WebTaskRunner::Task>);
-
  private:
   base::TimeTicks Now() const;
 
diff --git a/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler_unittest.cc b/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler_unittest.cc
index 0c14654..dc50950b 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler_unittest.cc
@@ -22,17 +22,8 @@
 namespace scheduler {
 namespace {
 
-class NopTask : public blink::WebTaskRunner::Task {
+class MockTask {
  public:
-  ~NopTask() override {}
-
-  void run() override {}
-};
-
-class MockTask : public blink::WebTaskRunner::Task {
- public:
-  ~MockTask() override {}
-
   MOCK_METHOD0(run, void());
 };
 
@@ -57,17 +48,9 @@
   std::string* calls_;  // NOT OWNED
 };
 
-class TestTask : public blink::WebTaskRunner::Task {
- public:
-  explicit TestTask(std::string* calls) : calls_(calls) {}
-
-  ~TestTask() override {}
-
-  void run() override { calls_->append(" run"); }
-
- private:
-  std::string* calls_;  // NOT OWNED
-};
+void runTestTask(std::string* calls) {
+  calls->append(" run");
+}
 
 void addTaskObserver(WebThreadImplForWorkerScheduler* thread,
                      TestObserver* observer) {
@@ -123,33 +106,35 @@
 };
 
 TEST_F(WebThreadImplForWorkerSchedulerTest, TestDefaultTask) {
-  std::unique_ptr<MockTask> task(new MockTask());
+  MockTask task;
   base::WaitableEvent completion(
       base::WaitableEvent::ResetPolicy::AUTOMATIC,
       base::WaitableEvent::InitialState::NOT_SIGNALED);
 
-  EXPECT_CALL(*task, run());
-  ON_CALL(*task, run())
-      .WillByDefault(Invoke([&completion]() { completion.Signal(); }));
+  EXPECT_CALL(task, run());
+  ON_CALL(task, run()).WillByDefault(Invoke([&completion]() {
+    completion.Signal();
+  }));
 
-  thread_->getWebTaskRunner()->postTask(blink::WebTraceLocation(),
-                                        task.release());
+  thread_->getWebTaskRunner()->postTask(
+      BLINK_FROM_HERE, WTF::bind(&MockTask::run, WTF::unretained(&task)));
   completion.Wait();
 }
 
 TEST_F(WebThreadImplForWorkerSchedulerTest,
        TestTaskExecutedBeforeThreadDeletion) {
-  std::unique_ptr<MockTask> task(new MockTask());
+  MockTask task;
   base::WaitableEvent completion(
       base::WaitableEvent::ResetPolicy::AUTOMATIC,
       base::WaitableEvent::InitialState::NOT_SIGNALED);
 
-  EXPECT_CALL(*task, run());
-  ON_CALL(*task, run())
-      .WillByDefault(Invoke([&completion]() { completion.Signal(); }));
+  EXPECT_CALL(task, run());
+  ON_CALL(task, run()).WillByDefault(Invoke([&completion]() {
+    completion.Signal();
+  }));
 
-  thread_->getWebTaskRunner()->postTask(blink::WebTraceLocation(),
-                                        task.release());
+  thread_->getWebTaskRunner()->postTask(
+      BLINK_FROM_HERE, WTF::bind(&MockTask::run, WTF::unretained(&task)));
   thread_.reset();
 }
 
@@ -163,10 +148,10 @@
   ON_CALL(*task, run(_))
       .WillByDefault(Invoke([&completion](double) { completion.Signal(); }));
 
-  thread_->postIdleTask(blink::WebTraceLocation(), task.release());
+  thread_->postIdleTask(BLINK_FROM_HERE, task.release());
   // We need to post a wakeup task or idle work will never happen.
-  thread_->getWebTaskRunner()->postDelayedTask(blink::WebTraceLocation(),
-                                               new NopTask(), 50ll);
+  thread_->getWebTaskRunner()->postDelayedTask(BLINK_FROM_HERE,
+                                               WTF::bind([] {}), 50ll);
 
   completion.Wait();
 }
@@ -177,8 +162,8 @@
 
   RunOnWorkerThread(FROM_HERE,
                     base::Bind(&addTaskObserver, thread_.get(), &observer));
-  thread_->getWebTaskRunner()->postTask(blink::WebTraceLocation(),
-                                        new TestTask(&calls));
+  thread_->getWebTaskRunner()->postTask(
+      BLINK_FROM_HERE, WTF::bind(&runTestTask, WTF::unretained(&calls)));
   RunOnWorkerThread(FROM_HERE,
                     base::Bind(&removeTaskObserver, thread_.get(), &observer));
 
@@ -191,17 +176,18 @@
 }
 
 TEST_F(WebThreadImplForWorkerSchedulerTest, TestShutdown) {
-  std::unique_ptr<MockTask> task(new MockTask());
-  std::unique_ptr<MockTask> delayed_task(new MockTask());
+  MockTask task;
+  MockTask delayed_task;
 
-  EXPECT_CALL(*task, run()).Times(0);
-  EXPECT_CALL(*delayed_task, run()).Times(0);
+  EXPECT_CALL(task, run()).Times(0);
+  EXPECT_CALL(delayed_task, run()).Times(0);
 
   RunOnWorkerThread(FROM_HERE, base::Bind(&shutdownOnThread, thread_.get()));
-  thread_->getWebTaskRunner()->postTask(blink::WebTraceLocation(),
-                                        task.release());
-  thread_->getWebTaskRunner()->postDelayedTask(blink::WebTraceLocation(),
-                                               task.release(), 50ll);
+  thread_->getWebTaskRunner()->postTask(
+      BLINK_FROM_HERE, WTF::bind(&MockTask::run, WTF::unretained(&task)));
+  thread_->getWebTaskRunner()->postDelayedTask(
+      BLINK_FROM_HERE,
+      WTF::bind(&MockTask::run, WTF::unretained(&delayed_task)), 50ll);
   thread_.reset();
 }
 
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl_unittest.cc
index 744c54eae..dcb5dab 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl_unittest.cc
@@ -57,23 +57,21 @@
 };
 
 namespace {
-class RepeatingTask : public blink::WebTaskRunner::Task {
- public:
-  RepeatingTask(blink::WebTaskRunner* web_task_runner, int* run_count)
-      : web_task_runner_(web_task_runner), run_count_(run_count) {}
 
-  ~RepeatingTask() override {}
+void runRepeatingTask(WebTaskRunner* task_runner, int* run_count);
 
-  void run() override {
-    (*run_count_)++;
-    web_task_runner_->postDelayedTask(
-        BLINK_FROM_HERE, new RepeatingTask(web_task_runner_, run_count_), 1.0);
-  }
+std::unique_ptr<WTF::Closure> makeRepeatingTask(
+    blink::WebTaskRunner* task_runner,
+    int* run_count) {
+  return WTF::bind(&runRepeatingTask, WTF::unretained(task_runner),
+                   WTF::unretained(run_count));
+}
 
- private:
-  blink::WebTaskRunner* web_task_runner_;  // NOT OWNED
-  int* run_count_;                         // NOT OWNED
-};
+void runRepeatingTask(WebTaskRunner* task_runner, int* run_count) {
+  ++*run_count;
+  task_runner->postDelayedTask(BLINK_FROM_HERE,
+                               makeRepeatingTask(task_runner, run_count), 1.0);
+}
 
 void IncrementCounter(int* counter) {
   ++*counter;
@@ -87,7 +85,7 @@
   int run_count = 0;
   web_frame_scheduler_->timerTaskRunner()->postDelayedTask(
       BLINK_FROM_HERE,
-      new RepeatingTask(web_frame_scheduler_->timerTaskRunner(), &run_count),
+      makeRepeatingTask(web_frame_scheduler_->timerTaskRunner(), &run_count),
       1.0);
 
   mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
@@ -101,7 +99,7 @@
   int run_count = 0;
   web_frame_scheduler_->timerTaskRunner()->postDelayedTask(
       BLINK_FROM_HERE,
-      new RepeatingTask(web_frame_scheduler_->timerTaskRunner(), &run_count),
+      makeRepeatingTask(web_frame_scheduler_->timerTaskRunner(), &run_count),
       1.0);
 
   mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
@@ -115,7 +113,7 @@
   int run_count = 0;
   web_frame_scheduler_->timerTaskRunner()->postDelayedTask(
       BLINK_FROM_HERE,
-      new RepeatingTask(web_frame_scheduler_->timerTaskRunner(), &run_count),
+      makeRepeatingTask(web_frame_scheduler_->timerTaskRunner(), &run_count),
       1.0);
 
   mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
@@ -130,7 +128,7 @@
   int run_count = 0;
   web_frame_scheduler_->timerTaskRunner()->postDelayedTask(
       BLINK_FROM_HERE,
-      new RepeatingTask(web_frame_scheduler_->timerTaskRunner(), &run_count),
+      makeRepeatingTask(web_frame_scheduler_->timerTaskRunner(), &run_count),
       1.0);
 
   mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
@@ -145,7 +143,7 @@
   int run_count = 0;
   web_frame_scheduler_->timerTaskRunner()->postDelayedTask(
       BLINK_FROM_HERE,
-      new RepeatingTask(web_frame_scheduler_->timerTaskRunner(), &run_count),
+      makeRepeatingTask(web_frame_scheduler_->timerTaskRunner(), &run_count),
       1.0);
 
   mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
@@ -159,7 +157,7 @@
   int run_count = 0;
   web_frame_scheduler_->timerTaskRunner()->postDelayedTask(
       BLINK_FROM_HERE,
-      new RepeatingTask(web_frame_scheduler_->timerTaskRunner(), &run_count),
+      makeRepeatingTask(web_frame_scheduler_->timerTaskRunner(), &run_count),
       1.0);
 
   mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
@@ -174,7 +172,7 @@
   int run_count = 0;
   web_frame_scheduler_->timerTaskRunner()->postDelayedTask(
       BLINK_FROM_HERE,
-      new RepeatingTask(web_frame_scheduler_->timerTaskRunner(), &run_count),
+      makeRepeatingTask(web_frame_scheduler_->timerTaskRunner(), &run_count),
       1.0);
 
   mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl_unittest.cc
index 287fe6e..0c94e408 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl_unittest.cc
@@ -79,23 +79,22 @@
 }
 
 namespace {
-class RepeatingTask : public blink::WebTaskRunner::Task {
- public:
-  RepeatingTask(blink::WebTaskRunner* web_task_runner, int* run_count)
-      : web_task_runner_(web_task_runner), run_count_(run_count) {}
 
-  ~RepeatingTask() override {}
+void runRepeatingTask(blink::WebTaskRunner* task_runner, int* run_count);
 
-  void run() override {
-    (*run_count_)++;
-    web_task_runner_->postDelayedTask(
-        BLINK_FROM_HERE, new RepeatingTask(web_task_runner_, run_count_), 1.0);
-  }
+std::unique_ptr<WTF::Closure> makeRepeatingTask(
+    blink::WebTaskRunner* task_runner,
+    int* run_count) {
+  return WTF::bind(&runRepeatingTask, WTF::unretained(task_runner),
+                   WTF::unretained(run_count));
+}
 
- private:
-  blink::WebTaskRunner* web_task_runner_;  // NOT OWNED
-  int* run_count_;                         // NOT OWNED
-};
+void runRepeatingTask(blink::WebTaskRunner* task_runner, int* run_count) {
+  ++*run_count;
+  task_runner->postDelayedTask(BLINK_FROM_HERE,
+                               makeRepeatingTask(task_runner, run_count), 1.0);
+}
+
 }  // namespace
 
 TEST_F(WebViewSchedulerImplTest, RepeatingTimer_PageInForeground) {
@@ -104,7 +103,7 @@
   int run_count = 0;
   web_frame_scheduler_->timerTaskRunner()->postDelayedTask(
       BLINK_FROM_HERE,
-      new RepeatingTask(web_frame_scheduler_->timerTaskRunner(), &run_count),
+      makeRepeatingTask(web_frame_scheduler_->timerTaskRunner(), &run_count),
       1.0);
 
   mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
@@ -117,7 +116,7 @@
   int run_count = 0;
   web_frame_scheduler_->timerTaskRunner()->postDelayedTask(
       BLINK_FROM_HERE,
-      new RepeatingTask(web_frame_scheduler_->timerTaskRunner(), &run_count),
+      makeRepeatingTask(web_frame_scheduler_->timerTaskRunner(), &run_count),
       1.0);
 
   mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
@@ -130,7 +129,7 @@
   int run_count = 0;
   web_frame_scheduler_->loadingTaskRunner()->postDelayedTask(
       BLINK_FROM_HERE,
-      new RepeatingTask(web_frame_scheduler_->loadingTaskRunner(), &run_count),
+      makeRepeatingTask(web_frame_scheduler_->loadingTaskRunner(), &run_count),
       1.0);
 
   mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
@@ -150,11 +149,11 @@
   int run_count2 = 0;
   web_frame_scheduler_->timerTaskRunner()->postDelayedTask(
       BLINK_FROM_HERE,
-      new RepeatingTask(web_frame_scheduler_->timerTaskRunner(), &run_count1),
+      makeRepeatingTask(web_frame_scheduler_->timerTaskRunner(), &run_count1),
       1.0);
   web_frame_scheduler2->timerTaskRunner()->postDelayedTask(
       BLINK_FROM_HERE,
-      new RepeatingTask(web_frame_scheduler2->timerTaskRunner(), &run_count2),
+      makeRepeatingTask(web_frame_scheduler2->timerTaskRunner(), &run_count2),
       1.0);
 
   mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
@@ -163,31 +162,26 @@
 }
 
 namespace {
-class VirtualTimeRecorderTask : public blink::WebTaskRunner::Task {
- public:
-  VirtualTimeRecorderTask(base::SimpleTestTickClock* clock,
-                          blink::WebTaskRunner* web_task_runner,
-                          std::vector<base::TimeTicks>* out_real_times,
-                          std::vector<size_t>* out_virtual_times_ms)
-      : clock_(clock),
-        web_task_runner_(web_task_runner),
-        out_real_times_(out_real_times),
-        out_virtual_times_ms_(out_virtual_times_ms) {}
 
-  ~VirtualTimeRecorderTask() override {}
+void runVirtualTimeRecorderTask(base::SimpleTestTickClock* clock,
+                                blink::WebTaskRunner* web_task_runner,
+                                std::vector<base::TimeTicks>* out_real_times,
+                                std::vector<size_t>* out_virtual_times_ms) {
+  out_real_times->push_back(clock->NowTicks());
+  out_virtual_times_ms->push_back(
+      web_task_runner->monotonicallyIncreasingVirtualTimeSeconds() * 1000.0);
+}
 
-  void run() override {
-    out_real_times_->push_back(clock_->NowTicks());
-    out_virtual_times_ms_->push_back(
-        web_task_runner_->monotonicallyIncreasingVirtualTimeSeconds() * 1000.0);
-  }
-
- private:
-  base::SimpleTestTickClock* clock_;              // NOT OWNED
-  blink::WebTaskRunner* web_task_runner_;         // NOT OWNED
-  std::vector<base::TimeTicks>* out_real_times_;  // NOT OWNED
-  std::vector<size_t>* out_virtual_times_ms_;     // NOT OWNED
-};
+std::unique_ptr<WTF::Closure> makeVirtualTimeRecorderTask(
+    base::SimpleTestTickClock* clock,
+    blink::WebTaskRunner* web_task_runner,
+    std::vector<base::TimeTicks>* out_real_times,
+    std::vector<size_t>* out_virtual_times_ms) {
+  return WTF::bind(&runVirtualTimeRecorderTask, WTF::unretained(clock),
+                   WTF::unretained(web_task_runner),
+                   WTF::unretained(out_real_times),
+                   WTF::unretained(out_virtual_times_ms));
+}
 }
 
 TEST_F(WebViewSchedulerImplTest, VirtualTime_TimerFastForwarding) {
@@ -203,21 +197,21 @@
 
   web_frame_scheduler_->timerTaskRunner()->postDelayedTask(
       BLINK_FROM_HERE,
-      new VirtualTimeRecorderTask(clock_.get(),
+      makeVirtualTimeRecorderTask(clock_.get(),
                                   web_frame_scheduler_->timerTaskRunner(),
                                   &real_times, &virtual_times_ms),
       2.0);
 
   web_frame_scheduler_->timerTaskRunner()->postDelayedTask(
       BLINK_FROM_HERE,
-      new VirtualTimeRecorderTask(clock_.get(),
+      makeVirtualTimeRecorderTask(clock_.get(),
                                   web_frame_scheduler_->timerTaskRunner(),
                                   &real_times, &virtual_times_ms),
       20.0);
 
   web_frame_scheduler_->timerTaskRunner()->postDelayedTask(
       BLINK_FROM_HERE,
-      new VirtualTimeRecorderTask(clock_.get(),
+      makeVirtualTimeRecorderTask(clock_.get(),
                                   web_frame_scheduler_->timerTaskRunner(),
                                   &real_times, &virtual_times_ms),
       200.0);
@@ -244,21 +238,21 @@
 
   web_frame_scheduler_->loadingTaskRunner()->postDelayedTask(
       BLINK_FROM_HERE,
-      new VirtualTimeRecorderTask(clock_.get(),
+      makeVirtualTimeRecorderTask(clock_.get(),
                                   web_frame_scheduler_->loadingTaskRunner(),
                                   &real_times, &virtual_times_ms),
       2.0);
 
   web_frame_scheduler_->loadingTaskRunner()->postDelayedTask(
       BLINK_FROM_HERE,
-      new VirtualTimeRecorderTask(clock_.get(),
+      makeVirtualTimeRecorderTask(clock_.get(),
                                   web_frame_scheduler_->loadingTaskRunner(),
                                   &real_times, &virtual_times_ms),
       20.0);
 
   web_frame_scheduler_->loadingTaskRunner()->postDelayedTask(
       BLINK_FROM_HERE,
-      new VirtualTimeRecorderTask(clock_.get(),
+      makeVirtualTimeRecorderTask(clock_.get(),
                                   web_frame_scheduler_->loadingTaskRunner(),
                                   &real_times, &virtual_times_ms),
       200.0);
@@ -281,7 +275,7 @@
   int run_count = 0;
   web_frame_scheduler_->timerTaskRunner()->postDelayedTask(
       BLINK_FROM_HERE,
-      new RepeatingTask(web_frame_scheduler_->timerTaskRunner(), &run_count),
+      makeRepeatingTask(web_frame_scheduler_->timerTaskRunner(), &run_count),
       1.0);
 
   mock_task_runner_->RunTasksWhile(mock_task_runner_->TaskRunCountBelow(2000));
@@ -294,42 +288,19 @@
 }
 
 namespace {
-class RunOrderTask : public blink::WebTaskRunner::Task {
- public:
-  RunOrderTask(int index, std::vector<int>* out_run_order)
-      : index_(index), out_run_order_(out_run_order) {}
 
-  ~RunOrderTask() override {}
+void runOrderTask(int index, std::vector<int>* out_run_order) {
+  out_run_order->push_back(index);
+}
 
-  void run() override { out_run_order_->push_back(index_); }
-
- private:
-  int index_;
-  std::vector<int>* out_run_order_;  // NOT OWNED
-};
-
-class DelayedRunOrderTask : public blink::WebTaskRunner::Task {
- public:
-  DelayedRunOrderTask(int index,
-                      blink::WebTaskRunner* task_runner,
-                      std::vector<int>* out_run_order)
-      : index_(index),
-        task_runner_(task_runner),
-        out_run_order_(out_run_order) {}
-
-  ~DelayedRunOrderTask() override {}
-
-  void run() override {
-    out_run_order_->push_back(index_);
-    task_runner_->postTask(BLINK_FROM_HERE,
-                           new RunOrderTask(index_ + 1, out_run_order_));
-  }
-
- private:
-  int index_;
-  blink::WebTaskRunner* task_runner_;  // NOT OWNED
-  std::vector<int>* out_run_order_;    // NOT OWNED
-};
+void delayedRunOrderTask(int index,
+                         blink::WebTaskRunner* task_runner,
+                         std::vector<int>* out_run_order) {
+  out_run_order->push_back(index);
+  task_runner->postTask(
+      BLINK_FROM_HERE,
+      WTF::bind(&runOrderTask, index + 1, WTF::unretained(out_run_order)));
+}
 }
 
 TEST_F(WebViewSchedulerImplTest, VirtualTime_NotAllowedToAdvance) {
@@ -339,18 +310,21 @@
   web_view_scheduler_->enableVirtualTime();
 
   web_frame_scheduler_->timerTaskRunner()->postTask(
-      BLINK_FROM_HERE, new RunOrderTask(0, &run_order));
+      BLINK_FROM_HERE,
+      WTF::bind(&runOrderTask, 0, WTF::unretained(&run_order)));
 
   web_frame_scheduler_->timerTaskRunner()->postDelayedTask(
       BLINK_FROM_HERE,
-      new DelayedRunOrderTask(1, web_frame_scheduler_->timerTaskRunner(),
-                              &run_order),
+      WTF::bind(&delayedRunOrderTask, 1,
+                WTF::unretained(web_frame_scheduler_->timerTaskRunner()),
+                WTF::unretained(&run_order)),
       2.0);
 
   web_frame_scheduler_->timerTaskRunner()->postDelayedTask(
       BLINK_FROM_HERE,
-      new DelayedRunOrderTask(3, web_frame_scheduler_->timerTaskRunner(),
-                              &run_order),
+      WTF::bind(&delayedRunOrderTask, 3,
+                WTF::unretained(web_frame_scheduler_->timerTaskRunner()),
+                WTF::unretained(&run_order)),
       4.0);
 
   mock_task_runner_->RunUntilIdle();
@@ -366,18 +340,21 @@
   web_view_scheduler_->enableVirtualTime();
 
   web_frame_scheduler_->timerTaskRunner()->postTask(
-      BLINK_FROM_HERE, new RunOrderTask(0, &run_order));
+      BLINK_FROM_HERE,
+      WTF::bind(&runOrderTask, 0, WTF::unretained(&run_order)));
 
   web_frame_scheduler_->timerTaskRunner()->postDelayedTask(
       BLINK_FROM_HERE,
-      new DelayedRunOrderTask(1, web_frame_scheduler_->timerTaskRunner(),
-                              &run_order),
+      WTF::bind(&delayedRunOrderTask, 1,
+                WTF::unretained(web_frame_scheduler_->timerTaskRunner()),
+                WTF::unretained(&run_order)),
       2.0);
 
   web_frame_scheduler_->timerTaskRunner()->postDelayedTask(
       BLINK_FROM_HERE,
-      new DelayedRunOrderTask(3, web_frame_scheduler_->timerTaskRunner(),
-                              &run_order),
+      WTF::bind(&delayedRunOrderTask, 3,
+                WTF::unretained(web_frame_scheduler_->timerTaskRunner()),
+                WTF::unretained(&run_order)),
       4.0);
 
   mock_task_runner_->RunUntilIdle();
@@ -401,7 +378,7 @@
   int run_count = 0;
   web_frame_scheduler_->timerTaskRunner()->postDelayedTask(
       BLINK_FROM_HERE,
-      new RepeatingTask(web_frame_scheduler_->timerTaskRunner(), &run_count),
+      makeRepeatingTask(web_frame_scheduler_->timerTaskRunner(), &run_count),
       1.0);
 
   mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
@@ -418,7 +395,8 @@
       web_view_scheduler_->createWebFrameSchedulerImpl(nullptr);
 
   web_frame_scheduler->timerTaskRunner()->postDelayedTask(
-      BLINK_FROM_HERE, new RunOrderTask(1, &run_order), 0.1);
+      BLINK_FROM_HERE, WTF::bind(&runOrderTask, 1, WTF::unretained(&run_order)),
+      1);
 
   mock_task_runner_->RunUntilIdle();
   EXPECT_TRUE(run_order.empty());
@@ -430,72 +408,47 @@
 }
 
 namespace {
-class DeleteWebFrameSchedulerTask : public blink::WebTaskRunner::Task {
- public:
-  explicit DeleteWebFrameSchedulerTask(WebViewSchedulerImpl* web_view_scheduler)
-      : web_frame_scheduler_(
-            web_view_scheduler->createWebFrameSchedulerImpl(nullptr)) {}
 
-  ~DeleteWebFrameSchedulerTask() override {}
+template <typename T>
+std::unique_ptr<WTF::Closure> makeDeletionTask(T* obj) {
+  return WTF::bind([](T* obj) { delete obj; }, WTF::unretained(obj));
+}
 
-  void run() override { web_frame_scheduler_.reset(); }
-
-  WebFrameSchedulerImpl* web_frame_scheduler() const {
-    return web_frame_scheduler_.get();
-  }
-
- private:
-  std::unique_ptr<WebFrameSchedulerImpl> web_frame_scheduler_;
-};
-
-class DeleteWebViewSchedulerTask : public blink::WebTaskRunner::Task {
- public:
-  explicit DeleteWebViewSchedulerTask(WebViewSchedulerImpl* web_view_scheduler)
-      : web_view_scheduler_(web_view_scheduler) {}
-
-  ~DeleteWebViewSchedulerTask() override {}
-
-  void run() override { web_view_scheduler_.reset(); }
-
- private:
-  std::unique_ptr<WebViewSchedulerImpl> web_view_scheduler_;
-};
 }  // namespace
 
 TEST_F(WebViewSchedulerImplTest, DeleteWebFrameSchedulers_InTask) {
   for (int i = 0; i < 10; i++) {
-    DeleteWebFrameSchedulerTask* task =
-        new DeleteWebFrameSchedulerTask(web_view_scheduler_.get());
-    task->web_frame_scheduler()->timerTaskRunner()->postDelayedTask(
-        BLINK_FROM_HERE, task, 1.0);
+    WebFrameSchedulerImpl* web_frame_scheduler =
+        web_view_scheduler_->createWebFrameSchedulerImpl(nullptr).release();
+    web_frame_scheduler->timerTaskRunner()->postDelayedTask(
+        BLINK_FROM_HERE, makeDeletionTask(web_frame_scheduler), 1);
   }
   mock_task_runner_->RunUntilIdle();
 }
 
 TEST_F(WebViewSchedulerImplTest, DeleteWebViewScheduler_InTask) {
   web_frame_scheduler_->timerTaskRunner()->postTask(
-      BLINK_FROM_HERE,
-      new DeleteWebViewSchedulerTask(web_view_scheduler_.release()));
+      BLINK_FROM_HERE, makeDeletionTask(web_view_scheduler_.release()));
   mock_task_runner_->RunUntilIdle();
 }
 
 TEST_F(WebViewSchedulerImplTest, DeleteThrottledQueue_InTask) {
   web_view_scheduler_->setPageVisible(false);
 
-  DeleteWebFrameSchedulerTask* delete_frame_task =
-      new DeleteWebFrameSchedulerTask(web_view_scheduler_.get());
+  WebFrameSchedulerImpl* web_frame_scheduler =
+      web_view_scheduler_->createWebFrameSchedulerImpl(nullptr).release();
   blink::WebTaskRunner* timer_task_runner =
-      delete_frame_task->web_frame_scheduler()->timerTaskRunner();
+      web_frame_scheduler->timerTaskRunner();
 
   int run_count = 0;
   timer_task_runner->postDelayedTask(
-      BLINK_FROM_HERE, new RepeatingTask(timer_task_runner, &run_count), 1.0);
+      BLINK_FROM_HERE, makeRepeatingTask(timer_task_runner, &run_count), 1.0);
 
   // Note this will run at time t = 10s since we start at time t = 5000us, and
   // it will prevent further tasks from running (i.e. the RepeatingTask) by
   // deleting the WebFrameScheduler.
-  timer_task_runner->postDelayedTask(BLINK_FROM_HERE, delete_frame_task,
-                                     9990.0);
+  timer_task_runner->postDelayedTask(
+      BLINK_FROM_HERE, makeDeletionTask(web_frame_scheduler), 9990.0);
 
   mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(100));
   EXPECT_EQ(10, run_count);
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler_unittest.cc
index 6fc53b0..f9111c7 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler_unittest.cc
@@ -26,7 +26,7 @@
 
 const int kWorkBatchSize = 2;
 
-class MockTask : public blink::WebTaskRunner::Task {
+class MockTask {
  public:
   MOCK_METHOD0(run, void());
 };
@@ -73,17 +73,17 @@
 TEST_F(WebThreadImplForRendererSchedulerTest, TestTaskObserver) {
   MockTaskObserver observer;
   thread_->addTaskObserver(&observer);
-  std::unique_ptr<MockTask> task(new MockTask());
+  MockTask task;
 
   {
     testing::InSequence sequence;
     EXPECT_CALL(observer, willProcessTask());
-    EXPECT_CALL(*task, run());
+    EXPECT_CALL(task, run());
     EXPECT_CALL(observer, didProcessTask());
   }
 
-  thread_->getWebTaskRunner()->postTask(blink::WebTraceLocation(),
-                                        task.release());
+  thread_->getWebTaskRunner()->postTask(
+      BLINK_FROM_HERE, WTF::bind(&MockTask::run, WTF::unretained(&task)));
   base::RunLoop().RunUntilIdle();
   thread_->removeTaskObserver(&observer);
 }
@@ -91,18 +91,18 @@
 TEST_F(WebThreadImplForRendererSchedulerTest, TestWorkBatchWithOneTask) {
   MockTaskObserver observer;
   thread_->addTaskObserver(&observer);
-  std::unique_ptr<MockTask> task(new MockTask());
+  MockTask task;
 
   SetWorkBatchSizeForTesting(kWorkBatchSize);
   {
     testing::InSequence sequence;
     EXPECT_CALL(observer, willProcessTask());
-    EXPECT_CALL(*task, run());
+    EXPECT_CALL(task, run());
     EXPECT_CALL(observer, didProcessTask());
   }
 
-  thread_->getWebTaskRunner()->postTask(blink::WebTraceLocation(),
-                                        task.release());
+  thread_->getWebTaskRunner()->postTask(
+      BLINK_FROM_HERE, WTF::bind(&MockTask::run, WTF::unretained(&task)));
   base::RunLoop().RunUntilIdle();
   thread_->removeTaskObserver(&observer);
 }
@@ -110,25 +110,25 @@
 TEST_F(WebThreadImplForRendererSchedulerTest, TestWorkBatchWithTwoTasks) {
   MockTaskObserver observer;
   thread_->addTaskObserver(&observer);
-  std::unique_ptr<MockTask> task1(new MockTask());
-  std::unique_ptr<MockTask> task2(new MockTask());
+  MockTask task1;
+  MockTask task2;
 
   SetWorkBatchSizeForTesting(kWorkBatchSize);
   {
     testing::InSequence sequence;
     EXPECT_CALL(observer, willProcessTask());
-    EXPECT_CALL(*task1, run());
+    EXPECT_CALL(task1, run());
     EXPECT_CALL(observer, didProcessTask());
 
     EXPECT_CALL(observer, willProcessTask());
-    EXPECT_CALL(*task2, run());
+    EXPECT_CALL(task2, run());
     EXPECT_CALL(observer, didProcessTask());
   }
 
-  thread_->getWebTaskRunner()->postTask(blink::WebTraceLocation(),
-                                        task1.release());
-  thread_->getWebTaskRunner()->postTask(blink::WebTraceLocation(),
-                                        task2.release());
+  thread_->getWebTaskRunner()->postTask(
+      BLINK_FROM_HERE, WTF::bind(&MockTask::run, WTF::unretained(&task1)));
+  thread_->getWebTaskRunner()->postTask(
+      BLINK_FROM_HERE, WTF::bind(&MockTask::run, WTF::unretained(&task2)));
   base::RunLoop().RunUntilIdle();
   thread_->removeTaskObserver(&observer);
 }
@@ -136,52 +136,43 @@
 TEST_F(WebThreadImplForRendererSchedulerTest, TestWorkBatchWithThreeTasks) {
   MockTaskObserver observer;
   thread_->addTaskObserver(&observer);
-  std::unique_ptr<MockTask> task1(new MockTask());
-  std::unique_ptr<MockTask> task2(new MockTask());
-  std::unique_ptr<MockTask> task3(new MockTask());
+  MockTask task1;
+  MockTask task2;
+  MockTask task3;
 
   SetWorkBatchSizeForTesting(kWorkBatchSize);
   {
     testing::InSequence sequence;
     EXPECT_CALL(observer, willProcessTask());
-    EXPECT_CALL(*task1, run());
+    EXPECT_CALL(task1, run());
     EXPECT_CALL(observer, didProcessTask());
 
     EXPECT_CALL(observer, willProcessTask());
-    EXPECT_CALL(*task2, run());
+    EXPECT_CALL(task2, run());
     EXPECT_CALL(observer, didProcessTask());
 
     EXPECT_CALL(observer, willProcessTask());
-    EXPECT_CALL(*task3, run());
+    EXPECT_CALL(task3, run());
     EXPECT_CALL(observer, didProcessTask());
   }
 
-  thread_->getWebTaskRunner()->postTask(blink::WebTraceLocation(),
-                                        task1.release());
-  thread_->getWebTaskRunner()->postTask(blink::WebTraceLocation(),
-                                        task2.release());
-  thread_->getWebTaskRunner()->postTask(blink::WebTraceLocation(),
-                                        task3.release());
+  thread_->getWebTaskRunner()->postTask(
+      BLINK_FROM_HERE, WTF::bind(&MockTask::run, WTF::unretained(&task1)));
+  thread_->getWebTaskRunner()->postTask(
+      BLINK_FROM_HERE, WTF::bind(&MockTask::run, WTF::unretained(&task2)));
+  thread_->getWebTaskRunner()->postTask(
+      BLINK_FROM_HERE, WTF::bind(&MockTask::run, WTF::unretained(&task3)));
   base::RunLoop().RunUntilIdle();
   thread_->removeTaskObserver(&observer);
 }
 
-class ExitRunLoopTask : public blink::WebTaskRunner::Task {
- public:
-  ExitRunLoopTask(base::RunLoop* run_loop) : run_loop_(run_loop) {}
-
-  void run() override { run_loop_->Quit(); }
-
- private:
-  base::RunLoop* run_loop_;
-};
-
 void EnterRunLoop(base::MessageLoop* message_loop, blink::WebThread* thread) {
   // Note: WebThreads do not support nested run loops, which is why we use a
   // run loop directly.
   base::RunLoop run_loop;
-  thread->getWebTaskRunner()->postTask(blink::WebTraceLocation(),
-                                       new ExitRunLoopTask(&run_loop));
+  thread->getWebTaskRunner()->postTask(
+      BLINK_FROM_HERE,
+      WTF::bind(&base::RunLoop::Quit, WTF::unretained(&run_loop)));
   message_loop->SetNestableTasksAllowed(true);
   run_loop.Run();
 }
diff --git a/third_party/WebKit/Source/platform/scheduler/test/fake_web_task_runner.cc b/third_party/WebKit/Source/platform/scheduler/test/fake_web_task_runner.cc
index 0d38666..304d1ade 100644
--- a/third_party/WebKit/Source/platform/scheduler/test/fake_web_task_runner.cc
+++ b/third_party/WebKit/Source/platform/scheduler/test/fake_web_task_runner.cc
@@ -68,17 +68,6 @@
   data_->time_ = new_time;
 }
 
-void FakeWebTaskRunner::postTask(const WebTraceLocation&, Task*) {
-  NOTREACHED();
-}
-
-void FakeWebTaskRunner::postDelayedTask(const WebTraceLocation&,
-                                        Task* task,
-                                        double) {
-  data_->task_queue_.push_back(
-      base::Bind(&WebTaskRunner::Task::run, base::Owned(task)));
-}
-
 void FakeWebTaskRunner::postDelayedTask(const WebTraceLocation&,
                                         const base::Closure& closure,
                                         double) {
diff --git a/third_party/WebKit/Source/platform/scheduler/test/fake_web_task_runner.h b/third_party/WebKit/Source/platform/scheduler/test/fake_web_task_runner.h
index 4a6c435..2753d2b2 100644
--- a/third_party/WebKit/Source/platform/scheduler/test/fake_web_task_runner.h
+++ b/third_party/WebKit/Source/platform/scheduler/test/fake_web_task_runner.h
@@ -25,8 +25,6 @@
   void setTime(double new_time);
 
   // WebTaskRunner implementation:
-  void postTask(const WebTraceLocation&, Task*) override;
-  void postDelayedTask(const WebTraceLocation&, Task*, double) override;
   void postDelayedTask(const WebTraceLocation&,
                        const base::Closure&,
                        double) override;
diff --git a/third_party/WebKit/Source/platform/testing/PaintPropertyTestHelpers.h b/third_party/WebKit/Source/platform/testing/PaintPropertyTestHelpers.h
new file mode 100644
index 0000000..8a74c39
--- /dev/null
+++ b/third_party/WebKit/Source/platform/testing/PaintPropertyTestHelpers.h
@@ -0,0 +1,36 @@
+// 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/graphics/paint/ClipPaintPropertyNode.h"
+#include "platform/graphics/paint/EffectPaintPropertyNode.h"
+#include "platform/graphics/paint/PaintChunkProperties.h"
+#include "platform/graphics/paint/ScrollPaintPropertyNode.h"
+#include "platform/graphics/paint/TransformPaintPropertyNode.h"
+
+namespace blink {
+namespace testing {
+
+static inline PassRefPtr<EffectPaintPropertyNode> createOpacityOnlyEffect(
+    PassRefPtr<const EffectPaintPropertyNode> parent,
+    float opacity) {
+  RefPtr<TransformPaintPropertyNode> localTransformSpace =
+      const_cast<TransformPaintPropertyNode*>(parent->localTransformSpace());
+  RefPtr<ClipPaintPropertyNode> outputClip =
+      const_cast<ClipPaintPropertyNode*>(parent->outputClip());
+  return EffectPaintPropertyNode::create(
+      std::move(parent), std::move(localTransformSpace), std::move(outputClip),
+      CompositorFilterOperations(), opacity);
+}
+
+static inline PaintChunkProperties defaultPaintChunkProperties() {
+  PaintChunkProperties defaultProperties;
+  defaultProperties.transform = TransformPaintPropertyNode::root();
+  defaultProperties.clip = ClipPaintPropertyNode::root();
+  defaultProperties.effect = EffectPaintPropertyNode::root();
+  defaultProperties.scroll = ScrollPaintPropertyNode::root();
+  return defaultProperties;
+}
+
+}  // namespace testing
+}  // namespace blink
diff --git a/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.h b/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.h
index 938dbb4..0b9e0e9 100644
--- a/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.h
+++ b/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.h
@@ -108,9 +108,6 @@
   void resumeTimerQueue() override {}
   void addPendingNavigation(WebScheduler::NavigatingFrameType) override {}
   void removePendingNavigation(WebScheduler::NavigatingFrameType) override {}
-
- private:
-  WTF::Deque<std::unique_ptr<WebTaskRunner::Task>> m_tasks;
 };
 
 class TestingPlatformSupport : public Platform {
diff --git a/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeProxy.cpp b/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeProxy.cpp
index bedc1c6..28ac4a83 100644
--- a/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeProxy.cpp
+++ b/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeProxy.cpp
@@ -167,7 +167,8 @@
       workerGlobalScope(), WaitUntilObserver::Fetch, fetchEventID);
   RespondWithObserver* respondWithObserver = RespondWithObserver::create(
       workerGlobalScope(), fetchEventID, webRequest.url(), webRequest.mode(),
-      webRequest.frameType(), webRequest.requestContext(), waitUntilObserver);
+      webRequest.redirectMode(), webRequest.frameType(),
+      webRequest.requestContext(), waitUntilObserver);
   Request* request = Request::create(
       workerGlobalScope()->scriptController()->getScriptState(), webRequest);
   request->getHeaders()->setGuard(Headers::ImmutableGuard);
@@ -244,7 +245,7 @@
   ForeignFetchRespondWithObserver* respondWithObserver =
       ForeignFetchRespondWithObserver::create(
           workerGlobalScope(), fetchEventID, webRequest.url(),
-          webRequest.mode(), webRequest.frameType(),
+          webRequest.mode(), webRequest.redirectMode(), webRequest.frameType(),
           webRequest.requestContext(), origin, waitUntilObserver);
   Request* request = Request::create(
       workerGlobalScope()->scriptController()->getScriptState(), webRequest);
diff --git a/third_party/WebKit/Source/web/SharedWorkerRepositoryClientImpl.cpp b/third_party/WebKit/Source/web/SharedWorkerRepositoryClientImpl.cpp
index 13f4441..7ed68f5 100644
--- a/third_party/WebKit/Source/web/SharedWorkerRepositoryClientImpl.cpp
+++ b/third_party/WebKit/Source/web/SharedWorkerRepositoryClientImpl.cpp
@@ -144,9 +144,7 @@
   }
 
   WebWorkerCreationError creationError;
-  String unusedSecureContextError;
-  bool isSecureContext =
-      worker->getExecutionContext()->isSecureContext(unusedSecureContextError);
+  bool isSecureContext = worker->getExecutionContext()->isSecureContext();
   std::unique_ptr<WebSharedWorkerConnector> webWorkerConnector =
       WTF::wrapUnique(m_client->createSharedWorkerConnector(
           url, name, getId(document), header, headerType,
diff --git a/third_party/WebKit/Source/web/WebDocument.cpp b/third_party/WebKit/Source/web/WebDocument.cpp
index 78d64db8..26f088f 100644
--- a/third_party/WebKit/Source/web/WebDocument.cpp
+++ b/third_party/WebKit/Source/web/WebDocument.cpp
@@ -79,14 +79,9 @@
   return WebSecurityOrigin(constUnwrap<Document>()->getSecurityOrigin());
 }
 
-bool WebDocument::isSecureContext(WebString& errorMessage) const {
+bool WebDocument::isSecureContext() const {
   const Document* document = constUnwrap<Document>();
-  if (!document)
-    return false;
-  String message;
-  bool result = document->isSecureContext(message);
-  errorMessage = message;
-  return result;
+  return document && document->isSecureContext();
 }
 
 WebString WebDocument::encoding() const {
diff --git a/third_party/WebKit/Source/web/WebHistoryItem.cpp b/third_party/WebKit/Source/web/WebHistoryItem.cpp
index 70e5a20b..08fafab 100644
--- a/third_party/WebKit/Source/web/WebHistoryItem.cpp
+++ b/third_party/WebKit/Source/web/WebHistoryItem.cpp
@@ -113,8 +113,8 @@
   m_private->setPageScaleFactor(scale);
 }
 
-WebVector<WebString> WebHistoryItem::documentState() const {
-  return m_private->documentState();
+WebVector<WebString> WebHistoryItem::getDocumentState() const {
+  return m_private->getDocumentState();
 }
 
 void WebHistoryItem::setDocumentState(const WebVector<WebString>& state) {
diff --git a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
index d49378a..97bbe6a 100644
--- a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
+++ b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
@@ -941,7 +941,7 @@
 }
 
 unsigned WebLocalFrameImpl::unloadListenerCount() const {
-  return frame()->localDOMWindow()->pendingUnloadEventListeners();
+  return frame()->domWindow()->pendingUnloadEventListeners();
 }
 
 void WebLocalFrameImpl::replaceSelection(const WebString& text) {
@@ -2062,7 +2062,7 @@
 
   // Legacy window.orientation API
   if (RuntimeEnabledFeatures::orientationEventEnabled() && frame()->domWindow())
-    frame()->localDOMWindow()->sendOrientationChangeEvent();
+    frame()->domWindow()->sendOrientationChangeEvent();
 }
 
 void WebLocalFrameImpl::didCallAddSearchProvider() {
@@ -2179,7 +2179,7 @@
     const WebSecurityOrigin& intendedTargetOrigin,
     const WebDOMEvent& event) {
   DCHECK(!event.isNull());
-  frame()->localDOMWindow()->dispatchMessageEventWithOriginCheck(
+  frame()->domWindow()->dispatchMessageEventWithOriginCheck(
       intendedTargetOrigin.get(), event,
       SourceLocation::create(String(), 0, 0, nullptr));
 }
diff --git a/third_party/WebKit/Source/web/WebPagePopupImpl.cpp b/third_party/WebKit/Source/web/WebPagePopupImpl.cpp
index 86336bd70..f7554080 100644
--- a/third_party/WebKit/Source/web/WebPagePopupImpl.cpp
+++ b/third_party/WebKit/Source/web/WebPagePopupImpl.cpp
@@ -304,7 +304,7 @@
           m_popupClient->ownerElement().document().existingAXObjectCache())
     cache->childrenChanged(&m_popupClient->ownerElement());
 
-  DCHECK(frame->localDOMWindow());
+  DCHECK(frame->domWindow());
   PagePopupSupplement::install(*frame, *this, m_popupClient);
   DCHECK_EQ(m_popupClient->ownerElement().document().existingAXObjectCache(),
             frame->document()->existingAXObjectCache());
@@ -322,8 +322,7 @@
   if (!m_page)
     return;
   ScriptForbiddenScope::AllowUserAgentScript allowScript;
-  if (LocalDOMWindow* window =
-          toLocalFrame(m_page->mainFrame())->localDOMWindow())
+  if (LocalDOMWindow* window = toLocalFrame(m_page->mainFrame())->domWindow())
     window->dispatchEvent(MessageEvent::create(message));
 }
 
@@ -545,7 +544,7 @@
 }
 
 LocalDOMWindow* WebPagePopupImpl::window() {
-  return m_page->deprecatedLocalMainFrame()->localDOMWindow();
+  return m_page->deprecatedLocalMainFrame()->domWindow();
 }
 
 void WebPagePopupImpl::layoutAndPaintAsync(
diff --git a/third_party/WebKit/Source/web/WebUserGestureIndicator.cpp b/third_party/WebKit/Source/web/WebUserGestureIndicator.cpp
index e1eaf1b..9e206ee 100644
--- a/third_party/WebKit/Source/web/WebUserGestureIndicator.cpp
+++ b/third_party/WebKit/Source/web/WebUserGestureIndicator.cpp
@@ -40,8 +40,15 @@
   return UserGestureIndicator::processingUserGesture();
 }
 
+bool WebUserGestureIndicator::isProcessingUserGestureThreadSafe() {
+  return UserGestureIndicator::processingUserGestureThreadSafe();
+}
+
+// TODO(csharrison): consumeUserGesture() and currentUserGestureToken() use
+// the thread-safe API, which many callers probably do not need. Consider
+// updating them if they are in any sort of critical path or called often.
 bool WebUserGestureIndicator::consumeUserGesture() {
-  return UserGestureIndicator::consumeUserGesture();
+  return UserGestureIndicator::consumeUserGestureThreadSafe();
 }
 
 bool WebUserGestureIndicator::processedUserGestureSinceLoad(
@@ -51,7 +58,7 @@
 }
 
 WebUserGestureToken WebUserGestureIndicator::currentUserGestureToken() {
-  return WebUserGestureToken(UserGestureIndicator::currentToken());
+  return WebUserGestureToken(UserGestureIndicator::currentTokenThreadSafe());
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/web/tests/BrowserControlsTest.cpp b/third_party/WebKit/Source/web/tests/BrowserControlsTest.cpp
index 330ab6e1..d8099ba 100644
--- a/third_party/WebKit/Source/web/tests/BrowserControlsTest.cpp
+++ b/third_party/WebKit/Source/web/tests/BrowserControlsTest.cpp
@@ -169,7 +169,9 @@
   webView->handleInputEvent(
       generateEvent(WebInputEvent::GestureScrollUpdate, 0, -25.f));
   EXPECT_FLOAT_EQ(25.f, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 0), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 0),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 
   // Browser controls should consume 25px and become hidden. Excess scroll
   // should be
@@ -177,13 +179,17 @@
   webView->handleInputEvent(
       generateEvent(WebInputEvent::GestureScrollUpdate, 0, -40.f));
   EXPECT_FLOAT_EQ(0.f, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 15), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 15),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 
   // Only page should consume scroll
   webView->handleInputEvent(
       generateEvent(WebInputEvent::GestureScrollUpdate, 0, -20.f));
   EXPECT_FLOAT_EQ(0.f, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 35), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 35),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 }
 
 // Scrolling up should show browser controls.
@@ -199,12 +205,16 @@
   webView->handleInputEvent(
       generateEvent(WebInputEvent::GestureScrollUpdate, 0, 10.f));
   EXPECT_FLOAT_EQ(10.f, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 0), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 0),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 
   webView->handleInputEvent(
       generateEvent(WebInputEvent::GestureScrollUpdate, 0, 50.f));
   EXPECT_FLOAT_EQ(50.f, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 0), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 0),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 }
 
 // Scrolling up after previous scroll downs should cause browser controls to be
@@ -225,32 +235,42 @@
   webView->handleInputEvent(
       generateEvent(WebInputEvent::GestureScrollUpdate, 0, -150.f));
   EXPECT_FLOAT_EQ(0.f, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 200), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 200),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 
   // Scroll up and ensure the browser controls does not move until we recover
   // 100px previously scrolled.
   webView->handleInputEvent(
       generateEvent(WebInputEvent::GestureScrollUpdate, 0, 40.f));
   EXPECT_FLOAT_EQ(0.f, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 160), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 160),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 
   webView->handleInputEvent(
       generateEvent(WebInputEvent::GestureScrollUpdate, 0, 60.f));
   EXPECT_FLOAT_EQ(0.f, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 100), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 100),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 
   // Now we have hit the threshold so further scroll up should be consumed by
   // browser controls.
   webView->handleInputEvent(
       generateEvent(WebInputEvent::GestureScrollUpdate, 0, 30.f));
   EXPECT_FLOAT_EQ(30.f, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 100), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 100),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 
   // Once top control is fully shown then page should consume any excess scroll.
   webView->handleInputEvent(
       generateEvent(WebInputEvent::GestureScrollUpdate, 0, 70.f));
   EXPECT_FLOAT_EQ(50.f, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 50), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 50),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 }
 
 // Scrolling down should always cause visible browser controls to start hiding
@@ -271,18 +291,24 @@
   webView->handleInputEvent(
       generateEvent(WebInputEvent::GestureScrollUpdate, 0, 100.f));
   EXPECT_FLOAT_EQ(50.f, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 50), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 50),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 
   // Scroll down and ensure only browser controls is scrolled
   webView->handleInputEvent(
       generateEvent(WebInputEvent::GestureScrollUpdate, 0, -40.f));
   EXPECT_FLOAT_EQ(10.f, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 50), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 50),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 
   webView->handleInputEvent(
       generateEvent(WebInputEvent::GestureScrollUpdate, 0, -60.f));
   EXPECT_FLOAT_EQ(0.f, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 100), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 100),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 }
 
 // Browser controls should not consume horizontal scroll.
@@ -299,12 +325,16 @@
   webView->handleInputEvent(
       generateEvent(WebInputEvent::GestureScrollUpdate, -110.f, -100.f));
   EXPECT_FLOAT_EQ(0.f, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(110, 50), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(110, 50),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 
   webView->handleInputEvent(
       generateEvent(WebInputEvent::GestureScrollUpdate, -40.f, 0));
   EXPECT_FLOAT_EQ(0.f, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(150, 50), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(150, 50),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 }
 
 // Page scale should not impact browser controls scrolling
@@ -396,35 +426,47 @@
   // main frame should not scroll.
   verticalScroll(-800.f);
   EXPECT_FLOAT_EQ(50.f, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 50), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 50),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 
   // Continued scroll down should start hiding browser controls but main frame
   // should not scroll.
   verticalScroll(-40.f);
   EXPECT_FLOAT_EQ(10.f, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 50), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 50),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 
   // Continued scroll down should scroll down the main frame
   verticalScroll(-40.f);
   EXPECT_FLOAT_EQ(0.f, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 80), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 80),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 
   // Test scroll up
   // scroll up should scroll overflow div first
   verticalScroll(800.f);
   EXPECT_FLOAT_EQ(0.f, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 80), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 80),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 
   // Continued scroll up should start showing browser controls but main frame
   // should not scroll.
   verticalScroll(40.f);
   EXPECT_FLOAT_EQ(40.f, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 80), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 80),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 
   // Continued scroll down up scroll up the main frame
   verticalScroll(40.f);
   EXPECT_FLOAT_EQ(50.f, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 50), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 50),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 }
 
 // Scrollable iframes should scroll before browser controls
@@ -440,35 +482,47 @@
   // frame should not scroll.
   verticalScroll(-800.f);
   EXPECT_FLOAT_EQ(50.f, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 50), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 50),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 
   // Continued scroll down should start hiding browser controls but main frame
   // should not scroll.
   verticalScroll(-40.f);
   EXPECT_FLOAT_EQ(10.f, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 50), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 50),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 
   // Continued scroll down should scroll down the main frame
   verticalScroll(-40.f);
   EXPECT_FLOAT_EQ(0.f, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 80), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 80),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 
   // Test scroll up
   // scroll up should scroll iframe first
   verticalScroll(800.f);
   EXPECT_FLOAT_EQ(0.f, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 80), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 80),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 
   // Continued scroll up should start showing browser controls but main frame
   // should not scroll.
   verticalScroll(40.f);
   EXPECT_FLOAT_EQ(40.f, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 80), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 80),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 
   // Continued scroll down up scroll up the main frame
   verticalScroll(40.f);
   EXPECT_FLOAT_EQ(50.f, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 50), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 50),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 }
 
 // Browser controls visibility should remain consistent when height is changed.
@@ -505,11 +559,15 @@
 
   verticalScroll(20.f);
   EXPECT_FLOAT_EQ(0.f, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 80), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 80),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 
   verticalScroll(-30.f);
   EXPECT_FLOAT_EQ(0.f, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 110), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 110),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 
   webView->browserControls().setShownRatio(1);
   EXPECT_FLOAT_EQ(0.f, webView->browserControls().contentOffset());
@@ -564,7 +622,9 @@
   // Only shown state is permitted so controls cannot hide
   verticalScroll(-20.f);
   EXPECT_FLOAT_EQ(50, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 120), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 120),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 
   // Setting permitted state should change content offset to match the
   // constraint.
@@ -575,7 +635,9 @@
   // Only hidden state is permitted so controls cannot show
   verticalScroll(30.f);
   EXPECT_FLOAT_EQ(0, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 90), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 90),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 
   // Setting permitted state to "both" should not change content offset.
   webView->updateBrowserControlsState(WebBrowserControlsBoth,
@@ -585,11 +647,15 @@
   // Both states are permitted so controls can either show or hide
   verticalScroll(50.f);
   EXPECT_FLOAT_EQ(50, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 90), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 90),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 
   verticalScroll(-50.f);
   EXPECT_FLOAT_EQ(0, webView->browserControls().contentOffset());
-  EXPECT_SIZE_EQ(ScrollOffset(0, 90), frame()->view()->getScrollOffset());
+  EXPECT_SIZE_EQ(
+      ScrollOffset(0, 90),
+      frame()->view()->layoutViewportScrollableArea()->getScrollOffset());
 
   // Setting permitted state to "both" should not change an in-flight offset.
   verticalScroll(20.f);
diff --git a/third_party/WebKit/Source/web/tests/IntersectionObserverTest.cpp b/third_party/WebKit/Source/web/tests/IntersectionObserverTest.cpp
index 3172f7a..825eddd 100644
--- a/third_party/WebKit/Source/web/tests/IntersectionObserverTest.cpp
+++ b/third_party/WebKit/Source/web/tests/IntersectionObserverTest.cpp
@@ -6,6 +6,7 @@
 
 #include "core/dom/IntersectionObserverCallback.h"
 #include "core/dom/IntersectionObserverInit.h"
+#include "core/frame/FrameView.h"
 #include "platform/testing/UnitTestHelpers.h"
 #include "web/WebViewImpl.h"
 #include "web/tests/sim/SimCompositor.h"
@@ -67,4 +68,63 @@
   EXPECT_TRUE(compositor().needsBeginFrame());
 }
 
+TEST_F(IntersectionObserverTest, ResumePostsTask) {
+  webView().resize(WebSize(800, 600));
+  SimRequest mainResource("https://example.com/", "text/html");
+  loadURL("https://example.com/");
+  mainResource.complete(
+      "<div id='leading-space' style='height: 700px;'></div>"
+      "<div id='target'></div>"
+      "<div id='trailing-space' style='height: 700px;'></div>");
+
+  IntersectionObserverInit observerInit;
+  DummyExceptionStateForTesting exceptionState;
+  TestIntersectionObserverCallback* observerCallback =
+      new TestIntersectionObserverCallback(document());
+  IntersectionObserver* observer = IntersectionObserver::create(
+      observerInit, *observerCallback, exceptionState);
+  ASSERT_FALSE(exceptionState.hadException());
+
+  Element* target = document().getElementById("target");
+  ASSERT_TRUE(target);
+  observer->observe(target, exceptionState);
+
+  compositor().beginFrame();
+  testing::runPendingTasks();
+  EXPECT_EQ(observerCallback->callCount(), 0);
+
+  // When document is not suspended, beginFrame() will generate notifications
+  // and post a task to deliver them.
+  document().view()->layoutViewportScrollableArea()->setScrollOffset(
+      ScrollOffset(0, 300), ProgrammaticScroll);
+  compositor().beginFrame();
+  EXPECT_EQ(observerCallback->callCount(), 0);
+  testing::runPendingTasks();
+  EXPECT_EQ(observerCallback->callCount(), 1);
+
+  // When a document is suspended, beginFrame() will generate a notification,
+  // but it will not be delivered.  The notification will, however, be
+  // available via takeRecords();
+  document().suspendScheduledTasks();
+  document().view()->layoutViewportScrollableArea()->setScrollOffset(
+      ScrollOffset(0, 0), ProgrammaticScroll);
+  compositor().beginFrame();
+  EXPECT_EQ(observerCallback->callCount(), 1);
+  testing::runPendingTasks();
+  EXPECT_EQ(observerCallback->callCount(), 1);
+  EXPECT_FALSE(observer->takeRecords(exceptionState).isEmpty());
+
+  // Generate a notification while document is suspended; then resume document.
+  // Notification should happen in a post task.
+  document().view()->layoutViewportScrollableArea()->setScrollOffset(
+      ScrollOffset(0, 300), ProgrammaticScroll);
+  compositor().beginFrame();
+  testing::runPendingTasks();
+  EXPECT_EQ(observerCallback->callCount(), 1);
+  document().resumeScheduledTasks();
+  EXPECT_EQ(observerCallback->callCount(), 1);
+  testing::runPendingTasks();
+  EXPECT_EQ(observerCallback->callCount(), 2);
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/web/tests/ScreenWakeLockTest.cpp b/third_party/WebKit/Source/web/tests/ScreenWakeLockTest.cpp
index 6c46408..99724999 100644
--- a/third_party/WebKit/Source/web/tests/ScreenWakeLockTest.cpp
+++ b/third_party/WebKit/Source/web/tests/ScreenWakeLockTest.cpp
@@ -109,8 +109,8 @@
 
   blink::Screen* screen() {
     DCHECK(frame());
-    DCHECK(frame()->localDOMWindow());
-    return frame()->localDOMWindow()->screen();
+    DCHECK(frame()->domWindow());
+    return frame()->domWindow()->screen();
   }
 
   bool screenKeepAwake() {
diff --git a/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp b/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp
index 354c64b..1a891323 100644
--- a/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp
+++ b/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp
@@ -1749,8 +1749,7 @@
   // body element as the viewport and don't apply scrolling to the HTML element.
   RuntimeEnabledFeatures::setScrollTopLeftInteropEnabled(false);
 
-  LocalDOMWindow* window =
-      webViewImpl()->mainFrameImpl()->frame()->localDOMWindow();
+  LocalDOMWindow* window = webViewImpl()->mainFrameImpl()->frame()->domWindow();
   window->scrollTo(100, 150);
   EXPECT_EQ(100, window->scrollX());
   EXPECT_EQ(150, window->scrollY());
diff --git a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
index 018aea3..de74b3f 100644
--- a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
@@ -1001,7 +1001,7 @@
   NonThrowableExceptionState exceptionState;
   MessagePortArray messagePorts;
   frame->domWindow()->postMessage(SerializedScriptValue::serialize("message"),
-                                  messagePorts, "*", frame->localDOMWindow(),
+                                  messagePorts, "*", frame->domWindow(),
                                   exceptionState);
   webViewHelper.reset();
   EXPECT_FALSE(exceptionState.hadException());
@@ -9144,7 +9144,7 @@
   ASSERT_TRUE(mainFrame()->isWebLocalFrame());
   ASSERT_TRUE(mainFrame()->firstChild()->isWebRemoteFrame());
   LocalDOMWindow* mainWindow =
-      toWebLocalFrameImpl(mainFrame())->frame()->localDOMWindow();
+      toWebLocalFrameImpl(mainFrame())->frame()->domWindow();
 
   KURL destination = toKURL("data:text/html:destination");
   mainWindow->open(destination.getString(), "frame1", "", mainWindow,
diff --git a/third_party/WebKit/Tools/Scripts/run-bindings-tests b/third_party/WebKit/Tools/Scripts/run-bindings-tests
index 6f4ab44..ea6a6ad 100755
--- a/third_party/WebKit/Tools/Scripts/run-bindings-tests
+++ b/third_party/WebKit/Tools/Scripts/run-bindings-tests
@@ -26,7 +26,10 @@
 import sys
 
 from webkitpy.bindings.bindings_tests import run_bindings_tests
+from webkitpy.common import webkit_finder
+webkit_finder.add_typ_dir_to_sys_path()
 
+import typ
 
 def main(argv):
     """Runs Blink bindings IDL compiler on test IDL files and compares the
@@ -36,15 +39,38 @@
     (this is automatically done as a presubmit script),
     and submit changes to the test results in the same patch.
     This makes it easier to track and review changes in generated code.
-
-    Options:
-       --reset-results: Overwrites reference files with the generated results.
-       --verbose: Show output on success and logging messages (not just failure)
     """
-    reset_results = '--reset-results' in argv
-    verbose = '--verbose' in argv
+    argument_parser = typ.ArgumentParser()
+    argument_parser.add_argument('--reset-results',
+        default=False,
+        action='store_true',
+        help='Overwrites reference files with the generated results.')
+    argument_parser.add_argument('--skip-unit-tests',
+        default=False,
+        action='store_true',
+        help='Skip running unit tests (only run reference tests).')
+    argument_parser.add_argument('--skip-reference-tests',
+        default=False,
+        action='store_true',
+        help='Skip running reference tests (only run unit tests).')
 
-    return run_bindings_tests(reset_results, verbose)
+    # First, run bindings unit tests.
+    runner = typ.Runner()
+    runner.parse_args(argument_parser, argv[1:])
+    args = runner.args
+    if argument_parser.exit_status is not None:
+        return argument_parser.exit_status
+    runner.args.top_level_dir = webkit_finder.get_bindings_scripts_dir()
+    if not args.skip_unit_tests:
+        return_code, _, _ = runner.run()
+        if return_code != 0:
+            return return_code
+
+    if args.skip_reference_tests:
+        return 0
+
+    # Now run the bindings end-to-end tests.
+    return run_bindings_tests(args.reset_results, args.verbose)
 
 
 if __name__ == '__main__':
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/layout_test_runner.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/layout_test_runner.py
index b46e9c2..acabb22 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/layout_test_runner.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/layout_test_runner.py
@@ -286,7 +286,7 @@
         self._update_test_input(test_input)
         start = time.time()
 
-        _log.debug("%s %s started", self._name, test_input.test_name)
+        # TODO(qyearsley): Re-add logging if it doesn't create too much load (crbug.com/673207).
         self._caller.post('started_test', test_input)
         result = single_test_runner.run_single_test(
             self._port, self._options, self._results_directory, self._name,
diff --git a/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerProvider.h b/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerProvider.h
index 513cb9d..33acad2b 100644
--- a/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerProvider.h
+++ b/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerProvider.h
@@ -59,10 +59,11 @@
       WebCallbacks<std::unique_ptr<WebServiceWorkerRegistration::Handle>,
                    const WebServiceWorkerError&>;
 
-  // Each element's ownership is transferred.
-  using WebServiceWorkerGetRegistrationsCallbacks = WebCallbacks<
-      std::unique_ptr<WebVector<WebServiceWorkerRegistration::Handle*>>,
-      const WebServiceWorkerError&>;
+  using WebServiceWorkerRegistrationHandles =
+      WebVector<std::unique_ptr<WebServiceWorkerRegistration::Handle>>;
+  using WebServiceWorkerGetRegistrationsCallbacks =
+      WebCallbacks<std::unique_ptr<WebServiceWorkerRegistrationHandles>,
+                   const WebServiceWorkerError&>;
   using WebServiceWorkerGetRegistrationForReadyCallbacks =
       WebCallbacks<std::unique_ptr<WebServiceWorkerRegistration::Handle>, void>;
 
diff --git a/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerResponseError.h b/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerResponseError.h
index 63eb837..efc6fff 100644
--- a/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerResponseError.h
+++ b/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerResponseError.h
@@ -24,8 +24,9 @@
   WebServiceWorkerResponseErrorNoForeignFetchResponse,
   WebServiceWorkerResponseErrorForeignFetchHeadersWithoutOrigin,
   WebServiceWorkerResponseErrorForeignFetchMismatchedOrigin,
+  WebServiceWorkerResponseErrorRedirectedResponseForNotFollowRequest,
   WebServiceWorkerResponseErrorLast =
-      WebServiceWorkerResponseErrorForeignFetchMismatchedOrigin,
+      WebServiceWorkerResponseErrorRedirectedResponseForNotFollowRequest,
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/public/web/WebDocument.h b/third_party/WebKit/public/web/WebDocument.h
index 4c72430..486e11ce 100644
--- a/third_party/WebKit/public/web/WebDocument.h
+++ b/third_party/WebKit/public/web/WebDocument.h
@@ -72,7 +72,7 @@
   BLINK_EXPORT WebURL url() const;
   // Note: Security checks should use the getSecurityOrigin(), not url().
   BLINK_EXPORT WebSecurityOrigin getSecurityOrigin() const;
-  BLINK_EXPORT bool isSecureContext(WebString& errorMessage) const;
+  BLINK_EXPORT bool isSecureContext() const;
 
   BLINK_EXPORT WebString encoding() const;
   BLINK_EXPORT WebString contentLanguage() const;
diff --git a/third_party/WebKit/public/web/WebHistoryItem.h b/third_party/WebKit/public/web/WebHistoryItem.h
index 070e7ed9..2b91f34 100644
--- a/third_party/WebKit/public/web/WebHistoryItem.h
+++ b/third_party/WebKit/public/web/WebHistoryItem.h
@@ -93,7 +93,7 @@
   BLINK_EXPORT float pageScaleFactor() const;
   BLINK_EXPORT void setPageScaleFactor(float);
 
-  BLINK_EXPORT WebVector<WebString> documentState() const;
+  BLINK_EXPORT WebVector<WebString> getDocumentState() const;
   BLINK_EXPORT void setDocumentState(const WebVector<WebString>&);
 
   BLINK_EXPORT long long itemSequenceNumber() const;
diff --git a/third_party/WebKit/public/web/WebUserGestureIndicator.h b/third_party/WebKit/public/web/WebUserGestureIndicator.h
index 44b1cacb..1c63f2c 100644
--- a/third_party/WebKit/public/web/WebUserGestureIndicator.h
+++ b/third_party/WebKit/public/web/WebUserGestureIndicator.h
@@ -40,8 +40,13 @@
 
 class WebUserGestureIndicator {
  public:
-  // Returns true if a user gesture is currently being processed.
+  // Returns true if a user gesture is currently being processed. Must be called
+  // on the main thread.
   BLINK_EXPORT static bool isProcessingUserGesture();
+  // Can be called from any thread. Note that this is slower than the non
+  // thread-safe version due to thread id lookups. Prefer the non thread-safe
+  // version for code that will only execute on the main thread.
+  BLINK_EXPORT static bool isProcessingUserGestureThreadSafe();
 
   // Returns true if a consumable gesture exists and has been successfully
   // consumed.
diff --git a/third_party/inspector_protocol/CodeGenerator.py b/third_party/inspector_protocol/CodeGenerator.py
index 8b28d136..1bc9535 100644
--- a/third_party/inspector_protocol/CodeGenerator.py
+++ b/third_party/inspector_protocol/CodeGenerator.py
@@ -440,6 +440,12 @@
         return self.check_options(self.config.protocol.options, domain, event, "include_events", "exclude_events", True)
 
 
+    def generate_type(self, domain, typename):
+        if not self.config.protocol.options:
+            return domain in self.generate_domains
+        return self.check_options(self.config.protocol.options, domain, typename, "include_types", "exclude_types", True)
+
+
     def is_async_command(self, domain, command):
         if not self.config.protocol.options:
             return False
@@ -473,6 +479,10 @@
         return True
 
 
+    def is_imported_dependency(self, domain):
+        return domain in self.generate_domains or domain in self.imported_domains
+
+
 def main():
     jinja_dir, config_file, config = read_config()
 
diff --git a/third_party/inspector_protocol/README.chromium b/third_party/inspector_protocol/README.chromium
index df3ade87..64b757f32 100644
--- a/third_party/inspector_protocol/README.chromium
+++ b/third_party/inspector_protocol/README.chromium
@@ -2,7 +2,7 @@
 Short Name: inspector_protocol
 URL: https://chromium.googlesource.com/deps/inspector_protocol/
 Version: 0
-Revision: c65b17da8a32bc6ab25b4ebbef1008f23c69e7d1
+Revision: 344219890fe40130571f5a5b17f261a654e3b8cc
 License: BSD
 License File: LICENSE
 Security Critical: no
diff --git a/third_party/inspector_protocol/lib/DispatcherBase_cpp.template b/third_party/inspector_protocol/lib/DispatcherBase_cpp.template
index 0d4a305..e9730eb 100644
--- a/third_party/inspector_protocol/lib/DispatcherBase_cpp.template
+++ b/third_party/inspector_protocol/lib/DispatcherBase_cpp.template
@@ -248,7 +248,13 @@
     m_dispatchers[name] = std::move(dispatcher);
 }
 
-DispatchResponse::Status UberDispatcher::dispatch(std::unique_ptr<Value> parsedMessage)
+void UberDispatcher::setupRedirects(const HashMap<String, String>& redirects)
+{
+    for (const auto& pair : redirects)
+        m_redirects[pair.first] = pair.second;
+}
+
+DispatchResponse::Status UberDispatcher::dispatch(std::unique_ptr<Value> parsedMessage, int* outCallId, String* outMethod)
 {
     if (!parsedMessage) {
         reportProtocolErrorTo(m_frontendChannel, DispatchResponse::kParseError, "Message must be a valid JSON");
@@ -263,6 +269,8 @@
     int callId = 0;
     protocol::Value* callIdValue = messageObject->get("id");
     bool success = callIdValue && callIdValue->asInteger(&callId);
+    if (outCallId)
+        *outCallId = callId;
     if (!success) {
         reportProtocolErrorTo(m_frontendChannel, DispatchResponse::kInvalidRequest, "Message must have integer 'id' porperty");
         return DispatchResponse::kError;
@@ -271,11 +279,17 @@
     protocol::Value* methodValue = messageObject->get("method");
     String method;
     success = methodValue && methodValue->asString(&method);
+    if (outMethod)
+        *outMethod = method;
     if (!success) {
         reportProtocolErrorTo(m_frontendChannel, callId, DispatchResponse::kInvalidRequest, "Message must have string 'method' porperty", nullptr);
         return DispatchResponse::kError;
     }
 
+    HashMap<String, String>::iterator redirectIt = m_redirects.find(method);
+    if (redirectIt != m_redirects.end())
+        method = redirectIt->second;
+
     size_t dotIndex = method.find(".");
     if (dotIndex == StringUtil::kNotFound) {
         if (m_fallThroughForNotFound)
diff --git a/third_party/inspector_protocol/lib/DispatcherBase_h.template b/third_party/inspector_protocol/lib/DispatcherBase_h.template
index 3a6069b..5404281 100644
--- a/third_party/inspector_protocol/lib/DispatcherBase_h.template
+++ b/third_party/inspector_protocol/lib/DispatcherBase_h.template
@@ -113,7 +113,8 @@
 public:
     explicit UberDispatcher(FrontendChannel*);
     void registerBackend(const String& name, std::unique_ptr<protocol::DispatcherBase>);
-    DispatchResponse::Status dispatch(std::unique_ptr<Value> message);
+    void setupRedirects(const HashMap<String, String>&);
+    DispatchResponse::Status dispatch(std::unique_ptr<Value> message, int* callId = nullptr, String* method = nullptr);
     FrontendChannel* channel() { return m_frontendChannel; }
     bool fallThroughForNotFound() { return m_fallThroughForNotFound; }
     void setFallThroughForNotFound(bool);
@@ -122,6 +123,7 @@
 private:
     FrontendChannel* m_frontendChannel;
     bool m_fallThroughForNotFound;
+    HashMap<String, String> m_redirects;
     protocol::HashMap<String, std::unique_ptr<protocol::DispatcherBase>> m_dispatchers;
 };
 
diff --git a/third_party/inspector_protocol/templates/TypeBuilder_cpp.template b/third_party/inspector_protocol/templates/TypeBuilder_cpp.template
index 14b55b9..026c1cdb 100644
--- a/third_party/inspector_protocol/templates/TypeBuilder_cpp.template
+++ b/third_party/inspector_protocol/templates/TypeBuilder_cpp.template
@@ -19,6 +19,7 @@
 const char Metainfo::commandPrefix[] = "{{domain.domain}}.";
 const char Metainfo::version[] = "{{domain.version}}";
   {% for type in domain.types %}
+    {% if not protocol.generate_type(domain.domain, type.id) %}{% continue %} {% endif %}
     {% if "enum" in type %}
 
 namespace {{type.id}}Enum {
@@ -200,18 +201,23 @@
         , m_backend(backend)
         , m_fallThroughForNotFound(fallThroughForNotFound) {
   {% for command in domain.commands %}
-    {% if "redirect" in command %}{% continue %}{% endif %}
+    {% if "redirect" in command %}
+      m_redirects["{{domain.domain}}.{{command.name}}"] = "{{command.redirect}}.{{command.name}}";
+      {% continue %}
+    {% endif %}
     {% if not protocol.generate_command(domain.domain, command.name) %}{% continue %}{% endif %}
         m_dispatchMap["{{domain.domain}}.{{command.name}}"] = &DispatcherImpl::{{command.name}};
   {% endfor %}
     }
     ~DispatcherImpl() override { }
     DispatchResponse::Status dispatch(int callId, const String& method, std::unique_ptr<protocol::DictionaryValue> messageObject) override;
+    HashMap<String, String>& redirects() { return m_redirects; }
 
 protected:
     using CallHandler = DispatchResponse::Status (DispatcherImpl::*)(int callId, std::unique_ptr<DictionaryValue> messageObject, ErrorSupport* errors);
     using DispatchMap = protocol::HashMap<String, CallHandler>;
     DispatchMap m_dispatchMap;
+    HashMap<String, String> m_redirects;
 
   {% for command in domain.commands %}
     {% if "redirect" in command %}{% continue %}{% endif %}
@@ -337,9 +343,9 @@
           &out_{{parameter.name}}
         {%- endfor %}
       {% endif %});
-      {% if "returns" in command %}
     if (response.status() == DispatchResponse::kFallThrough)
         return response.status();
+      {% if "returns" in command %}
     std::unique_ptr<protocol::DictionaryValue> result = DictionaryValue::create();
     if (response.status() == DispatchResponse::kSuccess) {
         {% for parameter in command.returns %}
@@ -378,9 +384,11 @@
   {% endfor %}
 
 // static
-void Dispatcher::wire(UberDispatcher* dispatcher, Backend* backend)
+void Dispatcher::wire(UberDispatcher* uber, Backend* backend)
 {
-    dispatcher->registerBackend("{{domain.domain}}", std::unique_ptr<protocol::DispatcherBase>(new DispatcherImpl(dispatcher->channel(), backend, dispatcher->fallThroughForNotFound())));
+    std::unique_ptr<DispatcherImpl> dispatcher(new DispatcherImpl(uber->channel(), backend, uber->fallThroughForNotFound()));
+    uber->setupRedirects(dispatcher->redirects());
+    uber->registerBackend("{{domain.domain}}", std::move(dispatcher));
 }
 
 } // {{domain.domain}}
diff --git a/third_party/inspector_protocol/templates/TypeBuilder_h.template b/third_party/inspector_protocol/templates/TypeBuilder_h.template
index 81dd7f2..681c473 100644
--- a/third_party/inspector_protocol/templates/TypeBuilder_h.template
+++ b/third_party/inspector_protocol/templates/TypeBuilder_h.template
@@ -14,7 +14,9 @@
 // For each imported domain we generate a ValueConversions struct instead of a full domain definition
 // and include Domain::API version from there.
 {% for name in domain.dependencies %}
+  {% if protocol.is_imported_dependency(name) %}
 #include {{format_include(config.protocol.package, name)}}
+  {% endif %}
 {% endfor %}
 {% if protocol.is_exported_domain(domain.domain) %}
 #include {{format_include(config.exported.package, domain.domain)}}
@@ -27,6 +29,7 @@
 
 // ------------- Forward and enum declarations.
   {% for type in domain.types %}
+    {% if not protocol.generate_type(domain.domain, type.id) %}{% continue %}{% endif %}
     {% if type.type == "object" %}
       {% if "properties" in type %}
 // {{type.description}}
@@ -41,6 +44,7 @@
     {% endif %}
   {% endfor %}
   {% for type in domain.types %}
+    {% if not protocol.generate_type(domain.domain, type.id) %}{% continue %}{% endif %}
     {% if "enum" in type %}
 
 namespace {{type.id}}Enum {
@@ -67,6 +71,7 @@
 
 // ------------- Type and builder declarations.
   {% for type in domain.types %}
+    {% if not protocol.generate_type(domain.domain, type.id) %}{% continue %}{% endif %}
     {% if not (type.type == "object") or not ("properties" in type) %}{% continue %}{% endif %}
 
 // {{type.description}}
diff --git a/third_party/wayland-protocols/include/protocol/keyboard-configuration-unstable-v1-client-protocol.h b/third_party/wayland-protocols/include/protocol/keyboard-configuration-unstable-v1-client-protocol.h
index e931bfbf..5939b44 100644
--- a/third_party/wayland-protocols/include/protocol/keyboard-configuration-unstable-v1-client-protocol.h
+++ b/third_party/wayland-protocols/include/protocol/keyboard-configuration-unstable-v1-client-protocol.h
@@ -96,6 +96,16 @@
  */
 extern const struct wl_interface zcr_keyboard_device_configuration_v1_interface;
 
+#ifndef ZCR_KEYBOARD_CONFIGURATION_V1_ERROR_ENUM
+#define ZCR_KEYBOARD_CONFIGURATION_V1_ERROR_ENUM
+enum zcr_keyboard_configuration_v1_error {
+	/**
+	 * the keyboard already has a device configuration object associated
+	 */
+	ZCR_KEYBOARD_CONFIGURATION_V1_ERROR_DEVICE_CONFIGURATION_EXISTS = 0,
+};
+#endif /* ZCR_KEYBOARD_CONFIGURATION_V1_ERROR_ENUM */
+
 #define ZCR_KEYBOARD_CONFIGURATION_V1_GET_KEYBOARD_DEVICE_CONFIGURATION	0
 
 /**
@@ -135,6 +145,9 @@
  *
  * Create keyboard_device_configuration object.
  * See zcr_keyboard_device_configuration interface for details.
+ * If the given wl_keyboard object already has a device configuration
+ * object associated, the keyboard_device_configuration_exists protocol
+ * error is raised.
  */
 static inline struct zcr_keyboard_device_configuration_v1 *
 zcr_keyboard_configuration_v1_get_keyboard_device_configuration(struct zcr_keyboard_configuration_v1 *zcr_keyboard_configuration_v1, struct wl_keyboard *keyboard)
diff --git a/third_party/wayland-protocols/include/protocol/keyboard-configuration-unstable-v1-server-protocol.h b/third_party/wayland-protocols/include/protocol/keyboard-configuration-unstable-v1-server-protocol.h
index 3eda503..5dbb81e5 100644
--- a/third_party/wayland-protocols/include/protocol/keyboard-configuration-unstable-v1-server-protocol.h
+++ b/third_party/wayland-protocols/include/protocol/keyboard-configuration-unstable-v1-server-protocol.h
@@ -99,6 +99,16 @@
  */
 extern const struct wl_interface zcr_keyboard_device_configuration_v1_interface;
 
+#ifndef ZCR_KEYBOARD_CONFIGURATION_V1_ERROR_ENUM
+#define ZCR_KEYBOARD_CONFIGURATION_V1_ERROR_ENUM
+enum zcr_keyboard_configuration_v1_error {
+	/**
+	 * the keyboard already has a device configuration object associated
+	 */
+	ZCR_KEYBOARD_CONFIGURATION_V1_ERROR_DEVICE_CONFIGURATION_EXISTS = 0,
+};
+#endif /* ZCR_KEYBOARD_CONFIGURATION_V1_ERROR_ENUM */
+
 /**
  * @ingroup iface_zcr_keyboard_configuration_v1
  * @struct zcr_keyboard_configuration_v1_interface
@@ -108,7 +118,10 @@
 	 * get keyboard_device_configuration interface for a keyboard
 	 *
 	 * Create keyboard_device_configuration object. See
-	 * zcr_keyboard_device_configuration interface for details.
+	 * zcr_keyboard_device_configuration interface for details. If the
+	 * given wl_keyboard object already has a device configuration
+	 * object associated, the keyboard_device_configuration_exists
+	 * protocol error is raised.
 	 */
 	void (*get_keyboard_device_configuration)(struct wl_client *client,
 						  struct wl_resource *resource,
diff --git a/third_party/wayland-protocols/protocol/keyboard-configuration-protocol.c b/third_party/wayland-protocols/protocol/keyboard-configuration-protocol.c
index b17117a4..0bddf1c 100644
--- a/third_party/wayland-protocols/protocol/keyboard-configuration-protocol.c
+++ b/third_party/wayland-protocols/protocol/keyboard-configuration-protocol.c
@@ -41,7 +41,7 @@
 };
 
 WL_EXPORT const struct wl_interface zcr_keyboard_configuration_v1_interface = {
-	"zcr_keyboard_configuration_v1", 1,
+	"zcr_keyboard_configuration_v1", 2,
 	1, zcr_keyboard_configuration_v1_requests,
 	0, NULL,
 };
diff --git a/third_party/wayland-protocols/unstable/keyboard/keyboard-configuration-unstable-v1.xml b/third_party/wayland-protocols/unstable/keyboard/keyboard-configuration-unstable-v1.xml
index 6acd844f..8d3cf72 100644
--- a/third_party/wayland-protocols/unstable/keyboard/keyboard-configuration-unstable-v1.xml
+++ b/third_party/wayland-protocols/unstable/keyboard/keyboard-configuration-unstable-v1.xml
@@ -24,7 +24,7 @@
     DEALINGS IN THE SOFTWARE.
   </copyright>
 
-  <interface name="zcr_keyboard_configuration_v1" version="1">
+  <interface name="zcr_keyboard_configuration_v1" version="2">
     <description summary="extends wl_keyboard with events for device configuration change">
       Allows a wl_keyboard to notify device configuration change events of
       the keyboard to the client.
@@ -39,10 +39,18 @@
       interface version number is reset.
     </description>
 
+    <enum name="error">
+      <entry name="device_configuration_exists" value="0"
+             summary="the keyboard already has a device configuration object associated"/>
+    </enum>
+
     <request name="get_keyboard_device_configuration">
       <description summary="get keyboard_device_configuration interface for a keyboard">
         Create keyboard_device_configuration object.
         See zcr_keyboard_device_configuration interface for details.
+        If the given wl_keyboard object already has a device configuration
+        object associated, the keyboard_device_configuration_exists protocol
+        error is raised.
       </description>
       <arg name="id" type="new_id" interface="zcr_keyboard_device_configuration_v1"/>
       <arg name="keyboard" type="object" interface="wl_keyboard"/>
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 90f5d6a2..0a3d9416 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -186,7 +186,7 @@
       'Site Isolation Android': 'android_release_bot_minimal_symbols_arm64',
       'Site Isolation Linux': 'release_trybot',
       'Site Isolation Win': 'release_trybot_x86',
-      'ThinLTO Linux ToT': 'thin_lto_clang_tot_release_static',
+      'ThinLTO Linux ToT': 'thin_lto_clang_tot_release_static_use_lld',
       'UBSanVptr Linux': 'ubsan_vptr_release_bot',
       'WebKit Linux - TraceWrappables': 'debug_bot',
       'WebKit Linux - WPTServe': 'release_bot',
@@ -1405,8 +1405,8 @@
       'syzyasan', 'no_pch', 'release', 'x86',
     ],
 
-    'thin_lto_clang_tot_release_static': [
-      'thin_lto', 'clang_tot', 'release', 'static',
+    'thin_lto_clang_tot_release_static_use_lld': [
+      'thin_lto', 'clang_tot', 'release', 'static', 'use_lld',
     ],
 
     'tsan_disable_nacl_debug_bot': [
@@ -1422,11 +1422,11 @@
     ],
 
     'ubsan_release_bot': [
-      'ubsan', 'ubsan_no_recover_hack', 'release_bot',
+      'ubsan', 'release_bot',
     ],
 
     'ubsan_vptr_edge_release_bot': [
-      'ubsan_vptr', 'ubsan_no_recover_hack', 'edge', 'release_bot',
+      'ubsan_vptr', 'edge', 'release_bot',
     ],
 
     'ubsan_vptr_release_bot': [
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 31dc08ef..1bd84dc3 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -8694,6 +8694,19 @@
   </summary>
 </histogram>
 
+<histogram
+    name="DataReductionProxy.DaysSinceSavingsCleared.NegativeSystemClock"
+    units="days">
+  <owner>tbansal@chromium.org</owner>
+  <owner>bengr@chromium.org</owner>
+  <summary>
+    Records the number of days since the data reduction savings were cleared
+    because the system clock moved back by more than 1 day. Recorded at Chrome
+    startup if data reduction proxy is enabled, and if the data reduction proxy
+    savings were cleared in some previous Chrome session.
+  </summary>
+</histogram>
+
 <histogram name="DataReductionProxy.EnabledState"
     enum="DataReductionProxyEnabledState">
   <owner>bengr@chromium.org</owner>
@@ -9043,6 +9056,17 @@
   </summary>
 </histogram>
 
+<histogram name="DataReductionProxy.SavingsCleared.NegativeSystemClock"
+    enum="BooleanCleared">
+  <owner>tbansal@chromium.org</owner>
+  <owner>bengr@chromium.org</owner>
+  <summary>
+    Records if the data reduction savings were cleared because the system clock
+    moved back by more than 1 day. Recorded at Chrome startup if the data
+    reduction proxy is enabled.
+  </summary>
+</histogram>
+
 <histogram name="DataReductionProxy.SecureProxyCheck.Latency" units="ms">
   <owner>bengr@chromium.org</owner>
   <summary>
@@ -9160,6 +9184,19 @@
   </summary>
 </histogram>
 
+<histogram name="DataReductionProxy.WarmupURL.FetchInitiated" units="count">
+  <owner>tbansal@chromium.org</owner>
+  <summary>
+    Number of times the data reduction proxy warm up URL was fetched.
+  </summary>
+</histogram>
+
+<histogram name="DataReductionProxy.WarmupURL.FetchSuccessful"
+    enum="BooleanSuccess">
+  <owner>tbansal@chromium.org</owner>
+  <summary>Whether the warm up URL was fetched succesfully.</summary>
+</histogram>
+
 <histogram name="DataUsage.MatchingRulesCount.Invalid" units="count">
   <owner>bengr@chromium.org</owner>
   <owner>rajendrant@chromium.org</owner>
@@ -48349,6 +48386,15 @@
   </summary>
 </histogram>
 
+<histogram name="Precache.CacheSize.AllEntries" units="KB">
+  <owner>jamartin@chromium.org</owner>
+  <owner>bengr@chromium.org</owner>
+  <summary>
+    The size in kilobytes occupied by all the entries existing in the cache at
+    the time of the last precache.
+  </summary>
+</histogram>
+
 <histogram name="Precache.CacheStatus.NonPrefetch" enum="HttpCachePattern">
   <owner>jamartin@chromium.org</owner>
   <owner>bengr@chromium.org</owner>
@@ -77180,6 +77226,11 @@
   <int value="1" label="Checked"/>
 </enum>
 
+<enum name="BooleanCleared" type="int">
+  <int value="0" label="Not cleared"/>
+  <int value="1" label="Cleared"/>
+</enum>
+
 <enum name="BooleanClicked" type="int">
   <int value="0" label="Not Clicked"/>
   <int value="1" label="Clicked"/>
@@ -87521,6 +87572,8 @@
   <int value="1694" label="V8BarcodeDetector_Detect_Method"/>
   <int value="1695" label="V8FaceDetector_Detect_Method"/>
   <int value="1696" label="FullscreenAllowedByOrientationChange"/>
+  <int value="1697"
+      label="ServiceWorkerRespondToNavigationRequestWithRedirectedResponse"/>
 </enum>
 
 <enum name="FetchRequestMode" type="int">
@@ -101935,6 +101988,10 @@
   <int value="8" label="ErrorResponseTypeOpaqueForClientRequest"/>
   <int value="9" label="ErrorResponseTypeOpaqueRedirect"/>
   <int value="10" label="ErrorBodyLocked"/>
+  <int value="11" label="NoForeignFetchResponse"/>
+  <int value="12" label="ForeignFetchHeadersWithoutOrigin"/>
+  <int value="13" label="ForeignFetchMismatchedOrigin"/>
+  <int value="14" label="RedirectedResponseForNotFollowRequest"/>
 </enum>
 
 <enum name="ServiceWorkerSite" type="int">
diff --git a/tools/metrics/rappor/rappor.xml b/tools/metrics/rappor/rappor.xml
index 6f0adcf9..99f01e9 100644
--- a/tools/metrics/rappor/rappor.xml
+++ b/tools/metrics/rappor/rappor.xml
@@ -1063,6 +1063,30 @@
   </summary>
 </rappor-metric>
 
+<rappor-metric
+    name="Media.Autoplay.CrossOrigin.UserPausedAutoplayingVideo.ChildFrame"
+    type="ETLD_PLUS_ONE">
+  <owner>avayvod@chromium.org</owner>
+  <owner>mlamouri@chromium.org</owner>
+  <owner>zqzhang@chromium.org</owner>
+  <summary>
+    The eTLD+1 of a cross-origin iframe URL containing an autoplaying video but
+    the user actively paused it.
+  </summary>
+</rappor-metric>
+
+<rappor-metric
+    name="Media.Autoplay.CrossOrigin.UserPausedAutoplayingVideo.TopLevelFrame"
+    type="ETLD_PLUS_ONE">
+  <owner>avayvod@chromium.org</owner>
+  <owner>mlamouri@chromium.org</owner>
+  <owner>zqzhang@chromium.org</owner>
+  <summary>
+    The eTLD+1 of the top-level frame URL that has a cross-origin iframe
+    containing an autoplaying video but the user actively paused it.
+  </summary>
+</rappor-metric>
+
 <rappor-metric name="Media.OriginUrl.EME" type="ETLD_PLUS_ONE">
   <owner>xhwang@chromium.org</owner>
   <summary>
diff --git a/tools/perf/chrome_telemetry_build/BUILD.gn b/tools/perf/chrome_telemetry_build/BUILD.gn
index 8914f3c..a6e576b2 100644
--- a/tools/perf/chrome_telemetry_build/BUILD.gn
+++ b/tools/perf/chrome_telemetry_build/BUILD.gn
@@ -85,7 +85,57 @@
 
   data = [
     "//tools/perf/chrome_telemetry_build/",
-    "//third_party/catapult/",
+
+    # Breakdown the catapult directory so we can exclude
+    # third_party/catapult/tracing/test_data.  See crbug.com/670284
+    "//third_party/catapult/AUTHORS",
+    "//third_party/catapult/bin/",
+    "//third_party/catapult/catapult_build/",
+    "//third_party/catapult/codereview.settings",
+    "//third_party/catapult/common/",
+    "//third_party/catapult/CONTRIBUTING.md",
+    "//third_party/catapult/dashboard/",
+    "//third_party/catapult/dependency_manager/",
+    "//third_party/catapult/devil/",
+    "//third_party/catapult/docs/",
+    "//third_party/catapult/experimental/",
+    "//third_party/catapult/firefighter/",
+    "//third_party/catapult/hooks/",
+    "//third_party/catapult/infra/",
+    "//third_party/catapult/LICENSE",
+    "//third_party/catapult/navbar.md",
+    "//third_party/catapult/netlog_viewer/",
+    "//third_party/catapult/OWNERS",
+    "//third_party/catapult/PRESUBMIT.py",
+    "//third_party/catapult/pylintrc",
+    "//third_party/catapult/README.md",
+    "//third_party/catapult/systrace/",
+    "//third_party/catapult/telemetry/",
+    "//third_party/catapult/third_party/",
+    "//third_party/catapult/trace_processor/",
+
+    # We don't want to include catapult/tracing/test_data
+    "//third_party/catapult/tracing/app.yaml",
+    "//third_party/catapult/tracing/bin/",
+    "//third_party/catapult/tracing/bower.json",
+    "//third_party/catapult/tracing/BUILD.gn",
+    "//third_party/catapult/tracing/docs/",
+    "//third_party/catapult/tracing/images/",
+    "//third_party/catapult/tracing/LICENSE",
+    "//third_party/catapult/tracing/OWNERS",
+    "//third_party/catapult/tracing/package.json",
+    "//third_party/catapult/tracing/PRESUBMIT.py",
+    "//third_party/catapult/tracing/README.md",
+    "//third_party/catapult/tracing/skp_data/",
+    "//third_party/catapult/tracing/third_party/",
+    "//third_party/catapult/tracing/trace_viewer.gyp",
+    "//third_party/catapult/tracing/trace_viewer.gypi",
+    "//third_party/catapult/tracing/tracing/",
+    "//third_party/catapult/tracing/tracing_build/",
+    "//third_party/catapult/tracing/tracing_examples/",
+    "//third_party/catapult/tracing/tracing_project.py",
+    "//third_party/catapult/WATCHLISTS",
+
     "//components/crash/content/tools/generate_breakpad_symbols.py",
   ]
 
diff --git a/tools/perf/generate_perf_json.py b/tools/perf/generate_perf_json.py
index b0c29a4..14869ee 100755
--- a/tools/perf/generate_perf_json.py
+++ b/tools/perf/generate_perf_json.py
@@ -152,7 +152,13 @@
       {
        'gpu': '8086:22b1',
        'os': 'Windows-10-10586',
-       'device_ids': ['build47-b4', 'build48-b4'],
+       'device_ids': [
+           'build136-b1', 'build137-b1', 'build138-b1', 'build139-b1',
+           'build140-b1', 'build141-b1', 'build142-b1', 'build143-b1',
+           'build144-b1', 'build145-b1', 'build146-b1', 'build147-b1',
+           'build148-b1', 'build149-b1', 'build150-b1', 'build151-b1',
+           'build152-b1', 'build153-b1', 'build154-b1', 'build155-b1',
+           'build47-b4', 'build48-b4'],
        'perf_tests': [
          ('cc_perftests', 0),
          ('gpu_perftests', 0),
@@ -161,8 +167,7 @@
          ('performance_browser_tests', 1),
          ('tracing_perftests', 1)]
       }
-    ],
-    use_whitelist=True)
+    ])
   waterfall = add_tester(
     waterfall, 'Android Swarming N5X Tester',
     'fyi-android-swarming-n5x', 'android',
@@ -177,8 +182,7 @@
            'build245-m4--device7'
         ]
       }
-    ],
-    use_whitelist=True)
+    ])
   return waterfall
 
 
@@ -692,6 +696,7 @@
   benchmark_sharding_map['22'] = shard_benchmarks(22, all_benchmarks)
   benchmark_sharding_map['5'] = shard_benchmarks(5, all_benchmarks)
   benchmark_sharding_map['1'] = shard_benchmarks(1, all_benchmarks)
+  benchmark_sharding_map['7'] = shard_benchmarks(7, all_benchmarks)
 
   for name, config in waterfall['testers'].iteritems():
     use_whitelist = config['use_whitelist']
diff --git a/ui/android/java/res/layout/dropdown_item.xml b/ui/android/java/res/layout/dropdown_item.xml
index 29964fbf..5159c83 100644
--- a/ui/android/java/res/layout/dropdown_item.xml
+++ b/ui/android/java/res/layout/dropdown_item.xml
@@ -12,7 +12,6 @@
     android:orientation="horizontal" >
 
     <!-- These layout params are overwritten in DropdownAdapter.java -->
-
     <ImageView
         android:id="@+id/start_dropdown_icon"
         android:layout_width="wrap_content"
diff --git a/ui/android/java/src/org/chromium/ui/DropdownAdapter.java b/ui/android/java/src/org/chromium/ui/DropdownAdapter.java
index d8ad3f3..2a5a6e3 100644
--- a/ui/android/java/src/org/chromium/ui/DropdownAdapter.java
+++ b/ui/android/java/src/org/chromium/ui/DropdownAdapter.java
@@ -30,14 +30,34 @@
     private final Context mContext;
     private final Set<Integer> mSeparators;
     private final boolean mAreAllItemsEnabled;
+    private final Integer mBackgroundColor;
+    private final Integer mDividerColor;
+    private final Integer mDropdownItemHeight;
 
-    public DropdownAdapter(
-            Context context, List<? extends DropdownItem> items, Set<Integer> separators) {
+    /**
+     * Creates an {@code ArrayAdapter} with specified parameters.
+     * @param context Application context.
+     * @param items List of labels and icons to display.
+     * @param separators Set of positions that separate {@code items}.
+     * @param backgroundColor Popup background color, or {@code null} to use default background
+     * color. The default color is {@code Color.TRANSPARENT}.
+     * @param dividerColor If {@code null}, use the values in colors.xml for the divider
+     * between items. Otherwise, uses {@param dividerColor} for the divider between items. Always
+     * uses the values in colors.xml for the dark divider for the separators.
+     * @param dropdownItemHeight If {@code null}, uses the {@code dropdown_item_height} in
+     * dimens.xml. Otherwise, uses {@param dropdownItemHeight}.
+     */
+    public DropdownAdapter(Context context, List<? extends DropdownItem> items,
+            Set<Integer> separators, Integer backgroundColor, Integer dividerColor,
+            Integer dropdownItemHeight) {
         super(context, R.layout.dropdown_item);
+        mContext = context;
         addAll(items);
         mSeparators = separators;
-        mContext = context;
         mAreAllItemsEnabled = checkAreAllItemsEnabled();
+        mBackgroundColor = backgroundColor;
+        mDividerColor = dividerColor;
+        mDropdownItemHeight = dropdownItemHeight;
     }
 
     private boolean checkAreAllItemsEnabled() {
@@ -57,25 +77,35 @@
             LayoutInflater inflater =
                     (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
             layout = inflater.inflate(R.layout.dropdown_item, null);
-            layout.setBackground(new DropdownDividerDrawable());
+            layout.setBackground(new DropdownDividerDrawable(mBackgroundColor));
+        }
+        DropdownDividerDrawable divider = (DropdownDividerDrawable) layout.getBackground();
+        int height;
+        if (mDropdownItemHeight == null) {
+            height = mContext.getResources().getDimensionPixelSize(R.dimen.dropdown_item_height);
+        } else {
+            height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+                    mDropdownItemHeight, mContext.getResources().getDisplayMetrics());
         }
 
-        DropdownDividerDrawable divider = (DropdownDividerDrawable) layout.getBackground();
-        int height = mContext.getResources().getDimensionPixelSize(R.dimen.dropdown_item_height);
         if (position == 0) {
-            divider.setColor(Color.TRANSPARENT);
+            divider.setDividerColor(Color.TRANSPARENT);
         } else {
             int dividerHeight = mContext.getResources().getDimensionPixelSize(
                     R.dimen.dropdown_item_divider_height);
             height += dividerHeight;
             divider.setHeight(dividerHeight);
+            int dividerColor;
             if (mSeparators != null && mSeparators.contains(position)) {
-                divider.setColor(ApiCompatibilityUtils.getColor(mContext.getResources(),
-                        R.color.dropdown_dark_divider_color));
+                dividerColor = ApiCompatibilityUtils.getColor(mContext.getResources(),
+                        R.color.dropdown_dark_divider_color);
+            } else if (mDividerColor == null) {
+                dividerColor = ApiCompatibilityUtils.getColor(mContext.getResources(),
+                        R.color.dropdown_divider_color);
             } else {
-                divider.setColor(ApiCompatibilityUtils.getColor(mContext.getResources(),
-                        R.color.dropdown_divider_color));
+                dividerColor = mDividerColor;
             }
+            divider.setDividerColor(dividerColor);
         }
 
         DropdownItem item = getItem(position);
@@ -113,7 +143,7 @@
         }
 
         labelView.setEnabled(item.isEnabled());
-        if (item.isGroupHeader()) {
+        if (item.isGroupHeader() || item.isBoldLabel()) {
             labelView.setTypeface(null, Typeface.BOLD);
         } else {
             labelView.setTypeface(null, Typeface.NORMAL);
diff --git a/ui/android/java/src/org/chromium/ui/DropdownDividerDrawable.java b/ui/android/java/src/org/chromium/ui/DropdownDividerDrawable.java
index 014192a5..1b45064f 100644
--- a/ui/android/java/src/org/chromium/ui/DropdownDividerDrawable.java
+++ b/ui/android/java/src/org/chromium/ui/DropdownDividerDrawable.java
@@ -13,16 +13,24 @@
 
 class DropdownDividerDrawable extends Drawable {
 
-    private Paint mPaint;
-    private Rect mDividerRect;
+    private final Paint mPaint;
+    private final Rect mDividerRect;
+    private final Integer mBackgroundColor;
 
-    public DropdownDividerDrawable() {
+    /**
+     * Creates a drawable to draw a divider line that separates the list of {@link DropdownItem}
+     * and, optionally, paints the rectangular canvas.
+     * @param backgroundColor Popup background color. If {@code null}, does not paint the canvas.
+     */
+    public DropdownDividerDrawable(Integer backgroundColor) {
         mPaint = new Paint();
         mDividerRect = new Rect();
+        mBackgroundColor = backgroundColor;
     }
 
     @Override
     public void draw(Canvas canvas) {
+        if (mBackgroundColor != null) canvas.drawColor(mBackgroundColor);
         canvas.drawRect(mDividerRect, mPaint);
     }
 
@@ -35,7 +43,7 @@
         mDividerRect.set(0, 0, mDividerRect.right, height);
     }
 
-    public void setColor(int color) {
+    public void setDividerColor(int color) {
         mPaint.setColor(color);
     }
 
diff --git a/ui/android/java/src/org/chromium/ui/DropdownItem.java b/ui/android/java/src/org/chromium/ui/DropdownItem.java
index 7ad26d5..d28db1d 100644
--- a/ui/android/java/src/org/chromium/ui/DropdownItem.java
+++ b/ui/android/java/src/org/chromium/ui/DropdownItem.java
@@ -36,6 +36,10 @@
      */
     boolean isMultilineLabel();
     /**
+     * Returns whether the label should be displayed in bold.
+     */
+    boolean isBoldLabel();
+    /**
      * Returns resource ID of label's font color.
      */
     int getLabelFontColorResId();
diff --git a/ui/android/java/src/org/chromium/ui/DropdownItemBase.java b/ui/android/java/src/org/chromium/ui/DropdownItemBase.java
index 9554d33d..9a0c7658 100644
--- a/ui/android/java/src/org/chromium/ui/DropdownItemBase.java
+++ b/ui/android/java/src/org/chromium/ui/DropdownItemBase.java
@@ -40,6 +40,11 @@
     }
 
     @Override
+    public boolean isBoldLabel() {
+        return false;
+    }
+
+    @Override
     public int getLabelFontColorResId() {
         return R.drawable.dropdown_label_color;
     }
diff --git a/ui/app_list/DEPS b/ui/app_list/DEPS
index 73162da..18ae5370 100644
--- a/ui/app_list/DEPS
+++ b/ui/app_list/DEPS
@@ -1,6 +1,7 @@
 include_rules = [
   "+components/keyed_service/core",
   "+components/sync",
+  "+mojo/public/cpp",
   "+skia",
   "+third_party/google_toolbox_for_mac/src",
   "+third_party/skia",
diff --git a/ui/app_list/presenter/BUILD.gn b/ui/app_list/presenter/BUILD.gn
index 521ab5e..2f7b0e7 100644
--- a/ui/app_list/presenter/BUILD.gn
+++ b/ui/app_list/presenter/BUILD.gn
@@ -8,8 +8,23 @@
 
 assert(use_aura)
 
+mojom("mojom") {
+  sources = [
+    "app_list_presenter.mojom",
+  ]
+  deps = [
+    "//services/ui/public/interfaces",
+  ]
+
+  export_class_attribute = "APP_LIST_PRESENTER_EXPORT"
+  export_define = "APP_LIST_PRESENTER_IMPLEMENTATION=1"
+  export_header = "ui/app_list/presenter/app_list_presenter_export.h"
+}
+
 component("presenter") {
   sources = [
+    "app_list.cc",
+    "app_list.h",
     "app_list_presenter.h",
     "app_list_presenter_delegate.cc",
     "app_list_presenter_delegate.h",
@@ -24,7 +39,9 @@
   defines = [ "APP_LIST_PRESENTER_IMPLEMENTATION" ]
 
   public_deps = [
+    ":mojom",
     "//base",
+    "//mojo/public/cpp/bindings",
     "//ui/app_list",
     "//ui/aura",
     "//ui/compositor",
@@ -37,15 +54,6 @@
   ]
 }
 
-mojom("mojom") {
-  sources = [
-    "app_list_presenter.mojom",
-  ]
-  deps = [
-    "//services/ui/public/interfaces",
-  ]
-}
-
 static_library("test_support") {
   sources = [
     "test/app_list_presenter_impl_test_api.cc",
diff --git a/ui/app_list/presenter/app_list.cc b/ui/app_list/presenter/app_list.cc
new file mode 100644
index 0000000..9dda27a8
--- /dev/null
+++ b/ui/app_list/presenter/app_list.cc
@@ -0,0 +1,25 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/app_list/presenter/app_list.h"
+
+namespace app_list {
+
+AppList::AppList() {}
+
+AppList::~AppList() {}
+
+void AppList::BindRequest(mojom::AppListRequest request) {
+  bindings_.AddBinding(this, std::move(request));
+}
+
+mojom::AppListPresenter* AppList::GetAppListPresenter() {
+  return presenter_.get();
+}
+
+void AppList::SetAppListPresenter(mojom::AppListPresenterPtr presenter) {
+  presenter_ = std::move(presenter);
+}
+
+}  // namespace app_list
diff --git a/ui/app_list/presenter/app_list.h b/ui/app_list/presenter/app_list.h
new file mode 100644
index 0000000..2cf701d
--- /dev/null
+++ b/ui/app_list/presenter/app_list.h
@@ -0,0 +1,41 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_APP_LIST_PRESENTER_APP_LIST_H_
+#define UI_APP_LIST_PRESENTER_APP_LIST_H_
+
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "ui/app_list/presenter/app_list_presenter.mojom.h"
+#include "ui/app_list/presenter/app_list_presenter_export.h"
+
+namespace app_list {
+
+// Stores the app list presenter interface pointer.
+class APP_LIST_PRESENTER_EXPORT AppList : public mojom::AppList {
+ public:
+  AppList();
+  ~AppList() override;
+
+  // Binds the mojom::AppList interface request to this object.
+  void BindRequest(mojom::AppListRequest request);
+
+  // Get a raw pointer to the mojom::AppListPresenter interface; may be null.
+  mojom::AppListPresenter* GetAppListPresenter();
+
+  // mojom::AppList:
+  void SetAppListPresenter(mojom::AppListPresenterPtr presenter) override;
+
+ private:
+  // Bindings for the mojom::AppList interface.
+  mojo::BindingSet<mojom::AppList> bindings_;
+
+  // App list presenter interface in chrome; used to show/hide the app list.
+  mojom::AppListPresenterPtr presenter_;
+
+  DISALLOW_COPY_AND_ASSIGN(AppList);
+};
+
+}  // namespace app_list
+
+#endif  // UI_APP_LIST_PRESENTER_APP_LIST_H_
diff --git a/ui/app_list/presenter/app_list_presenter.mojom b/ui/app_list/presenter/app_list_presenter.mojom
index 3ffa45a..8522ca5 100644
--- a/ui/app_list/presenter/app_list_presenter.mojom
+++ b/ui/app_list/presenter/app_list_presenter.mojom
@@ -6,6 +6,17 @@
 
 import "services/ui/public/interfaces/window_manager_constants.mojom";
 
+// TODO(msw): Rename this file to app_list.mojom; move to ash?
+// TODO(msw): Ash should implement the app list and presenter; chrome should
+//            just push data about its apps into the app list interface.
+
+// Implemented by ash. Used by chrome to set the presenter interface.
+interface AppList {
+  // Set the app list presenter interface, to let ash trigger Chrome's app list.
+  SetAppListPresenter(AppListPresenter presenter);
+};
+
+// Implemented by chrome. Used by ash to actually show and dismiss the app list.
 interface AppListPresenter {
   // Show the app list on the specified display.
   Show(int64 display_id);
diff --git a/ui/aura/mus/text_input_client_impl.cc b/ui/aura/mus/text_input_client_impl.cc
index 2dbc39e..782e834 100644
--- a/ui/aura/mus/text_input_client_impl.cc
+++ b/ui/aura/mus/text_input_client_impl.cc
@@ -38,9 +38,7 @@
 
 void TextInputClientImpl::InsertChar(std::unique_ptr<ui::Event> event) {
   DCHECK(event->IsKeyEvent());
-  ui::KeyEvent* key_event = event->AsKeyEvent();
-  DCHECK(key_event->is_char());
-  text_input_client_->InsertChar(*key_event);
+  text_input_client_->InsertChar(*event->AsKeyEvent());
 }
 
 }  // namespace aura
diff --git a/ui/base/ime/input_method_chromeos.cc b/ui/base/ime/input_method_chromeos.cc
index a8ac902..27d0a559 100644
--- a/ui/base/ime/input_method_chromeos.cc
+++ b/ui/base/ime/input_method_chromeos.cc
@@ -57,34 +57,9 @@
     ui::IMEBridge::Get()->SetInputContextHandler(NULL);
 }
 
-bool InputMethodChromeOS::OnUntranslatedIMEMessage(
-    const base::NativeEvent& event,
-    NativeEventResult* result) {
-  return false;
-}
-
-void InputMethodChromeOS::ProcessKeyEventDone(ui::KeyEvent* event,
-                                              bool is_handled) {
-  DCHECK(event);
-  if (event->type() == ET_KEY_PRESSED) {
-    if (is_handled) {
-      // IME event has a priority to be handled, so that character composer
-      // should be reset.
-      character_composer_.Reset();
-    } else {
-      // If IME does not handle key event, passes keyevent to character composer
-      // to be able to compose complex characters.
-      is_handled = ExecuteCharacterComposer(*event);
-    }
-  }
-
-  if (event->type() == ET_KEY_PRESSED || event->type() == ET_KEY_RELEASED)
-    ProcessKeyEventPostIME(event, is_handled);
-
-  handling_key_event_ = false;
-}
-
-void InputMethodChromeOS::DispatchKeyEvent(ui::KeyEvent* event) {
+void InputMethodChromeOS::DispatchKeyEvent(
+    ui::KeyEvent* event,
+    std::unique_ptr<AckCallback> ack_callback) {
   DCHECK(event->IsKeyEvent());
   DCHECK(!(event->flags() & ui::EF_IS_SYNTHESIZED));
 
@@ -114,28 +89,68 @@
         // Treating as PostIME event if character composer handles key event and
         // generates some IME event,
         ProcessKeyEventPostIME(event, true);
+        if (ack_callback)
+          ack_callback->Run(true);
         return;
       }
       ProcessUnfilteredKeyPressEvent(event);
     } else {
       ignore_result(DispatchKeyEventPostIME(event));
     }
+    if (ack_callback)
+      ack_callback->Run(false);
     return;
   }
 
   handling_key_event_ = true;
   if (GetEngine()->IsInterestedInKeyEvent()) {
-    ui::IMEEngineHandlerInterface::KeyEventDoneCallback callback =
-        base::Bind(&InputMethodChromeOS::ProcessKeyEventDone,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   // Pass the ownership of the new copied event.
-                   base::Owned(new ui::KeyEvent(*event)));
+    ui::IMEEngineHandlerInterface::KeyEventDoneCallback callback = base::Bind(
+        &InputMethodChromeOS::ProcessKeyEventDone,
+        weak_ptr_factory_.GetWeakPtr(),
+        // Pass the ownership of the new copied event.
+        base::Owned(new ui::KeyEvent(*event)), Passed(&ack_callback));
     GetEngine()->ProcessKeyEvent(*event, callback);
   } else {
-    ProcessKeyEventDone(event, false);
+    ProcessKeyEventDone(event, std::move(ack_callback), false);
   }
 }
 
+bool InputMethodChromeOS::OnUntranslatedIMEMessage(
+    const base::NativeEvent& event,
+    NativeEventResult* result) {
+  return false;
+}
+
+void InputMethodChromeOS::ProcessKeyEventDone(
+    ui::KeyEvent* event,
+    std::unique_ptr<AckCallback> ack_callback,
+    bool is_handled) {
+  DCHECK(event);
+  if (event->type() == ET_KEY_PRESSED) {
+    if (is_handled) {
+      // IME event has a priority to be handled, so that character composer
+      // should be reset.
+      character_composer_.Reset();
+    } else {
+      // If IME does not handle key event, passes keyevent to character composer
+      // to be able to compose complex characters.
+      is_handled = ExecuteCharacterComposer(*event);
+    }
+  }
+
+  if (ack_callback)
+    ack_callback->Run(is_handled);
+
+  if (event->type() == ET_KEY_PRESSED || event->type() == ET_KEY_RELEASED)
+    ProcessKeyEventPostIME(event, is_handled);
+
+  handling_key_event_ = false;
+}
+
+void InputMethodChromeOS::DispatchKeyEvent(ui::KeyEvent* event) {
+  DispatchKeyEvent(event, nullptr);
+}
+
 void InputMethodChromeOS::OnTextInputTypeChanged(
     const TextInputClient* client) {
   if (!IsTextInputClientFocused(client))
diff --git a/ui/base/ime/input_method_chromeos.h b/ui/base/ime/input_method_chromeos.h
index a4145cdd..e3a8728 100644
--- a/ui/base/ime/input_method_chromeos.h
+++ b/ui/base/ime/input_method_chromeos.h
@@ -27,6 +27,10 @@
   explicit InputMethodChromeOS(internal::InputMethodDelegate* delegate);
   ~InputMethodChromeOS() override;
 
+  using AckCallback = base::Callback<void(bool)>;
+  void DispatchKeyEvent(ui::KeyEvent* event,
+                        std::unique_ptr<AckCallback> ack_callback);
+
   // Overridden from InputMethod:
   bool OnUntranslatedIMEMessage(const base::NativeEvent& event,
                                 NativeEventResult* result) override;
@@ -100,7 +104,9 @@
   void HidePreeditText();
 
   // Callback function for IMEEngineHandlerInterface::ProcessKeyEvent.
-  void ProcessKeyEventDone(ui::KeyEvent* event, bool is_handled);
+  void ProcessKeyEventDone(ui::KeyEvent* event,
+                           std::unique_ptr<AckCallback> ack_callback,
+                           bool is_handled);
 
   // Returns whether an non-password input field is focused.
   bool IsNonPasswordInputFieldFocused();
diff --git a/ui/login/account_picker/screen_account_picker.js b/ui/login/account_picker/screen_account_picker.js
index 7cac00b..5044a3d 100644
--- a/ui/login/account_picker/screen_account_picker.js
+++ b/ui/login/account_picker/screen_account_picker.js
@@ -266,6 +266,14 @@
      * @param {array} users Array of user instances.
      */
     initializePinKeyboardStateForUsers_: function(users) {
+      // It is possible that the PIN keyboard HTML has already been loaded. If
+      // that is the case, we want to show the user pods with the PIN keyboard
+      // immediately without running the PIN show/hide effect.
+      document.body.classList.add('disable-pin-animation');
+      setTimeout(function() {
+        document.body.classList.remove('disable-pin-animation');
+      });
+
       for (var i = 0; i < users.length; ++i) {
         var user = users[i];
         if (user.showPin) {
diff --git a/ui/login/account_picker/user_pod_row.css b/ui/login/account_picker/user_pod_row.css
index f4bf5d6..7ef24e11 100644
--- a/ui/login/account_picker/user_pod_row.css
+++ b/ui/login/account_picker/user_pod_row.css
@@ -54,6 +54,10 @@
   top: -87px !important;
 }
 
+.disable-pin-animation .pod.pin-enabled {
+  transition: none;
+}
+
 .pod .pin-container {
   height: 204px;
   position: absolute;
diff --git a/ui/login/screen_container.css b/ui/login/screen_container.css
index cf505f2d..6e0fcfe 100644
--- a/ui/login/screen_container.css
+++ b/ui/login/screen_container.css
@@ -34,6 +34,10 @@
                          checked to determine if loaded. */
 }
 
+.disable-pin-animation .pin-container {
+  transition: none;
+}
+
 #scroll-container {
   bottom: 0;        /* Allows content overlap with control bar. */
   left: 0;
diff --git a/ui/views/accessibility/ax_view_obj_wrapper.cc b/ui/views/accessibility/ax_view_obj_wrapper.cc
index d2a496f..75d7545 100644
--- a/ui/views/accessibility/ax_view_obj_wrapper.cc
+++ b/ui/views/accessibility/ax_view_obj_wrapper.cc
@@ -79,7 +79,7 @@
 }
 
 void AXViewObjWrapper::MakeVisible() {
-  // TODO(dtseng): Implement.
+  view_->ScrollRectToVisible(view_->GetLocalBounds());
 }
 
 void AXViewObjWrapper::SetSelection(int32_t start, int32_t end) {
diff --git a/ui/views/controls/button/label_button.cc b/ui/views/controls/button/label_button.cc
index 03738f8..21891fc 100644
--- a/ui/views/controls/button/label_button.cc
+++ b/ui/views/controls/button/label_button.cc
@@ -159,25 +159,13 @@
   label_->SetSubpixelRenderingEnabled(enabled);
 }
 
-const gfx::FontList& LabelButton::GetFontList() const {
-  return label_->font_list();
-}
-
-void LabelButton::SetFontList(const gfx::FontList& font_list) {
-  cached_normal_font_list_ = font_list;
-  if (PlatformStyle::kDefaultLabelButtonHasBoldFont) {
-    cached_bold_font_list_ = font_list.DeriveWithWeight(
-        GetValueBolderThan(font_list.GetFontWeight()));
-    if (is_default_) {
-      label_->SetFontList(cached_bold_font_list_);
-      return;
-    }
-  }
-  label_->SetFontList(cached_normal_font_list_);
+void LabelButton::SetFontListDeprecated(const gfx::FontList& font_list) {
+  SetFontList(font_list);
 }
 
 void LabelButton::AdjustFontSize(int font_size_delta) {
-  LabelButton::SetFontList(GetFontList().DeriveWithSizeDelta(font_size_delta));
+  LabelButton::SetFontList(
+      label()->font_list().DeriveWithSizeDelta(font_size_delta));
 }
 
 void LabelButton::SetElideBehavior(gfx::ElideBehavior elide_behavior) {
@@ -393,6 +381,19 @@
   return GetLocalBounds();
 }
 
+void LabelButton::SetFontList(const gfx::FontList& font_list) {
+  cached_normal_font_list_ = font_list;
+  if (PlatformStyle::kDefaultLabelButtonHasBoldFont) {
+    cached_bold_font_list_ = font_list.DeriveWithWeight(
+        GetValueBolderThan(font_list.GetFontWeight()));
+    if (is_default_) {
+      label_->SetFontList(cached_bold_font_list_);
+      return;
+    }
+  }
+  label_->SetFontList(cached_normal_font_list_);
+}
+
 void LabelButton::OnPaint(gfx::Canvas* canvas) {
   View::OnPaint(canvas);
   Painter::PaintFocusPainter(this, canvas, focus_painter_.get());
diff --git a/ui/views/controls/button/label_button.h b/ui/views/controls/button/label_button.h
index a78ccb0..6228ab2b 100644
--- a/ui/views/controls/button/label_button.h
+++ b/ui/views/controls/button/label_button.h
@@ -56,10 +56,8 @@
   // Sets whether subpixel rendering is used on the label.
   void SetTextSubpixelRenderingEnabled(bool enabled);
 
-  // Gets or sets the font list used by this button.
-  const gfx::FontList& GetFontList() const;
-  // TODO(estade): make this function protected.
-  virtual void SetFontList(const gfx::FontList& font_list);
+  // TODO(estade): remove. See crbug.com/633986
+  void SetFontListDeprecated(const gfx::FontList& font_list);
 
   // Adjusts the font size up or down by the given amount.
   virtual void AdjustFontSize(int font_size_delta);
@@ -120,6 +118,9 @@
   // these bounds if they need room to do manual painting.
   virtual gfx::Rect GetChildAreaBounds();
 
+  // Sets the font list used by this button.
+  virtual void SetFontList(const gfx::FontList& font_list);
+
   // View:
   void OnPaint(gfx::Canvas* canvas) override;
   void OnFocus() override;
diff --git a/ui/views/controls/button/label_button_unittest.cc b/ui/views/controls/button/label_button_unittest.cc
index 4696e73..459991d 100644
--- a/ui/views/controls/button/label_button_unittest.cc
+++ b/ui/views/controls/button/label_button_unittest.cc
@@ -291,24 +291,21 @@
   EXPECT_LT(button_->GetPreferredSize().height(), image_size);
 }
 
-TEST_F(LabelButtonTest, FontList) {
+TEST_F(LabelButtonTest, AdjustFontSize) {
   button_->SetText(base::ASCIIToUTF16("abc"));
 
-  const gfx::FontList original_font_list = button_->GetFontList();
-  const gfx::FontList large_font_list =
-      original_font_list.DeriveWithSizeDelta(100);
   const int original_width = button_->GetPreferredSize().width();
   const int original_height = button_->GetPreferredSize().height();
 
   // The button size increases when the font size is increased.
-  button_->SetFontList(large_font_list);
+  button_->AdjustFontSize(100);
   EXPECT_GT(button_->GetPreferredSize().width(), original_width);
   EXPECT_GT(button_->GetPreferredSize().height(), original_height);
 
   // The button returns to its original size when the minimal size is cleared
   // and the original font size is restored.
   button_->SetMinSize(gfx::Size());
-  button_->SetFontList(original_font_list);
+  button_->AdjustFontSize(-100);
   EXPECT_EQ(original_width, button_->GetPreferredSize().width());
   EXPECT_EQ(original_height, button_->GetPreferredSize().height());
 }
diff --git a/ui/views/mus/text_input_client_impl.cc b/ui/views/mus/text_input_client_impl.cc
index 9e5b216..4193e127 100644
--- a/ui/views/mus/text_input_client_impl.cc
+++ b/ui/views/mus/text_input_client_impl.cc
@@ -38,9 +38,7 @@
 
 void TextInputClientImpl::InsertChar(std::unique_ptr<ui::Event> event) {
   DCHECK(event->IsKeyEvent());
-  ui::KeyEvent* key_event = event->AsKeyEvent();
-  DCHECK(key_event->is_char());
-  text_input_client_->InsertChar(*key_event);
+  text_input_client_->InsertChar(*event->AsKeyEvent());
 }
 
 }  // namespace views
diff --git a/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html b/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html
index c6d0ea2..5353cef 100644
--- a/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html
+++ b/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html
@@ -109,7 +109,7 @@
 
       :host(:not([narrow]):not([showing-search])) #icon,
       :host(:not([narrow])) #prompt {
-        opacity: 0.6;
+        opacity: 0.7;
       }
 
       :host([narrow]:not([showing-search])) #searchTerm {
diff --git a/ui/webui/resources/css/md_colors.css b/ui/webui/resources/css/md_colors.css
index a7d22d6..b757acbc 100644
--- a/ui/webui/resources/css/md_colors.css
+++ b/ui/webui/resources/css/md_colors.css
@@ -5,7 +5,8 @@
 :root {
   /* This is a custom, Chrome-specific color that does not have a --paper or
    * --google equivalent. */
-  --md-background-color: rgb(241, 241, 241);
+  --md-background-color: #f1f1f1;
+  --md-loading-message-color: #6e6e6e;
   /* This is --google-blue-700, rewritten as a native custom property for speed.
    */
   --md-toolbar-color: rgb(51, 103, 214);
diff --git a/ui/wm/core/shadow.cc b/ui/wm/core/shadow.cc
index 8319095..6b1290d 100644
--- a/ui/wm/core/shadow.cc
+++ b/ui/wm/core/shadow.cc
@@ -15,10 +15,6 @@
 
 namespace {
 
-// The opacity used for active shadow when animating between
-// inactive/active shadow.
-const float kInactiveShadowAnimationOpacity = 0.2f;
-
 // Rounded corners are overdrawn on top of the window's content layer,
 // we need to exclude them from the occlusion area.
 const int kRoundedCornerRadius = 2;
@@ -73,18 +69,16 @@
 
 void Shadow::Init(Style style) {
   style_ = style;
-
   layer_.reset(new ui::Layer(ui::LAYER_NOT_DRAWN));
-  shadow_layer_.reset(new ui::Layer(ui::LAYER_NINE_PATCH));
-  layer()->Add(shadow_layer_.get());
-
-  UpdateImagesForStyle();
-  shadow_layer_->set_name("Shadow");
-  shadow_layer_->SetVisible(true);
-  shadow_layer_->SetFillsBoundsOpaquely(false);
+  RecreateShadowLayer();
 }
 
 void Shadow::SetContentBounds(const gfx::Rect& content_bounds) {
+  // When the window moves but doesn't change size, this is a no-op. (The
+  // origin stays the same in this case.)
+  if (content_bounds == content_bounds_)
+    return;
+
   content_bounds_ = content_bounds;
   UpdateLayerBounds();
 }
@@ -93,64 +87,49 @@
   if (style_ == style)
     return;
 
-  Style old_style = style_;
   style_ = style;
 
   // Stop waiting for any as yet unfinished implicit animations.
   StopObservingImplicitAnimations();
 
-  // If we're switching to or from the small style, don't bother with
-  // animations.
-  if (style == STYLE_SMALL || old_style == STYLE_SMALL) {
-    UpdateImagesForStyle();
-    // Make sure the shadow is fully opaque.
-    shadow_layer_->SetOpacity(1.0f);
-    return;
-  }
-
-  // If we're becoming active, switch images now.  Because the inactive image
-  // has a very low opacity the switch isn't noticeable and this approach
-  // allows us to use only a single set of shadow images at a time.
-  if (style == STYLE_ACTIVE) {
-    UpdateImagesForStyle();
-    // Opacity was baked into inactive image, start opacity low to match.
-    shadow_layer_->SetOpacity(kInactiveShadowAnimationOpacity);
-  }
+  // The old shadow layer is the new fading out layer.
+  DCHECK(shadow_layer_);
+  fading_layer_ = std::move(shadow_layer_);
+  RecreateShadowLayer();
+  shadow_layer_->SetOpacity(0.f);
 
   {
-    // Property sets within this scope will be implicitly animated.
-    ui::ScopedLayerAnimationSettings settings(shadow_layer_->GetAnimator());
+    // Observe the fade out animation so we can clean up the layer when done.
+    ui::ScopedLayerAnimationSettings settings(fading_layer_->GetAnimator());
     settings.AddObserver(this);
     settings.SetTransitionDuration(
         base::TimeDelta::FromMilliseconds(kShadowAnimationDurationMs));
-    switch (style_) {
-      case STYLE_ACTIVE:
-        // Animate the active shadow from kInactiveShadowAnimationOpacity to
-        // 1.0f.
-        shadow_layer_->SetOpacity(1.0f);
-        break;
-      case STYLE_INACTIVE:
-        // The opacity will be reset to 1.0f when animation is completed.
-        shadow_layer_->SetOpacity(kInactiveShadowAnimationOpacity);
-        break;
-      default:
-        NOTREACHED() << "Unhandled style " << style_;
-        break;
-    }
+    fading_layer_->SetOpacity(0.f);
+  }
+
+  {
+    // We don't care to observe this one.
+    ui::ScopedLayerAnimationSettings settings(shadow_layer_->GetAnimator());
+    settings.SetTransitionDuration(
+        base::TimeDelta::FromMilliseconds(kShadowAnimationDurationMs));
+    shadow_layer_->SetOpacity(1.f);
   }
 }
 
 void Shadow::OnImplicitAnimationsCompleted() {
-  // If we just finished going inactive, switch images.  This doesn't cause
-  // a visual pop because the inactive image opacity is so low.
-  if (style_ == STYLE_INACTIVE) {
-    UpdateImagesForStyle();
-    // Opacity is baked into inactive image, so set fully opaque.
-    shadow_layer_->SetOpacity(1.0f);
-  }
+  fading_layer_.reset();
+  // The size needed for layer() may be smaller now that |fading_layer_| is
+  // removed.
+  UpdateLayerBounds();
 }
 
-void Shadow::UpdateImagesForStyle() {
+void Shadow::RecreateShadowLayer() {
+  shadow_layer_.reset(new ui::Layer(ui::LAYER_NINE_PATCH));
+  shadow_layer_->set_name("Shadow");
+  shadow_layer_->SetVisible(true);
+  shadow_layer_->SetFillsBoundsOpaquely(false);
+  layer()->Add(shadow_layer_.get());
+
   const ShadowDetails& details = GetDetailsForElevation(ElevationForStyle());
   shadow_layer_->UpdateNinePatchLayerImage(details.ninebox_image);
   // The ninebox grid is defined in terms of the image size. The shadow blurs in
@@ -170,15 +149,37 @@
   // Shadow margins are negative, so this expands outwards from
   // |content_bounds_|.
   const gfx::Insets margins = gfx::ShadowValue::GetMargin(details.values);
-  gfx::Rect layer_bounds = content_bounds_;
-  layer_bounds.Inset(margins);
-  layer()->SetBounds(layer_bounds);
-  const gfx::Rect shadow_layer_bounds(layer_bounds.size());
+  gfx::Rect new_layer_bounds = content_bounds_;
+  new_layer_bounds.Inset(margins);
+  gfx::Rect shadow_layer_bounds(new_layer_bounds.size());
+
+  // When there's an old shadow fading out, the bounds of layer() have to be
+  // big enough to encompass both shadows.
+  if (fading_layer_) {
+    const gfx::Rect old_layer_bounds = layer()->bounds();
+    gfx::Rect combined_layer_bounds = old_layer_bounds;
+    combined_layer_bounds.Union(new_layer_bounds);
+    layer()->SetBounds(combined_layer_bounds);
+
+    // If this is reached via SetContentBounds, we might hypothetically need
+    // to change the size of the fading layer, but the fade is so fast it's
+    // not really an issue.
+    gfx::Rect fading_layer_bounds(fading_layer_->bounds());
+    fading_layer_bounds.Offset(old_layer_bounds.origin() -
+                               combined_layer_bounds.origin());
+    fading_layer_->SetBounds(fading_layer_bounds);
+
+    shadow_layer_bounds.Offset(new_layer_bounds.origin() -
+                               combined_layer_bounds.origin());
+  } else {
+    layer()->SetBounds(new_layer_bounds);
+  }
+
   shadow_layer_->SetBounds(shadow_layer_bounds);
 
   // Occlude the region inside the bounding box. Occlusion uses shadow layer
   // space. See nine_patch_layer.h for more context on what's going on here.
-  gfx::Rect occlusion_bounds = shadow_layer_bounds;
+  gfx::Rect occlusion_bounds(shadow_layer_bounds.size());
   occlusion_bounds.Inset(-margins + gfx::Insets(kRoundedCornerRadius));
   shadow_layer_->UpdateNinePatchOcclusion(occlusion_bounds);
 
diff --git a/ui/wm/core/shadow.h b/ui/wm/core/shadow.h
index e0b7a1db..24fbfed 100644
--- a/ui/wm/core/shadow.h
+++ b/ui/wm/core/shadow.h
@@ -62,8 +62,8 @@
   void OnImplicitAnimationsCompleted() override;
 
  private:
-  // Updates the shadow images to the current |style_|.
-  void UpdateImagesForStyle();
+  // Updates the shadow layer and its image to the current |style_|.
+  void RecreateShadowLayer();
 
   // Updates the shadow layer bounds based on the inteior inset and the current
   // |content_bounds_|.
@@ -84,6 +84,10 @@
   // The actual shadow layer corresponding to a cc::NinePatchLayer.
   std::unique_ptr<ui::Layer> shadow_layer_;
 
+  // When the style changes, the old shadow cross-fades with the new one.
+  // When non-null, this is an old |shadow_layer_| that's being animated out.
+  std::unique_ptr<ui::Layer> fading_layer_;
+
   // Bounds of the content that the shadow encloses.
   gfx::Rect content_bounds_;
 
diff --git a/url/origin.cc b/url/origin.cc
index 0cb4c10c..53600b1 100644
--- a/url/origin.cc
+++ b/url/origin.cc
@@ -85,11 +85,21 @@
                uint16_t port,
                base::StringPiece suborigin,
                SchemeHostPort::ConstructPolicy policy)
-    : tuple_(scheme, host, port, policy) {
+    : tuple_(scheme.as_string(), host.as_string(), port, policy) {
   unique_ = tuple_.IsInvalid();
   suborigin_ = suborigin.as_string();
 }
 
+Origin::Origin(std::string scheme,
+               std::string host,
+               uint16_t port,
+               std::string suborigin,
+               SchemeHostPort::ConstructPolicy policy)
+    : tuple_(std::move(scheme), std::move(host), port, policy) {
+  unique_ = tuple_.IsInvalid();
+  suborigin_ = std::move(suborigin);
+}
+
 Origin::~Origin() {
 }
 
@@ -101,18 +111,12 @@
   return Origin(scheme, host, port, "", SchemeHostPort::CHECK_CANONICALIZATION);
 }
 
-Origin Origin::CreateFromNormalizedTuple(base::StringPiece scheme,
-                                         base::StringPiece host,
-                                         uint16_t port) {
-  return CreateFromNormalizedTupleWithSuborigin(scheme, host, port, "");
-}
-
 Origin Origin::CreateFromNormalizedTupleWithSuborigin(
-    base::StringPiece scheme,
-    base::StringPiece host,
+    std::string scheme,
+    std::string host,
     uint16_t port,
-    base::StringPiece suborigin) {
-  return Origin(scheme, host, port, suborigin,
+    std::string suborigin) {
+  return Origin(std::move(scheme), std::move(host), port, std::move(suborigin),
                 SchemeHostPort::ALREADY_CANONICALIZED);
 }
 
diff --git a/url/origin.h b/url/origin.h
index 1c28588f..4b838e4 100644
--- a/url/origin.h
+++ b/url/origin.h
@@ -104,18 +104,13 @@
 
   // Creates an origin without sanity checking that the host is canonicalized.
   // This should only be used when converting between already normalized types,
-  // and should NOT be used for IPC.
-  static Origin CreateFromNormalizedTuple(base::StringPiece scheme,
-                                          base::StringPiece host,
-                                          uint16_t port);
-
-  // Same as CreateFromNormalizedTuple() above, but adds a suborigin component
-  // as well.
+  // and should NOT be used for IPC. Method takes std::strings for use with move
+  // operators to avoid copies.
   static Origin CreateFromNormalizedTupleWithSuborigin(
-      base::StringPiece scheme,
-      base::StringPiece host,
+      std::string scheme,
+      std::string host,
       uint16_t port,
-      base::StringPiece suborigin);
+      std::string suborigin);
 
   ~Origin();
 
@@ -173,6 +168,11 @@
          uint16_t port,
          base::StringPiece suborigin,
          SchemeHostPort::ConstructPolicy policy);
+  Origin(std::string scheme,
+         std::string host,
+         uint16_t port,
+         std::string suborigin,
+         SchemeHostPort::ConstructPolicy policy);
 
   SchemeHostPort tuple_;
   bool unique_;
diff --git a/url/origin_unittest.cc b/url/origin_unittest.cc
index 0f17c26..a5c3042 100644
--- a/url/origin_unittest.cc
+++ b/url/origin_unittest.cc
@@ -90,20 +90,11 @@
                     << test_case.port;
     }
     SCOPED_TRACE(scope_message);
-
-    url::Origin origin_without_suborigin =
-        url::Origin::CreateFromNormalizedTuple(test_case.scheme, test_case.host,
-                                               test_case.port);
-
     url::Origin origin_with_suborigin =
         url::Origin::CreateFromNormalizedTupleWithSuborigin(
             test_case.scheme, test_case.host, test_case.port,
             test_case.suborigin);
 
-    EXPECT_EQ(test_case.scheme, origin_without_suborigin.scheme());
-    EXPECT_EQ(test_case.host, origin_without_suborigin.host());
-    EXPECT_EQ(test_case.port, origin_without_suborigin.port());
-
     EXPECT_EQ(test_case.scheme, origin_with_suborigin.scheme());
     EXPECT_EQ(test_case.host, origin_with_suborigin.host());
     EXPECT_EQ(test_case.port, origin_with_suborigin.port());
diff --git a/url/scheme_host_port.cc b/url/scheme_host_port.cc
index 0fe87c50..6c03101e 100644
--- a/url/scheme_host_port.cc
+++ b/url/scheme_host_port.cc
@@ -116,24 +116,24 @@
 SchemeHostPort::SchemeHostPort() : port_(0) {
 }
 
-SchemeHostPort::SchemeHostPort(base::StringPiece scheme,
-                               base::StringPiece host,
+SchemeHostPort::SchemeHostPort(std::string scheme,
+                               std::string host,
                                uint16_t port,
                                ConstructPolicy policy)
     : port_(0) {
   if (!IsValidInput(scheme, host, port, policy))
     return;
 
-  scheme.CopyToString(&scheme_);
-  host.CopyToString(&host_);
+  scheme_ = std::move(scheme);
+  host_ = std::move(host);
   port_ = port;
 }
 
 SchemeHostPort::SchemeHostPort(base::StringPiece scheme,
                                base::StringPiece host,
                                uint16_t port)
-    : SchemeHostPort(scheme,
-                     host,
+    : SchemeHostPort(scheme.as_string(),
+                     host.as_string(),
                      port,
                      ConstructPolicy::CHECK_CANONICALIZATION) {}
 
diff --git a/url/scheme_host_port.h b/url/scheme_host_port.h
index 065e4aa..b2e030d 100644
--- a/url/scheme_host_port.h
+++ b/url/scheme_host_port.h
@@ -96,8 +96,8 @@
   // that the host and port are canonicalized. This should only be used when
   // converting between already normalized types, and should NOT be used for
   // IPC.
-  SchemeHostPort(base::StringPiece scheme,
-                 base::StringPiece host,
+  SchemeHostPort(std::string scheme,
+                 std::string host,
                  uint16_t port,
                  ConstructPolicy policy);