diff --git a/.gitignore b/.gitignore
index 81c2a0c..689792c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -348,6 +348,7 @@
 /third_party/fontconfig/src
 /third_party/freetype-android/src
 /third_party/freetype2/src
+/third_party/gestures/gestures
 /third_party/gles2_conform
 /third_party/glslang/src
 /third_party/glslang-angle/src
@@ -383,6 +384,7 @@
 /third_party/libc++-static/libc++.a
 /third_party/libaddressinput/src
 /third_party/libdrm/src
+/third_party/libevdev/src
 /third_party/libexif/sources
 /third_party/libFuzzer/src
 /third_party/libjingle/source
diff --git a/DEPS b/DEPS
index 8e010e6..84c5723 100644
--- a/DEPS
+++ b/DEPS
@@ -44,7 +44,7 @@
   # 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': '7c484d9bc270bef918beda9d7411f6c07ab37a5b',
+  'v8_revision': 'a0395e141961135d20e0db9181a687a2a4d6cb51',
   # 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.
@@ -88,7 +88,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling NaCl
   # and whatever else without interference from each other.
-  'nacl_revision': '5dfe030a71ca66e72c5719ef5034c2ed24706c43',
+  'nacl_revision': '026b76327c0c443fcf98064e315ca398c4b544d1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype-android
   # 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': '886ff596e4884a69b7977a6929165e239955ae5b',
+  'catapult_revision': '0c217fe8765ca4102cb770031fb18334979ac0c9',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -437,6 +437,14 @@
     'src/third_party/wayland-protocols/src':
       Var('chromium_git') + '/external/anongit.freedesktop.org/git/wayland/wayland-protocols.git' + '@' + '2e541a36deff5f2e16e25e27f7f93d26822eecc2',
 
+    # The libevdev library (Chrome OS version).
+    'src/third_party/libevdev/src':
+      Var('chromium_git') + '/chromiumos/platform/libevdev.git' + '@' + '9f7a1961eb4726211e18abd147d5a11a4ea86744',
+
+    # Chrome OS touchpad gestures library.
+    'src/third_party/gestures/gestures':
+      Var('chromium_git') + '/chromiumos/platform/gestures.git' + '@' + '5a656849c7d2b0d0ddbe0ac6d300c1e2fada0bb4',
+
     # Wireless Display Software. Used on Chrome OS.
     'src/third_party/wds/src':
       Var('chromium_git') + '/external/github.com/01org/wds' + '@' + 'ac3d8210d95f3000bf5c8e16a79dbbbf22d554a5',
diff --git a/android_webview/test/BUILD.gn b/android_webview/test/BUILD.gn
index f351364..a270995 100644
--- a/android_webview/test/BUILD.gn
+++ b/android_webview/test/BUILD.gn
@@ -269,7 +269,6 @@
   deps = [
     "//android_webview:android_webview_java",
     "//base:base_java",
-    "//base:base_java_test_support",
     "//content/public/test/android:content_java_test_support",
   ]
   java_files = [
diff --git a/ash/aura/wm_root_window_controller_aura.cc b/ash/aura/wm_root_window_controller_aura.cc
index 368f3ca7..2196442 100644
--- a/ash/aura/wm_root_window_controller_aura.cc
+++ b/ash/aura/wm_root_window_controller_aura.cc
@@ -4,7 +4,6 @@
 
 #include "ash/aura/wm_root_window_controller_aura.h"
 
-#include "ash/aura/wm_shell_aura.h"
 #include "ash/aura/wm_window_aura.h"
 #include "ash/common/shelf/shelf_widget.h"
 #include "ash/common/shelf/wm_shelf.h"
@@ -61,10 +60,6 @@
   return root_window_controller_->wm_shelf()->shelf_widget() != nullptr;
 }
 
-WmShell* WmRootWindowControllerAura::GetShell() {
-  return WmShell::Get();
-}
-
 WmShelf* WmRootWindowControllerAura::GetShelf() {
   return root_window_controller_->wm_shelf();
 }
diff --git a/ash/aura/wm_root_window_controller_aura.h b/ash/aura/wm_root_window_controller_aura.h
index ec78df2..cbeba00 100644
--- a/ash/aura/wm_root_window_controller_aura.h
+++ b/ash/aura/wm_root_window_controller_aura.h
@@ -31,7 +31,6 @@
 
   // WmRootWindowController:
   bool HasShelf() override;
-  WmShell* GetShell() override;
   WmShelf* GetShelf() override;
   WmWindow* GetWindow() override;
   void OnInitialWallpaperAnimationStarted() override;
diff --git a/ash/aura/wm_shell_aura.cc b/ash/aura/wm_shell_aura.cc
index 1d27a92..1d99a96 100644
--- a/ash/aura/wm_shell_aura.cc
+++ b/ash/aura/wm_shell_aura.cc
@@ -318,15 +318,6 @@
   }
 }
 
-void WmShellAura::SessionStateChanged(session_manager::SessionState state) {
-  // Create the shelf if necessary.
-  WmShell::SessionStateChanged(state);
-
-  // Recreate the keyboard after initial login and after multiprofile login.
-  if (state == session_manager::SessionState::ACTIVE)
-    Shell::GetInstance()->CreateKeyboard();
-}
-
 void WmShellAura::OnDisplayConfigurationChanging() {
   for (auto& observer : display_observers_)
     observer.OnDisplayConfigurationChanging();
diff --git a/ash/aura/wm_shell_aura.h b/ash/aura/wm_shell_aura.h
index e0093b73..f05840b 100644
--- a/ash/aura/wm_shell_aura.h
+++ b/ash/aura/wm_shell_aura.h
@@ -95,9 +95,6 @@
   void OnAttemptToReactivateWindow(aura::Window* request_active,
                                    aura::Window* actual_active) override;
 
-  // SessionStateObserver:
-  void SessionStateChanged(session_manager::SessionState state) override;
-
   // WindowTreeHostManager::Observer:
   void OnDisplayConfigurationChanging() override;
   void OnDisplayConfigurationChanged() override;
diff --git a/ash/common/frame/caption_buttons/frame_caption_button.cc b/ash/common/frame/caption_buttons/frame_caption_button.cc
index d496f1b..74f1ef9 100644
--- a/ash/common/frame/caption_buttons/frame_caption_button.cc
+++ b/ash/common/frame/caption_buttons/frame_caption_button.cc
@@ -56,9 +56,10 @@
 
 void FrameCaptionButton::SetImage(CaptionButtonIcon icon,
                                   Animate animate,
-                                  gfx::VectorIconId icon_image_id) {
+                                  const gfx::VectorIcon& icon_definition) {
   gfx::ImageSkia new_icon_image = gfx::CreateVectorIcon(
-      icon_image_id, use_light_images_ ? SK_ColorWHITE : gfx::kChromeIconGrey);
+      icon_definition,
+      use_light_images_ ? SK_ColorWHITE : gfx::kChromeIconGrey);
 
   // The early return is dependent on |animate| because callers use SetImage()
   // with ANIMATE_NO to progress the crossfade animation to the end.
@@ -72,7 +73,7 @@
     crossfade_icon_image_ = icon_image_;
 
   icon_ = icon;
-  icon_image_id_ = icon_image_id;
+  icon_definition_ = &icon_definition;
   icon_image_ = new_icon_image;
 
   if (animate == ANIMATE_YES) {
diff --git a/ash/common/frame/caption_buttons/frame_caption_button.h b/ash/common/frame/caption_buttons/frame_caption_button.h
index 3f80862..8b6df28 100644
--- a/ash/common/frame/caption_buttons/frame_caption_button.h
+++ b/ash/common/frame/caption_buttons/frame_caption_button.h
@@ -15,7 +15,7 @@
 
 namespace gfx {
 class SlideAnimation;
-enum class VectorIconId;
+struct VectorIcon;
 }
 
 namespace ash {
@@ -32,12 +32,12 @@
   ~FrameCaptionButton() override;
 
   // Sets the image to use to paint the button. If |animate| is ANIMATE_YES,
-  // the button crossfades to the new visuals. If the image id matches the one
+  // the button crossfades to the new visuals. If the image matches the one
   // currently used by the button and |animate| is ANIMATE_NO, the crossfade
   // animation is progressed to the end.
   void SetImage(CaptionButtonIcon icon,
                 Animate animate,
-                gfx::VectorIconId icon_image_id);
+                const gfx::VectorIcon& icon_image);
 
   // Returns true if the button is crossfading to new visuals set in
   // SetImage().
@@ -59,8 +59,6 @@
 
   CaptionButtonIcon icon() const { return icon_; }
 
-  gfx::VectorIconId icon_image_id() const { return icon_image_id_; }
-
   void set_size(const gfx::Size& size) { size_ = size; }
 
  protected:
@@ -90,7 +88,7 @@
 
   // The image id (kept for the purposes of testing) and image used to paint the
   // button's icon.
-  gfx::VectorIconId icon_image_id_;
+  const gfx::VectorIcon* icon_definition_ = nullptr;
   gfx::ImageSkia icon_image_;
 
   // The icon image to crossfade from.
diff --git a/ash/common/frame/caption_buttons/frame_caption_button_container_view.cc b/ash/common/frame/caption_buttons/frame_caption_button_container_view.cc
index 77f8006..3539a04 100644
--- a/ash/common/frame/caption_buttons/frame_caption_button_container_view.cc
+++ b/ash/common/frame/caption_buttons/frame_caption_button_container_view.cc
@@ -19,7 +19,7 @@
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/geometry/point.h"
-#include "ui/gfx/vector_icons_public.h"
+#include "ui/gfx/vector_icon_types.h"
 #include "ui/strings/grit/ui_strings.h"  // Accessibility names
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_delegate.h"
@@ -148,14 +148,15 @@
 
 void FrameCaptionButtonContainerView::SetButtonImage(
     CaptionButtonIcon icon,
-    gfx::VectorIconId icon_image_id) {
-  button_icon_id_map_[icon] = icon_image_id;
+    const gfx::VectorIcon& icon_definition) {
+  button_icon_map_[icon] = &icon_definition;
 
   FrameCaptionButton* buttons[] = {minimize_button_, size_button_,
                                    close_button_};
   for (size_t i = 0; i < arraysize(buttons); ++i) {
     if (buttons[i]->icon() == icon)
-      buttons[i]->SetImage(icon, FrameCaptionButton::ANIMATE_NO, icon_image_id);
+      buttons[i]->SetImage(icon, FrameCaptionButton::ANIMATE_NO,
+                           icon_definition);
   }
 }
 
@@ -299,9 +300,9 @@
   FrameCaptionButton::Animate fcb_animate =
       (animate == ANIMATE_YES) ? FrameCaptionButton::ANIMATE_YES
                                : FrameCaptionButton::ANIMATE_NO;
-  auto it = button_icon_id_map_.find(icon);
-  if (it != button_icon_id_map_.end())
-    button->SetImage(icon, fcb_animate, it->second);
+  auto it = button_icon_map_.find(icon);
+  if (it != button_icon_map_.end())
+    button->SetImage(icon, fcb_animate, *it->second);
 }
 
 bool FrameCaptionButtonContainerView::ShouldSizeButtonBeVisible() const {
diff --git a/ash/common/frame/caption_buttons/frame_caption_button_container_view.h b/ash/common/frame/caption_buttons/frame_caption_button_container_view.h
index 55fd39c..014071a 100644
--- a/ash/common/frame/caption_buttons/frame_caption_button_container_view.h
+++ b/ash/common/frame/caption_buttons/frame_caption_button_container_view.h
@@ -16,7 +16,7 @@
 
 namespace gfx {
 class SlideAnimation;
-enum class VectorIconId;
+struct VectorIcon;
 }
 
 namespace views {
@@ -68,7 +68,8 @@
   // Sets the id of the vector image to paint the button for |icon|. The
   // FrameCaptionButtonContainerView will keep track of the image to use for
   // |icon| even if none of the buttons currently use |icon|.
-  void SetButtonImage(CaptionButtonIcon icon, gfx::VectorIconId icon_image_id);
+  void SetButtonImage(CaptionButtonIcon icon,
+                      const gfx::VectorIcon& icon_definition);
 
   // Sets whether the buttons should be painted as active. Does not schedule
   // a repaint.
@@ -141,9 +142,9 @@
   FrameCaptionButton* size_button_;
   FrameCaptionButton* close_button_;
 
-  // Mapping of the image ID needed to paint a button for each of the values of
+  // Mapping of the image needed to paint a button for each of the values of
   // CaptionButtonIcon.
-  std::map<CaptionButtonIcon, gfx::VectorIconId> button_icon_id_map_;
+  std::map<CaptionButtonIcon, const gfx::VectorIcon*> button_icon_map_;
 
   // Animation that affects the position of |minimize_button_| and the
   // visibility of |size_button_|.
diff --git a/ash/common/frame/caption_buttons/frame_caption_button_container_view_unittest.cc b/ash/common/frame/caption_buttons/frame_caption_button_container_view_unittest.cc
index 067e868..21fce7ca 100644
--- a/ash/common/frame/caption_buttons/frame_caption_button_container_view_unittest.cc
+++ b/ash/common/frame/caption_buttons/frame_caption_button_container_view_unittest.cc
@@ -8,10 +8,10 @@
 #include "ash/common/frame/caption_buttons/frame_caption_button.h"
 #include "ash/common/wm/maximize_mode/maximize_mode_controller.h"
 #include "ash/common/wm_shell.h"
+#include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/test/ash_test_base.h"
 #include "grit/ash_resources.h"
 #include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/vector_icons_public.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_delegate.h"
 
@@ -71,7 +71,7 @@
         GetAshLayoutSize(AshLayoutSize::NON_BROWSER_CAPTION_BUTTON));
     for (int icon = 0; icon < CAPTION_BUTTON_ICON_COUNT; ++icon) {
       container->SetButtonImage(static_cast<CaptionButtonIcon>(icon),
-                                gfx::VectorIconId::WINDOW_CONTROL_CLOSE);
+                                ash::kWindowControlCloseIcon);
     }
   }
 
diff --git a/ash/common/frame/default_header_painter.cc b/ash/common/frame/default_header_painter.cc
index f333bf1..4856f7e9 100644
--- a/ash/common/frame/default_header_painter.cc
+++ b/ash/common/frame/default_header_painter.cc
@@ -7,6 +7,7 @@
 #include "ash/common/ash_layout_constants.h"
 #include "ash/common/frame/caption_buttons/frame_caption_button_container_view.h"
 #include "ash/common/frame/header_painter_util.h"
+#include "ash/resources/vector_icons/vector_icons.h"
 #include "base/debug/leak_annotations.h"
 #include "base/logging.h"  // DCHECK
 #include "grit/ash_resources.h"
@@ -21,7 +22,6 @@
 #include "ui/gfx/image/image.h"
 #include "ui/gfx/scoped_canvas.h"
 #include "ui/gfx/skia_util.h"
-#include "ui/gfx/vector_icons_public.h"
 #include "ui/views/view.h"
 #include "ui/views/widget/native_widget_aura.h"
 #include "ui/views/widget/widget.h"
@@ -283,29 +283,27 @@
 
 void DefaultHeaderPainter::UpdateAllButtonImages() {
   caption_button_container_->SetUseLightImages(ShouldUseLightImages());
-  caption_button_container_->SetButtonImage(
-      CAPTION_BUTTON_ICON_MINIMIZE, gfx::VectorIconId::WINDOW_CONTROL_MINIMIZE);
+  caption_button_container_->SetButtonImage(CAPTION_BUTTON_ICON_MINIMIZE,
+                                            kWindowControlMinimizeIcon);
 
   UpdateSizeButtonImages();
 
-  caption_button_container_->SetButtonImage(
-      CAPTION_BUTTON_ICON_CLOSE, gfx::VectorIconId::WINDOW_CONTROL_CLOSE);
+  caption_button_container_->SetButtonImage(CAPTION_BUTTON_ICON_CLOSE,
+                                            kWindowControlCloseIcon);
 
-  caption_button_container_->SetButtonImage(
-      CAPTION_BUTTON_ICON_LEFT_SNAPPED,
-      gfx::VectorIconId::WINDOW_CONTROL_LEFT_SNAPPED);
+  caption_button_container_->SetButtonImage(CAPTION_BUTTON_ICON_LEFT_SNAPPED,
+                                            kWindowControlLeftSnappedIcon);
 
-  caption_button_container_->SetButtonImage(
-      CAPTION_BUTTON_ICON_RIGHT_SNAPPED,
-      gfx::VectorIconId::WINDOW_CONTROL_RIGHT_SNAPPED);
+  caption_button_container_->SetButtonImage(CAPTION_BUTTON_ICON_RIGHT_SNAPPED,
+                                            kWindowControlRightSnappedIcon);
 }
 
 void DefaultHeaderPainter::UpdateSizeButtonImages() {
-  gfx::VectorIconId icon_id = frame_->IsMaximized() || frame_->IsFullscreen()
-                                  ? gfx::VectorIconId::WINDOW_CONTROL_RESTORE
-                                  : gfx::VectorIconId::WINDOW_CONTROL_MAXIMIZE;
+  const gfx::VectorIcon& icon = frame_->IsMaximized() || frame_->IsFullscreen()
+                                    ? kWindowControlRestoreIcon
+                                    : kWindowControlMaximizeIcon;
   caption_button_container_->SetButtonImage(
-      CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE, icon_id);
+      CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE, icon);
 }
 
 gfx::Rect DefaultHeaderPainter::GetLocalBounds() const {
diff --git a/ash/common/shelf/overflow_button.cc b/ash/common/shelf/overflow_button.cc
index 2bf558a..145aeb06 100644
--- a/ash/common/shelf/overflow_button.cc
+++ b/ash/common/shelf/overflow_button.cc
@@ -11,6 +11,7 @@
 #include "ash/common/shelf/shelf_view.h"
 #include "ash/common/shelf/wm_shelf.h"
 #include "ash/common/shelf/wm_shelf_util.h"
+#include "ash/resources/vector_icons/vector_icons.h"
 #include "base/memory/ptr_util.h"
 #include "grit/ash_resources.h"
 #include "grit/ash_strings.h"
@@ -24,7 +25,6 @@
 #include "ui/gfx/skbitmap_operations.h"
 #include "ui/gfx/skia_util.h"
 #include "ui/gfx/transform.h"
-#include "ui/gfx/vector_icons_public.h"
 #include "ui/views/animation/flood_fill_ink_drop_ripple.h"
 #include "ui/views/animation/ink_drop_impl.h"
 #include "ui/views/animation/ink_drop_mask.h"
@@ -43,8 +43,7 @@
     set_ink_drop_base_color(kShelfInkDropBaseColor);
     set_ink_drop_visible_opacity(kShelfInkDropVisibleOpacity);
     set_hide_ink_drop_when_showing_context_menu(false);
-    bottom_image_md_ =
-        CreateVectorIcon(gfx::VectorIconId::SHELF_OVERFLOW, kShelfIconColor);
+    bottom_image_md_ = CreateVectorIcon(kShelfOverflowIcon, kShelfIconColor);
     bottom_image_ = &bottom_image_md_;
   } else {
     bottom_image_ = ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
diff --git a/ash/common/shelf/shelf_widget.cc b/ash/common/shelf/shelf_widget.cc
index 7b37ef4..4ebc52e 100644
--- a/ash/common/shelf/shelf_widget.cc
+++ b/ash/common/shelf/shelf_widget.cc
@@ -331,12 +331,6 @@
   // Ensure the newly created |shelf_| gets current values.
   background_animator_.Initialize(this);
 
-  // TODO(jamescook): The IsActiveUserSessionStarted() check may not be needed
-  // because the shelf is only created after the first user session is active.
-  // The ShelfView seems to always be visible after login. At the lock screen
-  // the shelf is hidden because its container is hidden. During auto-hide it is
-  // hidden because ShelfWidget is transparent. Some of the ShelfView visibility
-  // code could be simplified. http://crbug.com/674773
   shelf_view_->SetVisible(
       WmShell::Get()->GetSessionStateDelegate()->IsActiveUserSessionStarted());
   shelf_layout_manager_->LayoutShelf();
@@ -348,6 +342,11 @@
   return shelf_view_ && shelf_view_->visible();
 }
 
+void ShelfWidget::SetShelfVisibility(bool visible) {
+  if (shelf_view_)
+    shelf_view_->SetVisible(visible);
+}
+
 bool ShelfWidget::IsShowingAppList() const {
   return GetAppListButton() && GetAppListButton()->is_showing_app_list();
 }
diff --git a/ash/common/shelf/shelf_widget.h b/ash/common/shelf/shelf_widget.h
index b87355f..688a1c789 100644
--- a/ash/common/shelf/shelf_widget.h
+++ b/ash/common/shelf/shelf_widget.h
@@ -60,6 +60,8 @@
   ShelfView* CreateShelfView();
   void PostCreateShelf();
 
+  // Set visibility of the shelf.
+  void SetShelfVisibility(bool visible);
   bool IsShelfVisible() const;
 
   bool IsShowingAppList() const;
diff --git a/ash/common/system/chromeos/bluetooth/tray_bluetooth.cc b/ash/common/system/chromeos/bluetooth/tray_bluetooth.cc
index ed5ae69e..028be209 100644
--- a/ash/common/system/chromeos/bluetooth/tray_bluetooth.cc
+++ b/ash/common/system/chromeos/bluetooth/tray_bluetooth.cc
@@ -331,8 +331,10 @@
                                       false, bluetooth_enabled);
     if (discovered_not_paired_devices_.size() > 0) {
       if (UseMd()) {
-        scroll_content()->AddChildView(
-            TrayPopupUtils::CreateListItemSeparator(false));
+        if (scroll_content()->has_children()) {
+          scroll_content()->AddChildView(
+              TrayPopupUtils::CreateListItemSeparator(false));
+        }
       } else {
         AddScrollSeparator();
       }
diff --git a/ash/common/system/chromeos/ime_menu/ime_menu_tray.cc b/ash/common/system/chromeos/ime_menu/ime_menu_tray.cc
index db6d2a0..fd98926 100644
--- a/ash/common/system/chromeos/ime_menu/ime_menu_tray.cc
+++ b/ash/common/system/chromeos/ime_menu/ime_menu_tray.cc
@@ -30,6 +30,8 @@
 #include "grit/ash_resources.h"
 #include "grit/ash_strings.h"
 #include "ui/base/ime/chromeos/input_method_manager.h"
+#include "ui/base/ime/ime_bridge.h"
+#include "ui/base/ime/text_input_client.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/paint_vector_icon.h"
@@ -75,6 +77,12 @@
   return !TrayPopupUtils::CanOpenWebUISettings(login);
 }
 
+// Returns true if the current input context type is password.
+bool IsInPasswordInputContext() {
+  return ui::IMEBridge::Get()->GetCurrentInputContext().type ==
+         ui::TEXT_INPUT_TYPE_PASSWORD;
+}
+
 class ImeMenuLabel : public views::Label {
  public:
   ImeMenuLabel() {}
@@ -408,18 +416,13 @@
                                        ImeListView::SHOW_SINGLE_IME);
   bubble_view->AddChildView(ime_list_view_);
 
-  // The bottom view that contains buttons are not supported in login/lock
-  // screen.
-  if (!IsInLoginOrLockScreen()) {
-    if (ShouldShowEmojiHandwritingVoiceButtons()) {
-      bubble_view->AddChildView(
-          new ImeButtonsView(this, true, true, true, true));
-    } else if (!MaterialDesignController::IsSystemTrayMenuMaterial()) {
-      // For MD, we don't need |ImeButtonsView| as the settings button will be
-      // shown in the title row.
-      bubble_view->AddChildView(
-          new ImeButtonsView(this, false, false, false, true));
-    }
+  if (ShouldShowEmojiHandwritingVoiceButtons()) {
+    bubble_view->AddChildView(new ImeButtonsView(this, true, true, true, true));
+  } else if (!MaterialDesignController::IsSystemTrayMenuMaterial()) {
+    // For MD, we don't need |ImeButtonsView| as the settings button will be
+    // shown in the title row.
+    bubble_view->AddChildView(
+        new ImeButtonsView(this, false, false, false, true));
   }
 
   bubble_.reset(new TrayBubbleWrapper(this, bubble_view));
@@ -484,9 +487,15 @@
 }
 
 bool ImeMenuTray::ShouldShowEmojiHandwritingVoiceButtons() const {
+  // Emoji, handwriting and voice input is not supported for these cases:
+  // 1) features::kEHVInputOnImeMenu is not enabled.
+  // 2) third party IME extensions.
+  // 3) login/lock screen.
+  // 4) password input client.
   return InputMethodManager::Get() &&
          InputMethodManager::Get()->IsEmojiHandwritingVoiceOnImeMenuEnabled() &&
-         !current_ime_.third_party;
+         !current_ime_.third_party && !IsInLoginOrLockScreen() &&
+         !IsInPasswordInputContext();
 }
 
 bool ImeMenuTray::ShouldShowKeyboardToggle() const {
diff --git a/ash/common/system/chromeos/ime_menu/ime_menu_tray_unittest.cc b/ash/common/system/chromeos/ime_menu/ime_menu_tray_unittest.cc
index 1ca9a879..bc8d7da4 100644
--- a/ash/common/system/chromeos/ime_menu/ime_menu_tray_unittest.cc
+++ b/ash/common/system/chromeos/ime_menu/ime_menu_tray_unittest.cc
@@ -16,6 +16,10 @@
 #include "ash/test/status_area_widget_test_helper.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/accessibility/ax_node_data.h"
+#include "ui/base/ime/chromeos/input_method_manager.h"
+#include "ui/base/ime/chromeos/mock_input_method_manager.h"
+#include "ui/base/ime/ime_bridge.h"
+#include "ui/base/ime/text_input_flags.h"
 #include "ui/events/event.h"
 #include "ui/views/controls/label.h"
 
@@ -76,6 +80,13 @@
     return true;
   }
 
+  // Focuses in the given type of input context.
+  void FocusInInputContext(ui::TextInputType input_type) {
+    ui::IMEEngineHandlerInterface::InputContext input_context(
+        input_type, ui::TEXT_INPUT_MODE_DEFAULT, ui::TEXT_INPUT_FLAG_NONE);
+    ui::IMEBridge::Get()->SetCurrentInputContext(input_context);
+  }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(ImeMenuTrayTest);
 };
@@ -281,4 +292,22 @@
   EXPECT_FALSE(accessibility_delegate->IsVirtualKeyboardEnabled());
 }
 
+TEST_F(ImeMenuTrayTest, ShowEmojiHandwritingVoiceButtons) {
+  FocusInInputContext(ui::TEXT_INPUT_TYPE_TEXT);
+  EXPECT_FALSE(GetTray()->ShouldShowEmojiHandwritingVoiceButtons());
+
+  chromeos::input_method::InputMethodManager* input_method_manager =
+      chromeos::input_method::InputMethodManager::Get();
+  EXPECT_FALSE(input_method_manager);
+  chromeos::input_method::InputMethodManager::Initialize(
+      new chromeos::input_method::MockInputMethodManager);
+  input_method_manager = chromeos::input_method::InputMethodManager::Get();
+  EXPECT_TRUE(input_method_manager &&
+              input_method_manager->IsEmojiHandwritingVoiceOnImeMenuEnabled());
+  EXPECT_TRUE(GetTray()->ShouldShowEmojiHandwritingVoiceButtons());
+
+  FocusInInputContext(ui::TEXT_INPUT_TYPE_PASSWORD);
+  EXPECT_FALSE(GetTray()->ShouldShowEmojiHandwritingVoiceButtons());
+}
+
 }  // namespace ash
diff --git a/ash/common/system/chromeos/session/logout_button_tray.cc b/ash/common/system/chromeos/session/logout_button_tray.cc
index e3cfc2e..d86f6aa 100644
--- a/ash/common/system/chromeos/session/logout_button_tray.cc
+++ b/ash/common/system/chromeos/session/logout_button_tray.cc
@@ -17,6 +17,7 @@
 #include "ash/common/system/user/login_status.h"
 #include "ash/common/wm_shell.h"
 #include "ash/public/cpp/shelf_types.h"
+#include "ash/resources/vector_icons/vector_icons.h"
 #include "base/logging.h"
 #include "grit/ash_resources.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -25,7 +26,6 @@
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/paint_vector_icon.h"
-#include "ui/gfx/vector_icons_public.h"
 #include "ui/views/bubble/tray_bubble_view.h"
 #include "ui/views/controls/button/label_button.h"
 #include "ui/views/controls/button/label_button_border.h"
@@ -116,6 +116,10 @@
     // crbug.com/623987
     button->AdjustFontSize(2);
     button_ = button;
+
+    // Since |logout_button_tray| has a red background and it is distinguished
+    // by itself, no separator is needed on its right side.
+    set_separator_visibility(false);
   } else {
     button_ = new LogoutButton(this);
   }
@@ -197,9 +201,8 @@
   } else {
     button_->SetText(base::string16());
     button_->SetAccessibleName(title);
-    button_->SetImage(
-        views::LabelButton::STATE_NORMAL,
-        gfx::CreateVectorIcon(gfx::VectorIconId::SHELF_LOGOUT, kTrayIconColor));
+    button_->SetImage(views::LabelButton::STATE_NORMAL,
+                      gfx::CreateVectorIcon(kShelfLogoutIcon, kTrayIconColor));
     button_->SetMinSize(gfx::Size(button_size, button_size));
   }
   UpdateVisibility();
diff --git a/ash/common/system/chromeos/virtual_keyboard/virtual_keyboard_tray.cc b/ash/common/system/chromeos/virtual_keyboard/virtual_keyboard_tray.cc
index eb88267..c75781c 100644
--- a/ash/common/system/chromeos/virtual_keyboard/virtual_keyboard_tray.cc
+++ b/ash/common/system/chromeos/virtual_keyboard/virtual_keyboard_tray.cc
@@ -15,6 +15,7 @@
 #include "ash/common/system/tray/tray_utils.h"
 #include "ash/common/wm_shell.h"
 #include "ash/common/wm_window.h"
+#include "ash/resources/vector_icons/vector_icons.h"
 #include "grit/ash_resources.h"
 #include "grit/ash_strings.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -23,7 +24,6 @@
 #include "ui/events/event.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/paint_vector_icon.h"
-#include "ui/gfx/vector_icons_public.h"
 #include "ui/keyboard/keyboard_controller.h"
 #include "ui/views/controls/image_view.h"
 
@@ -37,7 +37,7 @@
     SetInkDropMode(InkDropMode::ON);
     SetContentsBackground(false);
     gfx::ImageSkia image_md =
-        CreateVectorIcon(gfx::VectorIconId::SHELF_KEYBOARD, kShelfIconColor);
+        CreateVectorIcon(kShelfKeyboardIcon, kShelfIconColor);
     icon_->SetImage(image_md);
   } else {
     SetContentsBackground(true);
diff --git a/ash/common/system/overview/overview_button_tray.cc b/ash/common/system/overview/overview_button_tray.cc
index badd42c..4bd5aad 100644
--- a/ash/common/system/overview/overview_button_tray.cc
+++ b/ash/common/system/overview/overview_button_tray.cc
@@ -15,12 +15,12 @@
 #include "ash/common/wm/overview/window_selector_controller.h"
 #include "ash/common/wm_shell.h"
 #include "ash/public/cpp/shelf_types.h"
+#include "ash/resources/vector_icons/vector_icons.h"
 #include "grit/ash_resources.h"
 #include "grit/ash_strings.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/paint_vector_icon.h"
-#include "ui/gfx/vector_icons_public.h"
 #include "ui/views/border.h"
 #include "ui/views/controls/image_view.h"
 
@@ -44,7 +44,7 @@
     SetInkDropMode(InkDropMode::ON);
     SetContentsBackground(false);
     gfx::ImageSkia image_md =
-        CreateVectorIcon(gfx::VectorIconId::SHELF_OVERVIEW, kShelfIconColor);
+        CreateVectorIcon(kShelfOverviewIcon, kShelfIconColor);
     icon_->SetImage(image_md);
   } else {
     SetContentsBackground(true);
diff --git a/ash/common/system/tray/system_tray.cc b/ash/common/system/tray/system_tray.cc
index 2760977..12e20f3a 100644
--- a/ash/common/system/tray/system_tray.cc
+++ b/ash/common/system/tray/system_tray.cc
@@ -221,6 +221,10 @@
   if (MaterialDesignController::IsShelfMaterial()) {
     SetInkDropMode(InkDropMode::ON);
     SetContentsBackground(false);
+
+    // Since |system_tray| locates on the right most position, no separator is
+    // required on its right side.
+    set_separator_visibility(false);
   } else {
     SetContentsBackground(true);
   }
diff --git a/ash/common/system/tray/tray_background_view.cc b/ash/common/system/tray/tray_background_view.cc
index 3da2d1b..4fdc3dcf 100644
--- a/ash/common/system/tray/tray_background_view.cc
+++ b/ash/common/system/tray/tray_background_view.cc
@@ -291,6 +291,7 @@
       shelf_alignment_(SHELF_ALIGNMENT_BOTTOM),
       background_(NULL),
       is_active_(false),
+      separator_visible_(true),
       widget_observer_(new TrayWidgetObserver(this)) {
   DCHECK(wm_shelf_);
   set_notify_enter_exit_on_child(true);
@@ -581,7 +582,8 @@
   ActionableView::OnPaint(canvas);
   if (!MaterialDesignController::IsShelfMaterial() ||
       shelf()->GetBackgroundType() ==
-          ShelfBackgroundType::SHELF_BACKGROUND_DEFAULT) {
+          ShelfBackgroundType::SHELF_BACKGROUND_DEFAULT ||
+      !separator_visible_) {
     return;
   }
   //  In the given |canvas|, for a horizontal shelf draw a separator line to the
diff --git a/ash/common/system/tray/tray_background_view.h b/ash/common/system/tray/tray_background_view.h
index 4788f23..ad991328 100644
--- a/ash/common/system/tray/tray_background_view.h
+++ b/ash/common/system/tray/tray_background_view.h
@@ -128,6 +128,9 @@
   // ShelfBackgroundAnimatorObserver:
   void UpdateShelfItemBackground(int alpha) override;
 
+  // Updates the visibility of this tray's separator.
+  void set_separator_visibility(bool visible) { separator_visible_ = visible; }
+
   // Gets the anchor for bubbles, which is tray_container().
   views::View* GetBubbleAnchor() const;
 
@@ -179,6 +182,10 @@
   // in non-MD version and how the ink drop ripples behave in MD version.
   bool is_active_;
 
+  // Visibility of this tray's separator which is a line of 1x32px and 4px to
+  // right of tray.
+  bool separator_visible_;
+
   std::unique_ptr<TrayWidgetObserver> widget_observer_;
   std::unique_ptr<TrayEventFilter> tray_event_filter_;
 
diff --git a/ash/common/system/tray/tray_popup_header_button.cc b/ash/common/system/tray/tray_popup_header_button.cc
index 804fcb8..576ec92e 100644
--- a/ash/common/system/tray/tray_popup_header_button.cc
+++ b/ash/common/system/tray/tray_popup_header_button.cc
@@ -44,7 +44,7 @@
   SetToggledImage(views::Button::STATE_NORMAL,
                   bundle.GetImageNamed(disabled_resource_id).ToImageSkia());
   SetImage(views::Button::STATE_HOVERED,
-           bundle.GetImageNamed(enabled_resource_id_hover).ToImageSkia());
+           *bundle.GetImageNamed(enabled_resource_id_hover).ToImageSkia());
   SetToggledImage(
       views::Button::STATE_HOVERED,
       bundle.GetImageNamed(disabled_resource_id_hover).ToImageSkia());
@@ -74,7 +74,7 @@
 void TrayPopupHeaderButton::Initialize(const gfx::ImageSkia& icon,
                                        int accessible_name_id) {
   ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
-  SetImage(views::Button::STATE_NORMAL, &icon);
+  SetImage(views::Button::STATE_NORMAL, icon);
   SetImageAlignment(views::ImageButton::ALIGN_CENTER,
                     views::ImageButton::ALIGN_MIDDLE);
   SetAccessibleName(bundle.GetLocalizedString(accessible_name_id));
diff --git a/ash/common/test/test_session_state_delegate.cc b/ash/common/test/test_session_state_delegate.cc
index 9132b8ce..28b60f3 100644
--- a/ash/common/test/test_session_state_delegate.cc
+++ b/ash/common/test/test_session_state_delegate.cc
@@ -161,9 +161,12 @@
 }
 
 void TestSessionStateDelegate::SetHasActiveUser(bool has_active_user) {
-  session_state_ = has_active_user
-                       ? session_manager::SessionState::ACTIVE
-                       : session_manager::SessionState::LOGIN_PRIMARY;
+  if (!has_active_user) {
+    session_state_ = session_manager::SessionState::LOGIN_PRIMARY;
+  } else {
+    session_state_ = session_manager::SessionState::ACTIVE;
+    WmShell::Get()->ShowShelf();
+  }
 }
 
 void TestSessionStateDelegate::SetActiveUserSessionStarted(
diff --git a/ash/common/wm/overview/window_selector_item.cc b/ash/common/wm/overview/window_selector_item.cc
index 182beb5..647b739 100644
--- a/ash/common/wm/overview/window_selector_item.cc
+++ b/ash/common/wm/overview/window_selector_item.cc
@@ -23,6 +23,7 @@
 #include "ash/common/wm_window.h"
 #include "ash/common/wm_window_property.h"
 #include "ash/public/cpp/shell_window_ids.h"
+#include "ash/resources/vector_icons/vector_icons.h"
 #include "base/auto_reset.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -37,7 +38,6 @@
 #include "ui/gfx/geometry/safe_integer_conversions.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/gfx/transform_util.h"
-#include "ui/gfx/vector_icons_public.h"
 #include "ui/strings/grit/ui_strings.h"
 #include "ui/views/background.h"
 #include "ui/views/border.h"
@@ -130,9 +130,8 @@
 WindowSelectorItem::OverviewCloseButton::OverviewCloseButton(
     views::ButtonListener* listener)
     : views::ImageButton(listener) {
-  icon_image_ = gfx::CreateVectorIcon(gfx::VectorIconId::WINDOW_CONTROL_CLOSE,
-                                      kCloseButtonColor);
-  SetImage(views::CustomButton::STATE_NORMAL, &icon_image_);
+  SetImage(views::CustomButton::STATE_NORMAL,
+           gfx::CreateVectorIcon(kWindowControlCloseIcon, kCloseButtonColor));
   SetImageAlignment(views::ImageButton::ALIGN_CENTER,
                     views::ImageButton::ALIGN_MIDDLE);
   SetMinimumImageSize(gfx::Size(kHeaderHeight, kHeaderHeight));
diff --git a/ash/common/wm/overview/window_selector_item.h b/ash/common/wm/overview/window_selector_item.h
index f2ff9df..65b4293 100644
--- a/ash/common/wm/overview/window_selector_item.h
+++ b/ash/common/wm/overview/window_selector_item.h
@@ -75,8 +75,6 @@
     void ResetListener() { listener_ = nullptr; }
 
    private:
-    gfx::ImageSkia icon_image_;
-
     DISALLOW_COPY_AND_ASSIGN(OverviewCloseButton);
   };
 
diff --git a/ash/common/wm_root_window_controller.cc b/ash/common/wm_root_window_controller.cc
index c3207c1..9063e95 100644
--- a/ash/common/wm_root_window_controller.cc
+++ b/ash/common/wm_root_window_controller.cc
@@ -221,6 +221,15 @@
   shelf->shelf_widget()->PostCreateShelf();
 }
 
+void WmRootWindowController::ShowShelf() {
+  WmShelf* shelf = GetShelf();
+  if (!shelf->IsShelfInitialized())
+    return;
+  // TODO(jamescook): Move this into WmShelf.
+  shelf->shelf_widget()->SetShelfVisibility(true);
+  shelf->shelf_widget()->status_area_widget()->Show();
+}
+
 SystemTray* WmRootWindowController::GetSystemTray() {
   ShelfWidget* shelf_widget = GetShelf()->shelf_widget();
   if (!shelf_widget || !shelf_widget->status_area_widget())
diff --git a/ash/common/wm_root_window_controller.h b/ash/common/wm_root_window_controller.h
index b61bbfa..6ac288a 100644
--- a/ash/common/wm_root_window_controller.h
+++ b/ash/common/wm_root_window_controller.h
@@ -34,7 +34,6 @@
 class SystemTray;
 class WallpaperWidgetController;
 class WmShelf;
-class WmShell;
 class WmWindow;
 class WorkspaceController;
 
@@ -93,13 +92,15 @@
 
   virtual bool HasShelf() = 0;
 
-  virtual WmShell* GetShell() = 0;
-
   virtual WmShelf* GetShelf() = 0;
 
   // Creates the shelf for this root window and notifies observers.
   void CreateShelf();
 
+  // Show shelf view if it was created hidden (before session has started).
+  // TODO(jamescook): Eliminate this and handle show via Shelf.
+  void ShowShelf();
+
   // Returns the system tray controller. May be null for external displays.
   SystemTray* GetSystemTray();
 
diff --git a/ash/common/wm_shell.cc b/ash/common/wm_shell.cc
index 5635d75..f86da79 100644
--- a/ash/common/wm_shell.cc
+++ b/ash/common/wm_shell.cc
@@ -153,6 +153,11 @@
     root_window->GetRootWindowController()->CreateShelf();
 }
 
+void WmShell::ShowShelf() {
+  for (WmWindow* root_window : GetAllRootWindows())
+    root_window->GetRootWindowController()->ShowShelf();
+}
+
 void WmShell::CreateShelfDelegate() {
   // May be called multiple times as shelves are created and destroyed.
   if (shelf_delegate_)
@@ -269,7 +274,6 @@
       window_cycle_controller_(base::MakeUnique<WindowCycleController>()),
       window_selector_controller_(
           base::MakeUnique<WindowSelectorController>()) {
-  session_controller_->AddSessionStateObserver(this);
 
   prefs::mojom::PreferencesManagerPtr pref_manager_ptr;
   // Can be null in tests.
@@ -280,9 +284,7 @@
   pref_store_ = new preferences::PrefObserverStore(std::move(pref_manager_ptr));
 }
 
-WmShell::~WmShell() {
-  session_controller_->RemoveSessionStateObserver(this);
-}
+WmShell::~WmShell() {}
 
 WmRootWindowController* WmShell::GetPrimaryRootWindowController() {
   return GetPrimaryRootWindow()->GetRootWindowController();
@@ -416,11 +418,4 @@
   accelerator_controller_ = std::move(accelerator_controller);
 }
 
-void WmShell::SessionStateChanged(session_manager::SessionState state) {
-  // Create the shelf when a session becomes active. It's safe to do this
-  // multiple times (e.g. initial login vs. multiprofile add session).
-  if (state == session_manager::SessionState::ACTIVE)
-    CreateShelf();
-}
-
 }  // namespace ash
diff --git a/ash/common/wm_shell.h b/ash/common/wm_shell.h
index 46e28b5..7073651 100644
--- a/ash/common/wm_shell.h
+++ b/ash/common/wm_shell.h
@@ -13,7 +13,6 @@
 #include "ash/ash_export.h"
 #include "ash/common/metrics/gesture_action_type.h"
 #include "ash/common/metrics/user_metrics_action.h"
-#include "ash/common/session/session_state_observer.h"
 #include "ash/common/wm/lock_state_observer.h"
 #include "base/observer_list.h"
 #include "components/ui_devtools/devtools_server.h"
@@ -102,7 +101,7 @@
 }
 
 // Similar to ash::Shell. Eventually the two will be merged.
-class ASH_EXPORT WmShell : public SessionStateObserver {
+class ASH_EXPORT WmShell {
  public:
   // This is necessary for a handful of places that is difficult to plumb
   // through context.
@@ -357,6 +356,9 @@
   // Initializes the appropriate shelves. Does nothing for any existing shelves.
   void CreateShelf();
 
+  // Show shelf view if it was created hidden (before session has started).
+  void ShowShelf();
+
   void CreateShelfDelegate();
 
   // Called after maximize mode has started, windows might still animate though.
@@ -445,7 +447,7 @@
 
  protected:
   explicit WmShell(std::unique_ptr<ShellDelegate> shell_delegate);
-  ~WmShell() override;
+  virtual ~WmShell();
 
   base::ObserverList<ShellObserver>* shell_observers() {
     return &shell_observers_;
@@ -473,9 +475,6 @@
   void SetAcceleratorController(
       std::unique_ptr<AcceleratorController> accelerator_controller);
 
-  // SessionStateObserver:
-  void SessionStateChanged(session_manager::SessionState state) override;
-
  private:
   friend class AcceleratorControllerTest;
   friend class ScopedRootWindowForNewWindows;
diff --git a/ash/display/display_configuration_controller.cc b/ash/display/display_configuration_controller.cc
index 7f9302a..1645345 100644
--- a/ash/display/display_configuration_controller.cc
+++ b/ash/display/display_configuration_controller.cc
@@ -13,7 +13,7 @@
 
 #if defined(OS_CHROMEOS)
 #include "ash/display/display_animator_chromeos.h"
-#include "base/sys_info.h"
+#include "chromeos/system/devicemode.h"
 #include "grit/ash_strings.h"
 #include "ui/base/l10n/l10n_util.h"
 #endif
@@ -59,7 +59,7 @@
       weak_ptr_factory_(this) {
   window_tree_host_manager_->AddObserver(this);
 #if defined(OS_CHROMEOS)
-  if (base::SysInfo::IsRunningOnChromeOS())
+  if (chromeos::IsRunningAsSystemCompositor())
     limiter_.reset(new DisplayChangeLimiter);
   display_animator_.reset(new DisplayAnimatorChromeOS());
 #endif
diff --git a/ash/frame/caption_buttons/frame_size_button_unittest.cc b/ash/frame/caption_buttons/frame_size_button_unittest.cc
index 0de43d49..a14c83d6 100644
--- a/ash/frame/caption_buttons/frame_size_button_unittest.cc
+++ b/ash/frame/caption_buttons/frame_size_button_unittest.cc
@@ -8,6 +8,7 @@
 #include "ash/common/frame/caption_buttons/frame_caption_button.h"
 #include "ash/common/frame/caption_buttons/frame_caption_button_container_view.h"
 #include "ash/common/wm/window_state.h"
+#include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
 #include "ash/wm/window_state_aura.h"
@@ -18,7 +19,6 @@
 #include "ui/display/screen.h"
 #include "ui/events/gesture_detection/gesture_configuration.h"
 #include "ui/events/test/event_generator.h"
-#include "ui/gfx/vector_icons_public.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_delegate.h"
 
@@ -65,8 +65,7 @@
           GetAshLayoutSize(AshLayoutSize::NON_BROWSER_CAPTION_BUTTON));
       for (int icon = 0; icon < CAPTION_BUTTON_ICON_COUNT; ++icon) {
         caption_button_container_->SetButtonImage(
-            static_cast<CaptionButtonIcon>(icon),
-            gfx::VectorIconId::WINDOW_CONTROL_CLOSE);
+            static_cast<CaptionButtonIcon>(icon), kWindowControlCloseIcon);
       }
 
       AddChildView(caption_button_container_);
diff --git a/ash/mus/bridge/wm_root_window_controller_mus.cc b/ash/mus/bridge/wm_root_window_controller_mus.cc
index 6e6faed2..a5a3279a 100644
--- a/ash/mus/bridge/wm_root_window_controller_mus.cc
+++ b/ash/mus/bridge/wm_root_window_controller_mus.cc
@@ -73,10 +73,6 @@
   return GetShelf() != nullptr;
 }
 
-WmShell* WmRootWindowControllerMus::GetShell() {
-  return shell_;
-}
-
 WmShelf* WmRootWindowControllerMus::GetShelf() {
   return root_window_controller_->wm_shelf();
 }
diff --git a/ash/mus/bridge/wm_root_window_controller_mus.h b/ash/mus/bridge/wm_root_window_controller_mus.h
index 3cd66a04..8d0b64ee 100644
--- a/ash/mus/bridge/wm_root_window_controller_mus.h
+++ b/ash/mus/bridge/wm_root_window_controller_mus.h
@@ -51,7 +51,6 @@
 
   // WmRootWindowController:
   bool HasShelf() override;
-  WmShell* GetShell() override;
   WmShelf* GetShelf() override;
   WmWindow* GetWindow() override;
 
diff --git a/ash/mus/root_window_controller.cc b/ash/mus/root_window_controller.cc
index cbc62d6..337cf849 100644
--- a/ash/mus/root_window_controller.cc
+++ b/ash/mus/root_window_controller.cc
@@ -135,7 +135,6 @@
       window_type == ui::mojom::WindowType::WINDOW ||
       window_type == ui::mojom::WindowType::PANEL;
   if (provide_non_client_frame) {
-    (*properties)[ui::mojom::kWaitForUnderlay_Property].clear();
     // See NonClientFrameController for details on lifetime.
     NonClientFrameController* non_client_frame_controller =
         new NonClientFrameController(container_window, context, bounds,
diff --git a/ash/mus/test/ash_test_impl_mus.cc b/ash/mus/test/ash_test_impl_mus.cc
index 043a4ed..0f85cb7 100644
--- a/ash/mus/test/ash_test_impl_mus.cc
+++ b/ash/mus/test/ash_test_impl_mus.cc
@@ -4,12 +4,8 @@
 
 #include "ash/mus/test/ash_test_impl_mus.h"
 
-#include "ash/common/session/session_controller.h"
 #include "ash/common/test/ash_test.h"
-#include "ash/common/wm_shell.h"
 #include "ash/mus/bridge/wm_window_mus.h"
-#include "ash/public/cpp/session_types.h"
-#include "ash/public/interfaces/session_controller.mojom.h"
 #include "base/memory/ptr_util.h"
 #include "services/ui/public/cpp/property_type_converters.h"
 #include "services/ui/public/interfaces/window_manager.mojom.h"
@@ -44,9 +40,6 @@
 
 void AshTestImplMus::SetUp() {
   wm_test_base_->SetUp();
-
-  // Most tests assume the user is logged in (and hence the shelf is created).
-  SimulateUserLogin();
 }
 
 void AshTestImplMus::TearDown() {
@@ -107,29 +100,6 @@
                           WmWindowAura::GetAuraWindow(window));
 }
 
-void AshTestImplMus::SimulateUserLogin() {
-  SessionController* session_controller = WmShell::Get()->session_controller();
-
-  // Simulate the first user logging in.
-  mojom::UserSessionPtr session = mojom::UserSession::New();
-  session->session_id = 1;
-  session->type = user_manager::USER_TYPE_REGULAR;
-  const std::string email("ash.user@example.com");
-  session->serialized_account_id = AccountId::FromUserEmail(email).Serialize();
-  session->display_name = "Ash User";
-  session->display_email = email;
-  session_controller->UpdateUserSession(std::move(session));
-
-  // Simulate the user session becoming active.
-  mojom::SessionInfoPtr info = mojom::SessionInfo::New();
-  info->max_users = 10;
-  info->can_lock_screen = true;
-  info->should_lock_screen_automatically = false;
-  info->add_user_session_policy = AddUserSessionPolicy::ALLOWED;
-  info->state = session_manager::SessionState::ACTIVE;
-  session_controller->SetSessionInfo(std::move(info));
-}
-
 }  // namespace mus
 
 // static
diff --git a/ash/mus/test/ash_test_impl_mus.h b/ash/mus/test/ash_test_impl_mus.h
index 1f6c9c1f..1f62ab3 100644
--- a/ash/mus/test/ash_test_impl_mus.h
+++ b/ash/mus/test/ash_test_impl_mus.h
@@ -42,10 +42,6 @@
   void AddTransientChild(WmWindow* parent, WmWindow* window) override;
 
  private:
-  // Simulates the first user logging in and the session becoming active.
-  // Classic ash handles this via AshTestHelper and TestSessionStateDelegate.
-  void SimulateUserLogin();
-
   // TODO(sky): fold WmTestBase directly into this class when no more subclasses
   // of WmTestBase.
   std::unique_ptr<WmTestBase> wm_test_base_;
diff --git a/ash/mus/window_manager.cc b/ash/mus/window_manager.cc
index f3ebdc9..59464880 100644
--- a/ash/mus/window_manager.cc
+++ b/ash/mus/window_manager.cc
@@ -8,7 +8,6 @@
 
 #include <utility>
 
-#include "ash/common/session/session_controller.h"
 #include "ash/common/wm/container_finder.h"
 #include "ash/common/wm/window_state.h"
 #include "ash/display/screen_position_controller.h"
@@ -135,6 +134,9 @@
                               this, pointer_watcher_event_router_.get()));
   shell_->Initialize(blocking_pool);
   lookup_.reset(new WmLookupMus);
+
+  // TODO: this should be called when logged in. See http://crbug.com/654606.
+  shell_->CreateShelf();
 }
 
 aura::client::ActivationClient* WindowManager::activation_client() {
@@ -220,9 +222,8 @@
       root_window_controller_ptr.get();
   root_window_controllers_.insert(std::move(root_window_controller_ptr));
 
-  // Create a shelf if a user is already logged in.
-  if (shell_->session_controller()->NumberOfLoggedInUsers())
-    root_window_controller->wm_root_window_controller()->CreateShelf();
+  // TODO: this should be called when logged in. See http://crbug.com/654606.
+  root_window_controller->wm_root_window_controller()->CreateShelf();
 
   for (auto& observer : observers_)
     observer.OnRootWindowControllerAdded(root_window_controller);
diff --git a/ash/resources/vector_icons/BUILD.gn b/ash/resources/vector_icons/BUILD.gn
index 6531c789..14b065bb 100644
--- a/ash/resources/vector_icons/BUILD.gn
+++ b/ash/resources/vector_icons/BUILD.gn
@@ -71,8 +71,16 @@
     "palette_tray_icon_laser_pointer.icon",
     "palette_tray_icon_magnify.1x.icon",
     "palette_tray_icon_magnify.icon",
+    "shelf_keyboard.1x.icon",
+    "shelf_keyboard.icon",
+    "shelf_logout.1x.icon",
+    "shelf_logout.icon",
     "shelf_notifications.1x.icon",
     "shelf_notifications.icon",
+    "shelf_overflow.1x.icon",
+    "shelf_overflow.icon",
+    "shelf_overview.1x.icon",
+    "shelf_overview.icon",
     "system_menu_accessibility.1x.icon",
     "system_menu_accessibility.icon",
     "system_menu_accessibility_auto_click.1x.icon",
@@ -198,6 +206,20 @@
     "system_tray_update.icon",
     "system_tray_volume_mute.1x.icon",
     "system_tray_volume_mute.icon",
+    "window_control_back.1x.icon",
+    "window_control_back.icon",
+    "window_control_close.1x.icon",
+    "window_control_close.icon",
+    "window_control_left_snapped.1x.icon",
+    "window_control_left_snapped.icon",
+    "window_control_maximize.1x.icon",
+    "window_control_maximize.icon",
+    "window_control_minimize.1x.icon",
+    "window_control_minimize.icon",
+    "window_control_restore.1x.icon",
+    "window_control_restore.icon",
+    "window_control_right_snapped.1x.icon",
+    "window_control_right_snapped.icon",
   ]
 
   output_cc = "$target_gen_dir/vector_icons.cc"
diff --git a/ui/gfx/vector_icons/shelf_keyboard.1x.icon b/ash/resources/vector_icons/shelf_keyboard.1x.icon
similarity index 100%
rename from ui/gfx/vector_icons/shelf_keyboard.1x.icon
rename to ash/resources/vector_icons/shelf_keyboard.1x.icon
diff --git a/ui/gfx/vector_icons/shelf_keyboard.icon b/ash/resources/vector_icons/shelf_keyboard.icon
similarity index 100%
rename from ui/gfx/vector_icons/shelf_keyboard.icon
rename to ash/resources/vector_icons/shelf_keyboard.icon
diff --git a/ui/gfx/vector_icons/shelf_logout.1x.icon b/ash/resources/vector_icons/shelf_logout.1x.icon
similarity index 100%
rename from ui/gfx/vector_icons/shelf_logout.1x.icon
rename to ash/resources/vector_icons/shelf_logout.1x.icon
diff --git a/ui/gfx/vector_icons/shelf_logout.icon b/ash/resources/vector_icons/shelf_logout.icon
similarity index 100%
rename from ui/gfx/vector_icons/shelf_logout.icon
rename to ash/resources/vector_icons/shelf_logout.icon
diff --git a/ui/gfx/vector_icons/shelf_overflow.1x.icon b/ash/resources/vector_icons/shelf_overflow.1x.icon
similarity index 100%
rename from ui/gfx/vector_icons/shelf_overflow.1x.icon
rename to ash/resources/vector_icons/shelf_overflow.1x.icon
diff --git a/ui/gfx/vector_icons/shelf_overflow.icon b/ash/resources/vector_icons/shelf_overflow.icon
similarity index 100%
rename from ui/gfx/vector_icons/shelf_overflow.icon
rename to ash/resources/vector_icons/shelf_overflow.icon
diff --git a/ui/gfx/vector_icons/shelf_overview.1x.icon b/ash/resources/vector_icons/shelf_overview.1x.icon
similarity index 100%
rename from ui/gfx/vector_icons/shelf_overview.1x.icon
rename to ash/resources/vector_icons/shelf_overview.1x.icon
diff --git a/ui/gfx/vector_icons/shelf_overview.icon b/ash/resources/vector_icons/shelf_overview.icon
similarity index 100%
rename from ui/gfx/vector_icons/shelf_overview.icon
rename to ash/resources/vector_icons/shelf_overview.icon
diff --git a/ui/gfx/vector_icons/window_control_back.1x.icon b/ash/resources/vector_icons/window_control_back.1x.icon
similarity index 100%
rename from ui/gfx/vector_icons/window_control_back.1x.icon
rename to ash/resources/vector_icons/window_control_back.1x.icon
diff --git a/ui/gfx/vector_icons/window_control_back.icon b/ash/resources/vector_icons/window_control_back.icon
similarity index 100%
rename from ui/gfx/vector_icons/window_control_back.icon
rename to ash/resources/vector_icons/window_control_back.icon
diff --git a/ui/gfx/vector_icons/window_control_close.1x.icon b/ash/resources/vector_icons/window_control_close.1x.icon
similarity index 100%
rename from ui/gfx/vector_icons/window_control_close.1x.icon
rename to ash/resources/vector_icons/window_control_close.1x.icon
diff --git a/ui/gfx/vector_icons/window_control_close.icon b/ash/resources/vector_icons/window_control_close.icon
similarity index 100%
rename from ui/gfx/vector_icons/window_control_close.icon
rename to ash/resources/vector_icons/window_control_close.icon
diff --git a/ui/gfx/vector_icons/window_control_left_snapped.1x.icon b/ash/resources/vector_icons/window_control_left_snapped.1x.icon
similarity index 100%
rename from ui/gfx/vector_icons/window_control_left_snapped.1x.icon
rename to ash/resources/vector_icons/window_control_left_snapped.1x.icon
diff --git a/ui/gfx/vector_icons/window_control_left_snapped.icon b/ash/resources/vector_icons/window_control_left_snapped.icon
similarity index 100%
rename from ui/gfx/vector_icons/window_control_left_snapped.icon
rename to ash/resources/vector_icons/window_control_left_snapped.icon
diff --git a/ui/gfx/vector_icons/window_control_maximize.1x.icon b/ash/resources/vector_icons/window_control_maximize.1x.icon
similarity index 100%
rename from ui/gfx/vector_icons/window_control_maximize.1x.icon
rename to ash/resources/vector_icons/window_control_maximize.1x.icon
diff --git a/ui/gfx/vector_icons/window_control_maximize.icon b/ash/resources/vector_icons/window_control_maximize.icon
similarity index 100%
rename from ui/gfx/vector_icons/window_control_maximize.icon
rename to ash/resources/vector_icons/window_control_maximize.icon
diff --git a/ui/gfx/vector_icons/window_control_minimize.1x.icon b/ash/resources/vector_icons/window_control_minimize.1x.icon
similarity index 100%
rename from ui/gfx/vector_icons/window_control_minimize.1x.icon
rename to ash/resources/vector_icons/window_control_minimize.1x.icon
diff --git a/ui/gfx/vector_icons/window_control_minimize.icon b/ash/resources/vector_icons/window_control_minimize.icon
similarity index 100%
rename from ui/gfx/vector_icons/window_control_minimize.icon
rename to ash/resources/vector_icons/window_control_minimize.icon
diff --git a/ui/gfx/vector_icons/window_control_restore.1x.icon b/ash/resources/vector_icons/window_control_restore.1x.icon
similarity index 100%
rename from ui/gfx/vector_icons/window_control_restore.1x.icon
rename to ash/resources/vector_icons/window_control_restore.1x.icon
diff --git a/ui/gfx/vector_icons/window_control_restore.icon b/ash/resources/vector_icons/window_control_restore.icon
similarity index 100%
rename from ui/gfx/vector_icons/window_control_restore.icon
rename to ash/resources/vector_icons/window_control_restore.icon
diff --git a/ui/gfx/vector_icons/window_control_right_snapped.1x.icon b/ash/resources/vector_icons/window_control_right_snapped.1x.icon
similarity index 100%
rename from ui/gfx/vector_icons/window_control_right_snapped.1x.icon
rename to ash/resources/vector_icons/window_control_right_snapped.1x.icon
diff --git a/ui/gfx/vector_icons/window_control_right_snapped.icon b/ash/resources/vector_icons/window_control_right_snapped.icon
similarity index 100%
rename from ui/gfx/vector_icons/window_control_right_snapped.icon
rename to ash/resources/vector_icons/window_control_right_snapped.icon
diff --git a/ash/root_window_controller_unittest.cc b/ash/root_window_controller_unittest.cc
index 48aadbd..f204b44 100644
--- a/ash/root_window_controller_unittest.cc
+++ b/ash/root_window_controller_unittest.cc
@@ -8,7 +8,6 @@
 
 #include "ash/aura/wm_window_aura.h"
 #include "ash/common/material_design/material_design_controller.h"
-#include "ash/common/session/session_controller.h"
 #include "ash/common/session/session_state_delegate.h"
 #include "ash/common/system/tray/system_tray_delegate.h"
 #include "ash/common/wm/system_modal_container_layout_manager.h"
@@ -18,7 +17,6 @@
 #include "ash/common/wm_shell.h"
 #include "ash/common/wm_window.h"
 #include "ash/public/cpp/shell_window_ids.h"
-#include "ash/public/interfaces/session_controller.mojom.h"
 #include "ash/shell.h"
 #include "ash/test/ash_md_test_base.h"
 #include "ash/test/ash_test_base.h"
@@ -977,8 +975,8 @@
   // Track the keyboard container window.
   aura::WindowTracker tracker;
   tracker.Add(keyboard_container);
-  // Reinitialize the keyboard.
-  Shell::GetInstance()->CreateKeyboard();
+  // Mock a login user profile change to reinitialize the keyboard.
+  Shell::GetInstance()->OnLoginUserProfilePrepared();
   // keyboard_container should no longer be present.
   EXPECT_FALSE(tracker.Contains(keyboard_container));
 }
@@ -1012,9 +1010,7 @@
   }
 
   // Mock a login user profile change to reinitialize the keyboard.
-  mojom::SessionInfoPtr info = mojom::SessionInfo::New();
-  info->state = session_manager::SessionState::ACTIVE;
-  WmShell::Get()->session_controller()->SetSessionInfo(std::move(info));
+  Shell::GetInstance()->OnLoginUserProfilePrepared();
   EXPECT_EQ(display::Screen::GetScreen()->GetPrimaryDisplay().work_area(),
             before);
 }
diff --git a/ash/shell.cc b/ash/shell.cc
index e451910..4c3106f4 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -100,6 +100,7 @@
 #include "chromeos/audio/audio_a11y_controller.h"
 #include "chromeos/chromeos_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/system/devicemode.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/env.h"
 #include "ui/aura/layout_manager.h"
@@ -271,6 +272,11 @@
     observer.OnLoginStateChanged(status);
 }
 
+void Shell::OnLoginUserProfilePrepared() {
+  wm_shell_->CreateShelf();
+  CreateKeyboard();
+}
+
 void Shell::OnAppTerminating() {
   for (auto& observer : *wm_shell_->shell_observers())
     observer.OnAppTerminating();
@@ -579,7 +585,7 @@
   display_configurator_->AddObserver(projecting_observer_.get());
   wm_shell_->AddShellObserver(projecting_observer_.get());
 
-  if (!display_initialized && base::SysInfo::IsRunningOnChromeOS()) {
+  if (!display_initialized && chromeos::IsRunningAsSystemCompositor()) {
     display_change_observer_ = base::MakeUnique<display::DisplayChangeObserver>(
         display_configurator_.get(), display_manager_.get());
 
diff --git a/ash/shell.h b/ash/shell.h
index c8d0c06..86d2677f 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -196,6 +196,9 @@
   // Called when the user logs in.
   void OnLoginStateChanged(LoginStatus status);
 
+  // Called after the logged-in user's profile is ready.
+  void OnLoginUserProfilePrepared();
+
   // Called when the application is exiting.
   void OnAppTerminating();
 
diff --git a/base/BUILD.gn b/base/BUILD.gn
index f7b27d2..40f5713 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -2143,10 +2143,15 @@
   }
 
   if (is_android) {
+    sources -= [
+      "process/process_unittest.cc",
+      "process/process_util_unittest.cc",
+    ]
     deps += [
       ":base_java",
       ":base_java_unittest_support",
       "//base/android/jni_generator:jni_generator_tests",
+      "//base/test:test_support_java",
     ]
   }
 
diff --git a/base/debug/proc_maps_linux_unittest.cc b/base/debug/proc_maps_linux_unittest.cc
index 2e35ca6..9b5bcaca 100644
--- a/base/debug/proc_maps_linux_unittest.cc
+++ b/base/debug/proc_maps_linux_unittest.cc
@@ -227,8 +227,12 @@
     // ignore checking for the stack and address when running under Valgrind.
     // See http://crbug.com/431702 for more details.
     if (!RunningOnValgrind() && regions[i].path == "[stack]") {
+// On Android the test is run on a background thread, since [stack] is for
+// the main thread, we cannot test this.
+#if !defined(OS_ANDROID)
       EXPECT_GE(address, regions[i].start);
       EXPECT_LT(address, regions[i].end);
+#endif
       EXPECT_TRUE(regions[i].permissions & MappedMemoryRegion::READ);
       EXPECT_TRUE(regions[i].permissions & MappedMemoryRegion::WRITE);
       EXPECT_FALSE(regions[i].permissions & MappedMemoryRegion::EXECUTE);
diff --git a/base/files/file_locking_unittest.cc b/base/files/file_locking_unittest.cc
index beb93998..b709b75 100644
--- a/base/files/file_locking_unittest.cc
+++ b/base/files/file_locking_unittest.cc
@@ -165,8 +165,8 @@
   void ExitChildCleanly() {
     ASSERT_TRUE(SignalEvent(kSignalExit));
     int rv = -1;
-    ASSERT_TRUE(lock_child_.WaitForExitWithTimeout(
-        TestTimeouts::action_timeout(), &rv));
+    ASSERT_TRUE(WaitForMultiprocessTestChildExit(
+        lock_child_, TestTimeouts::action_timeout(), &rv));
     ASSERT_EQ(0, rv);
   }
 
@@ -220,7 +220,7 @@
   StartChildAndSignalLock(kExitUnlock);
 
   ASSERT_NE(File::FILE_OK, lock_file_.Lock());
-  ASSERT_TRUE(lock_child_.Terminate(0, true));
+  ASSERT_TRUE(TerminateMultiProcessTestChild(lock_child_, 0, true));
   ASSERT_EQ(File::FILE_OK, lock_file_.Lock());
   ASSERT_EQ(File::FILE_OK, lock_file_.Unlock());
 }
diff --git a/base/posix/global_descriptors.h b/base/posix/global_descriptors.h
index edb299d..30db2b7 100644
--- a/base/posix/global_descriptors.h
+++ b/base/posix/global_descriptors.h
@@ -52,18 +52,7 @@
 
   // Often we want a canonical descriptor for a given Key. In this case, we add
   // the following constant to the key value:
-#if !defined(OS_ANDROID)
   static const int kBaseDescriptor = 3;  // 0, 1, 2 are already taken.
-#else
-  // 3 used by __android_log_write().
-  // 4 used by... something important on Android M.
-  // 5 used by... something important on Android L... on low-end devices.
-  // TODO(amistry): An Android, this mechanism is only used for tests since the
-  // content child launcher spawns a process by creating a new Activity using
-  // the Android APIs. For tests, come up with a way that doesn't require using
-  // a pre-defined fd.
-  static const int kBaseDescriptor = 6;
-#endif
 
   // Return the singleton instance of GlobalDescriptors.
   static GlobalDescriptors* GetInstance();
diff --git a/base/process/process.h b/base/process/process.h
index 55384758..978ca78 100644
--- a/base/process/process.h
+++ b/base/process/process.h
@@ -108,12 +108,12 @@
   // any process.
   // NOTE: |exit_code| is optional, nullptr can be passed if the exit code is
   // not required.
-  bool WaitForExit(int* exit_code);
+  bool WaitForExit(int* exit_code) const;
 
   // Same as WaitForExit() but only waits for up to |timeout|.
   // NOTE: |exit_code| is optional, nullptr can be passed if the exit code
   // is not required.
-  bool WaitForExitWithTimeout(TimeDelta timeout, int* exit_code);
+  bool WaitForExitWithTimeout(TimeDelta timeout, int* exit_code) const;
 
 #if defined(OS_MACOSX)
   // The Mac needs a Mach port in order to manipulate a process's priority,
diff --git a/base/process/process_posix.cc b/base/process/process_posix.cc
index 20fab921..55b7ac90 100644
--- a/base/process/process_posix.cc
+++ b/base/process/process_posix.cc
@@ -350,11 +350,11 @@
 }
 #endif  // !defined(OS_NACL_NONSFI)
 
-bool Process::WaitForExit(int* exit_code) {
+bool Process::WaitForExit(int* exit_code) const {
   return WaitForExitWithTimeout(TimeDelta::Max(), exit_code);
 }
 
-bool Process::WaitForExitWithTimeout(TimeDelta timeout, int* exit_code) {
+bool Process::WaitForExitWithTimeout(TimeDelta timeout, int* exit_code) const {
   // Record the event that this thread is blocking upon (for hang diagnosis).
   base::debug::ScopedProcessWaitActivity process_activity(this);
 
diff --git a/base/process/process_util_unittest.cc b/base/process/process_util_unittest.cc
index 87fdd01..7031706 100644
--- a/base/process/process_util_unittest.cc
+++ b/base/process/process_util_unittest.cc
@@ -257,7 +257,7 @@
 }
 #endif  // defined(OS_WIN)
 
-#if !defined(OS_MACOSX)
+#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
 // This test is disabled on Mac, since it's flaky due to ReportCrash
 // taking a variable amount of time to parse and load the debug and
 // symbol data for this unit test's executable before firing the
@@ -266,23 +266,14 @@
 // TODO(gspencer): turn this test process into a very small program
 // with no symbols (instead of using the multiprocess testing
 // framework) to reduce the ReportCrash overhead.
+//
+// It is disabled on Android as MultiprocessTests are started as services that
+// the framework restarts on crashes.
 const char kSignalFileCrash[] = "CrashingChildProcess.die";
 
 MULTIPROCESS_TEST_MAIN(CrashingChildProcess) {
   WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileCrash).c_str());
-#if defined(OS_ANDROID)
-  // Android L+ expose signal and sigaction symbols that override the system
-  // ones. There is a bug in these functions where a request to set the handler
-  // to SIG_DFL is ignored. In that case, an infinite loop is entered as the
-  // signal is repeatedly sent to the crash dump signal handler.
-  // To work around this, directly call the system's sigaction.
-  struct kernel_sigaction sa;
-  memset(&sa, 0, sizeof(sa));
-  sys_sigemptyset(&sa.sa_mask);
-  sa.sa_handler_ = SIG_DFL;
-  sa.sa_flags = SA_RESTART;
-  sys_rt_sigaction(SIGSEGV, &sa, NULL, sizeof(kernel_sigset_t));
-#elif defined(OS_POSIX)
+#if defined(OS_POSIX)
   // Have to disable to signal handler for segv so we can get a crash
   // instead of an abnormal termination through the crash dump handler.
   ::signal(SIGSEGV, SIG_DFL);
@@ -331,7 +322,7 @@
   base::debug::EnableInProcessStackDumping();
   remove(signal_file.c_str());
 }
-#endif  // !defined(OS_MACOSX)
+#endif  // !defined(OS_MACOSX) && !defined(OS_ANDROID)
 
 MULTIPROCESS_TEST_MAIN(KilledChildProcess) {
   WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileKill).c_str());
diff --git a/base/process/process_win.cc b/base/process/process_win.cc
index 6629f456..afc6a786 100644
--- a/base/process/process_win.cc
+++ b/base/process/process_win.cc
@@ -137,12 +137,12 @@
   return result;
 }
 
-bool Process::WaitForExit(int* exit_code) {
+bool Process::WaitForExit(int* exit_code) const {
   return WaitForExitWithTimeout(TimeDelta::FromMilliseconds(INFINITE),
                                 exit_code);
 }
 
-bool Process::WaitForExitWithTimeout(TimeDelta timeout, int* exit_code) {
+bool Process::WaitForExitWithTimeout(TimeDelta timeout, int* exit_code) const {
   // Record the event that this thread is blocking upon (for hang diagnosis).
   base::debug::ScopedProcessWaitActivity process_activity(this);
 
diff --git a/base/test/BUILD.gn b/base/test/BUILD.gn
index 44d8c29..265ef44a 100644
--- a/base/test/BUILD.gn
+++ b/base/test/BUILD.gn
@@ -56,7 +56,9 @@
     "mock_entropy_provider.h",
     "mock_log.cc",
     "mock_log.h",
+    "multiprocess_test.cc",
     "multiprocess_test.h",
+    "multiprocess_test_android.cc",
     "null_task_runner.cc",
     "null_task_runner.h",
     "opaque_ref_counted.cc",
@@ -148,8 +150,6 @@
       "launcher/test_launcher_tracer.h",
       "launcher/test_results_tracker.cc",
       "launcher/unit_test_launcher.cc",
-      "multiprocess_test.cc",
-      "multiprocess_test_android.cc",
     ]
   }
 
@@ -193,7 +193,11 @@
   }
 
   if (is_android) {
-    deps += [ ":base_unittests_jni_headers" ]
+    deps += [
+      ":base_unittests_jni_headers",
+      ":test_support_jni_headers",
+    ]
+    public_deps += [ ":test_support_java" ]
   }
 
   if (is_nacl_nonsfi) {
@@ -329,4 +333,42 @@
     ]
     jni_package = "base"
   }
+
+  generate_jni("test_support_jni_headers") {
+    sources = [
+      "android/java/src/org/chromium/base/MainReturnCodeResult.java",
+      "android/java/src/org/chromium/base/MultiprocessTestClientLauncher.java",
+    ]
+    jni_package = "base"
+  }
+
+  android_library("test_support_java") {
+    testonly = true
+    deps = [
+      "//base:base_java",
+      "//testing/android/native_test:native_main_runner_java",
+      "//third_party/android_tools:android_support_annotations_java",
+      "//third_party/jsr-305:jsr_305_javalib",
+    ]
+    srcjar_deps = [ ":test_support_java_aidl" ]
+    java_files = [
+      "android/java/src/org/chromium/base/FileDescriptorInfo.java",
+      "android/java/src/org/chromium/base/MainReturnCodeResult.java",
+      "android/java/src/org/chromium/base/MultiprocessTestClientLauncher.java",
+      "android/java/src/org/chromium/base/MultiprocessTestClientService.java",
+      "android/java/src/org/chromium/base/MultiprocessTestClientService0.java",
+      "android/java/src/org/chromium/base/MultiprocessTestClientService1.java",
+      "android/java/src/org/chromium/base/MultiprocessTestClientService2.java",
+      "android/java/src/org/chromium/base/MultiprocessTestClientService3.java",
+      "android/java/src/org/chromium/base/MultiprocessTestClientService4.java",
+    ]
+  }
+
+  android_aidl("test_support_java_aidl") {
+    testonly = true
+    import_include = "android/java/src"
+    sources = [
+      "android/java/src/org/chromium/base/ITestClient.aidl",
+    ]
+  }
 }
diff --git a/base/test/android/java/src/org/chromium/base/FileDescriptorInfo.aidl b/base/test/android/java/src/org/chromium/base/FileDescriptorInfo.aidl
new file mode 100644
index 0000000..9bc4f960
--- /dev/null
+++ b/base/test/android/java/src/org/chromium/base/FileDescriptorInfo.aidl
@@ -0,0 +1,7 @@
+// 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.base;
+
+parcelable FileDescriptorInfo;
diff --git a/base/test/android/java/src/org/chromium/base/FileDescriptorInfo.java b/base/test/android/java/src/org/chromium/base/FileDescriptorInfo.java
new file mode 100644
index 0000000..c1c3d11
--- /dev/null
+++ b/base/test/android/java/src/org/chromium/base/FileDescriptorInfo.java
@@ -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.
+
+package org.chromium.base;
+
+import android.annotation.SuppressLint;
+import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
+import android.os.Parcelable;
+
+/**
+ * Parcelable class that contains file descriptor and a key that identifies it.
+ * TODO(jcivelli): should be merged with
+ * org.chromium.content.common.FileDescriptorInfo
+ */
+@SuppressLint("ParcelClassLoader")
+public final class FileDescriptorInfo implements Parcelable {
+    /** An consumer chosen ID that uniquely identifies a file descriptor. */
+    public final int key;
+
+    /** A file descriptor to access the file. */
+    public final ParcelFileDescriptor fd;
+
+    public FileDescriptorInfo(int key, ParcelFileDescriptor fd) {
+        this.key = key;
+        this.fd = fd;
+    }
+
+    FileDescriptorInfo(Parcel in) {
+        key = in.readInt();
+        fd = in.readParcelable(null);
+    }
+
+    @Override
+    public int describeContents() {
+        return CONTENTS_FILE_DESCRIPTOR;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(key);
+        dest.writeParcelable(fd, CONTENTS_FILE_DESCRIPTOR);
+    }
+
+    public static final Parcelable.Creator<FileDescriptorInfo> CREATOR =
+            new Parcelable.Creator<FileDescriptorInfo>() {
+                @Override
+                public FileDescriptorInfo createFromParcel(Parcel in) {
+                    return new FileDescriptorInfo(in);
+                }
+
+                @Override
+                public FileDescriptorInfo[] newArray(int size) {
+                    return new FileDescriptorInfo[size];
+                }
+            };
+}
diff --git a/base/test/android/java/src/org/chromium/base/ITestClient.aidl b/base/test/android/java/src/org/chromium/base/ITestClient.aidl
new file mode 100644
index 0000000..949d9630
--- /dev/null
+++ b/base/test/android/java/src/org/chromium/base/ITestClient.aidl
@@ -0,0 +1,45 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+import org.chromium.base.FileDescriptorInfo;
+import org.chromium.base.MainReturnCodeResult;
+
+/**
+ * This interface is used to control child processes.
+ */
+interface ITestClient {
+  /**
+   * Runs the native <code>main</code> method in that service's process.
+   * @param args the arguments passed to <code>main</code>
+   * @param fdsToMap a list of file descriptors that are mapped in the native code
+   * in <code>base::GlobalDescriptors</code>.
+   * @return the process ID for the service's process.
+   */
+  int launch(in String[] args, in FileDescriptorInfo[] fdsToMap);
+
+  /**
+   * Blocks until the <code>main</code> method started with {@link #launch()} returns, or returns
+   * immediately if main has already returned.
+   * @param timeoutMs time in milliseconds after which this method returns even if the main method
+   * has not returned yet.
+   * @return a result containing whether a timeout occured and the value returned by the
+   * <code>main</code> method
+   */
+  MainReturnCodeResult waitForMainToReturn(int timeoutMs);
+
+  /**
+   * Forces the service process to terminate and block until the process stops.
+   * @param exitCode the exit code the process should terminate with.
+   * @return always true, a return value is only returned to force the call to be synchronous.
+   */
+  boolean forceStopSynchronous(int exitCode);
+
+  /**
+   * Forces the service process to terminate.
+   * @param exitCode the exit code the process should terminate with.
+   */
+  void forceStop(int exitCode);
+}
diff --git a/base/test/android/java/src/org/chromium/base/MainReturnCodeResult.aidl b/base/test/android/java/src/org/chromium/base/MainReturnCodeResult.aidl
new file mode 100644
index 0000000..dc7501f
--- /dev/null
+++ b/base/test/android/java/src/org/chromium/base/MainReturnCodeResult.aidl
@@ -0,0 +1,7 @@
+// 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.base;
+
+parcelable MainReturnCodeResult;
diff --git a/base/test/android/java/src/org/chromium/base/MainReturnCodeResult.java b/base/test/android/java/src/org/chromium/base/MainReturnCodeResult.java
new file mode 100644
index 0000000..05a15b58
--- /dev/null
+++ b/base/test/android/java/src/org/chromium/base/MainReturnCodeResult.java
@@ -0,0 +1,64 @@
+// 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.base;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.JNINamespace;
+
+/**
+ * Contains the result of a native main method that ran in a child process.
+ */
+@JNINamespace("base::android")
+public final class MainReturnCodeResult implements Parcelable {
+    private final int mMainReturnCode;
+    private final boolean mTimedOut;
+
+    public MainReturnCodeResult(int mainReturnCode, boolean timedOut) {
+        mMainReturnCode = mainReturnCode;
+        mTimedOut = timedOut;
+    }
+
+    MainReturnCodeResult(Parcel in) {
+        mMainReturnCode = in.readInt();
+        mTimedOut = (in.readInt() != 0);
+    }
+
+    @CalledByNative
+    public int getReturnCode() {
+        return mMainReturnCode;
+    }
+
+    @CalledByNative
+    public boolean hasTimedOut() {
+        return mTimedOut;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mMainReturnCode);
+        dest.writeInt(mTimedOut ? 1 : 0);
+    }
+
+    public static final Parcelable.Creator<MainReturnCodeResult> CREATOR =
+            new Parcelable.Creator<MainReturnCodeResult>() {
+                @Override
+                public MainReturnCodeResult createFromParcel(Parcel in) {
+                    return new MainReturnCodeResult(in);
+                }
+
+                @Override
+                public MainReturnCodeResult[] newArray(int size) {
+                    return new MainReturnCodeResult[size];
+                }
+            };
+}
diff --git a/base/test/android/java/src/org/chromium/base/MultiprocessTestClientLauncher.java b/base/test/android/java/src/org/chromium/base/MultiprocessTestClientLauncher.java
new file mode 100644
index 0000000..6c1f398
--- /dev/null
+++ b/base/test/android/java/src/org/chromium/base/MultiprocessTestClientLauncher.java
@@ -0,0 +1,293 @@
+// 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.base;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.JNINamespace;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+
+import javax.annotation.concurrent.GuardedBy;
+
+/**
+ * Helper class for launching test client processes for multiprocess unit tests.
+ */
+@JNINamespace("base::android")
+public final class MultiprocessTestClientLauncher {
+    private static final String TAG = "cr_MProcTCLauncher";
+
+    private static ConnectionAllocator sConnectionAllocator = new ConnectionAllocator();
+
+    // Not supposed to be instantiated.
+    private MultiprocessTestClientLauncher() {}
+
+    private static class ConnectionAllocator {
+        // Services are identified by a slot number, which is used in the service name to
+        // differentiate them (MultiprocessTestClientService0, MultiprocessTestClientService1, ...).
+        // They are stored in a FIFO queue in order to minimize the risk of the framework reusing a
+        // service without restarting its associated process (which can cause all kind of problems
+        // with static native variables already being initialized).
+        private static final int MAX_SUBPROCESS_COUNT = 5;
+
+        private final Object mLock = new Object();
+
+        @GuardedBy("mLock")
+        private final Queue<Integer> mFreeServiceSlot = new LinkedList<>();
+        @GuardedBy("mLock")
+        private final List<ClientServiceConnection> mConnections = new ArrayList<>();
+
+        public ConnectionAllocator() {
+            synchronized (mLock) {
+                for (int i = 0; i < MAX_SUBPROCESS_COUNT; i++) {
+                    mFreeServiceSlot.add(i);
+                }
+            }
+        }
+
+        public ClientServiceConnection allocateConnection(
+                String[] commandLine, FileDescriptorInfo[] filesToMap) {
+            synchronized (mLock) {
+                while (mFreeServiceSlot.isEmpty()) {
+                    try {
+                        mLock.wait();
+                    } catch (InterruptedException ie) {
+                        Log.e(TAG, "Interrupted while waiting for a free connection.");
+                    }
+                }
+
+                int slot = mFreeServiceSlot.remove();
+                ClientServiceConnection connection =
+                        new ClientServiceConnection(slot, commandLine, filesToMap);
+                mConnections.add(connection);
+                return connection;
+            }
+        }
+
+        public void freeConnection(ClientServiceConnection connection) {
+            synchronized (mLock) {
+                mFreeServiceSlot.add(connection.getSlot());
+                mConnections.remove(connection);
+            }
+        }
+
+        public ClientServiceConnection getConnectionByPid(int pid) {
+            synchronized (mLock) {
+                // List of connections is short, iterating is OK.
+                for (ClientServiceConnection connection : mConnections) {
+                    if (connection.getPid() == pid) {
+                        return connection;
+                    }
+                }
+            }
+            return null;
+        }
+    }
+
+    private static class ClientServiceConnection implements ServiceConnection {
+        private final String[] mCommandLine;
+        private final FileDescriptorInfo[] mFilesToMap;
+        private final Object mConnectedLock = new Object();
+        private final int mSlot;
+        private ITestClient mService = null;
+        @GuardedBy("mConnectedLock")
+        private boolean mConnected;
+        private int mPid;
+
+        ClientServiceConnection(int slot, String[] commandLine, FileDescriptorInfo[] filesToMap) {
+            mSlot = slot;
+            mCommandLine = commandLine;
+            mFilesToMap = filesToMap;
+        }
+
+        public void waitForConnection() {
+            synchronized (mConnectedLock) {
+                while (!mConnected) {
+                    try {
+                        mConnectedLock.wait();
+                    } catch (InterruptedException ie) {
+                        Log.e(TAG, "Interrupted while waiting for connection.");
+                    }
+                }
+            }
+        }
+
+        @Override
+        public void onServiceConnected(ComponentName className, IBinder service) {
+            try {
+                mService = ITestClient.Stub.asInterface(service);
+                mPid = mService.launch(mCommandLine, mFilesToMap);
+                synchronized (mConnectedLock) {
+                    mConnected = true;
+                    mConnectedLock.notifyAll();
+                }
+            } catch (RemoteException e) {
+                Log.e(TAG, "Connect failed");
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName className) {
+            if (mPid == 0) {
+                Log.e(TAG, "Early ClientServiceConnection disconnection.");
+                return;
+            }
+            sConnectionAllocator.freeConnection(this);
+        }
+
+        public ITestClient getService() {
+            return mService;
+        }
+
+        public String getServiceClassName() {
+            // In order to use different processes, we have to declare multiple services in the
+            // AndroidManifest.xml file, each service associated with its own process. The various
+            // services are functionnaly identical but need to each have their own class.
+            // We differentiate them by their class name having a trailing number.
+            return MultiprocessTestClientService.class.getName() + mSlot;
+        }
+
+        public boolean isConnected() {
+            synchronized (mConnectedLock) {
+                return mConnected;
+            }
+        }
+
+        public int getSlot() {
+            return mSlot;
+        }
+
+        public int getPid() {
+            return mPid;
+        }
+    }
+
+    /**
+     * Spawns and connects to a child process.
+     * May not be called from the main thread.
+     *
+     * @param context context used to obtain the application context.
+     * @param commandLine the child process command line argv.
+     * @return the PID of the started process or 0 if the process could not be started.
+     */
+    @CalledByNative
+    private static int launchClient(final Context context, final String[] commandLine,
+            final FileDescriptorInfo[] filesToMap) {
+        if (ThreadUtils.runningOnUiThread()) {
+            // This can't be called on the main thread as the native side will block until
+            // onServiceConnected above is called, which cannot happen if the main thread is
+            // blocked.
+            throw new RuntimeException("launchClient cannot be called on the main thread");
+        }
+
+        ClientServiceConnection connection =
+                sConnectionAllocator.allocateConnection(commandLine, filesToMap);
+        Intent intent = new Intent();
+        String className = connection.getServiceClassName();
+        intent.setComponent(new ComponentName(context.getPackageName(), className));
+        if (!context.bindService(
+                    intent, connection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT)) {
+            Log.e(TAG, "Failed to bind service: " + context.getPackageName() + "." + className);
+            sConnectionAllocator.freeConnection(connection);
+            return 0;
+        }
+
+        connection.waitForConnection();
+
+        return connection.getPid();
+    }
+
+    /**
+     * Blocks until the main method invoked by a previous call to launchClient terminates or until
+     * the specified time-out expires.
+     * Returns immediately if main has already returned.
+     * @param context context used to obtain the application context.
+     * @param pid the process ID that was returned by the call to launchClient
+     * @param timeoutMs the timeout in milliseconds after which the method returns even if main has
+     *        not returned.
+     * @return the return code returned by the main method or whether it timed-out.
+     */
+    @CalledByNative
+    private static MainReturnCodeResult waitForMainToReturn(
+            Context context, int pid, int timeoutMs) {
+        ClientServiceConnection connection = sConnectionAllocator.getConnectionByPid(pid);
+        if (connection == null) {
+            Log.e(TAG, "waitForMainToReturn called on unknown connection for pid " + pid);
+            return null;
+        }
+        try {
+            return connection.getService().waitForMainToReturn(timeoutMs);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Remote call to waitForMainToReturn failed.");
+            return null;
+        } finally {
+            freeConnection(context, connection);
+        }
+    }
+
+    @CalledByNative
+    private static boolean terminate(Context context, int pid, int exitCode, boolean wait) {
+        ClientServiceConnection connection = sConnectionAllocator.getConnectionByPid(pid);
+        if (connection == null) {
+            Log.e(TAG, "terminate called on unknown connection for pid " + pid);
+            return false;
+        }
+        try {
+            if (wait) {
+                connection.getService().forceStopSynchronous(exitCode);
+            } else {
+                connection.getService().forceStop(exitCode);
+            }
+        } catch (RemoteException e) {
+            // We expect this failure, since the forceStop's service implementation calls
+            // System.exit().
+        } finally {
+            freeConnection(context, connection);
+        }
+        return true;
+    }
+
+    private static void freeConnection(Context context, ClientServiceConnection connection) {
+        context.unbindService(connection);
+        sConnectionAllocator.freeConnection(connection);
+    }
+
+    /** Does not take ownership of of fds. */
+    @CalledByNative
+    private static FileDescriptorInfo[] makeFdInfoArray(int[] keys, int[] fds) {
+        FileDescriptorInfo[] fdInfos = new FileDescriptorInfo[keys.length];
+        for (int i = 0; i < keys.length; i++) {
+            FileDescriptorInfo fdInfo = makeFdInfo(keys[i], fds[i]);
+            if (fdInfo == null) {
+                Log.e(TAG, "Failed to make file descriptor (" + keys[i] + ", " + fds[i] + ").");
+                return null;
+            }
+            fdInfos[i] = fdInfo;
+        }
+        return fdInfos;
+    }
+
+    private static FileDescriptorInfo makeFdInfo(int id, int fd) {
+        ParcelFileDescriptor parcelableFd = null;
+        try {
+            parcelableFd = ParcelFileDescriptor.fromFd(fd);
+        } catch (IOException e) {
+            Log.e(TAG, "Invalid FD provided for process connection, aborting connection.", e);
+            return null;
+        }
+        return new FileDescriptorInfo(id, parcelableFd);
+    }
+}
diff --git a/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService.java b/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService.java
new file mode 100644
index 0000000..c786438
--- /dev/null
+++ b/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService.java
@@ -0,0 +1,143 @@
+// 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.base;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Process;
+
+import org.chromium.base.annotations.SuppressFBWarnings;
+import org.chromium.base.library_loader.LibraryLoader;
+import org.chromium.base.library_loader.LibraryProcessType;
+import org.chromium.base.library_loader.ProcessInitException;
+import org.chromium.native_test.MainRunner;
+
+import javax.annotation.concurrent.GuardedBy;
+
+/**
+ * The service implementation used to host all multiprocess test client code.
+ */
+public class MultiprocessTestClientService extends Service {
+    private static final String TAG = "cr_TestClient";
+
+    private static boolean sAlreadyInitialized = false;
+
+    private final Handler mHandler = new Handler();
+
+    private final Object mResultLock = new Object();
+
+    @GuardedBy("mResultLock")
+    private MainReturnCodeResult mResult;
+
+    private final ITestClient.Stub mBinder = new ITestClient.Stub() {
+        @Override
+        public int launch(final String[] commandLine, FileDescriptorInfo[] fdsToMap) {
+            final int[] fdKeys = new int[fdsToMap.length];
+            final int[] fdFds = new int[fdsToMap.length];
+            for (int i = 0; i < fdsToMap.length; i++) {
+                fdKeys[i] = fdsToMap[i].key;
+                // Take ownership of the file descriptor so they outlive the FileDescriptorInfo
+                // instances. Native code will own them.
+                fdFds[i] = fdsToMap[i].fd.detachFd();
+            }
+            // Don't run main directly, it would block and the response would not be returned.
+            // We post to the main thread as this thread does not have a Looper.
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    int result = MainRunner.runMain(commandLine, fdKeys, fdFds);
+                    setMainReturnValue(result);
+                }
+            });
+            return Process.myPid();
+        }
+
+        @SuppressFBWarnings("RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE")
+        @Override
+        public MainReturnCodeResult waitForMainToReturn(int timeoutMs) {
+            synchronized (mResultLock) {
+                while (mResult == null) {
+                    try {
+                        mResultLock.wait(timeoutMs);
+                    } catch (InterruptedException ie) {
+                        continue;
+                    }
+                    // Check if we timed-out.
+                    if (mResult == null) {
+                        Log.e(TAG, "Failed to wait for main return value.");
+                        return new MainReturnCodeResult(0, true /* timed-out */);
+                    }
+                }
+                return mResult;
+            }
+        }
+
+        @SuppressFBWarnings("DM_EXIT")
+        @Override
+        public boolean forceStopSynchronous(int exitCode) {
+            System.exit(exitCode);
+            return true;
+        }
+
+        @SuppressFBWarnings("DM_EXIT")
+        @Override
+        public void forceStop(int exitCode) {
+            System.exit(exitCode);
+        }
+    };
+
+    @SuppressFBWarnings("DM_EXIT")
+    @Override
+    public void onCreate() {
+        super.onCreate();
+
+        if (sAlreadyInitialized) {
+            // The framework controls how services are reused and even though nothing is bound to a
+            // service it might be kept around. Since we really want to fork a new process when we
+            // bind, we'll kill the process early when a service is reused, forcing the framework to
+            // recreate the service in a new process.
+            // This is not ideal, but there are no clear alternatives at this point.
+            Log.e(TAG, "Service being reused, forcing stoppage.");
+            System.exit(0);
+            return;
+        }
+        markInitialized();
+
+        ContextUtils.initApplicationContext(getApplicationContext());
+
+        PathUtils.setPrivateDataDirectorySuffix("chrome_multiprocess_test_client_service");
+
+        loadLibraries();
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return mBinder;
+    }
+
+    private void loadLibraries() {
+        try {
+            LibraryLoader.get(LibraryProcessType.PROCESS_CHILD).loadNow();
+        } catch (ProcessInitException pie) {
+            Log.e(TAG, "Unable to load native libraries.", pie);
+        }
+        ContextUtils.initApplicationContextForNative();
+    }
+
+    private void setMainReturnValue(int result) {
+        synchronized (mResultLock) {
+            mResult = new MainReturnCodeResult(result, false /* timed-out */);
+            mResultLock.notifyAll();
+        }
+    }
+
+    private static void markInitialized() {
+        // We don't set sAlreadyInitialized directly in onCreate to avoid FindBugs complaining about
+        // a static member been set from a non-static function.
+        sAlreadyInitialized = true;
+    }
+}
diff --git a/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService0.java b/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService0.java
new file mode 100644
index 0000000..6bdd867
--- /dev/null
+++ b/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService0.java
@@ -0,0 +1,10 @@
+// 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.base;
+
+/**
+ * A subclass used only to differentiate different test client service process instances.
+ */
+public class MultiprocessTestClientService0 extends MultiprocessTestClientService {}
diff --git a/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService1.java b/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService1.java
new file mode 100644
index 0000000..69827f0
--- /dev/null
+++ b/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService1.java
@@ -0,0 +1,10 @@
+// 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.base;
+
+/**
+ * A subclass used only to differentiate different test client service process instances.
+ */
+public class MultiprocessTestClientService1 extends MultiprocessTestClientService {}
diff --git a/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService2.java b/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService2.java
new file mode 100644
index 0000000..aad11f1c
--- /dev/null
+++ b/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService2.java
@@ -0,0 +1,10 @@
+// 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.base;
+
+/**
+ * A subclass used only to differentiate different test client service process instances.
+ */
+public class MultiprocessTestClientService2 extends MultiprocessTestClientService {}
diff --git a/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService3.java b/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService3.java
new file mode 100644
index 0000000..20d2561
--- /dev/null
+++ b/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService3.java
@@ -0,0 +1,10 @@
+// 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.base;
+
+/**
+ * A subclass used only to differentiate different test client service process instances.
+ */
+public class MultiprocessTestClientService3 extends MultiprocessTestClientService {}
diff --git a/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService4.java b/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService4.java
new file mode 100644
index 0000000..4b14551
--- /dev/null
+++ b/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService4.java
@@ -0,0 +1,10 @@
+// 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.base;
+
+/**
+ * A subclass used only to differentiate different test client service process instances.
+ */
+public class MultiprocessTestClientService4 extends MultiprocessTestClientService {}
diff --git a/base/test/multiprocess_test.cc b/base/test/multiprocess_test.cc
index 5a3208a3..3f64ef5 100644
--- a/base/test/multiprocess_test.cc
+++ b/base/test/multiprocess_test.cc
@@ -26,6 +26,19 @@
 
   return LaunchProcess(command_line, options);
 }
+
+bool WaitForMultiprocessTestChildExit(const Process& process,
+                                      TimeDelta timeout,
+                                      int* exit_code) {
+  return process.WaitForExitWithTimeout(timeout, exit_code);
+}
+
+bool TerminateMultiProcessTestChild(const Process& process,
+                                    int exit_code,
+                                    bool wait) {
+  return process.Terminate(exit_code, wait);
+}
+
 #endif  // !defined(OS_ANDROID)
 
 CommandLine GetMultiProcessTestChildBaseCommandLine() {
diff --git a/base/test/multiprocess_test.h b/base/test/multiprocess_test.h
index ae4c3eb2..bf966375 100644
--- a/base/test/multiprocess_test.h
+++ b/base/test/multiprocess_test.h
@@ -40,7 +40,7 @@
 //     // Do stuff involving |test_child_process| and the child process....
 //
 //     int rv = -1;
-//     ASSERT_TRUE(test_child_process.WaitForExitWithTimeout(
+//     ASSERT_TRUE(base::WaitForMultiprocessTestChildExit(test_child_process,
 //         TestTimeouts::action_timeout(), &rv));
 //     EXPECT_EQ(0, rv);
 //   }
@@ -51,6 +51,10 @@
 //     // Code here runs in a child process....
 //     return 0;
 //   }
+//
+// If you need to terminate the child process, use the
+// TerminateMultiProcessTestChild method to ensure that test will work on
+// Android.
 
 // Spawns a child process and executes the function |procname| declared using
 // |MULTIPROCESS_TEST_MAIN()| or |MULTIPROCESS_TEST_MAIN_WITH_SETUP()|.
@@ -66,24 +70,17 @@
 // may add any flags needed for your child process.
 CommandLine GetMultiProcessTestChildBaseCommandLine();
 
-#if defined(OS_ANDROID)
+// Waits for the child process to exit. Returns true if the process exited
+// within |timeout| and sets |exit_code| if non null.
+bool WaitForMultiprocessTestChildExit(const Process& process,
+                                      TimeDelta timeout,
+                                      int* exit_code);
 
-// Enable the alternate test child implementation which support spawning a child
-// after threads have been created. If used, this MUST be the first line of
-// main(). The main function is passed in to avoid a link-time dependency in
-// component builds.
-void InitAndroidMultiProcessTestHelper(int (*main)(int, char**));
-
-// Returns true if the current process is a test child.
-bool AndroidIsChildProcess();
-
-// Wait for a test child to exit if the alternate test child implementation is
-// being used.
-bool AndroidWaitForChildExitWithTimeout(
-    const Process& process, TimeDelta timeout, int* exit_code)
-    WARN_UNUSED_RESULT;
-
-#endif  // defined(OS_ANDROID)
+// Terminates |process| with |exit_code|. If |wait| is true, this call blocks
+// until the process actually terminates.
+bool TerminateMultiProcessTestChild(const Process& process,
+                                    int exit_code,
+                                    bool wait);
 
 // MultiProcessTest ------------------------------------------------------------
 
diff --git a/base/test/multiprocess_test_android.cc b/base/test/multiprocess_test_android.cc
index f58b452..c74f013d 100644
--- a/base/test/multiprocess_test_android.cc
+++ b/base/test/multiprocess_test_android.cc
@@ -4,451 +4,87 @@
 
 #include "base/test/multiprocess_test.h"
 
-#include <errno.h>
 #include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <unistd.h>
-
-#include <memory>
-#include <utility>
 #include <vector>
 
+#include "base/android/context_utils.h"
+#include "base/android/jni_android.h"
+#include "base/android/jni_array.h"
+#include "base/android/scoped_java_ref.h"
 #include "base/base_switches.h"
 #include "base/command_line.h"
-#include "base/containers/hash_tables.h"
-#include "base/lazy_instance.h"
 #include "base/logging.h"
-#include "base/macros.h"
-#include "base/pickle.h"
-#include "base/posix/global_descriptors.h"
-#include "base/posix/unix_domain_socket_linux.h"
-#include "testing/multiprocess_func_list.h"
+#include "jni/MainReturnCodeResult_jni.h"
+#include "jni/MultiprocessTestClientLauncher_jni.h"
 
 namespace base {
 
-namespace {
-
-const int kMaxMessageSize = 1024 * 1024;
-const int kFragmentSize = 4096;
-
-// Message sent between parent process and helper child process.
-enum class MessageType : uint32_t {
-  START_REQUEST,
-  START_RESPONSE,
-  WAIT_REQUEST,
-  WAIT_RESPONSE,
-};
-
-struct MessageHeader {
-  uint32_t size;
-  MessageType type;
-};
-
-struct StartProcessRequest {
-  MessageHeader header =
-      {sizeof(StartProcessRequest), MessageType::START_REQUEST};
-
-  uint32_t num_args = 0;
-  uint32_t num_fds = 0;
-};
-
-struct StartProcessResponse {
-  MessageHeader header =
-      {sizeof(StartProcessResponse), MessageType::START_RESPONSE};
-
-  pid_t child_pid;
-};
-
-struct WaitProcessRequest {
-  MessageHeader header =
-      {sizeof(WaitProcessRequest), MessageType::WAIT_REQUEST};
-
-  pid_t pid;
-  uint64_t timeout_ms;
-};
-
-struct WaitProcessResponse {
-  MessageHeader header =
-      {sizeof(WaitProcessResponse), MessageType::WAIT_RESPONSE};
-
-  bool success = false;
-  int32_t exit_code = 0;
-};
-
-// Helper class that implements an alternate test child launcher for
-// multi-process tests. The default implementation doesn't work if the child is
-// launched after starting threads. However, for some tests (i.e. Mojo), this
-// is necessary. This implementation works around that issue by forking a helper
-// process very early in main(), before any real work is done. Then, when a
-// child needs to be spawned, a message is sent to that helper process, which
-// then forks and returns the result to the parent. The forked child then calls
-// main() and things look as though a brand new process has been fork/exec'd.
-class LaunchHelper {
- public:
-  using MainFunction = int (*)(int, char**);
-
-  LaunchHelper() {}
-
-  // Initialise the alternate test child implementation.
-  void Init(MainFunction main);
-
-  // Starts a child test helper process.
-  Process StartChildTestHelper(const std::string& procname,
-                               const CommandLine& base_command_line,
-                               const LaunchOptions& options);
-
-  // Waits for a child test helper process.
-  bool WaitForChildExitWithTimeout(const Process& process, TimeDelta timeout,
-                                   int* exit_code);
-
-  bool IsReady() const { return child_fd_ != -1; }
-  bool IsChild() const { return is_child_; }
-
- private:
-  // Wrappers around sendmsg/recvmsg that supports message fragmentation.
-  void Send(int fd, const MessageHeader* msg, const std::vector<int>& fds);
-  ssize_t Recv(int fd, void* buf, std::vector<ScopedFD>* fds);
-
-  // Parent process implementation.
-  void DoParent(int fd);
-  // Helper process implementation.
-  void DoHelper(int fd);
-
-  void StartProcessInHelper(const StartProcessRequest* request,
-                           std::vector<ScopedFD> fds);
-  void WaitForChildInHelper(const WaitProcessRequest* request);
-
-  bool is_child_ = false;
-
-  // Parent vars.
-  int child_fd_ = -1;
-
-  // Helper vars.
-  int parent_fd_ = -1;
-  MainFunction main_ = nullptr;
-
-  DISALLOW_COPY_AND_ASSIGN(LaunchHelper);
-};
-
-void LaunchHelper::Init(MainFunction main) {
-  main_ = main;
-
-  // Create a communication channel between the parent and child launch helper.
-  // fd[0] belongs to the parent, fd[1] belongs to the child.
-  int fds[2] = {-1, -1};
-  int rv = socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds);
-  PCHECK(rv == 0);
-  CHECK_NE(-1, fds[0]);
-  CHECK_NE(-1, fds[1]);
-
-  pid_t pid = fork();
-  PCHECK(pid >= 0) << "Fork failed";
-  if (pid) {
-    // Parent.
-    rv = close(fds[1]);
-    PCHECK(rv == 0);
-    DoParent(fds[0]);
-  } else {
-    // Helper.
-    rv = close(fds[0]);
-    PCHECK(rv == 0);
-    DoHelper(fds[1]);
-    NOTREACHED();
-    _exit(0);
-  }
-}
-
-void LaunchHelper::Send(
-    int fd, const MessageHeader* msg, const std::vector<int>& fds) {
-  uint32_t bytes_remaining = msg->size;
-  const char* buf = reinterpret_cast<const char*>(msg);
-  while (bytes_remaining) {
-    size_t send_size =
-        (bytes_remaining > kFragmentSize) ? kFragmentSize : bytes_remaining;
-    bool success = UnixDomainSocket::SendMsg(
-        fd, buf, send_size,
-        (bytes_remaining == msg->size) ? fds : std::vector<int>());
-    CHECK(success);
-    bytes_remaining -= send_size;
-    buf += send_size;
-  }
-}
-
-ssize_t LaunchHelper::Recv(int fd, void* buf, std::vector<ScopedFD>* fds) {
-  ssize_t size = UnixDomainSocket::RecvMsg(fd, buf, kFragmentSize, fds);
-  if (size <= 0)
-    return size;
-
-  const MessageHeader* header = reinterpret_cast<const MessageHeader*>(buf);
-  CHECK(header->size < kMaxMessageSize);
-  uint32_t bytes_remaining = header->size - size;
-  char* buffer = reinterpret_cast<char*>(buf);
-  buffer += size;
-  while (bytes_remaining) {
-    std::vector<ScopedFD> dummy_fds;
-    size = UnixDomainSocket::RecvMsg(fd, buffer, kFragmentSize, &dummy_fds);
-    if (size <= 0)
-      return size;
-
-    CHECK(dummy_fds.empty());
-    CHECK(size == kFragmentSize ||
-          static_cast<size_t>(size) == bytes_remaining);
-    bytes_remaining -= size;
-    buffer += size;
-  }
-  return header->size;
-}
-
-void LaunchHelper::DoParent(int fd) {
-  child_fd_ = fd;
-}
-
-void LaunchHelper::DoHelper(int fd) {
-  parent_fd_ = fd;
-  is_child_ = true;
-  std::unique_ptr<char[]> buf(new char[kMaxMessageSize]);
-  while (true) {
-    // Wait for a message from the parent.
-    std::vector<ScopedFD> fds;
-    ssize_t size = Recv(parent_fd_, buf.get(), &fds);
-    if (size == 0 || (size < 0 && errno == ECONNRESET)) {
-      _exit(0);
-    }
-    PCHECK(size > 0);
-
-    const MessageHeader* header =
-        reinterpret_cast<const MessageHeader*>(buf.get());
-    CHECK_EQ(static_cast<ssize_t>(header->size), size);
-    switch (header->type) {
-      case MessageType::START_REQUEST:
-        StartProcessInHelper(
-            reinterpret_cast<const StartProcessRequest*>(buf.get()),
-            std::move(fds));
-        break;
-      case MessageType::WAIT_REQUEST:
-        WaitForChildInHelper(
-            reinterpret_cast<const WaitProcessRequest*>(buf.get()));
-        break;
-      default:
-        LOG(FATAL) << "Unsupported message type: "
-                   << static_cast<uint32_t>(header->type);
-    }
-  }
-}
-
-void LaunchHelper::StartProcessInHelper(const StartProcessRequest* request,
-                                        std::vector<ScopedFD> fds) {
-  pid_t pid = fork();
-  PCHECK(pid >= 0) << "Fork failed";
-  if (pid) {
-    // Helper.
-    StartProcessResponse resp;
-    resp.child_pid = pid;
-    Send(parent_fd_, reinterpret_cast<const MessageHeader*>(&resp),
-         std::vector<int>());
-  } else {
-    // Child.
-    PCHECK(close(parent_fd_) == 0);
-    parent_fd_ = -1;
-    CommandLine::Reset();
-
-    Pickle serialised_extra(reinterpret_cast<const char*>(request + 1),
-                            request->header.size - sizeof(StartProcessRequest));
-    PickleIterator iter(serialised_extra);
-    std::vector<std::string> args;
-    for (size_t i = 0; i < request->num_args; i++) {
-      std::string arg;
-      CHECK(iter.ReadString(&arg));
-      args.push_back(std::move(arg));
-    }
-
-    CHECK_EQ(request->num_fds, fds.size());
-    for (size_t i = 0; i < request->num_fds; i++) {
-      int new_fd;
-      CHECK(iter.ReadInt(&new_fd));
-      int old_fd = fds[i].release();
-      if (new_fd != old_fd) {
-        if (dup2(old_fd, new_fd) < 0) {
-          PLOG(FATAL) << "dup2";
-        }
-        PCHECK(close(old_fd) == 0);
-      }
-    }
-
-    // argv has argc+1 elements, where the last element is NULL.
-    std::unique_ptr<char*[]> argv(new char*[args.size() + 1]);
-    for (size_t i = 0; i < args.size(); i++) {
-      argv[i] = const_cast<char*>(args[i].c_str());
-    }
-    argv[args.size()] = nullptr;
-    _exit(main_(args.size(), argv.get()));
-    NOTREACHED();
-  }
-}
-
-void LaunchHelper::WaitForChildInHelper(const WaitProcessRequest* request) {
-  Process process(request->pid);
-  TimeDelta timeout = TimeDelta::FromMilliseconds(request->timeout_ms);
-  int exit_code = -1;
-  bool success = process.WaitForExitWithTimeout(timeout, &exit_code);
-
-  WaitProcessResponse resp;
-  resp.exit_code = exit_code;
-  resp.success = success;
-  Send(parent_fd_, reinterpret_cast<const MessageHeader*>(&resp),
-       std::vector<int>());
-}
-
-Process LaunchHelper::StartChildTestHelper(const std::string& procname,
-                                           const CommandLine& base_command_line,
-                                           const LaunchOptions& options) {
-
-  CommandLine command_line(base_command_line);
-  if (!command_line.HasSwitch(switches::kTestChildProcess))
-    command_line.AppendSwitchASCII(switches::kTestChildProcess, procname);
-
-  StartProcessRequest request;
-  Pickle serialised_extra;
-  const CommandLine::StringVector& argv = command_line.argv();
-  for (const auto& arg : argv)
-    CHECK(serialised_extra.WriteString(arg));
-  request.num_args = argv.size();
-
-  std::vector<int> fds_to_send;
-  if (options.fds_to_remap) {
-    for (auto p : *options.fds_to_remap) {
-      CHECK(serialised_extra.WriteInt(p.second));
-      fds_to_send.push_back(p.first);
-    }
-    request.num_fds = options.fds_to_remap->size();
-  }
-
-  size_t buf_size = sizeof(StartProcessRequest) + serialised_extra.size();
-  request.header.size = buf_size;
-  std::unique_ptr<char[]> buffer(new char[buf_size]);
-  memcpy(buffer.get(), &request, sizeof(StartProcessRequest));
-  memcpy(buffer.get() + sizeof(StartProcessRequest), serialised_extra.data(),
-         serialised_extra.size());
-
-  // Send start message.
-  Send(child_fd_, reinterpret_cast<const MessageHeader*>(buffer.get()),
-       fds_to_send);
-
-  // Synchronously get response.
-  StartProcessResponse response;
-  std::vector<ScopedFD> recv_fds;
-  ssize_t resp_size = Recv(child_fd_, &response, &recv_fds);
-  PCHECK(resp_size == sizeof(StartProcessResponse));
-
-  return Process(response.child_pid);
-}
-
-bool LaunchHelper::WaitForChildExitWithTimeout(
-    const Process& process, TimeDelta timeout, int* exit_code) {
-
-  WaitProcessRequest request;
-  request.pid = process.Handle();
-  request.timeout_ms = timeout.InMilliseconds();
-
-  Send(child_fd_, reinterpret_cast<const MessageHeader*>(&request),
-       std::vector<int>());
-
-  WaitProcessResponse response;
-  std::vector<ScopedFD> recv_fds;
-  ssize_t resp_size = Recv(child_fd_, &response, &recv_fds);
-  PCHECK(resp_size == sizeof(WaitProcessResponse));
-
-  if (!response.success)
-    return false;
-
-  *exit_code = response.exit_code;
-  return true;
-}
-
-LazyInstance<LaunchHelper>::Leaky g_launch_helper;
-
-}  // namespace
-
-void InitAndroidMultiProcessTestHelper(int (*main)(int, char**)) {
-  DCHECK(main);
-  // Don't allow child processes to themselves create new child processes.
-  if (g_launch_helper.Get().IsChild())
-    return;
-  g_launch_helper.Get().Init(main);
-}
-
-bool AndroidIsChildProcess() {
-  return g_launch_helper.Get().IsChild();
-}
-
-bool AndroidWaitForChildExitWithTimeout(
-    const Process& process, TimeDelta timeout, int* exit_code) {
-  CHECK(g_launch_helper.Get().IsReady());
-  return g_launch_helper.Get().WaitForChildExitWithTimeout(
-      process, timeout, exit_code);
-}
-
 // A very basic implementation for Android. On Android tests can run in an APK
 // and we don't have an executable to exec*. This implementation does the bare
 // minimum to execute the method specified by procname (in the child process).
 //  - All options except |fds_to_remap| are ignored.
+//
+// NOTE: This MUST NOT run on the main thread of the NativeTest application.
 Process SpawnMultiProcessTestChild(const std::string& procname,
                                    const CommandLine& base_command_line,
                                    const LaunchOptions& options) {
-  if (g_launch_helper.Get().IsReady()) {
-    return g_launch_helper.Get().StartChildTestHelper(
-        procname, base_command_line, options);
-  }
+  JNIEnv* env = android::AttachCurrentThread();
+  DCHECK(env);
 
-  // TODO(viettrungluu): The FD-remapping done below is wrong in the presence of
-  // cycles (e.g., fd1 -> fd2, fd2 -> fd1). crbug.com/326576
-  FileHandleMappingVector empty;
-  const FileHandleMappingVector* fds_to_remap =
-      options.fds_to_remap ? options.fds_to_remap : &empty;
-
-  pid_t pid = fork();
-
-  if (pid < 0) {
-    PLOG(ERROR) << "fork";
-    return Process();
-  }
-  if (pid > 0) {
-    // Parent process.
-    return Process(pid);
-  }
-  // Child process.
-  base::hash_set<int> fds_to_keep_open;
-  for (FileHandleMappingVector::const_iterator it = fds_to_remap->begin();
-       it != fds_to_remap->end(); ++it) {
-    fds_to_keep_open.insert(it->first);
-  }
-  // Keep standard FDs (stdin, stdout, stderr, etc.) open since this
-  // is not meant to spawn a daemon.
-  int base = GlobalDescriptors::kBaseDescriptor;
-  for (int fd = base; fd < sysconf(_SC_OPEN_MAX); ++fd) {
-    if (fds_to_keep_open.find(fd) == fds_to_keep_open.end()) {
-      close(fd);
+  std::vector<int> fd_keys;
+  std::vector<int> fd_fds;
+  if (options.fds_to_remap) {
+    for (auto& iter : *options.fds_to_remap) {
+      fd_keys.push_back(iter.second);
+      fd_fds.push_back(iter.first);
     }
   }
-  for (FileHandleMappingVector::const_iterator it = fds_to_remap->begin();
-       it != fds_to_remap->end(); ++it) {
-    int old_fd = it->first;
-    int new_fd = it->second;
-    if (dup2(old_fd, new_fd) < 0) {
-      PLOG(FATAL) << "dup2";
-    }
-    close(old_fd);
-  }
-  CommandLine::Reset();
-  CommandLine::Init(0, nullptr);
-  CommandLine* command_line = CommandLine::ForCurrentProcess();
-  command_line->InitFromArgv(base_command_line.argv());
-  if (!command_line->HasSwitch(switches::kTestChildProcess))
-    command_line->AppendSwitchASCII(switches::kTestChildProcess, procname);
 
-  _exit(multi_process_function_list::InvokeChildProcessTest(procname));
-  return Process();
+  android::ScopedJavaLocalRef<jobjectArray> fds =
+      android::Java_MultiprocessTestClientLauncher_makeFdInfoArray(
+          env, base::android::ToJavaIntArray(env, fd_keys),
+          base::android::ToJavaIntArray(env, fd_fds));
+
+  CommandLine command_line(base_command_line);
+  if (!command_line.HasSwitch(switches::kTestChildProcess)) {
+    command_line.AppendSwitchASCII(switches::kTestChildProcess, procname);
+  }
+
+  android::ScopedJavaLocalRef<jobjectArray> j_argv =
+      android::ToJavaArrayOfStrings(env, command_line.argv());
+  jint pid = android::Java_MultiprocessTestClientLauncher_launchClient(
+      env, android::GetApplicationContext(), j_argv, fds);
+  return Process(pid);
+}
+
+bool WaitForMultiprocessTestChildExit(const Process& process,
+                                      TimeDelta timeout,
+                                      int* exit_code) {
+  JNIEnv* env = android::AttachCurrentThread();
+  DCHECK(env);
+
+  base::android::ScopedJavaLocalRef<jobject> result_code =
+      android::Java_MultiprocessTestClientLauncher_waitForMainToReturn(
+          env, android::GetApplicationContext(), process.Pid(),
+          static_cast<int32_t>(timeout.InMilliseconds()));
+  if (result_code.is_null() ||
+      Java_MainReturnCodeResult_hasTimedOut(env, result_code)) {
+    return false;
+  }
+  if (exit_code) {
+    *exit_code = Java_MainReturnCodeResult_getReturnCode(env, result_code);
+  }
+  return true;
+}
+
+bool TerminateMultiProcessTestChild(const Process& process,
+                                    int exit_code,
+                                    bool wait) {
+  JNIEnv* env = android::AttachCurrentThread();
+  DCHECK(env);
+
+  return android::Java_MultiprocessTestClientLauncher_terminate(
+      env, android::GetApplicationContext(), process.Pid(), exit_code, wait);
 }
 
 }  // namespace base
diff --git a/base/test/test_support_android.cc b/base/test/test_support_android.cc
index d77405fb..10839f5 100644
--- a/base/test/test_support_android.cc
+++ b/base/test/test_support_android.cc
@@ -160,9 +160,6 @@
 namespace base {
 
 void InitAndroidTestLogging() {
-  if (base::AndroidIsChildProcess())
-    return;
-
   logging::LoggingSettings settings;
   settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
   logging::InitLogging(settings);
diff --git a/blimp/client/support/compositor/blimp_layer_tree_settings.cc b/blimp/client/support/compositor/blimp_layer_tree_settings.cc
index 9f31e72..0971dfb8 100644
--- a/blimp/client/support/compositor/blimp_layer_tree_settings.cc
+++ b/blimp/client/support/compositor/blimp_layer_tree_settings.cc
@@ -17,10 +17,6 @@
 #include "ui/gfx/buffer_types.h"
 #include "ui/gl/gl_switches.h"
 
-#if defined(OS_ANDROID)
-#include "ui/gfx/android/device_display_info.h"
-#endif
-
 namespace blimp {
 namespace client {
 
@@ -171,45 +167,6 @@
 #endif
 
   int default_tile_size = 256;
-#if defined(OS_ANDROID)
-  gfx::DeviceDisplayInfo info;
-  bool real_size_supported = true;
-  int display_width = info.GetPhysicalDisplayWidth();
-  int display_height = info.GetPhysicalDisplayHeight();
-  if (display_width == 0 || display_height == 0) {
-    real_size_supported = false;
-    display_width = info.GetDisplayWidth();
-    display_height = info.GetDisplayHeight();
-  }
-
-  int portrait_width = std::min(display_width, display_height);
-  int landscape_width = std::max(display_width, display_height);
-
-  if (real_size_supported) {
-    // Maximum HD dimensions should be 768x1280
-    // Maximum FHD dimensions should be 1200x1920
-    if (portrait_width > 768 || landscape_width > 1280)
-      default_tile_size = 384;
-    if (portrait_width > 1200 || landscape_width > 1920)
-      default_tile_size = 512;
-
-    // Adjust for some resolutions that barely straddle an extra
-    // tile when in portrait mode. This helps worst case scroll/raster
-    // by not needing a full extra tile for each row.
-    if (default_tile_size == 256 && portrait_width == 768)
-      default_tile_size += 32;
-    if (default_tile_size == 384 && portrait_width == 1200)
-      default_tile_size += 32;
-  } else {
-    // We don't know the exact resolution due to screen controls etc.
-    // So this just estimates the values above using tile counts.
-    int numTiles = (display_width * display_height) / (256 * 256);
-    if (numTiles > 16)
-      default_tile_size = 384;
-    if (numTiles >= 40)
-      default_tile_size = 512;
-  }
-#endif
   settings->default_tile_size.SetSize(default_tile_size, default_tile_size);
 
   settings->renderer_settings.buffer_to_texture_target_map =
diff --git a/build/android/pylib/gtest/gtest_test_instance.py b/build/android/pylib/gtest/gtest_test_instance.py
index 394b9e8..678f68b1 100644
--- a/build/android/pylib/gtest/gtest_test_instance.py
+++ b/build/android/pylib/gtest/gtest_test_instance.py
@@ -25,7 +25,16 @@
   'content_browsertests',
 ]
 
-RUN_IN_SUB_THREAD_TEST_SUITES = ['net_unittests']
+RUN_IN_SUB_THREAD_TEST_SUITES = [
+  # Multiprocess tests should be run outside of the main thread.
+  'base_unittests',  # file_locking_unittest.cc uses a child process.
+  'ipc_perftests',
+  'ipc_tests',
+  'mojo_message_pipe_perftests',
+  'mojo_public_bindings_perftests',
+  'mojo_system_unittests',
+  'net_unittests'
+]
 
 
 # Used for filtering large data deps at a finer grain than what's allowed in
diff --git a/chrome/VERSION b/chrome/VERSION
index f2a32fe9..6237332f 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=57
 MINOR=0
-BUILD=2977
+BUILD=2978
 PATCH=0
diff --git a/chrome/android/java/res/drawable-hdpi/history_large.png b/chrome/android/java/res/drawable-hdpi/history_large.png
deleted file mode 100644
index 113dead..0000000
--- a/chrome/android/java/res/drawable-hdpi/history_large.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/history_large.png b/chrome/android/java/res/drawable-mdpi/history_large.png
deleted file mode 100644
index 4083155..0000000
--- a/chrome/android/java/res/drawable-mdpi/history_large.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/history_large.png b/chrome/android/java/res/drawable-xhdpi/history_large.png
deleted file mode 100644
index e875087..0000000
--- a/chrome/android/java/res/drawable-xhdpi/history_large.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/history_large.png b/chrome/android/java/res/drawable-xxhdpi/history_large.png
deleted file mode 100644
index 0c91370..0000000
--- a/chrome/android/java/res/drawable-xxhdpi/history_large.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/history_large.png b/chrome/android/java/res/drawable-xxxhdpi/history_large.png
deleted file mode 100644
index efa726c..0000000
--- a/chrome/android/java/res/drawable-xxxhdpi/history_large.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable/history_big.xml b/chrome/android/java/res/drawable/history_big.xml
new file mode 100644
index 0000000..78cd966d
--- /dev/null
+++ b/chrome/android/java/res/drawable/history_big.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2017 The Chromium Authors. All rights reserved.
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file. -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    tools:targetApi="21"
+    android:height="64dp"
+    android:width="64dp"
+    android:viewportHeight="24.0"
+    android:viewportWidth="24.0" >
+    <path
+        android:fillColor="@color/google_grey_700"
+        android:pathData="M13,3c-4.97,0 -9,4.03 -9,9L1,12l3.89,3.89 0.07,0.14L9,12L6,12c0,-3.87 3.13,-7 7,-7s7,3.13 7,7 -3.13,7 -7,7c-1.93,0 -3.68,-0.79 -4.94,-2.06l-1.42,1.42C8.27,19.99 10.51,21 13,21c4.97,0 9,-4.03 9,-9s-4.03,-9 -9,-9zM12,8v5l4.28,2.54 0.72,-1.21 -3.5,-2.08L13.5,8L12,8z" />
+</vector>
diff --git a/chrome/android/java/res/drawable/ic_block_red.xml b/chrome/android/java/res/drawable/ic_block_red.xml
new file mode 100644
index 0000000..cce211c
--- /dev/null
+++ b/chrome/android/java/res/drawable/ic_block_red.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2017 The Chromium Authors. All rights reserved.
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file. -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    tools:targetApi="21"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0" >
+    <path
+        android:fillColor="@color/google_red_700"
+        android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM4,12c0,-4.42 3.58,-8 8,-8 1.85,0 3.55,0.63 4.9,1.69L5.69,16.9C4.63,15.55 4,13.85 4,12zM12,20c-1.85,0 -3.55,-0.63 -4.9,-1.69L18.31,7.1C19.37,8.45 20,10.15 20,12c0,4.42 -3.58,8 -8,8z" />
+</vector>
diff --git a/chrome/android/java/res/layout/selectable_list_layout.xml b/chrome/android/java/res/layout/selectable_list_layout.xml
index 4d82211..811a518 100644
--- a/chrome/android/java/res/layout/selectable_list_layout.xml
+++ b/chrome/android/java/res/layout/selectable_list_layout.xml
@@ -32,7 +32,7 @@
         android:layout_height="wrap_content"
         android:drawablePadding="3dp"
         android:layout_centerInParent="true"
-        android:textColor="#5B5B5B"
+        android:textColor="@color/google_grey_700"
         android:textSize="16sp"
         android:visibility="gone" />
 
diff --git a/chrome/android/java/res/values/colors.xml b/chrome/android/java/res/values/colors.xml
index 32cda291..9f684e85 100644
--- a/chrome/android/java/res/values/colors.xml
+++ b/chrome/android/java/res/values/colors.xml
@@ -25,6 +25,7 @@
     <color name="google_grey_400">#bdbdbd</color>
     <color name="google_grey_500">#9E9E9E</color>
     <color name="google_grey_600">#757575</color>
+    <color name="google_grey_700">#616161</color>
     <color name="toolbar_shadow_color">#1d000000</color>
     <color name="toolbar_light_tint">#A3000000</color>
     <color name="light_grey">#ccc</color>
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 e2cd124..d2e9ce9 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
@@ -59,8 +59,9 @@
 
     @CalledByNative
     public static void createHistoryItemAndAddToList(
-            List<HistoryItem> items, String url, String domain, String title, long[] timestamps) {
-        items.add(new HistoryItem(url, domain, title, timestamps));
+            List<HistoryItem> items, String url, String domain, String title, long[] timestamps,
+            boolean blockedVisit) {
+        items.add(new HistoryItem(url, domain, title, timestamps, blockedVisit));
     }
 
     @CalledByNative
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 397b30b..a11c9da 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
@@ -24,6 +24,7 @@
 import org.chromium.ui.text.NoUnderlineClickableSpan;
 import org.chromium.ui.text.SpanApplier;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
 
@@ -57,6 +58,8 @@
     private long mNextQueryEndTime;
     private String mQueryText = EMPTY_QUERY;
 
+    private final ArrayList<HistoryItemView> mItemViews;
+
     public HistoryAdapter(SelectionDelegate<HistoryItem> delegate, HistoryManager manager,
             HistoryProvider provider) {
         setHasStableIds(true);
@@ -64,6 +67,7 @@
         mHistoryProvider = provider;
         mHistoryProvider.setObserver(this);
         mManager = manager;
+        mItemViews = new ArrayList<>();
     }
 
     /**
@@ -150,11 +154,23 @@
         mHistoryProvider.removeItems();
     }
 
+    /**
+     * Should be called when the user's sign in state changes.
+     */
+    public void onSignInStateChange() {
+        for (HistoryItemView itemView : mItemViews) {
+            itemView.onSignInStateChange();
+        }
+    }
+
     @Override
     protected ViewHolder createViewHolder(ViewGroup parent) {
         View v = LayoutInflater.from(parent.getContext()).inflate(
                 R.layout.history_item_view, parent, false);
-        return new SelectableItemViewHolder<HistoryItem>(v, mSelectionDelegate);
+        SelectableItemViewHolder<HistoryItem> viewHolder =
+                new SelectableItemViewHolder<>(v, mSelectionDelegate);
+        mItemViews.add((HistoryItemView) viewHolder.itemView);
+        return viewHolder;
     }
 
     @Override
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 a89dd9c1..708651f 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
@@ -6,6 +6,8 @@
 
 import android.text.TextUtils;
 
+import org.chromium.base.ContextUtils;
+import org.chromium.chrome.R;
 import org.chromium.chrome.browser.widget.DateDividedAdapter.TimedItem;
 
 import java.util.Arrays;
@@ -15,6 +17,7 @@
     private final String mUrl;
     private final String mDomain;
     private final String mTitle;
+    private final boolean mWasBlockedVisit;
     private final long mTimestamp;
     private final long[] mTimestampList;
     private Long mStableId;
@@ -26,12 +29,17 @@
      * @param domain The string to display for the item's domain.
      * @param title The string to display for the item's title.
      * @param timestamps The list of timestamps for this item.
+     * @param blockedVisit Whether the visit to this item was blocked when it was attempted.
      */
-    public HistoryItem(String url, String domain, String title, long[] timestamps) {
+    public HistoryItem(String url, String domain, String title, long[] timestamps,
+            boolean blockedVisit) {
         mUrl = url;
         mDomain = domain;
-        mTitle = TextUtils.isEmpty(title) ? url : title;
+        mTitle = blockedVisit ? ContextUtils.getApplicationContext().getString(
+                R.string.android_history_blocked_site)
+                : TextUtils.isEmpty(title) ? url : title;
         mTimestampList = Arrays.copyOf(timestamps, timestamps.length);
+        mWasBlockedVisit = blockedVisit;
 
         // The last timestamp in the list is the most recent visit.
         mTimestamp = mTimestampList[mTimestampList.length - 1];
@@ -52,6 +60,11 @@
         return mTitle;
     }
 
+    /** @return Whether the visit to this item was blocked when it was attempted. */
+    public Boolean wasBlockedVisit() {
+        return mWasBlockedVisit;
+    }
+
     @Override
     public long getTimestamp() {
         return mTimestamp;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryItemView.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryItemView.java
index 26e1b70..2eb056a1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryItemView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryItemView.java
@@ -7,6 +7,7 @@
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
+import android.support.graphics.drawable.VectorDrawableCompat;
 import android.support.v4.graphics.drawable.RoundedBitmapDrawable;
 import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory;
 import android.util.AttributeSet;
@@ -17,6 +18,7 @@
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.favicon.LargeIconBridge.LargeIconCallback;
+import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.widget.RoundedIconGenerator;
 import org.chromium.chrome.browser.widget.TintedImageButton;
 import org.chromium.chrome.browser.widget.selection.SelectableItemView;
@@ -29,6 +31,7 @@
     private TextView mDomain;
     private TintedImageButton mRemoveButton;
     private ImageView mIconImageView;
+    private VectorDrawableCompat mBlockedVisitDrawable;
 
     private HistoryManager mHistoryManager;
     private final RoundedIconGenerator mIconGenerator;
@@ -63,6 +66,8 @@
                 remove();
             }
         });
+
+        updateRemoveButtonVisibility();
     }
 
     @Override
@@ -73,8 +78,23 @@
 
         mTitle.setText(item.getTitle());
         mDomain.setText(item.getDomain());
-        mIconImageView.setImageResource(R.drawable.default_favicon);
-        if (mHistoryManager != null) requestIcon();
+
+        if (item.wasBlockedVisit()) {
+            if (mBlockedVisitDrawable == null) {
+                mBlockedVisitDrawable = VectorDrawableCompat.create(
+                        getContext().getResources(), R.drawable.ic_block_red,
+                        getContext().getTheme());
+            }
+            mIconImageView.setImageDrawable(mBlockedVisitDrawable);
+            mTitle.setTextColor(
+                    ApiCompatibilityUtils.getColor(getResources(), R.color.google_red_700));
+        } else {
+            mIconImageView.setImageResource(R.drawable.default_favicon);
+            if (mHistoryManager != null) requestIcon();
+
+            mTitle.setTextColor(
+                    ApiCompatibilityUtils.getColor(getResources(), R.color.default_text_color));
+        }
     }
 
     /**
@@ -85,7 +105,7 @@
         if (mHistoryManager == manager) return;
 
         mHistoryManager = manager;
-        requestIcon();
+        if (!getItem().wasBlockedVisit()) requestIcon();
     }
 
     /**
@@ -95,6 +115,13 @@
         getItem().remove();
     }
 
+    /**
+     * Should be called when the user's sign in state changes.
+     */
+    public void onSignInStateChange() {
+        updateRemoveButtonVisibility();
+    }
+
     @Override
     protected void onClick() {
         if (getItem() != null) getItem().open();
@@ -121,4 +148,10 @@
         mHistoryManager.getLargeIconBridge().getLargeIconForUrl(
                 getItem().getUrl(), mMinIconSize, this);
     }
+
+    private void updateRemoveButtonVisibility() {
+        mRemoveButton.setVisibility(
+                PrefServiceBridge.getInstance().canDeleteBrowsingHistory() ? View.VISIBLE
+                        : View.GONE);
+    }
 }
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 c94b4b600..863b012d 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
@@ -12,6 +12,7 @@
 import android.net.Uri;
 import android.provider.Browser;
 import android.support.annotation.VisibleForTesting;
+import android.support.graphics.drawable.VectorDrawableCompat;
 import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.RecyclerView;
 import android.support.v7.widget.RecyclerView.OnScrollListener;
@@ -31,8 +32,9 @@
 import org.chromium.chrome.browser.preferences.PreferencesLauncher;
 import org.chromium.chrome.browser.preferences.privacy.ClearBrowsingDataPreferences;
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.signin.SigninManager;
+import org.chromium.chrome.browser.signin.SigninManager.SignInStateObserver;
 import org.chromium.chrome.browser.util.IntentUtils;
-import org.chromium.chrome.browser.widget.TintedDrawable;
 import org.chromium.chrome.browser.widget.selection.SelectableListLayout;
 import org.chromium.chrome.browser.widget.selection.SelectionDelegate;
 import org.chromium.ui.base.DeviceFormFactor;
@@ -42,7 +44,7 @@
 /**
  * Displays and manages the UI for browsing history.
  */
-public class HistoryManager implements OnMenuItemClickListener {
+public class HistoryManager implements OnMenuItemClickListener, SignInStateObserver {
     private static final int FAVICON_MAX_CACHE_SIZE_BYTES = 10 * 1024 * 1024; // 10MB
     private static final int MEGABYTES_TO_BYTES =  1024 * 1024;
     private static final String METRICS_PREFIX = "Android.HistoryPage.";
@@ -79,8 +81,9 @@
                 R.id.normal_menu_group, R.id.selection_mode_menu_group, this);
         mToolbar.setManager(this);
         mEmptyView = mSelectableListLayout.initializeEmptyView(
-                TintedDrawable.constructTintedDrawable(mActivity.getResources(),
-                        R.drawable.history_large),
+                VectorDrawableCompat.create(
+                        mActivity.getResources(), R.drawable.history_big,
+                        mActivity.getTheme()),
                 R.string.history_manager_empty);
 
         mHistoryAdapter.initialize();
@@ -107,6 +110,8 @@
                 FAVICON_MAX_CACHE_SIZE_BYTES);
         mLargeIconBridge.createCache(maxSize);
 
+        SigninManager.get(mActivity).addSignInStateObserver(this);
+
         recordUserAction("Show");
     }
 
@@ -158,6 +163,7 @@
         mHistoryAdapter.onDestroyed();
         mLargeIconBridge.destroy();
         mLargeIconBridge = null;
+        SigninManager.get(mActivity).removeSignInStateObserver(this);
     }
 
     /**
@@ -311,4 +317,16 @@
         RecordHistogram.recordCount100Histogram(
                 METRICS_PREFIX + action + "Selected", selectedItems.size());
     }
+
+    @Override
+    public void onSignedIn() {
+        mToolbar.onSignInStateChange();
+        mHistoryAdapter.onSignInStateChange();
+    }
+
+    @Override
+    public void onSignedOut() {
+        mToolbar.onSignInStateChange();
+        mHistoryAdapter.onSignInStateChange();
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManagerToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManagerToolbar.java
index 03df352..d7ed967 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManagerToolbar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManagerToolbar.java
@@ -10,6 +10,8 @@
 import android.text.TextWatcher;
 import android.util.AttributeSet;
 import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.MenuItem;
 import android.view.View;
 import android.view.inputmethod.EditorInfo;
 import android.widget.EditText;
@@ -17,7 +19,9 @@
 import android.widget.TextView;
 import android.widget.TextView.OnEditorActionListener;
 
+import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.widget.TintedImageButton;
 import org.chromium.chrome.browser.widget.selection.SelectionToolbar;
 import org.chromium.ui.UiUtils;
@@ -41,10 +45,7 @@
         super(context, attrs);
         inflateMenu(R.menu.history_manager_menu);
 
-        if (DeviceFormFactor.isTablet(getContext())) {
-            getMenu().removeItem(R.id.close_menu_id);
-        }
-
+        updateMenuItemVisibility();
         // TODO(twellington): Add content descriptions to the number roll view.
     }
 
@@ -156,4 +157,43 @@
         // Call #onSelectionStateChange() to reset toolbar buttons and title.
         super.onSelectionStateChange(mSelectionDelegate.getSelectedItems());
     }
+
+    /**
+     * Should be called when the user's sign in state changes.
+     */
+    public void onSignInStateChange() {
+        updateMenuItemVisibility();
+    }
+
+    private void updateMenuItemVisibility() {
+        if (DeviceFormFactor.isTablet(getContext())) {
+            getMenu().removeItem(R.id.close_menu_id);
+        }
+
+        // Once the selection mode delete or incognito menu options are removed, they will not
+        // be added back until the user refreshes the history UI. This could happen if the user is
+        // signed in to an account that cannot remove browsing history or has incognito disabled and
+        // signs out.
+        if (!PrefServiceBridge.getInstance().canDeleteBrowsingHistory()) {
+            getMenu().removeItem(R.id.selection_mode_delete_menu_id);
+        }
+        if (!PrefServiceBridge.getInstance().isIncognitoModeEnabled()) {
+            getMenu().removeItem(R.id.selection_mode_open_in_incognito);
+        }
+    }
+
+    @VisibleForTesting
+    MenuItem getItemById(int menuItemId) {
+        Menu menu = getMenu();
+        for (int i = 0; i < menu.size(); i++) {
+            MenuItem item = menu.getItem(i);
+            if (item.getItemId() == menuItemId) return item;
+        }
+        return null;
+    }
+
+    @VisibleForTesting
+    Menu getMenuForTest() {
+        return getMenu();
+    }
 }
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index 5b6f3ce..ad2ce78 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -549,6 +549,9 @@
       <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_ANDROID_HISTORY_BLOCKED_SITE" desc="The text displayed in the history page indicating that a visit to a web site was blocked due to an administrator policy.">
+        Blocked site
+      </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/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java
index 9a9367e..f4d554e4 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.history;
 
+import android.accounts.Account;
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.app.Instrumentation.ActivityMonitor;
@@ -24,17 +25,25 @@
 import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.IntentHandler;
+import org.chromium.chrome.browser.childaccounts.ChildAccountService;
+import org.chromium.chrome.browser.preferences.PrefServiceBridge;
+import org.chromium.chrome.browser.signin.SigninManager;
+import org.chromium.chrome.browser.signin.SigninManager.SignInStateObserver;
 import org.chromium.chrome.browser.widget.TintedImageButton;
 import org.chromium.chrome.browser.widget.selection.SelectableItemView;
 import org.chromium.chrome.browser.widget.selection.SelectableItemViewHolder;
 import org.chromium.chrome.browser.widget.selection.SelectionDelegate.SelectionObserver;
 import org.chromium.chrome.test.util.ChromeRestriction;
+import org.chromium.chrome.test.util.browser.signin.SigninTestUtil;
+import org.chromium.chrome.test.util.browser.sync.SyncTestUtil;
 import org.chromium.components.signin.ChromeSigninController;
 import org.chromium.content.browser.test.util.Criteria;
 import org.chromium.content.browser.test.util.CriteriaHelper;
 
 import java.util.Date;
 import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Tests the {@link HistoryActivity}.
@@ -42,9 +51,10 @@
 @Restriction(ChromeRestriction.RESTRICTION_TYPE_PHONE)
 public class HistoryActivityTest extends BaseActivityInstrumentationTestCase<HistoryActivity> {
     private static class TestObserver extends RecyclerView.AdapterDataObserver
-            implements SelectionObserver<HistoryItem> {
+            implements SelectionObserver<HistoryItem>, SignInStateObserver {
         public final CallbackHelper onChangedCallback = new CallbackHelper();
         public final CallbackHelper onSelectionCallback = new CallbackHelper();
+        public final CallbackHelper onSigninStateChangedCallback = new CallbackHelper();
 
         private Handler mHandler;
 
@@ -73,6 +83,26 @@
                 }
             });
         }
+
+        @Override
+        public void onSignedIn() {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    onSigninStateChangedCallback.notifyCalled();
+                }
+            });
+        }
+
+        @Override
+        public void onSignedOut() {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    onSigninStateChangedCallback.notifyCalled();
+                }
+            });
+        }
     }
 
     private StubbedHistoryProvider mHistoryProvider;
@@ -293,6 +323,27 @@
         assertEquals(3, mAdapter.getItemCount());
     }
 
+    @SmallTest
+    public void testSupervisedUser() throws Exception {
+        final HistoryManagerToolbar toolbar = mHistoryManager.getToolbarForTests();
+        SelectableItemView<HistoryItem> item = getItemView(2);
+        toggleItemSelection(2);
+
+        assertTrue(toolbar.getItemById(R.id.selection_mode_open_in_incognito).isVisible());
+        assertTrue(toolbar.getItemById(R.id.selection_mode_open_in_incognito).isEnabled());
+        assertTrue(toolbar.getItemById(R.id.selection_mode_delete_menu_id).isVisible());
+        assertTrue(toolbar.getItemById(R.id.selection_mode_delete_menu_id).isEnabled());
+        assertEquals(View.VISIBLE, item.findViewById(R.id.remove).getVisibility());
+
+        signInToSupervisedAccount();
+
+        assertNull(toolbar.getItemById(R.id.selection_mode_open_in_incognito));
+        assertNull(toolbar.getItemById(R.id.selection_mode_delete_menu_id));
+        assertEquals(View.GONE, item.findViewById(R.id.remove).getVisibility());
+
+        signOut();
+    }
+
     private void toggleItemSelection(int position) throws Exception {
         int callCount = mTestObserver.onSelectionCallback.getCallCount();
         final SelectableItemView<HistoryItem> itemView = getItemView(position);
@@ -331,4 +382,62 @@
             }
         });
     }
+
+    private void signInToSupervisedAccount() throws Exception {
+        // Set supervised user.
+        assertTrue(ThreadUtils.runOnUiThreadBlocking(new Callable<Boolean>() {
+            @Override
+            public Boolean call() throws Exception {
+                PrefServiceBridge.getInstance().setSupervisedUserId("ChildAccountSUID");
+                return ChildAccountService.isChildAccount()
+                        && !PrefServiceBridge.getInstance().canDeleteBrowsingHistory()
+                        && !PrefServiceBridge.getInstance().isIncognitoModeEnabled();
+            }
+        }));
+
+        // Sign in to account.
+        SigninTestUtil.setUpAuthForTest(getInstrumentation());
+        final Account account = SigninTestUtil.addTestAccount();
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                SigninManager.get(getActivity()).onFirstRunCheckDone();
+                SigninManager.get(getActivity()).addSignInStateObserver(mTestObserver);
+                SigninManager.get(getActivity()).signIn(account, null, null);
+            }
+        });
+        mTestObserver.onSigninStateChangedCallback.waitForCallback(0, 1,
+                SyncTestUtil.TIMEOUT_MS, TimeUnit.MILLISECONDS);
+        assertEquals(account, SigninTestUtil.getCurrentAccount());
+    }
+
+    private void signOut() throws Exception {
+        // Clear supervised user id.
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                PrefServiceBridge.getInstance().setSupervisedUserId("");
+            }
+        });
+
+        // Sign out of account.
+        int currentCallCount = mTestObserver.onSigninStateChangedCallback.getCallCount();
+        SigninTestUtil.resetSigninState();
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                SigninManager.get(getActivity()).signOut(null);
+            }
+        });
+        mTestObserver.onSigninStateChangedCallback.waitForCallback(currentCallCount, 1);
+        assertNull(SigninTestUtil.getCurrentAccount());
+
+        // Remove observer
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                SigninManager.get(getActivity()).removeSignInStateObserver(mTestObserver);
+            }
+        });
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryAdapterTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryAdapterTest.java
index e2b780e..0040d6b5f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryAdapterTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryAdapterTest.java
@@ -11,7 +11,9 @@
 import android.support.test.filters.SmallTest;
 import android.test.InstrumentationTestCase;
 
+import org.chromium.base.ContextUtils;
 import org.chromium.base.ThreadUtils;
+import org.chromium.chrome.R;
 import org.chromium.chrome.browser.widget.selection.SelectionDelegate;
 
 import java.util.Date;
@@ -216,6 +218,24 @@
         checkAdapterContents(false);
     }
 
+    @SmallTest
+    public void testBlockedSite() {
+        Date today = new Date();
+        long[] timestamps = {today.getTime()};
+        HistoryItem item1 = StubbedHistoryProvider.createHistoryItem(0, timestamps);
+        mHistoryProvider.addItem(item1);
+
+        HistoryItem item2 = StubbedHistoryProvider.createHistoryItem(5, timestamps);
+        mHistoryProvider.addItem(item2);
+
+        initializeAdapter();
+
+        checkAdapterContents(true, null, null, item1, item2);
+        assertEquals(ContextUtils.getApplicationContext().getString(
+                R.string.android_history_blocked_site), item2.getTitle());
+        assertTrue(item2.wasBlockedVisit());
+    }
+
     private void checkAdapterContents(boolean hasHeader, Object... expectedItems) {
         assertEquals(expectedItems.length, mAdapter.getItemCount());
         assertEquals(hasHeader, mAdapter.hasListHeader());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/history/StubbedHistoryProvider.java b/chrome/android/javatests/src/org/chromium/chrome/browser/history/StubbedHistoryProvider.java
index bd22f6b7..6feba1ac 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/history/StubbedHistoryProvider.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/history/StubbedHistoryProvider.java
@@ -101,15 +101,20 @@
 
     public static HistoryItem createHistoryItem(int which, long[] timestamps) {
         if (which == 0) {
-            return new HistoryItem("http://google.com/", "www.google.com", "Google", timestamps);
+            return new HistoryItem("http://google.com/", "www.google.com", "Google", timestamps,
+                    false);
         } else if (which == 1) {
-            return new HistoryItem("http://foo.com/", "www.foo.com", "Foo", timestamps);
+            return new HistoryItem("http://foo.com/", "www.foo.com", "Foo", timestamps, false);
         } else if (which == 2) {
-            return new HistoryItem("http://bar.com/", "www.bar.com", "Bar", timestamps);
+            return new HistoryItem("http://bar.com/", "www.bar.com", "Bar", timestamps, false);
         } else if (which == 3) {
-            return new HistoryItem("http://news.com/", "www.news.com", "News", timestamps);
+            return new HistoryItem("http://news.com/", "www.news.com", "News", timestamps, false);
         } else if (which == 4) {
-            return new HistoryItem("http://eng.com/", "www.eng.com", "Engineering", timestamps);
+            return new HistoryItem("http://eng.com/", "www.eng.com", "Engineering", timestamps,
+                    false);
+        } else if (which == 5) {
+            return new HistoryItem("http://blocked.com/", "www.blocked.com", "Cannot Visit",
+                    timestamps, true);
         } else {
             return null;
         }
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index cac754d..03f8b6b 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -4177,6 +4177,9 @@
   <message name="IDS_REMOVABLE_DEVICE_NAVIGATION_MESSAGE" desc="Text of notification message to navigate users to Files.app. If user clicks a button in the notification, Files.app opens.">
     Explore the device's content in the Files app.
   </message>
+  <message name="IDS_REMOVABLE_DEVICE_NAVIGATION_MESSAGE_READONLY_POLICY" desc="Text of notification message to navigate users to Files.app when attaching a removable media, but the administrator's poilcy forbids writing data to them. If user clicks a button in the notification, Files.app opens.">
+    Explore the device's content in the Files app. The content is restricted by an admin and can’t be modified.
+  </message>
   <message name="IDS_REMOVABLE_DEVICE_NAVIGATION_BUTTON_LABEL" desc="Text of a button label in a notification to navigate users to Files.app. If user clicks the button, Files.app opens.">
     Open Files app
   </message>
diff --git a/chrome/app/vector_icons/BUILD.gn b/chrome/app/vector_icons/BUILD.gn
index 35502cd..76953eba 100644
--- a/chrome/app/vector_icons/BUILD.gn
+++ b/chrome/app/vector_icons/BUILD.gn
@@ -11,6 +11,7 @@
     "browser_tools.icon",
     "browser_tools_error.icon",
     "browser_tools_update.icon",
+    "laptop.icon",
     "navigate_back.1x.icon",
     "navigate_back.icon",
     "navigate_forward.1x.icon",
@@ -21,6 +22,22 @@
     "navigate_reload.icon",
     "navigate_stop.1x.icon",
     "navigate_stop.icon",
+    "smartphone.icon",
+    "tab.icon",
+    "tab_audio.1x.icon",
+    "tab_audio.icon",
+    "tab_audio_muting.1x.icon",
+    "tab_audio_muting.icon",
+    "tab_bluetooth_connected.icon",
+    "tab_close_hovered_pressed.1x.icon",
+    "tab_close_hovered_pressed.icon",
+    "tab_close_normal.1x.icon",
+    "tab_close_normal.icon",
+    "tab_media_capturing.icon",
+    "tab_media_recording.icon",
+    "tab_usb_connected.1x.icon",
+    "tab_usb_connected.icon",
+    "tablet.icon",
   ]
 
   output_cc = "$target_gen_dir/vector_icons.cc"
diff --git a/ui/gfx/vector_icons/laptop.icon b/chrome/app/vector_icons/laptop.icon
similarity index 100%
rename from ui/gfx/vector_icons/laptop.icon
rename to chrome/app/vector_icons/laptop.icon
diff --git a/ui/gfx/vector_icons/smartphone.icon b/chrome/app/vector_icons/smartphone.icon
similarity index 100%
rename from ui/gfx/vector_icons/smartphone.icon
rename to chrome/app/vector_icons/smartphone.icon
diff --git a/ui/gfx/vector_icons/tab.icon b/chrome/app/vector_icons/tab.icon
similarity index 100%
rename from ui/gfx/vector_icons/tab.icon
rename to chrome/app/vector_icons/tab.icon
diff --git a/ui/gfx/vector_icons/tab_audio.1x.icon b/chrome/app/vector_icons/tab_audio.1x.icon
similarity index 100%
rename from ui/gfx/vector_icons/tab_audio.1x.icon
rename to chrome/app/vector_icons/tab_audio.1x.icon
diff --git a/ui/gfx/vector_icons/tab_audio.icon b/chrome/app/vector_icons/tab_audio.icon
similarity index 100%
rename from ui/gfx/vector_icons/tab_audio.icon
rename to chrome/app/vector_icons/tab_audio.icon
diff --git a/ui/gfx/vector_icons/tab_audio_muting.1x.icon b/chrome/app/vector_icons/tab_audio_muting.1x.icon
similarity index 100%
rename from ui/gfx/vector_icons/tab_audio_muting.1x.icon
rename to chrome/app/vector_icons/tab_audio_muting.1x.icon
diff --git a/ui/gfx/vector_icons/tab_audio_muting.icon b/chrome/app/vector_icons/tab_audio_muting.icon
similarity index 100%
rename from ui/gfx/vector_icons/tab_audio_muting.icon
rename to chrome/app/vector_icons/tab_audio_muting.icon
diff --git a/ui/gfx/vector_icons/tab_bluetooth_connected.icon b/chrome/app/vector_icons/tab_bluetooth_connected.icon
similarity index 100%
rename from ui/gfx/vector_icons/tab_bluetooth_connected.icon
rename to chrome/app/vector_icons/tab_bluetooth_connected.icon
diff --git a/ui/gfx/vector_icons/tab_close_hovered_pressed.1x.icon b/chrome/app/vector_icons/tab_close_hovered_pressed.1x.icon
similarity index 100%
rename from ui/gfx/vector_icons/tab_close_hovered_pressed.1x.icon
rename to chrome/app/vector_icons/tab_close_hovered_pressed.1x.icon
diff --git a/ui/gfx/vector_icons/tab_close_hovered_pressed.icon b/chrome/app/vector_icons/tab_close_hovered_pressed.icon
similarity index 100%
rename from ui/gfx/vector_icons/tab_close_hovered_pressed.icon
rename to chrome/app/vector_icons/tab_close_hovered_pressed.icon
diff --git a/ui/gfx/vector_icons/tab_close_normal.1x.icon b/chrome/app/vector_icons/tab_close_normal.1x.icon
similarity index 100%
rename from ui/gfx/vector_icons/tab_close_normal.1x.icon
rename to chrome/app/vector_icons/tab_close_normal.1x.icon
diff --git a/ui/gfx/vector_icons/tab_close_normal.icon b/chrome/app/vector_icons/tab_close_normal.icon
similarity index 100%
rename from ui/gfx/vector_icons/tab_close_normal.icon
rename to chrome/app/vector_icons/tab_close_normal.icon
diff --git a/ui/gfx/vector_icons/tab_media_capturing.icon b/chrome/app/vector_icons/tab_media_capturing.icon
similarity index 100%
rename from ui/gfx/vector_icons/tab_media_capturing.icon
rename to chrome/app/vector_icons/tab_media_capturing.icon
diff --git a/ui/gfx/vector_icons/tab_media_recording.icon b/chrome/app/vector_icons/tab_media_recording.icon
similarity index 100%
rename from ui/gfx/vector_icons/tab_media_recording.icon
rename to chrome/app/vector_icons/tab_media_recording.icon
diff --git a/ui/gfx/vector_icons/tab_usb_connected.1x.icon b/chrome/app/vector_icons/tab_usb_connected.1x.icon
similarity index 100%
rename from ui/gfx/vector_icons/tab_usb_connected.1x.icon
rename to chrome/app/vector_icons/tab_usb_connected.1x.icon
diff --git a/ui/gfx/vector_icons/tab_usb_connected.icon b/chrome/app/vector_icons/tab_usb_connected.icon
similarity index 100%
rename from ui/gfx/vector_icons/tab_usb_connected.icon
rename to chrome/app/vector_icons/tab_usb_connected.icon
diff --git a/ui/gfx/vector_icons/tablet.icon b/chrome/app/vector_icons/tablet.icon
similarity index 100%
rename from ui/gfx/vector_icons/tablet.icon
rename to chrome/app/vector_icons/tablet.icon
diff --git a/chrome/browser/android/history/browsing_history_bridge.cc b/chrome/browser/android/history/browsing_history_bridge.cc
index 61fc2bb..5e45e13 100644
--- a/chrome/browser/android/history/browsing_history_bridge.cc
+++ b/chrome/browser/android/history/browsing_history_bridge.cc
@@ -83,7 +83,8 @@
         base::android::ConvertUTF8ToJavaString(env, it->url.spec()),
         base::android::ConvertUTF16ToJavaString(env, domain),
         base::android::ConvertUTF16ToJavaString(env, it->title),
-        base::android::ToJavaLongArray(env, timestamps));
+        base::android::ToJavaLongArray(env, timestamps),
+        it->blocked_visit);
 
     timestamps.clear();
   }
diff --git a/chrome/browser/app_controller_mac_browsertest.mm b/chrome/browser/app_controller_mac_browsertest.mm
index 52ced35b..1cd7d028 100644
--- a/chrome/browser/app_controller_mac_browsertest.mm
+++ b/chrome/browser/app_controller_mac_browsertest.mm
@@ -44,6 +44,7 @@
 #include "components/bookmarks/test/bookmark_test_helpers.h"
 #include "components/prefs/pref_service.h"
 #include "components/signin/core/common/profile_management_switches.h"
+#include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_navigation_observer.h"
@@ -393,7 +394,8 @@
 
 IN_PROC_BROWSER_TEST_F(AppControllerOpenShortcutBrowserTest,
                        OpenShortcutOnStartup) {
-  EXPECT_EQ(1, browser()->tab_strip_model()->count());
+  // The two tabs expected are the Welcome page and the desired URL.
+  EXPECT_EQ(2, browser()->tab_strip_model()->count());
   EXPECT_EQ(g_open_shortcut_url,
       browser()->tab_strip_model()->GetActiveWebContents()
           ->GetLastCommittedURL());
@@ -420,6 +422,15 @@
   // Ensure that there is exactly 1 tab showing, and the tab is the NTP.
   GURL ntp(chrome::kChromeUINewTabURL);
   EXPECT_EQ(1, browser()->tab_strip_model()->count());
+  browser()->tab_strip_model()->GetActiveWebContents()->GetController().LoadURL(
+      GURL(chrome::kChromeUINewTabURL), content::Referrer(),
+      ui::PageTransition::PAGE_TRANSITION_LINK, std::string());
+
+  // Wait for one navigation on the active web contents.
+  content::TestNavigationObserver ntp_navigation_observer(
+      browser()->tab_strip_model()->GetActiveWebContents());
+  ntp_navigation_observer.Wait();
+
   EXPECT_EQ(ntp,
             browser()
                 ->tab_strip_model()
@@ -429,11 +440,10 @@
   GURL simple(embedded_test_server()->GetURL("/simple.html"));
   SendAppleEventToOpenUrlToAppController(simple);
 
-  // Wait for one navigation on the active web contents.
   EXPECT_EQ(1, browser()->tab_strip_model()->count());
-  content::TestNavigationObserver obs(
-      browser()->tab_strip_model()->GetActiveWebContents(), 1);
-  obs.Wait();
+  content::TestNavigationObserver event_navigation_observer(
+      browser()->tab_strip_model()->GetActiveWebContents());
+  event_navigation_observer.Wait();
 
   EXPECT_EQ(simple,
             browser()
diff --git a/chrome/browser/chromeos/arc/arc_session_manager.cc b/chrome/browser/chromeos/arc/arc_session_manager.cc
index 3544f00..4c0c753 100644
--- a/chrome/browser/chromeos/arc/arc_session_manager.cc
+++ b/chrome/browser/chromeos/arc/arc_session_manager.cc
@@ -282,6 +282,17 @@
 void ArcSessionManager::OnProvisioningFinished(ProvisioningResult result) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
+  // If the Mojo message to notify finishing the provisioning is already sent
+  // from the container, it will be processed even after requesting to stop the
+  // container. Ignore all |result|s arriving while ARC is disabled, in order to
+  // avoid popping up an error message triggered below. This code intentionally
+  // does not support the case of reenabling.
+  if (!IsArcEnabled()) {
+    LOG(WARNING) << "Provisioning result received after Arc was disabled. "
+                 << "Ignoring result " << static_cast<int>(result) << ".";
+    return;
+  }
+
   // Due asynchronous nature of stopping the ARC instance,
   // OnProvisioningFinished may arrive after setting the |State::STOPPED| state
   // and |State::Active| is not guaranteed to be set here.
@@ -293,8 +304,8 @@
     DCHECK_NE(result, ProvisioningResult::SUCCESS);
     // TODO (khmel): Consider changing LOG to NOTREACHED once we guaranty that
     // no double message can happen in production.
-    LOG(WARNING) << " Provisioning result was already reported. Ignoring "
-                 << " additional result " << static_cast<int>(result) << ".";
+    LOG(WARNING) << "Provisioning result was already reported. Ignoring "
+                 << "additional result " << static_cast<int>(result) << ".";
     return;
   }
   provisioning_reported_ = true;
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc
index 045c478..ce62e90 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc
@@ -609,6 +609,8 @@
              IDS_REMOVABLE_DEVICE_NAVIGATION_BUTTON_LABEL);
   SET_STRING("REMOVABLE_DEVICE_NAVIGATION_MESSAGE",
              IDS_REMOVABLE_DEVICE_NAVIGATION_MESSAGE);
+  SET_STRING("REMOVABLE_DEVICE_NAVIGATION_MESSAGE_READONLY_POLICY",
+             IDS_REMOVABLE_DEVICE_NAVIGATION_MESSAGE_READONLY_POLICY);
   SET_STRING("REMOVE_FOLDER_SHORTCUT_BUTTON_LABEL",
              IDS_FILE_BROWSER_REMOVE_FOLDER_SHORTCUT_BUTTON_LABEL);
   SET_STRING("RENAME_BUTTON_LABEL", IDS_FILE_BROWSER_RENAME_BUTTON_LABEL);
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
index ce9134f..9cd43a2 100644
--- a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
+++ b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
@@ -21,7 +21,6 @@
 #include "base/metrics/sparse_histogram.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
-#include "base/sys_info.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/input_method/candidate_window_controller.h"
 #include "chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.h"
@@ -33,6 +32,7 @@
 #include "chrome/browser/ui/ash/ash_util.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
+#include "chromeos/system/devicemode.h"
 #include "components/prefs/pref_service.h"
 #include "components/user_manager/user_manager.h"
 #include "third_party/icu/source/common/unicode/uloc.h"
@@ -861,7 +861,7 @@
       is_ime_menu_activated_(false) {
   // TODO(mohsen): Revisit using FakeImeKeyboard with mash when InputController
   // work is ready. http://crbug.com/601981
-  if (base::SysInfo::IsRunningOnChromeOS() && !chrome::IsRunningInMash())
+  if (IsRunningAsSystemCompositor() && !chrome::IsRunningInMash())
     keyboard_.reset(ImeKeyboard::Create());
   else
     keyboard_.reset(new FakeImeKeyboard());
diff --git a/chrome/browser/chromeos/login/session/chrome_session_manager.cc b/chrome/browser/chromeos/login/session/chrome_session_manager.cc
index d50cfdd..4e96f2b 100644
--- a/chrome/browser/chromeos/login/session/chrome_session_manager.cc
+++ b/chrome/browser/chromeos/login/session/chrome_session_manager.cc
@@ -27,7 +27,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/ui/ash/ash_util.h"
-#include "chrome/browser/ui/ash/session_controller_client.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/audio/cras_audio_handler.h"
@@ -135,12 +134,8 @@
 
   bool is_running_test = command_line->HasSwitch(::switches::kTestName) ||
                          command_line->HasSwitch(::switches::kTestType);
-  if (is_running_test) {
-    // Some browser tests (e.g. BrowserTest.GetSizeForNewRenderView) require
-    // that ash is synchronously initialized before the first test window opens.
-    // Ensure the session-related mojo messages are sent to ash.
-    SessionControllerClient::FlushForTesting();
-  } else {
+
+  if (!is_running_test) {
     // Enable CrasAudioHandler logging when chrome restarts after crashing.
     if (chromeos::CrasAudioHandler::IsInitialized())
       chromeos::CrasAudioHandler::Get()->LogErrors();
diff --git a/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc b/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc
index 0292ad6..75874be 100644
--- a/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc
+++ b/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "ash/common/shelf/wm_shelf.h"
 #include "ash/common/wallpaper/wallpaper_controller.h"
 #include "ash/common/wm_shell.h"
 #include "base/memory/ptr_util.h"
@@ -368,6 +369,8 @@
   // For manager user, move wallpaper to locked container so that windows
   // created during the user image picker step are below it.
   ash::WmShell::Get()->wallpaper_controller()->MoveToLockedContainer();
+  ash::WmShelf::ForWindow(ash::WmShell::Get()->GetPrimaryRootWindow())
+      ->SetAlignment(ash::ShelfAlignment::SHELF_ALIGNMENT_BOTTOM_LOCKED);
 
   controller_->SetManagerProfile(manager_profile);
   if (actor_)
diff --git a/chrome/browser/chromeos/net/cert_verify_proc_chromeos_unittest.cc b/chrome/browser/chromeos/net/cert_verify_proc_chromeos_unittest.cc
index 749dfeb..4824ad33 100644
--- a/chrome/browser/chromeos/net/cert_verify_proc_chromeos_unittest.cc
+++ b/chrome/browser/chromeos/net/cert_verify_proc_chromeos_unittest.cc
@@ -85,8 +85,7 @@
     int error =
         verify_proc->Verify(cert, "127.0.0.1", std::string(), flags, NULL,
                             additional_trust_anchors, &verify_result);
-    if (verify_result.verified_cert.get() &&
-        !verify_result.verified_cert->GetIntermediateCertificates().empty()) {
+    if (!verify_result.verified_cert->GetIntermediateCertificates().empty()) {
       net::X509Certificate::OSCertHandle root =
           verify_result.verified_cert->GetIntermediateCertificates().back();
       root_subject_name->assign(root->subjectName);
diff --git a/chrome/browser/chromeos/options/wifi_config_view.cc b/chrome/browser/chromeos/options/wifi_config_view.cc
index 48ff949..84140764 100644
--- a/chrome/browser/chromeos/options/wifi_config_view.cc
+++ b/chrome/browser/chromeos/options/wifi_config_view.cc
@@ -1119,12 +1119,12 @@
             IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PASSPHRASE_HIDE));
     passphrase_visible_button_->SetImage(
         views::ImageButton::STATE_NORMAL,
-        ResourceBundle::GetSharedInstance().
-        GetImageSkiaNamed(IDR_NETWORK_SHOW_PASSWORD));
+        *ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+            IDR_NETWORK_SHOW_PASSWORD));
     passphrase_visible_button_->SetImage(
         views::ImageButton::STATE_HOVERED,
-        ResourceBundle::GetSharedInstance().
-        GetImageSkiaNamed(IDR_NETWORK_SHOW_PASSWORD_HOVER));
+        *ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+            IDR_NETWORK_SHOW_PASSWORD_HOVER));
     passphrase_visible_button_->SetToggledImage(
         views::ImageButton::STATE_NORMAL,
         ResourceBundle::GetSharedInstance().
diff --git a/chrome/browser/chromeos/options/wimax_config_view.cc b/chrome/browser/chromeos/options/wimax_config_view.cc
index 1236787f..92534666 100644
--- a/chrome/browser/chromeos/options/wimax_config_view.cc
+++ b/chrome/browser/chromeos/options/wimax_config_view.cc
@@ -280,12 +280,12 @@
             IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PASSPHRASE_HIDE));
     passphrase_visible_button_->SetImage(
         views::ImageButton::STATE_NORMAL,
-        ResourceBundle::GetSharedInstance().
-        GetImageSkiaNamed(IDR_NETWORK_SHOW_PASSWORD));
+        *ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+            IDR_NETWORK_SHOW_PASSWORD));
     passphrase_visible_button_->SetImage(
         views::ImageButton::STATE_HOVERED,
-        ResourceBundle::GetSharedInstance().
-        GetImageSkiaNamed(IDR_NETWORK_SHOW_PASSWORD_HOVER));
+        *ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+            IDR_NETWORK_SHOW_PASSWORD_HOVER));
     passphrase_visible_button_->SetToggledImage(
         views::ImageButton::STATE_NORMAL,
         ResourceBundle::GetSharedInstance().
diff --git a/chrome/browser/chromeos/preferences.cc b/chrome/browser/chromeos/preferences.cc
index 21a57fa..df889bd3 100644
--- a/chrome/browser/chromeos/preferences.cc
+++ b/chrome/browser/chromeos/preferences.cc
@@ -16,7 +16,6 @@
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/sys_info.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/accessibility/magnification_manager.h"
@@ -32,6 +31,7 @@
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/chromeos_switches.h"
+#include "chromeos/system/devicemode.h"
 #include "chromeos/system/statistics_provider.h"
 #include "chromeos/timezone/timezone_resolver.h"
 #include "components/drive/drive_pref_names.h"
@@ -111,7 +111,7 @@
     user_prefs::PrefRegistrySyncable* registry) {
   std::string hardware_keyboard_id;
   // TODO(yusukes): Remove the runtime hack.
-  if (base::SysInfo::IsRunningOnChromeOS()) {
+  if (IsRunningAsSystemCompositor()) {
     DCHECK(g_browser_process);
     PrefService* local_state = g_browser_process->local_state();
     DCHECK(local_state);
diff --git a/chrome/browser/chromeos/system/input_device_settings_impl_ozone.cc b/chrome/browser/chromeos/system/input_device_settings_impl_ozone.cc
index 7505514..412b742 100644
--- a/chrome/browser/chromeos/system/input_device_settings_impl_ozone.cc
+++ b/chrome/browser/chromeos/system/input_device_settings_impl_ozone.cc
@@ -5,8 +5,8 @@
 #include "chrome/browser/chromeos/system/input_device_settings.h"
 
 #include "base/macros.h"
-#include "base/sys_info.h"
 #include "chrome/browser/chromeos/system/fake_input_device_settings.h"
+#include "chromeos/system/devicemode.h"
 #include "content/public/browser/browser_thread.h"
 #include "services/service_manager/runner/common/client_util.h"
 #include "ui/ozone/public/input_controller.h"
@@ -165,7 +165,7 @@
 // static
 InputDeviceSettings* InputDeviceSettings::Get() {
   if (!g_instance) {
-    if (base::SysInfo::IsRunningOnChromeOS())
+    if (IsRunningAsSystemCompositor())
       g_instance = new InputDeviceSettingsImplOzone;
     else
       g_instance = new FakeInputDeviceSettings();
diff --git a/chrome/browser/permissions/permission_context_base.cc b/chrome/browser/permissions/permission_context_base.cc
index ffb0e8fb..8911b967 100644
--- a/chrome/browser/permissions/permission_context_base.cc
+++ b/chrome/browser/permissions/permission_context_base.cc
@@ -5,13 +5,18 @@
 #include "chrome/browser/permissions/permission_context_base.h"
 
 #include <stddef.h>
+
+#include <set>
+#include <string>
 #include <utility>
 
 #include "base/callback.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/stringprintf.h"
+#include "base/timer/timer.h"
 #include "build/build_config.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/browser/permissions/permission_decision_auto_blocker.h"
 #include "chrome/browser/permissions/permission_request.h"
@@ -21,14 +26,18 @@
 #include "chrome/browser/permissions/permission_uma_util.h"
 #include "chrome/browser/permissions/permission_util.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/safe_browsing/safe_browsing_service.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/content_settings/core/browser/website_settings_registry.h"
 #include "components/prefs/pref_service.h"
+#include "components/safe_browsing_db/database_manager.h"
 #include "components/variations/variations_associated_data.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
 #include "content/public/common/origin_util.h"
 #include "url/gurl.h"
 
@@ -42,6 +51,133 @@
 // static
 const char PermissionContextBase::kPermissionsKillSwitchBlockedValue[] =
     "blocked";
+// Maximum time in milliseconds to wait for safe browsing service to check a
+// url for blacklisting. After this amount of time, the check will be aborted
+// and the url will be treated as not blacklisted.
+// TODO(meredithl): Revisit this once UMA metrics have data about request time.
+const int kCheckUrlTimeoutMs = 2000;
+
+// The client used when checking whether a permission has been blacklisted by
+// Safe Browsing. The check is done asynchronously as no state can be stored in
+// PermissionContextBase (since additional permission requests may be made).
+// This class must be created and destroyed on the UI thread.
+class PermissionsBlacklistingClient
+    : public safe_browsing::SafeBrowsingDatabaseManager::Client,
+      public base::RefCountedThreadSafe<PermissionsBlacklistingClient>,
+      public content::WebContentsObserver {
+ public:
+  static void CheckSafeBrowsingBlacklist(
+      scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager,
+      content::PermissionType permission_type,
+      const GURL& request_origin,
+      content::WebContents* web_contents,
+      int timeout,
+      base::Callback<void(bool)> callback) {
+    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+    new PermissionsBlacklistingClient(db_manager, permission_type,
+                                      request_origin, web_contents, timeout,
+                                      callback);
+  }
+
+ private:
+  friend class base::RefCountedThreadSafe<PermissionsBlacklistingClient>;
+
+  PermissionsBlacklistingClient(
+      scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager,
+      content::PermissionType permission_type,
+      const GURL& request_origin,
+      content::WebContents* web_contents,
+      int timeout,
+      base::Callback<void(bool)> callback)
+      : content::WebContentsObserver(web_contents),
+        db_manager_(db_manager),
+        permission_type_(permission_type),
+        callback_(callback),
+        timeout_(timeout),
+        is_active_(true) {
+    // Balanced by a call to Release() in OnCheckApiBlacklistUrlResult().
+    AddRef();
+    content::BrowserThread::PostTask(
+        content::BrowserThread::IO, FROM_HERE,
+        base::Bind(&PermissionsBlacklistingClient::StartCheck, this,
+                   request_origin));
+  }
+
+  ~PermissionsBlacklistingClient() override {}
+
+  void StartCheck(const GURL& request_origin) {
+    DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+
+    // Start the timer to interrupt into the client callback method with an
+    // empty response if Safe Browsing times out.
+    safe_browsing::ThreatMetadata empty_metadata;
+    timer_ = base::MakeUnique<base::OneShotTimer>();
+    timer_->Start(
+        FROM_HERE, base::TimeDelta::FromMilliseconds(timeout_),
+        base::Bind(&PermissionsBlacklistingClient::OnCheckApiBlacklistUrlResult,
+                   this, request_origin, empty_metadata));
+    db_manager_->CheckApiBlacklistUrl(request_origin, this);
+  }
+
+  // SafeBrowsingDatabaseManager::Client implementation.
+  void OnCheckApiBlacklistUrlResult(
+      const GURL& url,
+      const safe_browsing::ThreatMetadata& metadata) override {
+    DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+
+    if (timer_->IsRunning())
+      timer_->Stop();
+    else
+      db_manager_->CancelApiCheck(this);
+    timer_.reset(nullptr);
+
+    // TODO(meredithl): Convert the strings returned from Safe Browsing to the
+    // ones used by PermissionUtil for comparison.
+    bool permission_blocked =
+        metadata.api_permissions.find(PermissionUtil::GetPermissionString(
+            permission_type_)) != metadata.api_permissions.end();
+
+    content::BrowserThread::PostTask(
+        content::BrowserThread::UI, FROM_HERE,
+        base::Bind(
+            &PermissionsBlacklistingClient::EvaluateBlacklistResultOnUiThread,
+            this, permission_blocked));
+  }
+
+  void EvaluateBlacklistResultOnUiThread(bool permission_blocked) {
+    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+    if (is_active_)
+      callback_.Run(permission_blocked);
+    Release();
+  }
+
+  // WebContentsObserver implementation. Sets the flag so that when the database
+  // manager returns with a result, it won't attempt to run the callback with a
+  // deleted WebContents.
+  void WebContentsDestroyed() override {
+    is_active_ = false;
+    Observe(nullptr);
+  }
+
+  scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager_;
+  content::PermissionType permission_type_;
+
+  // PermissionContextBase callback to run on the UI thread.
+  base::Callback<void(bool)> callback_;
+
+  // Timer to abort the Safe Browsing check if it takes too long. Created and
+  // used on the IO Thread.
+  std::unique_ptr<base::OneShotTimer> timer_;
+  int timeout_;
+
+  // True if |callback_| should be invoked, if web_contents() is destroyed, this
+  // is set to false.
+  bool is_active_;
+
+  DISALLOW_COPY_AND_ASSIGN(PermissionsBlacklistingClient);
+};
 
 PermissionContextBase::PermissionContextBase(
     Profile* profile,
@@ -50,6 +186,7 @@
     : profile_(profile),
       permission_type_(permission_type),
       content_settings_type_(content_settings_type),
+      safe_browsing_timeout_(kCheckUrlTimeoutMs),
       weak_factory_(this) {
 #if defined(OS_ANDROID)
   permission_queue_controller_.reset(new PermissionQueueController(
@@ -101,12 +238,60 @@
     return;
   }
 
+  if (base::FeatureList::IsEnabled(features::kPermissionsBlacklist)) {
+    if (!db_manager_) {
+      safe_browsing::SafeBrowsingService* sb_service =
+          g_browser_process->safe_browsing_service();
+      if (sb_service)
+        db_manager_ = sb_service->database_manager();
+    }
+
+    // The client contacts Safe Browsing, and runs the callback with the result.
+    PermissionsBlacklistingClient::CheckSafeBrowsingBlacklist(
+        db_manager_, permission_type_, requesting_origin, web_contents,
+        safe_browsing_timeout_,
+        base::Bind(&PermissionContextBase::ContinueRequestPermission,
+                   weak_factory_.GetWeakPtr(), web_contents, id,
+                   requesting_origin, embedding_origin, user_gesture,
+                   callback));
+  } else {
+    // TODO(meredithl): Add UMA metrics here.
+    ContinueRequestPermission(web_contents, id, requesting_origin,
+                              embedding_origin, user_gesture, callback,
+                              false /* permission blocked */);
+  }
+}
+
+void PermissionContextBase::ContinueRequestPermission(
+    content::WebContents* web_contents,
+    const PermissionRequestID& id,
+    const GURL& requesting_origin,
+    const GURL& embedding_origin,
+    bool user_gesture,
+    const BrowserPermissionCallback& callback,
+    bool permission_blocked) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  if (permission_blocked) {
+    // TODO(meredithl): Add UMA metrics here.
+    web_contents->GetMainFrame()->AddMessageToConsole(
+        content::CONSOLE_MESSAGE_LEVEL_LOG,
+        base::StringPrintf(
+            "%s permission has been auto-blocked.",
+            PermissionUtil::GetPermissionString(permission_type_).c_str()));
+    // Permission has been blacklisted, block the request.
+    // TODO(meredithl): Consider setting the content setting and persisting
+    // the decision to block.
+    callback.Run(CONTENT_SETTING_BLOCK);
+    return;
+  }
+  // Site is not blacklisted by Safe Browsing for the requested permission.
   ContentSetting content_setting =
       GetPermissionStatus(requesting_origin, embedding_origin);
   if (content_setting == CONTENT_SETTING_ALLOW) {
     HostContentSettingsMapFactory::GetForProfile(profile_)->UpdateLastUsage(
         requesting_origin, embedding_origin, content_settings_type_);
   }
+
   if (content_setting == CONTENT_SETTING_ALLOW ||
       content_setting == CONTENT_SETTING_BLOCK) {
     NotifyPermissionSet(id, requesting_origin, embedding_origin, callback,
@@ -325,3 +510,10 @@
                                       content_settings_type_, std::string(),
                                       content_setting);
 }
+
+void PermissionContextBase::SetSafeBrowsingDatabaseManagerAndTimeoutForTest(
+    scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager,
+    int timeout) {
+  db_manager_ = db_manager;
+  safe_browsing_timeout_ = timeout;
+}
diff --git a/chrome/browser/permissions/permission_context_base.h b/chrome/browser/permissions/permission_context_base.h
index 472c89a..15a32a03 100644
--- a/chrome/browser/permissions/permission_context_base.h
+++ b/chrome/browser/permissions/permission_context_base.h
@@ -28,6 +28,10 @@
 class WebContents;
 }
 
+namespace safe_browsing {
+class SafeBrowsingDatabaseManager;
+}
+
 using BrowserPermissionCallback = base::Callback<void(ContentSetting)>;
 
 // This base class contains common operations for granting permissions.
@@ -80,7 +84,9 @@
                                  bool user_gesture,
                                  const BrowserPermissionCallback& callback);
 
-  // Returns whether the permission has been granted, denied...
+  // Returns whether the permission has been granted, denied etc.
+  // TODO(meredithl): Ensure that the result accurately reflects whether the
+  // origin is blacklisted for this permission.
   ContentSetting GetPermissionStatus(const GURL& requesting_origin,
                                      const GURL& embedding_origin) const;
 
@@ -164,9 +170,26 @@
   // Called when a request is no longer used so it can be cleaned up.
   void CleanUpRequest(const PermissionRequestID& id);
 
+  // Called when the requesting origin and permission have been checked by Safe
+  // Browsing. |permission_blocked| determines whether to auto-block the
+  // permission request without prompting the user for a decision.
+  void ContinueRequestPermission(content::WebContents* web_contents,
+                                 const PermissionRequestID& id,
+                                 const GURL& requesting_origin,
+                                 const GURL& embedding_origin,
+                                 bool user_gesture,
+                                 const BrowserPermissionCallback& callback,
+                                 bool permission_blocked);
+
+  void SetSafeBrowsingDatabaseManagerAndTimeoutForTest(
+      scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager,
+      int timeout);
+
   Profile* profile_;
   const content::PermissionType permission_type_;
   const ContentSettingsType content_settings_type_;
+  int safe_browsing_timeout_;
+  scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager_;
 #if defined(OS_ANDROID)
   std::unique_ptr<PermissionQueueController> permission_queue_controller_;
 #endif
diff --git a/chrome/browser/permissions/permission_context_base_unittest.cc b/chrome/browser/permissions/permission_context_base_unittest.cc
index 4dfe1e41..9284d1a 100644
--- a/chrome/browser/permissions/permission_context_base_unittest.cc
+++ b/chrome/browser/permissions/permission_context_base_unittest.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/permissions/permission_context_base.h"
 
 #include <map>
+#include <set>
 #include <string>
 #include <utility>
 #include <vector>
@@ -14,6 +15,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/field_trial.h"
+#include "base/run_loop.h"
 #include "base/test/histogram_tester.h"
 #include "base/test/mock_entropy_provider.h"
 #include "base/test/scoped_feature_list.h"
@@ -31,7 +33,10 @@
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/content_settings/core/common/content_settings.h"
 #include "components/content_settings/core/common/content_settings_types.h"
+#include "components/safe_browsing_db/database_manager.h"
+#include "components/safe_browsing_db/test_database_manager.h"
 #include "components/variations/variations_associated_data.h"
+#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/permission_type.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
@@ -50,6 +55,47 @@
 const char* const kPromptGroupName = kPermissionsKillSwitchTestGroup;
 const char kPromptTrialName[] = "PermissionPromptsUX";
 
+class MockSafeBrowsingDatabaseManager
+    : public safe_browsing::TestSafeBrowsingDatabaseManager {
+ public:
+  explicit MockSafeBrowsingDatabaseManager(bool perform_callback)
+      : perform_callback_(perform_callback) {}
+
+  bool CheckApiBlacklistUrl(
+      const GURL& url,
+      safe_browsing::SafeBrowsingDatabaseManager::Client* client) override {
+    if (perform_callback_) {
+      safe_browsing::ThreatMetadata metadata;
+      const auto& blacklisted_permissions = permissions_blacklist_.find(url);
+      if (blacklisted_permissions != permissions_blacklist_.end())
+        metadata.api_permissions = blacklisted_permissions->second;
+      client->OnCheckApiBlacklistUrlResult(url, metadata);
+    }
+    // Returns false if scheme is HTTP/HTTPS and able to be checked.
+    return false;
+  }
+
+  bool CancelApiCheck(Client* client) override {
+    DCHECK(!perform_callback_);
+    // Returns true when client check could be stopped.
+    return true;
+  }
+
+  void BlacklistUrlPermissions(const GURL& url,
+                               const std::set<std::string> permissions) {
+    permissions_blacklist_[url] = permissions;
+  }
+
+ protected:
+  ~MockSafeBrowsingDatabaseManager() override {}
+
+ private:
+  bool perform_callback_;
+  std::map<GURL, std::set<std::string>> permissions_blacklist_;
+
+  DISALLOW_COPY_AND_ASSIGN(MockSafeBrowsingDatabaseManager);
+};
+
 class TestPermissionContext : public PermissionContextBase {
  public:
   TestPermissionContext(Profile* profile,
@@ -70,8 +116,16 @@
 
   bool tab_context_updated() const { return tab_context_updated_; }
 
+  // Once a decision for the requested permission has been made, run the
+  // callback.
   void TrackPermissionDecision(ContentSetting content_setting) {
     decisions_.push_back(content_setting);
+    // Null check required here as the quit_closure_ can also be run and reset
+    // first from within DecidePermission.
+    if (quit_closure_) {
+      quit_closure_.Run();
+      quit_closure_.Reset();
+    }
   }
 
   ContentSetting GetContentSettingFromMap(const GURL& url_a,
@@ -81,6 +135,44 @@
                                   content_settings_type(), std::string());
   }
 
+  void RequestPermission(content::WebContents* web_contents,
+                         const PermissionRequestID& id,
+                         const GURL& requesting_frame,
+                         bool user_gesture,
+                         const BrowserPermissionCallback& callback) override {
+    base::RunLoop run_loop;
+    quit_closure_ = run_loop.QuitClosure();
+    PermissionContextBase::RequestPermission(web_contents, id, requesting_frame,
+                                             true /* user_gesture */, callback);
+    run_loop.Run();
+  }
+
+  void DecidePermission(content::WebContents* web_contents,
+                        const PermissionRequestID& id,
+                        const GURL& requesting_origin,
+                        const GURL& embedding_origin,
+                        bool user_gesture,
+                        const BrowserPermissionCallback& callback) override {
+    PermissionContextBase::DecidePermission(web_contents, id, requesting_origin,
+                                            embedding_origin, user_gesture,
+                                            callback);
+    if (respond_permission_) {
+      respond_permission_.Run();
+      respond_permission_.Reset();
+    } else {
+      // Stop the run loop from spinning indefinitely if no response callback
+      // has been set, as is the case with TestParallelRequests.
+      quit_closure_.Run();
+      quit_closure_.Reset();
+    }
+  }
+
+  // Permission request will need to be responded to, so pass a callback to be
+  // run once the request has completed and the decision has been made.
+  void SetRespondPermissionCallback(base::Closure callback) {
+    respond_permission_ = callback;
+  }
+
  protected:
   void UpdateTabContext(const PermissionRequestID& id,
                         const GURL& requesting_origin,
@@ -95,7 +187,10 @@
  private:
   std::vector<ContentSetting> decisions_;
   bool tab_context_updated_;
-
+  base::Closure quit_closure_;
+  // Callback for responding to a permission once the request has been completed
+  // (valid URL, kill switch disabled, not blacklisted)
+  base::Closure respond_permission_;
   DISALLOW_COPY_AND_ASSIGN(TestPermissionContext);
 };
 
@@ -180,13 +275,15 @@
         web_contents()->GetRenderProcessHost()->GetID(),
         web_contents()->GetMainFrame()->GetRoutingID(),
         -1);
+    permission_context.SetRespondPermissionCallback(
+        base::Bind(&PermissionContextBaseTests::RespondToPermission,
+                   base::Unretained(this), &permission_context, id, url,
+                   persist, decision));
     permission_context.RequestPermission(
         web_contents(),
         id, url, true /* user_gesture */,
         base::Bind(&TestPermissionContext::TrackPermissionDecision,
                    base::Unretained(&permission_context)));
-
-    RespondToPermission(&permission_context, id, url, persist, decision);
     ASSERT_EQ(1u, permission_context.decisions().size());
     EXPECT_EQ(decision, permission_context.decisions()[0]);
     EXPECT_TRUE(permission_context.tab_context_updated());
@@ -237,13 +334,16 @@
       const PermissionRequestID id(
           web_contents()->GetRenderProcessHost()->GetID(),
           web_contents()->GetMainFrame()->GetRoutingID(), i);
+
+      permission_context.SetRespondPermissionCallback(
+          base::Bind(&PermissionContextBaseTests::RespondToPermission,
+                     base::Unretained(this), &permission_context, id, url,
+                     false, CONTENT_SETTING_ASK));
+
       permission_context.RequestPermission(
           web_contents(), id, url, true /* user_gesture */,
           base::Bind(&TestPermissionContext::TrackPermissionDecision,
                     base::Unretained(&permission_context)));
-
-      RespondToPermission(&permission_context, id, url, false, /* persist */
-                          CONTENT_SETTING_ASK);
       histograms.ExpectTotalCount(
           "Permissions.Prompt.Dismissed.PriorDismissCount." +
               PermissionUtil::GetPermissionString(permission_type),
@@ -281,13 +381,15 @@
       const PermissionRequestID id(
           web_contents()->GetRenderProcessHost()->GetID(),
           web_contents()->GetMainFrame()->GetRoutingID(), i);
+
+      permission_context.SetRespondPermissionCallback(
+          base::Bind(&PermissionContextBaseTests::RespondToPermission,
+                     base::Unretained(this), &permission_context, id, url,
+                     false, CONTENT_SETTING_ASK));
       permission_context.RequestPermission(
           web_contents(), id, url, true /* user_gesture */,
           base::Bind(&TestPermissionContext::TrackPermissionDecision,
                     base::Unretained(&permission_context)));
-
-      RespondToPermission(&permission_context, id, url, false, /* persist */
-                          CONTENT_SETTING_ASK);
       histograms.ExpectTotalCount(
           "Permissions.Prompt.Dismissed.PriorDismissCount.Geolocation",
           i + 1);
@@ -365,13 +467,15 @@
       const PermissionRequestID id(
           web_contents()->GetRenderProcessHost()->GetID(),
           web_contents()->GetMainFrame()->GetRoutingID(), i);
+      permission_context.SetRespondPermissionCallback(
+          base::Bind(&PermissionContextBaseTests::RespondToPermission,
+                     base::Unretained(this), &permission_context, id, url,
+                     false, CONTENT_SETTING_ASK));
       permission_context.RequestPermission(
           web_contents(), id, url, true /* user_gesture */,
           base::Bind(&TestPermissionContext::TrackPermissionDecision,
-                    base::Unretained(&permission_context)));
+                     base::Unretained(&permission_context)));
 
-      RespondToPermission(&permission_context, id, url, false, /* persist */
-                          CONTENT_SETTING_ASK);
       EXPECT_EQ(1u, permission_context.decisions().size());
       ASSERT_EQ(expected, permission_context.decisions()[0]);
       EXPECT_TRUE(permission_context.tab_context_updated());
@@ -431,14 +535,17 @@
         web_contents()->GetRenderProcessHost()->GetID(),
         web_contents()->GetMainFrame()->GetRoutingID(),
         -1);
+    permission_context.SetRespondPermissionCallback(
+        base::Bind(&PermissionContextBaseTests::RespondToPermission,
+                   base::Unretained(this), &permission_context, id, url, true,
+                   CONTENT_SETTING_ALLOW));
+
     permission_context.RequestPermission(
         web_contents(),
         id, url, true /* user_gesture */,
         base::Bind(&TestPermissionContext::TrackPermissionDecision,
                    base::Unretained(&permission_context)));
 
-    RespondToPermission(&permission_context, id, url, true, /* persist */
-                        CONTENT_SETTING_ALLOW);
     ASSERT_EQ(1u, permission_context.decisions().size());
     EXPECT_EQ(CONTENT_SETTING_ALLOW, permission_context.decisions()[0]);
     EXPECT_TRUE(permission_context.tab_context_updated());
@@ -490,20 +597,26 @@
         web_contents()->GetRenderProcessHost()->GetID(),
         web_contents()->GetMainFrame()->GetRoutingID(), 1);
 
+    bool persist = (response == CONTENT_SETTING_ALLOW ||
+                    response == CONTENT_SETTING_BLOCK);
+
+    // Request a permission without setting the callback to DecidePermission.
     permission_context.RequestPermission(
         web_contents(), id0, url, true /* user_gesture */,
         base::Bind(&TestPermissionContext::TrackPermissionDecision,
                    base::Unretained(&permission_context)));
-    permission_context.RequestPermission(
-        web_contents(), id1, url, true /* user_gesture */,
-        base::Bind(&TestPermissionContext::TrackPermissionDecision,
-                   base::Unretained(&permission_context)));
 
     EXPECT_EQ(0u, permission_context.decisions().size());
 
-    bool persist = (response == CONTENT_SETTING_ALLOW ||
-                    response == CONTENT_SETTING_BLOCK);
-    RespondToPermission(&permission_context, id0, url, persist, response);
+    // Set the callback, and make a second permission request.
+    permission_context.SetRespondPermissionCallback(
+        base::Bind(&PermissionContextBaseTests::RespondToPermission,
+                   base::Unretained(this), &permission_context, id0, url,
+                   persist, response));
+    permission_context.RequestPermission(
+        web_contents(), id1, url, true /* user_gesture */,
+        base::Bind(&TestPermissionContext::TrackPermissionDecision,
+                   base::Unretained(&permission_context)));
 
     ASSERT_EQ(2u, permission_context.decisions().size());
     EXPECT_EQ(response, permission_context.decisions()[0]);
@@ -513,6 +626,37 @@
     EXPECT_EQ(response, permission_context.GetContentSettingFromMap(url, url));
   }
 
+  void TestPermissionsBlacklisting(
+      content::PermissionType permission_type,
+      ContentSettingsType content_settings_type,
+      scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> db_manager,
+      const GURL& url,
+      int timeout,
+      ContentSetting response) {
+    NavigateAndCommit(url);
+    base::test::ScopedFeatureList scoped_feature_list;
+    scoped_feature_list.InitAndEnableFeature(features::kPermissionsBlacklist);
+    TestPermissionContext permission_context(profile(), permission_type,
+                                             content_settings_type);
+    permission_context.SetSafeBrowsingDatabaseManagerAndTimeoutForTest(
+        db_manager, timeout);
+    const PermissionRequestID id(
+        web_contents()->GetRenderProcessHost()->GetID(),
+        web_contents()->GetMainFrame()->GetRoutingID(), -1);
+    // The response callback needs to be set here to test a response being made
+    // in the case of a site not being blacklisted or a safe browsing timeout.
+    permission_context.SetRespondPermissionCallback(base::Bind(
+        &PermissionContextBaseTests::RespondToPermission,
+        base::Unretained(this), &permission_context, id, url, false, response));
+    permission_context.RequestPermission(
+        web_contents(), id, url, true /* user_gesture */,
+        base::Bind(&TestPermissionContext::TrackPermissionDecision,
+                   base::Unretained(&permission_context)));
+
+    ASSERT_EQ(1u, permission_context.decisions().size());
+    EXPECT_EQ(response, permission_context.decisions()[0]);
+  }
+
  private:
   // ChromeRenderViewHostTestHarness:
   void SetUp() override {
@@ -667,3 +811,52 @@
 TEST_F(PermissionContextBaseTests, TestParallelRequestsDismissed) {
   TestParallelRequests(CONTENT_SETTING_ASK);
 }
+
+// Tests a blacklisted (URL, permission) pair has had its permission request
+// blocked.
+TEST_F(PermissionContextBaseTests, TestPermissionsBlacklistingBlocked) {
+  scoped_refptr<MockSafeBrowsingDatabaseManager> db_manager =
+      new MockSafeBrowsingDatabaseManager(true /* perform_callback */);
+  const GURL url("https://www.example.com");
+  std::set<std::string> blacklisted_permissions{
+      PermissionUtil::GetPermissionString(
+          content::PermissionType::GEOLOCATION)};
+  db_manager->BlacklistUrlPermissions(url, blacklisted_permissions);
+  TestPermissionsBlacklisting(content::PermissionType::GEOLOCATION,
+                              CONTENT_SETTINGS_TYPE_GEOLOCATION, db_manager,
+                              url, 2000 /* timeout */, CONTENT_SETTING_BLOCK);
+}
+
+// Tests that a URL with a blacklisted permission is permitted to request a
+// non-blacklisted permission.
+TEST_F(PermissionContextBaseTests, TestPermissionsBlacklistingAllowed) {
+  scoped_refptr<MockSafeBrowsingDatabaseManager> db_manager =
+      new MockSafeBrowsingDatabaseManager(true /* perform_callback */);
+  const GURL url("https://www.example.com");
+  std::set<std::string> blacklisted_permissions{
+      PermissionUtil::GetPermissionString(
+          content::PermissionType::GEOLOCATION)};
+  db_manager->BlacklistUrlPermissions(url, blacklisted_permissions);
+  TestPermissionsBlacklisting(
+      content::PermissionType::GEOLOCATION, CONTENT_SETTINGS_TYPE_GEOLOCATION,
+      db_manager, url, 2000 /* timeout in ms */, CONTENT_SETTING_BLOCK);
+  TestPermissionsBlacklisting(content::PermissionType::NOTIFICATIONS,
+                              CONTENT_SETTINGS_TYPE_NOTIFICATIONS, db_manager,
+                              url, 2000 /* timeout in ms */,
+                              CONTENT_SETTING_ALLOW);
+}
+
+// Tests that a URL with a blacklisted permisison is permitted to request that
+// permission if Safe Browsing has timed out.
+TEST_F(PermissionContextBaseTests, TestSafeBrowsingTimeout) {
+  scoped_refptr<MockSafeBrowsingDatabaseManager> db_manager =
+      new MockSafeBrowsingDatabaseManager(false /* perform_callback */);
+  const GURL url("https://www.example.com");
+  std::set<std::string> blacklisted_permissions{
+      PermissionUtil::GetPermissionString(
+          content::PermissionType::GEOLOCATION)};
+  db_manager->BlacklistUrlPermissions(url, blacklisted_permissions);
+  TestPermissionsBlacklisting(content::PermissionType::GEOLOCATION,
+                              CONTENT_SETTINGS_TYPE_GEOLOCATION, db_manager,
+                              url, 0 /* timeout in ms */, CONTENT_SETTING_ASK);
+}
diff --git a/chrome/browser/resources/md_bookmarks/list.html b/chrome/browser/resources/md_bookmarks/list.html
index 2d9b163..8dd6be98 100644
--- a/chrome/browser/resources/md_bookmarks/list.html
+++ b/chrome/browser/resources/md_bookmarks/list.html
@@ -1,18 +1,22 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/shadow.html">
 <link rel="import" href="chrome://bookmarks/item.html">
 <link rel="import" href="chrome://bookmarks/shared_style.html">
 
 <dom-module id="bookmarks-list">
   <template>
-    <style include="shared-style">
+    <style include="shared-style cr-shared-style">
       :host {
         padding: 20px 32px;
       }
 
-      #bookmarks-card {
+      #bookmarksCard {
         @apply(--shadow-elevation-2dp);
         background-color: #fff;
         margin: 0 auto;
@@ -42,8 +46,29 @@
          $i18n{menuDelete}
       </button>
     </dialog>
-    <div id="bookmarks-card"
-        hidden$="[[isListEmpty_(selectedNode.children.length)]]">
+    <dialog is="cr-dialog" id="editBookmark">
+      <div class="title">$i18n{editBookmarkTitle}</div>
+      <div class="body">
+        <paper-input always-float-label id="name"
+            label="$i18n{editDialogNameInput}"
+            value="{{menuItem_.title}}">
+        </paper-input>
+        <paper-input always-float-label id="url"
+            label="$i18n{editDialogUrlInput}"
+            value="{{menuItem_.url}}">
+        </paper-input>
+      </div>
+      <div class="button-container">
+        <paper-button class="cancel-button" on-tap="onCancelEditTap_">
+          $i18n{cancelEdit}
+        </paper-button>
+        <paper-button class="action-button" on-tap="onSaveEditTap_">
+          $i18n{saveEdit}
+        </paper-button>
+      </div>
+    </dialog>
+    <div id="bookmarksCard">
+      <hidden$="[[isListEmpty_(selectedNode.children.length)]]">
       <template is="dom-repeat" items="[[selectedNode.children]]" as="item">
         <bookmarks-item item="[[item]]"></bookmarks-item>
       </template>
diff --git a/chrome/browser/resources/md_bookmarks/list.js b/chrome/browser/resources/md_bookmarks/list.js
index 59dda20..f1c3b6b6 100644
--- a/chrome/browser/resources/md_bookmarks/list.js
+++ b/chrome/browser/resources/md_bookmarks/list.js
@@ -32,6 +32,8 @@
   /** @private */
   onEditTap_: function() {
     this.closeDropdownMenu_();
+    if (this.menuItem_.url)
+      this.$.editBookmark.showModal();
   },
 
   /** @private */
@@ -58,6 +60,20 @@
   },
 
   /** @private */
+  onSaveEditTap_: function() {
+    chrome.bookmarks.update(this.menuItem_.id, {
+      'title': this.menuItem_.title,
+      'url': this.menuItem_.url,
+    });
+    this.$.editBookmark.close();
+  },
+
+  /** @private */
+  onCancelEditTap_: function() {
+    this.$.editBookmark.cancel();
+  },
+
+  /** @private */
   closeDropdownMenu_: function() {
     var menu = /** @type {!CrActionMenuElement} */ (
         this.$.dropdown);
diff --git a/chrome/browser/resources/md_bookmarks/shared_style.html b/chrome/browser/resources/md_bookmarks/shared_style.html
index fee4fc7..da88367 100644
--- a/chrome/browser/resources/md_bookmarks/shared_style.html
+++ b/chrome/browser/resources/md_bookmarks/shared_style.html
@@ -27,6 +27,11 @@
         height: 1px;
         margin: 8px 0;
       }
+
+      paper-button {
+        height: 32px;
+        margin: 0;
+      }
     </style>
   </template>
 </dom-module>
diff --git a/chrome/browser/resources/md_bookmarks/shared_vars.html b/chrome/browser/resources/md_bookmarks/shared_vars.html
index 5ed9116..efae3f43 100644
--- a/chrome/browser/resources/md_bookmarks/shared_vars.html
+++ b/chrome/browser/resources/md_bookmarks/shared_vars.html
@@ -4,6 +4,10 @@
     --card-min-width: 550px;
     --folder-active-color: #4285f4;
     --folder-inactive-color: #5a5a5a;
+    --paper-input-container-focus-color: var(--google-blue-500);
+    --paper-input-container-input: {
+      font-size: 13px;
+    };
     --primary-text-color: #333;
     --secondary-text-color: #757575;
     --sidebar-width: 256px;
diff --git a/chrome/browser/resources/md_bookmarks/store.js b/chrome/browser/resources/md_bookmarks/store.js
index 18506dd..bdbcb2e 100644
--- a/chrome/browser/resources/md_bookmarks/store.js
+++ b/chrome/browser/resources/md_bookmarks/store.js
@@ -55,9 +55,14 @@
     chrome.bookmarks.getTree(function(results) {
       this.setupStore_(results[0]);
     }.bind(this));
+    // Attach bookmarks API listeners.
     chrome.bookmarks.onRemoved.addListener(this.onBookmarkRemoved_.bind(this));
+    chrome.bookmarks.onChanged.addListener(this.onBookmarkChanged_.bind(this));
   },
 
+////////////////////////////////////////////////////////////////////////////////
+// bookmarks-store, private:
+
   /**
    * @param {BookmarkTreeNode} rootNode
    * @private
@@ -72,6 +77,76 @@
   },
 
   /**
+   * @param {BookmarkTreeNode} folder
+   * @private
+   * @return {boolean}
+   */
+  isAncestorOfSelected_: function(folder) {
+    return this.selectedNode.path.startsWith(folder.path);
+  },
+
+  /** @private */
+  updateSelectedNode_: function() {
+    var selectedNode = this.idToNodeMap_[this.selectedId];
+    this.linkPaths('selectedNode', selectedNode.path);
+    this._setSelectedNode(selectedNode);
+  },
+
+  /**
+   * Remove all descendants of a given node from the map.
+   * @param {string} id
+   * @private
+   */
+  removeDescendantsFromMap_: function(id) {
+    var node = this.idToNodeMap_[id];
+    if (!node)
+      return;
+
+    if (node.children) {
+      for (var i = 0; i < node.children.length; i++)
+        this.removeDescendantsFromMap_(node.children[i].id);
+    }
+    delete this.idToNodeMap_[id];
+  },
+
+////////////////////////////////////////////////////////////////////////////////
+// bookmarks-store, bookmarks API event listeners:
+
+  /**
+   * Callback for when a bookmark node is removed.
+   * If a folder is selected or is an ancestor of a selected folder, the parent
+   * of the removed folder will be selected.
+   * @param {string} id The id of the removed bookmark node.
+   * @param {!{index: number,
+   *           parentId: string,
+   *           node: BookmarkTreeNode}} removeInfo
+   */
+  onBookmarkRemoved_: function(id, removeInfo) {
+    if (this.isAncestorOfSelected_(this.idToNodeMap_[id]))
+      this.fire('selected-folder-changed', removeInfo.parentId);
+
+    var parentNode = this.idToNodeMap_[removeInfo.parentId];
+    this.splice(parentNode.path + '.children', removeInfo.index, 1);
+    this.removeDescendantsFromMap_(id);
+    BookmarksStore.generatePaths(parentNode, removeInfo.index);
+  },
+
+  /**
+   * Called when the title of a bookmark changes.
+   * @param {string} id The id of changed bookmark node.
+   * @param {!Object} changeInfo
+   */
+  onBookmarkChanged_: function(id, changeInfo) {
+    if (changeInfo.title)
+      this.set(this.idToNodeMap_[id].path + '.title', changeInfo.title);
+    if (changeInfo.url)
+      this.set(this.idToNodeMap_[id].path + '.url', changeInfo.url);
+  },
+
+////////////////////////////////////////////////////////////////////////////////
+// bookmarks-store, bookmarks app event listeners:
+
+  /**
    * Selects the folder specified by the event and deselects the previously
    * selected folder.
    * @param {CustomEvent} e
@@ -99,60 +174,11 @@
     if (!folder.isOpen && this.isAncestorOfSelected_(folder))
       this.fire('selected-folder-changed', folder.id);
   },
-
-  /**
-   * @param {BookmarkTreeNode} folder
-   * @private
-   * @return {boolean}
-   */
-  isAncestorOfSelected_: function(folder) {
-    return this.selectedNode.path.startsWith(folder.path);
-  },
-
-  /** @private */
-  updateSelectedNode_: function() {
-    var selectedNode = this.idToNodeMap_[this.selectedId];
-    this.linkPaths('selectedNode', selectedNode.path);
-    this._setSelectedNode(selectedNode);
-  },
-
-  /**
-   * Callback for when a bookmark node is removed.
-   * If a folder is selected or is an ancestor of a selected folder, the parent
-   * of the removed folder will be selected.
-   * @param {string} id The id of the removed bookmark node.
-   * @param {!{index: number,
-   *           parentId: string,
-   *           node: BookmarkTreeNode}} removeInfo
-   */
-  onBookmarkRemoved_: function(id, removeInfo) {
-    if (this.isAncestorOfSelected_(this.idToNodeMap_[id]))
-      this.fire('selected-folder-changed', removeInfo.parentId);
-
-    var parentNode = this.idToNodeMap_[removeInfo.parentId];
-    this.splice(parentNode.path + '.children', removeInfo.index, 1);
-    this.removeDescendantsFromMap_(id);
-    BookmarksStore.generatePaths(parentNode, removeInfo.index);
-  },
-
-  /**
-   * Remove all descendants of a given node from the map.
-   * @param {string} id
-   * @private
-   */
-  removeDescendantsFromMap_: function(id) {
-    var node = this.idToNodeMap_[id];
-    if (!node)
-      return;
-
-    if (node.children) {
-      for (var i = 0; i < node.children.length; i++)
-        this.removeDescendantsFromMap_(node.children[i].id);
-    }
-    delete this.idToNodeMap_[id];
-  },
 });
 
+////////////////////////////////////////////////////////////////////////////////
+// bookmarks-store, static methods:
+
 /**
  * Stores the path from the store to a node inside the node.
  * @param {BookmarkTreeNode} bookmarkNode
diff --git a/chrome/browser/resources/md_history/lazy_load.crisper.js b/chrome/browser/resources/md_history/lazy_load.crisper.js
index ef645d4..d0f32b9b 100644
--- a/chrome/browser/resources/md_history/lazy_load.crisper.js
+++ b/chrome/browser/resources/md_history/lazy_load.crisper.js
@@ -6,7 +6,7 @@
 // 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.
-cr.define("cr.ui",function(){function FocusGrid(){this.rows=[]}FocusGrid.prototype={ignoreFocusChange_:false,onFocus:function(row,e){if(this.ignoreFocusChange_)this.ignoreFocusChange_=false;else this.lastFocused_=e.currentTarget;this.rows.forEach(function(r){r.makeActive(r==row)})},onKeydown:function(row,e){var rowIndex=this.rows.indexOf(row);assert(rowIndex>=0);var newRow=-1;if(e.key=="ArrowUp")newRow=rowIndex-1;else if(e.key=="ArrowDown")newRow=rowIndex+1;else if(e.key=="PageUp")newRow=0;else if(e.key=="PageDown")newRow=this.rows.length-1;var rowToFocus=this.rows[newRow];if(rowToFocus){this.ignoreFocusChange_=true;rowToFocus.getEquivalentElement(this.lastFocused_).focus();e.preventDefault();return true}return false},destroy:function(){this.rows.forEach(function(row){row.destroy()});this.rows.length=0},getRowIndexForTarget:function(target){for(var i=0;i<this.rows.length;++i){if(this.rows[i].getElements().indexOf(target)>=0)return i}return-1},getRowForRoot:function(root){for(var i=0;i<this.rows.length;++i){if(this.rows[i].root==root)return this.rows[i]}return null},addRow:function(row){this.addRowBefore(row,null)},addRowBefore:function(row,nextRow){row.delegate=row.delegate||this;var nextRowIndex=nextRow?this.rows.indexOf(nextRow):-1;if(nextRowIndex==-1)this.rows.push(row);else this.rows.splice(nextRowIndex,0,row)},removeRow:function(row){var nextRowIndex=row?this.rows.indexOf(row):-1;if(nextRowIndex>-1)this.rows.splice(nextRowIndex,1)},ensureRowActive:function(preferredRow){if(this.rows.length==0)return;for(var i=0;i<this.rows.length;++i){if(this.rows[i].isActive())return}(this.rows[preferredRow||0]||this.rows[0]).makeActive(true)}};return{FocusGrid:FocusGrid}});Polymer.PaperButtonBehaviorImpl={properties:{elevation:{type:Number,reflectToAttribute:true,readOnly:true}},observers:["_calculateElevation(focused, disabled, active, pressed, receivedFocusFromKeyboard)","_computeKeyboardClass(receivedFocusFromKeyboard)"],hostAttributes:{role:"button",tabindex:"0",animated:true},_calculateElevation:function(){var e=1;if(this.disabled){e=0}else if(this.active||this.pressed){e=4}else if(this.receivedFocusFromKeyboard){e=3}this._setElevation(e)},_computeKeyboardClass:function(receivedFocusFromKeyboard){this.toggleClass("keyboard-focus",receivedFocusFromKeyboard)},_spaceKeyDownHandler:function(event){Polymer.IronButtonStateImpl._spaceKeyDownHandler.call(this,event);if(this.hasRipple()&&this.getRipple().ripples.length<1){this._ripple.uiDownAction()}},_spaceKeyUpHandler:function(event){Polymer.IronButtonStateImpl._spaceKeyUpHandler.call(this,event);if(this.hasRipple()){this._ripple.uiUpAction()}}};Polymer.PaperButtonBehavior=[Polymer.IronButtonState,Polymer.IronControlState,Polymer.PaperRippleBehavior,Polymer.PaperButtonBehaviorImpl];Polymer({is:"paper-button",behaviors:[Polymer.PaperButtonBehavior],properties:{raised:{type:Boolean,reflectToAttribute:true,value:false,observer:"_calculateElevation"}},_calculateElevation:function(){if(!this.raised){this._setElevation(0)}else{Polymer.PaperButtonBehaviorImpl._calculateElevation.apply(this)}}});Polymer.PaperItemBehaviorImpl={hostAttributes:{role:"option",tabindex:"0"}};Polymer.PaperItemBehavior=[Polymer.IronButtonState,Polymer.IronControlState,Polymer.PaperItemBehaviorImpl];Polymer({is:"paper-item",behaviors:[Polymer.PaperItemBehavior]});
+cr.define("cr.ui",function(){function FocusGrid(){this.rows=[]}FocusGrid.prototype={ignoreFocusChange_:false,onFocus:function(row,e){if(this.ignoreFocusChange_)this.ignoreFocusChange_=false;else this.lastFocused_=e.currentTarget;this.rows.forEach(function(r){r.makeActive(r==row)})},onKeydown:function(row,e){var rowIndex=this.rows.indexOf(row);assert(rowIndex>=0);var newRow=-1;if(e.key=="ArrowUp")newRow=rowIndex-1;else if(e.key=="ArrowDown")newRow=rowIndex+1;else if(e.key=="PageUp")newRow=0;else if(e.key=="PageDown")newRow=this.rows.length-1;var rowToFocus=this.rows[newRow];if(rowToFocus){this.ignoreFocusChange_=true;rowToFocus.getEquivalentElement(this.lastFocused_).focus();e.preventDefault();return true}return false},destroy:function(){this.rows.forEach(function(row){row.destroy()});this.rows.length=0},getRowIndexForTarget:function(target){for(var i=0;i<this.rows.length;++i){if(this.rows[i].getElements().indexOf(target)>=0)return i}return-1},getRowForRoot:function(root){for(var i=0;i<this.rows.length;++i){if(this.rows[i].root==root)return this.rows[i]}return null},addRow:function(row){this.addRowBefore(row,null)},addRowBefore:function(row,nextRow){row.delegate=row.delegate||this;var nextRowIndex=nextRow?this.rows.indexOf(nextRow):-1;if(nextRowIndex==-1)this.rows.push(row);else this.rows.splice(nextRowIndex,0,row)},removeRow:function(row){var nextRowIndex=row?this.rows.indexOf(row):-1;if(nextRowIndex>-1)this.rows.splice(nextRowIndex,1)},ensureRowActive:function(preferredRow){if(this.rows.length==0)return;for(var i=0;i<this.rows.length;++i){if(this.rows[i].isActive())return}(this.rows[preferredRow||0]||this.rows[0]).makeActive(true)}};return{FocusGrid:FocusGrid}});Polymer.PaperButtonBehaviorImpl={properties:{elevation:{type:Number,reflectToAttribute:true,readOnly:true}},observers:["_calculateElevation(focused, disabled, active, pressed, receivedFocusFromKeyboard)","_computeKeyboardClass(receivedFocusFromKeyboard)"],hostAttributes:{role:"button",tabindex:"0",animated:true},_calculateElevation:function(){var e=1;if(this.disabled){e=0}else if(this.active||this.pressed){e=4}else if(this.receivedFocusFromKeyboard){e=3}this._setElevation(e)},_computeKeyboardClass:function(receivedFocusFromKeyboard){this.toggleClass("keyboard-focus",receivedFocusFromKeyboard)},_spaceKeyDownHandler:function(event){Polymer.IronButtonStateImpl._spaceKeyDownHandler.call(this,event);if(this.hasRipple()&&this.getRipple().ripples.length<1){this._ripple.uiDownAction()}},_spaceKeyUpHandler:function(event){Polymer.IronButtonStateImpl._spaceKeyUpHandler.call(this,event);if(this.hasRipple()){this._ripple.uiUpAction()}}};Polymer.PaperButtonBehavior=[Polymer.IronButtonState,Polymer.IronControlState,Polymer.PaperRippleBehavior,Polymer.PaperButtonBehaviorImpl];Polymer({is:"paper-button",behaviors:[Polymer.PaperButtonBehavior],properties:{raised:{type:Boolean,reflectToAttribute:true,value:false,observer:"_calculateElevation"}},_calculateElevation:function(){if(!this.raised){this._setElevation(0)}else{Polymer.PaperButtonBehaviorImpl._calculateElevation.apply(this)}}});
 // 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/lazy_load.html b/chrome/browser/resources/md_history/lazy_load.html
index 6c57a95..9c17c48 100644
--- a/chrome/browser/resources/md_history/lazy_load.html
+++ b/chrome/browser/resources/md_history/lazy_load.html
@@ -6,6 +6,5 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-dropdown/iron-dropdown.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-item.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-tabs/paper-tab.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-tabs/paper-tabs.html">
diff --git a/chrome/browser/resources/md_history/lazy_load.vulcanized.html b/chrome/browser/resources/md_history/lazy_load.vulcanized.html
index 6fdf7a5..ec1d65f 100644
--- a/chrome/browser/resources/md_history/lazy_load.vulcanized.html
+++ b/chrome/browser/resources/md_history/lazy_load.vulcanized.html
@@ -337,130 +337,6 @@
   </template>
 
   </dom-module>
-<dom-module id="paper-item-shared-styles" assetpath="chrome://resources/polymer/v1_0/paper-item/" css-build="shadow">
-  <template>
-    <style scope="paper-item-shared-styles">:host, .paper-item {
-  display: block;
-        position: relative;
-        min-height: var(--paper-item-min-height, 48px);
-        padding: 0px 16px;
-}
-
-.paper-item {
-  font-family: var(--paper-font-subhead_-_font-family); -webkit-font-smoothing: var(--paper-font-subhead_-_-webkit-font-smoothing); font-size: var(--paper-font-subhead_-_font-size); font-weight: var(--paper-font-subhead_-_font-weight); line-height: var(--paper-font-subhead_-_line-height);
-        border:none;
-        outline: none;
-        background: white;
-        width: 100%;
-        text-align: left;
-}
-
-:host([hidden]), .paper-item[hidden] {
-  display: none !important;
-}
-
-:host(.iron-selected), .paper-item.iron-selected {
-  font-weight: var(--paper-item-selected-weight, bold);
-
-        ;
-}
-
-:host([disabled]), .paper-item[disabled] {
-  color: var(--paper-item-disabled-color,var(--disabled-text-color));;
-
-        ;
-}
-
-:host(:focus), .paper-item:focus {
-  position: relative;
-        outline: 0;
-
-        ;
-}
-
-:host(:focus):before, .paper-item:focus:before {
-  position: var(--layout-fit_-_position); top: var(--layout-fit_-_top); right: var(--layout-fit_-_right); bottom: var(--layout-fit_-_bottom); left: var(--layout-fit_-_left);
-
-        background: currentColor;
-        content: '';
-        opacity: var(--dark-divider-opacity);
-        pointer-events: none;
-
-        ;
-}
-
-</style>
-  </template>
-</dom-module>
-
-
-<dom-module id="paper-item" assetpath="chrome://resources/polymer/v1_0/paper-item/" css-build="shadow">
-  <template>
-    
-    <style scope="paper-item">:host, .paper-item {
-  display: block;
-        position: relative;
-        min-height: var(--paper-item-min-height, 48px);
-        padding: 0px 16px;
-}
-
-.paper-item {
-  font-family: var(--paper-font-subhead_-_font-family); -webkit-font-smoothing: var(--paper-font-subhead_-_-webkit-font-smoothing); font-size: var(--paper-font-subhead_-_font-size); font-weight: var(--paper-font-subhead_-_font-weight); line-height: var(--paper-font-subhead_-_line-height);
-        border:none;
-        outline: none;
-        background: white;
-        width: 100%;
-        text-align: left;
-}
-
-:host([hidden]), .paper-item[hidden] {
-  display: none !important;
-}
-
-:host(.iron-selected), .paper-item.iron-selected {
-  font-weight: var(--paper-item-selected-weight, bold);
-
-        ;
-}
-
-:host([disabled]), .paper-item[disabled] {
-  color: var(--paper-item-disabled-color,var(--disabled-text-color));;
-
-        ;
-}
-
-:host(:focus), .paper-item:focus {
-  position: relative;
-        outline: 0;
-
-        ;
-}
-
-:host(:focus):before, .paper-item:focus:before {
-  position: var(--layout-fit_-_position); top: var(--layout-fit_-_top); right: var(--layout-fit_-_right); bottom: var(--layout-fit_-_bottom); left: var(--layout-fit_-_left);
-
-        background: currentColor;
-        content: '';
-        opacity: var(--dark-divider-opacity);
-        pointer-events: none;
-
-        ;
-}
-
-:host {
-  display: var(--layout-horizontal_-_display); -ms-flex-direction: var(--layout-horizontal_-_-ms-flex-direction); -webkit-flex-direction: var(--layout-horizontal_-_-webkit-flex-direction); flex-direction: var(--layout-horizontal_-_flex-direction);
-        -ms-flex-align: var(--layout-center_-_-ms-flex-align); -webkit-align-items: var(--layout-center_-_-webkit-align-items); align-items: var(--layout-center_-_align-items);
-        font-family: var(--paper-font-subhead_-_font-family); -webkit-font-smoothing: var(--paper-font-subhead_-_-webkit-font-smoothing); font-size: var(--paper-font-subhead_-_font-size); font-weight: var(--paper-font-subhead_-_font-weight); line-height: var(--paper-font-subhead_-_line-height);
-
-        ;
-}
-
-</style>
-
-    <content></content>
-  </template>
-
-  </dom-module>
 <dom-module id="cr-action-menu" assetpath="chrome://resources/cr_elements/cr_action_menu/" css-build="shadow">
   <template>
     <style scope="cr-action-menu">:host {
diff --git a/chrome/browser/resources/md_history/list_container.html b/chrome/browser/resources/md_history/list_container.html
index 409a92ef..2c4971a 100644
--- a/chrome/browser/resources/md_history/list_container.html
+++ b/chrome/browser/resources/md_history/list_container.html
@@ -7,8 +7,8 @@
 <link rel="import" href="chrome://history/history_list.html">
 <link rel="import" href="chrome://history/shared_style.html">
 
-<!-- Lazy loaded: cr-dialog, cr-action-menu, history-grouped-list, paper-button,
-  paper-item. -->
+<!-- Lazy loaded: cr-dialog, cr-action-menu, history-grouped-list, paper-button.
+  -->
 
 <dom-module id="history-list-container">
   <template>
diff --git a/chrome/browser/resources/md_history/synced_device_manager.html b/chrome/browser/resources/md_history/synced_device_manager.html
index 78428c3..00630fe1 100644
--- a/chrome/browser/resources/md_history/synced_device_manager.html
+++ b/chrome/browser/resources/md_history/synced_device_manager.html
@@ -2,7 +2,6 @@
 <link rel="import" href="chrome://resources/html/cr/ui/focus_grid.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-item.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 33509c4..484d42a 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -1481,6 +1481,8 @@
       "views/cookie_info_view.h",
       "views/device_chooser_content_view.cc",
       "views/device_chooser_content_view.h",
+      "views/elevation_icon_setter.cc",
+      "views/elevation_icon_setter.h",
       "views/exclusive_access_bubble_views.cc",
       "views/exclusive_access_bubble_views.h",
       "views/exclusive_access_bubble_views_context.h",
@@ -1491,6 +1493,8 @@
       "views/extensions/extension_keybinding_registry_views.h",
       "views/frame/native_widget_mac_frameless_nswindow.h",
       "views/frame/native_widget_mac_frameless_nswindow.mm",
+      "views/global_error_bubble_view.cc",
+      "views/global_error_bubble_view.h",
       "views/harmony/harmony_layout_delegate.cc",
       "views/harmony/harmony_layout_delegate.h",
       "views/harmony/layout_delegate.cc",
@@ -1670,8 +1674,6 @@
         "views/dropdown_bar_host.cc",
         "views/dropdown_bar_host.h",
         "views/dropdown_bar_host_delegate.h",
-        "views/elevation_icon_setter.cc",
-        "views/elevation_icon_setter.h",
         "views/find_bar_host.cc",
         "views/find_bar_host.h",
         "views/find_bar_view.cc",
@@ -1722,8 +1724,6 @@
         "views/frame/web_contents_close_handler.cc",
         "views/frame/web_contents_close_handler.h",
         "views/frame/web_contents_close_handler_delegate.h",
-        "views/global_error_bubble_view.cc",
-        "views/global_error_bubble_view.h",
         "views/hung_renderer_view.cc",
         "views/hung_renderer_view.h",
         "views/ime/ime_warning_bubble_view.cc",
@@ -2317,6 +2317,8 @@
       "cocoa/bookmarks/bookmark_menu_cocoa_controller.mm",
       "cocoa/browser_window_command_handler.h",
       "cocoa/browser_window_command_handler.mm",
+      "cocoa/bubble_anchor_helper_views.h",
+      "cocoa/bubble_anchor_helper_views.mm",
       "cocoa/chrome_command_dispatcher_delegate.h",
       "cocoa/chrome_command_dispatcher_delegate.mm",
       "cocoa/chrome_style.cc",
@@ -2717,6 +2719,7 @@
         "cocoa/fullscreen_window.mm",
         "cocoa/global_error_bubble_controller.h",
         "cocoa/global_error_bubble_controller.mm",
+        "cocoa/global_error_bubble_controller_views.mm",
         "cocoa/gradient_button_cell.h",
         "cocoa/gradient_button_cell.mm",
         "cocoa/has_weak_browser_pointer.h",
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.cc b/chrome/browser/ui/ash/chrome_shell_delegate.cc
index 383874b..1805ff7a 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.cc
@@ -565,6 +565,7 @@
       // chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED instead.
       if (shelf_delegate_)
         shelf_delegate_->OnUserProfileReadyToSwitch(profile);
+      ash::Shell::GetInstance()->OnLoginUserProfilePrepared();
       break;
     }
     case chrome::NOTIFICATION_SESSION_STARTED:
@@ -572,6 +573,7 @@
       // start.
       if (user_manager::UserManager::Get()->GetLoggedInUsers().size() < 2)
         InitAfterFirstSessionStart();
+      ash::WmShell::Get()->ShowShelf();
       break;
     default:
       NOTREACHED() << "Unexpected notification " << type;
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_browsertest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_browsertest.cc
index 5a94a9c1..efb63e6 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_browsertest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_browsertest.cc
@@ -193,7 +193,6 @@
 
   void RunTestOnMainThreadLoop() override {
     controller_ = GetChromeLauncherControllerImpl();
-    ASSERT_TRUE(controller_);
     return extensions::PlatformAppBrowserTest::RunTestOnMainThreadLoop();
   }
 
@@ -264,7 +263,6 @@
         ash::WmShelf::ForWindow(ash::WmShell::Get()->GetPrimaryRootWindow());
     model_ = ash::WmShell::Get()->shelf_model();
     controller_ = GetChromeLauncherControllerImpl();
-    ASSERT_TRUE(controller_);
     return ExtensionBrowserTest::RunTestOnMainThreadLoop();
   }
 
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_stub.cc b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_stub.cc
index b197390..e7d4d41f 100644
--- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_stub.cc
+++ b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_stub.cc
@@ -10,10 +10,6 @@
 
 namespace chrome {
 
-MultiUserWindowManagerStub::MultiUserWindowManagerStub() {}
-
-MultiUserWindowManagerStub::~MultiUserWindowManagerStub() {}
-
 void MultiUserWindowManagerStub::SetWindowOwner(aura::Window* window,
                                                 const AccountId& account_id) {
   NOTIMPLEMENTED();
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_stub.h b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_stub.h
index a6153f5..f7e1be3b 100644
--- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_stub.h
+++ b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_stub.h
@@ -19,8 +19,8 @@
 // This is the implementation of MultiUserWindowManager for single user mode.
 class MultiUserWindowManagerStub : public MultiUserWindowManager {
  public:
-  MultiUserWindowManagerStub();
-  ~MultiUserWindowManagerStub() override;
+  MultiUserWindowManagerStub() {}
+  ~MultiUserWindowManagerStub() override {}
 
   // MultiUserWindowManager overrides:
   void SetWindowOwner(aura::Window* window,
diff --git a/chrome/browser/ui/ash/session_controller_client.cc b/chrome/browser/ui/ash/session_controller_client.cc
index fad60d4..b171cf2f 100644
--- a/chrome/browser/ui/ash/session_controller_client.cc
+++ b/chrome/browser/ui/ash/session_controller_client.cc
@@ -34,8 +34,6 @@
 
 namespace {
 
-SessionControllerClient* g_instance = nullptr;
-
 uint32_t GetSessionId(const User* user) {
   const UserList logged_in_users = UserManager::Get()->GetLoggedInUsers();
   // TODO(xiyuan): Update with real session id when user session tracking
@@ -85,15 +83,9 @@
   SendSessionInfoIfChanged();
   // User sessions and their order will be sent via UserSessionStateObserver
   // even for crash-n-restart.
-
-  DCHECK(!g_instance);
-  g_instance = this;
 }
 
 SessionControllerClient::~SessionControllerClient() {
-  DCHECK_EQ(this, g_instance);
-  g_instance = nullptr;
-
   SessionManager::Get()->RemoveObserver(this);
   UserManager::Get()->RemoveSessionStateObserver(this);
 }
@@ -233,11 +225,6 @@
   DoSwitchActiveUser(account_id);
 }
 
-// static
-void SessionControllerClient::FlushForTesting() {
-  g_instance->session_controller_.FlushForTesting();
-}
-
 void SessionControllerClient::OnSessionStateChanged() {
   SendSessionInfoIfChanged();
 }
diff --git a/chrome/browser/ui/ash/session_controller_client.h b/chrome/browser/ui/ash/session_controller_client.h
index c2d22c9..d97bc6b 100644
--- a/chrome/browser/ui/ash/session_controller_client.h
+++ b/chrome/browser/ui/ash/session_controller_client.h
@@ -50,9 +50,6 @@
   static void DoSwitchActiveUser(const AccountId& account_id);
   static void DoCycleActiveUser(bool next_user);
 
-  // Flushes the mojo pipe to ash.
-  static void FlushForTesting();
-
  private:
   // Connects or reconnects to the |session_controller_| interface and set
   // this object as its client.
diff --git a/chrome/browser/ui/cocoa/bubble_anchor_helper_views.h b/chrome/browser/ui/cocoa/bubble_anchor_helper_views.h
new file mode 100644
index 0000000..527c5ce
--- /dev/null
+++ b/chrome/browser/ui/cocoa/bubble_anchor_helper_views.h
@@ -0,0 +1,16 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_BUBBLE_ANCHOR_HELPER_VIEWS_H_
+#define CHROME_BROWSER_UI_COCOA_BUBBLE_ANCHOR_HELPER_VIEWS_H_
+
+namespace views {
+class BubbleDialogDelegateView;
+}
+
+// Monitors |bubble|'s parent window for size changes, and updates the bubble
+// anchor. The monitor will be deleted when |bubble| is closed.
+void KeepBubbleAnchored(views::BubbleDialogDelegateView* bubble);
+
+#endif  // CHROME_BROWSER_UI_COCOA_BUBBLE_ANCHOR_HELPER_VIEWS_H_
diff --git a/chrome/browser/ui/cocoa/bubble_anchor_helper_views.mm b/chrome/browser/ui/cocoa/bubble_anchor_helper_views.mm
new file mode 100644
index 0000000..fae302e
--- /dev/null
+++ b/chrome/browser/ui/cocoa/bubble_anchor_helper_views.mm
@@ -0,0 +1,109 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/cocoa/bubble_anchor_helper_views.h"
+
+#import <Cocoa/Cocoa.h>
+
+#import "base/mac/scoped_nsobject.h"
+#include "ui/views/bubble/bubble_dialog_delegate.h"
+#include "ui/views/widget/widget_observer.h"
+
+namespace {
+
+// Self-deleting object that hosts Objective-C observers watching for parent
+// window resizes to reposition a bubble Widget. Deletes itself when the bubble
+// Widget closes.
+class BubbleAnchorHelper : public views::WidgetObserver {
+ public:
+  explicit BubbleAnchorHelper(views::BubbleDialogDelegateView* bubble);
+
+ private:
+  // Observe |name| on the bubble parent window with a block to call ReAnchor().
+  void Observe(NSString* name);
+
+  // Whether offset from the left of the parent window is fixed.
+  bool IsMinXFixed() const {
+    return views::BubbleBorder::is_arrow_on_left(bubble_->arrow());
+  }
+
+  // Re-positions |bubble_| so that the offset to the parent window at
+  // construction time is preserved.
+  void ReAnchor();
+
+  // WidgetObserver:
+  void OnWidgetDestroying(views::Widget* widget) override;
+
+  base::scoped_nsobject<NSMutableArray> observer_tokens_;
+  views::BubbleDialogDelegateView* bubble_;
+  CGFloat horizontal_offset_;  // Offset from the left or right.
+  CGFloat vertical_offset_;    // Offset from the top.
+
+  DISALLOW_COPY_AND_ASSIGN(BubbleAnchorHelper);
+};
+
+}  // namespace
+
+void KeepBubbleAnchored(views::BubbleDialogDelegateView* bubble) {
+  new BubbleAnchorHelper(bubble);
+}
+
+BubbleAnchorHelper::BubbleAnchorHelper(views::BubbleDialogDelegateView* bubble)
+    : observer_tokens_([[NSMutableArray alloc] init]), bubble_(bubble) {
+  DCHECK(bubble->GetWidget());
+  DCHECK(bubble->parent_window());
+  bubble->GetWidget()->AddObserver(this);
+
+  NSRect parent_frame = [[bubble->parent_window() window] frame];
+  NSRect bubble_frame = [bubble->GetWidget()->GetNativeWindow() frame];
+
+  // Note: when anchored on the right, this doesn't support changes to the
+  // bubble size, just the parent size.
+  horizontal_offset_ =
+      (IsMinXFixed() ? NSMinX(parent_frame) : NSMaxX(parent_frame)) -
+      NSMinX(bubble_frame);
+  vertical_offset_ = NSMaxY(parent_frame) - NSMinY(bubble_frame);
+
+  Observe(NSWindowDidEnterFullScreenNotification);
+  Observe(NSWindowDidExitFullScreenNotification);
+  Observe(NSWindowDidResizeNotification);
+
+  // Also monitor move. Note that for user-initiated window moves this is not
+  // necessary: the bubble's child window status keeps the position pinned to
+  // the parent during the move (which is handy since AppKit doesn't send out
+  // notifications until the move completes). Programmatic -[NSWindow
+  // setFrame:..] calls, however, do not update child window positions for us.
+  Observe(NSWindowDidMoveNotification);
+}
+
+void BubbleAnchorHelper::Observe(NSString* name) {
+  NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
+  id token = [center addObserverForName:name
+                                 object:[bubble_->parent_window() window]
+                                  queue:nil
+                             usingBlock:^(NSNotification* notification) {
+                               ReAnchor();
+                             }];
+  [observer_tokens_ addObject:token];
+}
+
+void BubbleAnchorHelper::ReAnchor() {
+  NSRect bubble_frame = [bubble_->GetWidget()->GetNativeWindow() frame];
+  NSRect parent_frame = [[bubble_->parent_window() window] frame];
+  if (IsMinXFixed())
+    bubble_frame.origin.x = NSMinX(parent_frame) - horizontal_offset_;
+  else
+    bubble_frame.origin.x = NSMaxX(parent_frame) - horizontal_offset_;
+  bubble_frame.origin.y = NSMaxY(parent_frame) - vertical_offset_;
+  [bubble_->GetWidget()->GetNativeWindow() setFrame:bubble_frame
+                                            display:YES
+                                            animate:NO];
+}
+
+void BubbleAnchorHelper::OnWidgetDestroying(views::Widget* widget) {
+  widget->RemoveObserver(this);
+  for (id token in observer_tokens_.get())
+    [[NSNotificationCenter defaultCenter] removeObserver:token];
+  delete this;
+}
diff --git a/chrome/browser/ui/cocoa/bubble_anchor_helper_views_unittest.mm b/chrome/browser/ui/cocoa/bubble_anchor_helper_views_unittest.mm
new file mode 100644
index 0000000..5046914
--- /dev/null
+++ b/chrome/browser/ui/cocoa/bubble_anchor_helper_views_unittest.mm
@@ -0,0 +1,120 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/cocoa/bubble_anchor_helper_views.h"
+
+#import <Cocoa/Cocoa.h>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/test/material_design_controller_test_api.h"
+#include "ui/views/bubble/bubble_dialog_delegate.h"
+#include "ui/views/test/views_test_base.h"
+#include "ui/views/widget/widget.h"
+
+namespace {
+
+// Anchor offset in screen space (origin at bottom left of screen).
+constexpr int kHorizOffset = 210;
+constexpr int kVertOffset = 320;
+
+class TestBubbleDialogDelegateView : public views::BubbleDialogDelegateView {
+ public:
+  explicit TestBubbleDialogDelegateView(views::BubbleBorder::Arrow arrow)
+      : BubbleDialogDelegateView(nullptr, arrow) {
+    set_close_on_deactivate(false);
+    set_shadow(views::BubbleBorder::NO_ASSETS);
+    int screen_height = NSMaxY([[[NSScreen screens] firstObject] frame]);
+    SetAnchorRect(gfx::Rect(kHorizOffset, screen_height - kVertOffset, 0, 0));
+  }
+
+  ~TestBubbleDialogDelegateView() override {}
+
+  // BubbleDialogDelegateView overrides:
+  gfx::Size GetPreferredSize() const override { return gfx::Size(200, 150); }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TestBubbleDialogDelegateView);
+};
+
+NSWindow* ShowAnchoredBubble(NSWindow* parent,
+                             views::BubbleBorder::Arrow arrow) {
+  TestBubbleDialogDelegateView* bubble =
+      new TestBubbleDialogDelegateView(arrow);
+  bubble->set_parent_window([parent contentView]);
+  views::BubbleDialogDelegateView::CreateBubble(bubble);
+  bubble->GetWidget()->Show();
+  KeepBubbleAnchored(bubble);
+  return bubble->GetWidget()->GetNativeWindow();
+}
+
+}  // namespace
+
+using BubbleAnchorHelperViewsTest = views::ViewsTestBase;
+
+// Test that KeepBubbleAnchored(..) actually keeps the bubble anchored upon a
+// resize of the parent window.
+TEST_F(BubbleAnchorHelperViewsTest, AnchoringFixed) {
+  // Use MD anchoring since the arithmetic is simpler (no arrows).
+  ui::test::MaterialDesignControllerTestAPI md_test_api(
+      ui::MaterialDesignController::MATERIAL_NORMAL);
+  md_test_api.SetSecondaryUiMaterial(true);
+
+  // Released when closed.
+  NSRect parent_frame = NSMakeRect(100, 200, 300, 400);
+  NSWindow* parent =
+      [[NSWindow alloc] initWithContentRect:parent_frame
+                                  styleMask:NSBorderlessWindowMask
+                                    backing:NSBackingStoreBuffered
+                                      defer:NO];
+  [parent makeKeyAndOrderFront:nil];
+
+  NSWindow* child = ShowAnchoredBubble(parent, views::BubbleBorder::TOP_RIGHT);
+
+  // Anchored TOP_RIGHT, so Max X/Y should be anchored.
+  EXPECT_EQ(kHorizOffset, NSMaxX([child frame]));
+  EXPECT_EQ(kVertOffset, NSMaxY([child frame]));
+
+  // Resize the parent from the top right.
+  parent_frame.size.width += 50;
+  parent_frame.size.height += 60;
+  [parent setFrame:parent_frame display:YES animate:NO];
+  EXPECT_EQ(kHorizOffset + 50, NSMaxX([child frame]));
+  EXPECT_EQ(kVertOffset + 60, NSMaxY([child frame]));
+
+  // Resize from the bottom left (no change).
+  parent_frame.size.width -= 50;
+  parent_frame.size.height -= 60;
+  parent_frame = NSOffsetRect(parent_frame, 50, 60);
+  [parent setFrame:parent_frame display:YES animate:NO];
+  EXPECT_EQ(kHorizOffset + 50, NSMaxX([child frame]));
+  EXPECT_EQ(kVertOffset + 60, NSMaxY([child frame]));
+
+  // Move the window.
+  parent_frame = NSOffsetRect(parent_frame, -50, -60);
+  [parent setFrame:parent_frame display:YES animate:NO];
+  EXPECT_EQ(kHorizOffset, NSMaxX([child frame]));
+  EXPECT_EQ(kVertOffset, NSMaxY([child frame]));
+  [child close];
+
+  child = ShowAnchoredBubble(parent, views::BubbleBorder::TOP_LEFT);
+
+  // Anchored TOP_LEFT, so MinX / MaxY should be anchored.
+  EXPECT_EQ(kHorizOffset, NSMinX([child frame]));
+  EXPECT_EQ(kVertOffset, NSMaxY([child frame]));
+
+  // Resize the parent from right (no change).
+  parent_frame.size.width += 50;
+  [parent setFrame:parent_frame display:YES animate:NO];
+  EXPECT_EQ(kHorizOffset, NSMinX([child frame]));
+  EXPECT_EQ(kVertOffset, NSMaxY([child frame]));
+
+  // Resize the parent from the left.
+  parent_frame.size.width -= 50;
+  parent_frame.origin.x += 50;
+  [parent setFrame:parent_frame display:YES animate:NO];
+  EXPECT_EQ(kHorizOffset + 50, NSMinX([child frame]));
+  EXPECT_EQ(kVertOffset, NSMaxY([child frame]));
+
+  [parent close];  // Takes |child| with it.
+}
diff --git a/chrome/browser/ui/cocoa/global_error_bubble_controller.h b/chrome/browser/ui/cocoa/global_error_bubble_controller.h
index 3bce1d5b..ebb0e535 100644
--- a/chrome/browser/ui/cocoa/global_error_bubble_controller.h
+++ b/chrome/browser/ui/cocoa/global_error_bubble_controller.h
@@ -13,6 +13,7 @@
 #import "chrome/browser/ui/cocoa/base_bubble_controller.h"
 
 class Browser;
+class GlobalErrorBubbleViewBase;
 class GlobalErrorWithStandardBubble;
 @class GTMUILocalizerAndLayoutTweaker;
 @class GTMWidthBasedTweaker;
@@ -45,4 +46,11 @@
 
 @end
 
+// Helper to show a toolkit-views global error bubble. Implemented in a views-
+// specific file.
+GlobalErrorBubbleViewBase* ShowViewsGlobalErrorBubbleOnCocoaBrowser(
+    NSPoint anchor,
+    Browser* browser,
+    const base::WeakPtr<GlobalErrorWithStandardBubble>& error);
+
 #endif  // CHROME_BROWSER_UI_COCOA_GLOBAL_ERROR_BUBBLE_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/global_error_bubble_controller.mm b/chrome/browser/ui/cocoa/global_error_bubble_controller.mm
index 0b54a6b..73f4d2c 100644
--- a/chrome/browser/ui/cocoa/global_error_bubble_controller.mm
+++ b/chrome/browser/ui/cocoa/global_error_bubble_controller.mm
@@ -24,10 +24,20 @@
 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTweaker.h"
 #import "ui/base/cocoa/a11y_util.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/material_design/material_design_controller.h"
 #include "ui/gfx/image/image.h"
 
 namespace {
+
 const CGFloat kParagraphSpacing = 6;
+
+ToolbarController* ToolbarControllerForBrowser(Browser* browser) {
+  NSWindow* parent_window = browser->window()->GetNativeWindow();
+  BrowserWindowController* bwc =
+      [BrowserWindowController browserWindowControllerForWindow:parent_window];
+  return [bwc toolbarController];
+}
+
 } // namespace
 
 namespace GlobalErrorBubbleControllerInternal {
@@ -50,10 +60,7 @@
 
 + (GlobalErrorBubbleViewBase*)showForBrowser:(Browser*)browser
     error:(const base::WeakPtr<GlobalErrorWithStandardBubble>&)error {
-  NSWindow* parentWindow = browser->window()->GetNativeWindow();
-  BrowserWindowController* bwc = [BrowserWindowController
-      browserWindowControllerForWindow:parentWindow];
-  NSView* appMenuButton = [[bwc toolbarController] appMenuButton];
+  NSView* appMenuButton = [ToolbarControllerForBrowser(browser) appMenuButton];
   NSPoint offset = NSMakePoint(
       NSMidX([appMenuButton bounds]),
       app_menu_controller::kAppMenuBubblePointOffsetY);
@@ -164,5 +171,9 @@
 GlobalErrorBubbleViewBase* GlobalErrorBubbleViewBase::ShowStandardBubbleView(
     Browser* browser,
     const base::WeakPtr<GlobalErrorWithStandardBubble>& error) {
-  return [GlobalErrorBubbleController showForBrowser:browser error:error];
+  if (!ui::MaterialDesignController::IsSecondaryUiMaterial())
+    return [GlobalErrorBubbleController showForBrowser:browser error:error];
+
+  NSPoint ns_point = [ToolbarControllerForBrowser(browser) appMenuBubblePoint];
+  return ShowViewsGlobalErrorBubbleOnCocoaBrowser(ns_point, browser, error);
 }
diff --git a/chrome/browser/ui/cocoa/global_error_bubble_controller_views.mm b/chrome/browser/ui/cocoa/global_error_bubble_controller_views.mm
new file mode 100644
index 0000000..caa47d7
--- /dev/null
+++ b/chrome/browser/ui/cocoa/global_error_bubble_controller_views.mm
@@ -0,0 +1,32 @@
+// 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/platform_util.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_window.h"
+#import "chrome/browser/ui/cocoa/global_error_bubble_controller.h"
+#include "chrome/browser/ui/views/global_error_bubble_view.h"
+#import "chrome/browser/ui/cocoa/bubble_anchor_helper_views.h"
+#import "ui/base/cocoa/cocoa_base_utils.h"
+#import "ui/gfx/mac/coordinate_conversion.h"
+
+GlobalErrorBubbleViewBase* ShowViewsGlobalErrorBubbleOnCocoaBrowser(
+    NSPoint anchor,
+    Browser* browser,
+    const base::WeakPtr<GlobalErrorWithStandardBubble>& error) {
+  gfx::Point anchor_point =
+      gfx::ScreenPointFromNSPoint(ui::ConvertPointFromWindowToScreen(
+          browser->window()->GetNativeWindow(), anchor));
+  gfx::NativeView parent =
+      platform_util::GetViewForWindow(browser->window()->GetNativeWindow());
+  DCHECK(parent);
+
+  GlobalErrorBubbleView* bubble_view = new GlobalErrorBubbleView(
+      nullptr, anchor_point, views::BubbleBorder::TOP_RIGHT, browser, error);
+  bubble_view->set_parent_window(parent);
+  views::BubbleDialogDelegateView::CreateBubble(bubble_view);
+  bubble_view->GetWidget()->Show();
+  KeepBubbleAnchored(bubble_view);
+  return bubble_view;
+}
diff --git a/chrome/browser/ui/cocoa/hover_close_button.mm b/chrome/browser/ui/cocoa/hover_close_button.mm
index af88b06..a5e59d5 100644
--- a/chrome/browser/ui/cocoa/hover_close_button.mm
+++ b/chrome/browser/ui/cocoa/hover_close_button.mm
@@ -6,6 +6,7 @@
 
 #include "base/mac/foundation_util.h"
 #include "base/strings/sys_string_conversions.h"
+#include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/themes/theme_service.h"
 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
@@ -22,7 +23,6 @@
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/image/image_skia_util_mac.h"
 #include "ui/gfx/paint_vector_icon.h"
-#include "ui/gfx/vector_icons_public.h"
 #include "ui/resources/grit/ui_resources.h"
 
 namespace  {
@@ -160,31 +160,30 @@
 }
 
 - (NSImage*)imageForHoverState:(HoverState)hoverState {
-  gfx::VectorIconId vectorIconID;
+  const gfx::VectorIcon* vectorIcon = nullptr;
   SkColor vectorIconColor = gfx::kPlaceholderColor;
   TabView* tabView = [self tabView];
 
   switch (hoverState) {
     case kHoverStateNone:
-      vectorIconID = gfx::VectorIconId::TAB_CLOSE_NORMAL;
+      vectorIcon = &kTabCloseNormalIcon;
       vectorIconColor =
           tabView ? [tabView iconColor] : tabs::kDefaultTabTextColor;
       break;
     case kHoverStateMouseOver:
       // For mouse over, the icon color is the fill color of the circle.
-      vectorIconID = gfx::VectorIconId::TAB_CLOSE_HOVERED_PRESSED;
+      vectorIcon = &kTabCloseHoveredPressedIcon;
       vectorIconColor = SkColorSetARGB(0xFF, 0xDB, 0x44, 0x37);
       break;
     case kHoverStateMouseDown:
       // For mouse pressed, the icon color is the fill color of the circle.
-      vectorIconID = gfx::VectorIconId::TAB_CLOSE_HOVERED_PRESSED;
+      vectorIcon = &kTabCloseHoveredPressedIcon;
       vectorIconColor = SkColorSetARGB(0xFF, 0xA8, 0x35, 0x2A);
       break;
   }
 
   return NSImageFromImageSkia(
-      gfx::CreateVectorIcon(vectorIconID, kTabCloseButtonSize,
-          vectorIconColor));
+      gfx::CreateVectorIcon(*vectorIcon, kTabCloseButtonSize, vectorIconColor));
 }
 
 - (void)setHoverState:(HoverState)state {
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_controller.h b/chrome/browser/ui/cocoa/toolbar/toolbar_controller.h
index 316a89f9..07004145 100644
--- a/chrome/browser/ui/cocoa/toolbar/toolbar_controller.h
+++ b/chrome/browser/ui/cocoa/toolbar/toolbar_controller.h
@@ -165,6 +165,9 @@
 // Point on the save credit card icon for the save credit card bubble.
 - (NSPoint)saveCreditCardBubblePoint;
 
+// Point in the window's coordinate system for bubbles attached to the app menu.
+- (NSPoint)appMenuBubblePoint;
+
 // Returns the desired toolbar height for the given compression factor.
 - (CGFloat)desiredHeightForCompression:(CGFloat)compressByHeight;
 
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_controller.mm b/chrome/browser/ui/cocoa/toolbar/toolbar_controller.mm
index 73ce5ce8..6568fca 100644
--- a/chrome/browser/ui/cocoa/toolbar/toolbar_controller.mm
+++ b/chrome/browser/ui/cocoa/toolbar/toolbar_controller.mm
@@ -965,18 +965,28 @@
     return locationBarView_->GetBubblePointForDecoration(
         locationBarView_->star_decoration());
 
-  // Grab bottom middle of hotdogs.
-  NSRect frame = appMenuButton_.frame;
-  NSPoint point = NSMakePoint(NSMidX(frame), NSMinY(frame));
-  // Inset to account for the whitespace around the hotdogs.
-  point.y += app_menu_controller::kAppMenuBubblePointOffsetY;
-  return [self.view convertPoint:point toView:nil];
+  return [self appMenuBubblePoint];
 }
 
 - (NSPoint)saveCreditCardBubblePoint {
   return locationBarView_->GetSaveCreditCardBubblePoint();
 }
 
+- (NSPoint)appMenuBubblePoint {
+  NSRect frame = appMenuButton_.frame;
+  NSPoint point;
+  if (ui::MaterialDesignController::IsSecondaryUiMaterial()) {
+    // Use the bottom right for MD-style anchoring (no arrow).
+    point = NSMakePoint(NSMaxX(frame), NSMinY(frame));
+  } else {
+    // Grab bottom middle of hotdogs.
+    point = NSMakePoint(NSMidX(frame), NSMinY(frame));
+    // Inset to account for the whitespace around the hotdogs.
+    point.y += app_menu_controller::kAppMenuBubblePointOffsetY;
+  }
+  return [self.view convertPoint:point toView:nil];
+}
+
 - (CGFloat)baseToolbarHeight {
   // Height of the toolbar in pixels when the bookmark bar is closed.
   const CGFloat kBaseToolbarHeightNormal = 37;
diff --git a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
index 76cb4bb9..3d1c2ea2 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
@@ -86,6 +86,7 @@
 
 namespace {
 
+#if !defined(OS_CHROMEOS)
 // Check that there are two browsers. Find the one that is not |browser|.
 Browser* FindOneOtherBrowser(Browser* browser) {
   // There should only be one other browser.
@@ -107,12 +108,7 @@
   return false;
 #endif
 }
-
-GURL GetSigninPromoURL() {
-  return signin::GetPromoURL(
-      signin_metrics::AccessPoint::ACCESS_POINT_START_PAGE,
-      signin_metrics::Reason::REASON_SIGNIN_PRIMARY_ACCOUNT, false);
-}
+#endif
 
 }  // namespace
 
@@ -237,6 +233,9 @@
 
   Profile* profile = browser()->profile();
 
+  // Do not show Welcome Page this run.
+  profile->GetPrefs()->SetBoolean(prefs::kHasSeenWelcomePage, true);
+
   // Set the startup preference to open these URLs.
   SessionStartupPref pref(SessionStartupPref::URLS);
   pref.urls = urls;
@@ -489,216 +488,6 @@
   EXPECT_FALSE(StartupBrowserCreator::WasRestarted());
 }
 
-// Fails on official builds. See http://crbug.com/313856
-#if defined(GOOGLE_CHROME_BUILD)
-#define MAYBE_AddFirstRunTab DISABLED_AddFirstRunTab
-#else
-#define MAYBE_AddFirstRunTab AddFirstRunTab
-#endif
-IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorTest, MAYBE_AddFirstRunTab) {
-  ASSERT_TRUE(embedded_test_server()->Start());
-  StartupBrowserCreator browser_creator;
-  browser_creator.AddFirstRunTab(
-      embedded_test_server()->GetURL("/title1.html"));
-  browser_creator.AddFirstRunTab(
-      embedded_test_server()->GetURL("/title2.html"));
-
-  // Do a simple non-process-startup browser launch.
-  base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
-  StartupBrowserCreatorImpl launch(base::FilePath(), dummy, &browser_creator,
-                                   chrome::startup::IS_FIRST_RUN);
-  ASSERT_TRUE(launch.Launch(browser()->profile(), std::vector<GURL>(), false));
-
-  // This should have created a new browser window.
-  Browser* new_browser = FindOneOtherBrowser(browser());
-  ASSERT_TRUE(new_browser);
-
-  TabStripModel* tab_strip = new_browser->tab_strip_model();
-  EXPECT_EQ(2, tab_strip->count());
-
-  EXPECT_EQ("title1.html",
-            tab_strip->GetWebContentsAt(0)->GetURL().ExtractFileName());
-  EXPECT_EQ("title2.html",
-            tab_strip->GetWebContentsAt(1)->GetURL().ExtractFileName());
-}
-
-// Test hard-coded special first run tabs (defined in
-// StartupBrowserCreatorImpl::AddStartupURLs()).
-// Fails on official builds. See http://crbug.com/313856
-#if defined(GOOGLE_CHROME_BUILD)
-#define MAYBE_AddCustomFirstRunTab DISABLED_AddCustomFirstRunTab
-#else
-#define MAYBE_AddCustomFirstRunTab AddCustomFirstRunTab
-#endif
-IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorTest, MAYBE_AddCustomFirstRunTab) {
-  ASSERT_TRUE(embedded_test_server()->Start());
-  StartupBrowserCreator browser_creator;
-  browser_creator.AddFirstRunTab(
-      embedded_test_server()->GetURL("/title1.html"));
-  browser_creator.AddFirstRunTab(GURL("http://new_tab_page"));
-  browser_creator.AddFirstRunTab(
-      embedded_test_server()->GetURL("/title2.html"));
-  browser_creator.AddFirstRunTab(GURL("http://welcome_page"));
-
-  // Do a simple non-process-startup browser launch.
-  base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
-  StartupBrowserCreatorImpl launch(base::FilePath(), dummy, &browser_creator,
-                                   chrome::startup::IS_FIRST_RUN);
-  ASSERT_TRUE(launch.Launch(browser()->profile(), std::vector<GURL>(), false));
-
-  // This should have created a new browser window.
-  Browser* new_browser = FindOneOtherBrowser(browser());
-  ASSERT_TRUE(new_browser);
-
-  TabStripModel* tab_strip = new_browser->tab_strip_model();
-  EXPECT_EQ(4, tab_strip->count());
-
-  EXPECT_EQ("title1.html",
-            tab_strip->GetWebContentsAt(0)->GetURL().ExtractFileName());
-  EXPECT_EQ(GURL(chrome::kChromeUINewTabURL),
-            tab_strip->GetWebContentsAt(1)->GetURL());
-  EXPECT_EQ("title2.html",
-            tab_strip->GetWebContentsAt(2)->GetURL().ExtractFileName());
-  EXPECT_EQ(internals::GetWelcomePageURL(),
-            tab_strip->GetWebContentsAt(3)->GetURL());
-}
-
-IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorTest, SyncPromoNoWelcomePage) {
-  // Do a simple non-process-startup browser launch.
-  base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
-  StartupBrowserCreatorImpl launch(base::FilePath(), dummy,
-                                   chrome::startup::IS_FIRST_RUN);
-  ASSERT_TRUE(launch.Launch(browser()->profile(), std::vector<GURL>(), false));
-
-  // This should have created a new browser window.
-  Browser* new_browser = FindOneOtherBrowser(browser());
-  ASSERT_TRUE(new_browser);
-
-  TabStripModel* tab_strip = new_browser->tab_strip_model();
-
-  if (signin::ShouldShowPromoAtStartup(browser()->profile(), true)) {
-    // The browser should show only the promo.
-    ASSERT_EQ(1, tab_strip->count());
-    EXPECT_EQ(GetSigninPromoURL(), tab_strip->GetWebContentsAt(0)->GetURL());
-  } else if (IsWindows10OrNewer()) {
-    // The browser should show the welcome page and the NTP.
-    ASSERT_EQ(2, tab_strip->count());
-    EXPECT_EQ(GURL(internals::GetWelcomePageURL()),
-              tab_strip->GetWebContentsAt(0)->GetURL());
-    EXPECT_EQ(GURL(chrome::kChromeUINewTabURL),
-              tab_strip->GetWebContentsAt(1)->GetURL());
-  } else {
-    // The browser should show only the NTP.
-    ASSERT_EQ(1, tab_strip->count());
-    EXPECT_EQ(GURL(chrome::kChromeUINewTabURL),
-              tab_strip->GetWebContentsAt(0)->GetURL());
-  }
-}
-
-IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorTest, SyncPromoWithWelcomePage) {
-  first_run::SetShouldShowWelcomePage();
-
-  // Do a simple non-process-startup browser launch.
-  base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
-  StartupBrowserCreatorImpl launch(base::FilePath(), dummy,
-                                   chrome::startup::IS_FIRST_RUN);
-  ASSERT_TRUE(launch.Launch(browser()->profile(), std::vector<GURL>(), false));
-
-  // This should have created a new browser window.
-  Browser* new_browser = FindOneOtherBrowser(browser());
-  ASSERT_TRUE(new_browser);
-
-  TabStripModel* tab_strip = new_browser->tab_strip_model();
-  EXPECT_EQ(2, tab_strip->count());
-
-  if (IsWindows10OrNewer()) {
-    EXPECT_EQ(internals::GetWelcomePageURL(),
-              tab_strip->GetWebContentsAt(0)->GetURL());
-    EXPECT_EQ(GURL(chrome::kChromeUINewTabURL),
-              tab_strip->GetWebContentsAt(1)->GetURL());
-  } else {
-    if (signin::ShouldShowPromoAtStartup(browser()->profile(), true)) {
-      EXPECT_EQ(GetSigninPromoURL(), tab_strip->GetWebContentsAt(0)->GetURL());
-    } else {
-      EXPECT_EQ(GURL(chrome::kChromeUINewTabURL),
-                tab_strip->GetWebContentsAt(0)->GetURL());
-    }
-    EXPECT_EQ(internals::GetWelcomePageURL(),
-              tab_strip->GetWebContentsAt(1)->GetURL());
-  }
-}
-
-IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorTest, SyncPromoWithFirstRunTabs) {
-  ASSERT_TRUE(embedded_test_server()->Start());
-  StartupBrowserCreator browser_creator;
-  browser_creator.AddFirstRunTab(
-      embedded_test_server()->GetURL("/title1.html"));
-
-  // The welcome page should not be shown, even if
-  // first_run::ShouldShowWelcomePage() says so, when there are already
-  // more than 2 first run tabs.
-  first_run::SetShouldShowWelcomePage();
-
-  // Do a simple non-process-startup browser launch.
-  base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
-  StartupBrowserCreatorImpl launch(base::FilePath(), dummy, &browser_creator,
-                                   chrome::startup::IS_FIRST_RUN);
-  ASSERT_TRUE(launch.Launch(browser()->profile(), std::vector<GURL>(), false));
-
-  // This should have created a new browser window.
-  Browser* new_browser = FindOneOtherBrowser(browser());
-  ASSERT_TRUE(new_browser);
-
-  TabStripModel* tab_strip = new_browser->tab_strip_model();
-  if (signin::ShouldShowPromoAtStartup(browser()->profile(), true)) {
-    EXPECT_EQ(2, tab_strip->count());
-    EXPECT_EQ(GetSigninPromoURL(), tab_strip->GetWebContentsAt(0)->GetURL());
-    EXPECT_EQ("title1.html",
-              tab_strip->GetWebContentsAt(1)->GetURL().ExtractFileName());
-  } else {
-    EXPECT_EQ(1, tab_strip->count());
-    EXPECT_EQ("title1.html",
-              tab_strip->GetWebContentsAt(0)->GetURL().ExtractFileName());
-  }
-}
-
-// The welcome page should still be shown if there are more than 2 first run
-// tabs, but the welcome page was explcitly added to the first run tabs.
-IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorTest,
-                       SyncPromoWithFirstRunTabsIncludingWelcomePage) {
-  ASSERT_TRUE(embedded_test_server()->Start());
-  StartupBrowserCreator browser_creator;
-  browser_creator.AddFirstRunTab(
-      embedded_test_server()->GetURL("/title1.html"));
-  browser_creator.AddFirstRunTab(GURL("http://welcome_page"));
-
-  // Do a simple non-process-startup browser launch.
-  base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
-  StartupBrowserCreatorImpl launch(base::FilePath(), dummy, &browser_creator,
-                                   chrome::startup::IS_FIRST_RUN);
-  ASSERT_TRUE(launch.Launch(browser()->profile(), std::vector<GURL>(), false));
-
-  // This should have created a new browser window.
-  Browser* new_browser = FindOneOtherBrowser(browser());
-  ASSERT_TRUE(new_browser);
-
-  TabStripModel* tab_strip = new_browser->tab_strip_model();
-  if (signin::ShouldShowPromoAtStartup(browser()->profile(), true)) {
-    EXPECT_EQ(3, tab_strip->count());
-    EXPECT_EQ(GetSigninPromoURL(), tab_strip->GetWebContentsAt(0)->GetURL());
-    EXPECT_EQ("title1.html",
-              tab_strip->GetWebContentsAt(1)->GetURL().ExtractFileName());
-    EXPECT_EQ(internals::GetWelcomePageURL(),
-              tab_strip->GetWebContentsAt(2)->GetURL());
-  } else {
-    EXPECT_EQ(2, tab_strip->count());
-    EXPECT_EQ("title1.html",
-              tab_strip->GetWebContentsAt(0)->GetURL().ExtractFileName());
-    EXPECT_EQ(internals::GetWelcomePageURL(),
-              tab_strip->GetWebContentsAt(1)->GetURL());
-  }
-}
-
 #if !defined(OS_CHROMEOS)
 IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorTest, StartupURLsForTwoProfiles) {
   Profile* default_profile = browser()->profile();
@@ -729,6 +518,10 @@
   pref2.urls = urls2;
   SessionStartupPref::SetStartupPref(other_profile, pref2);
 
+  // Do not show the Welcome Page for either profile.
+  default_profile->GetPrefs()->SetBoolean(prefs::kHasSeenWelcomePage, true);
+  other_profile->GetPrefs()->SetBoolean(prefs::kHasSeenWelcomePage, true);
+
   // Close the browser.
   CloseBrowserAsynchronously(browser());
 
@@ -908,6 +701,12 @@
   Profile* profile_urls = profile_manager->GetProfile(dest_path4);
   ASSERT_TRUE(profile_urls);
 
+  // Avoid showing the Welcome page on all four profiles.
+  profile_home1->GetPrefs()->SetBoolean(prefs::kHasSeenWelcomePage, true);
+  profile_home2->GetPrefs()->SetBoolean(prefs::kHasSeenWelcomePage, true);
+  profile_last->GetPrefs()->SetBoolean(prefs::kHasSeenWelcomePage, true);
+  profile_urls->GetPrefs()->SetBoolean(prefs::kHasSeenWelcomePage, true);
+
   // Set the profiles to open urls, open last visited pages or display the home
   // page.
   SessionStartupPref pref_home(SessionStartupPref::DEFAULT);
@@ -1164,11 +963,6 @@
   void SetUpCommandLine(base::CommandLine* command_line) override;
   void SetUpInProcessBrowserTestFixture() override;
 
-  // Returns true if the platform supports showing the sync promo on first run.
-  static bool PlatformSupportsSyncPromo() {
-    return !IsWindows10OrNewer();
-  }
-
   policy::MockConfigurationPolicyProvider provider_;
   policy::PolicyMap policy_map_;
 };
@@ -1193,331 +987,37 @@
   policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
 }
 
-#if defined(GOOGLE_CHROME_BUILD) && defined(OS_MACOSX)
-// http://crbug.com/314819
-#define MAYBE_SyncPromoForbidden DISABLED_SyncPromoForbidden
-#else
-#define MAYBE_SyncPromoForbidden SyncPromoForbidden
-#endif
-IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorFirstRunTest,
-                       MAYBE_SyncPromoForbidden) {
-  // Consistently enable the welcome page on all platforms.
-  first_run::SetShouldShowWelcomePage();
-
-  // Simulate the following master_preferences:
-  // {
-  //  "sync_promo": {
-  //    "show_on_first_run_allowed": false
-  //  }
-  // }
-  StartupBrowserCreator browser_creator;
-  browser()->profile()->GetPrefs()->SetBoolean(
-      prefs::kSignInPromoShowOnFirstRunAllowed, false);
-
-  // Do a process-startup browser launch.
-  base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
-  StartupBrowserCreatorImpl launch(base::FilePath(), dummy, &browser_creator,
-                                   chrome::startup::IS_FIRST_RUN);
-  ASSERT_TRUE(launch.Launch(browser()->profile(), std::vector<GURL>(), true));
-
-  // This should have created a new browser window.
-  Browser* new_browser = FindOneOtherBrowser(browser());
-  ASSERT_TRUE(new_browser);
-
-  // Verify that the NTP and the welcome page are shown.
-  TabStripModel* tab_strip = new_browser->tab_strip_model();
-  ASSERT_EQ(2, tab_strip->count());
-  if (IsWindows10OrNewer()) {
-    EXPECT_EQ(internals::GetWelcomePageURL(),
-              tab_strip->GetWebContentsAt(0)->GetURL());
-    EXPECT_EQ(GURL(chrome::kChromeUINewTabURL),
-              tab_strip->GetWebContentsAt(1)->GetURL());
-  } else {
-    EXPECT_EQ(GURL(chrome::kChromeUINewTabURL),
-              tab_strip->GetWebContentsAt(0)->GetURL());
-    EXPECT_EQ(internals::GetWelcomePageURL(),
-              tab_strip->GetWebContentsAt(1)->GetURL());
-  }
-}
-
-#if defined(GOOGLE_CHROME_BUILD) && defined(OS_MACOSX)
-// http://crbug.com/314819
-#define MAYBE_SyncPromoAllowed DISABLED_SyncPromoAllowed
-#else
-#define MAYBE_SyncPromoAllowed SyncPromoAllowed
-#endif
-IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorFirstRunTest,
-                       MAYBE_SyncPromoAllowed) {
-  if (!PlatformSupportsSyncPromo())
-    return;
-  // Consistently enable the welcome page on all platforms.
-  first_run::SetShouldShowWelcomePage();
-
-  // Simulate the following master_preferences:
-  // {
-  //  "sync_promo": {
-  //    "show_on_first_run_allowed": true
-  //  }
-  // }
-  StartupBrowserCreator browser_creator;
-  browser()->profile()->GetPrefs()->SetBoolean(
-      prefs::kSignInPromoShowOnFirstRunAllowed, true);
-
-  // Do a process-startup browser launch.
-  base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
-  StartupBrowserCreatorImpl launch(base::FilePath(), dummy, &browser_creator,
-                                   chrome::startup::IS_FIRST_RUN);
-  ASSERT_TRUE(launch.Launch(browser()->profile(), std::vector<GURL>(), true));
-
-  // This should have created a new browser window.
-  Browser* new_browser = FindOneOtherBrowser(browser());
-  ASSERT_TRUE(new_browser);
-
-  // Verify that the sync promo and the welcome page are shown.
-  TabStripModel* tab_strip = new_browser->tab_strip_model();
-  ASSERT_EQ(2, tab_strip->count());
-  EXPECT_EQ(GetSigninPromoURL(), tab_strip->GetWebContentsAt(0)->GetURL());
-  EXPECT_EQ(internals::GetWelcomePageURL(),
-            tab_strip->GetWebContentsAt(1)->GetURL());
-}
-
-#if defined(GOOGLE_CHROME_BUILD) && defined(OS_MACOSX)
-// http://crbug.com/314819
-#define MAYBE_FirstRunTabsPromoAllowed DISABLED_FirstRunTabsPromoAllowed
-#else
-#define MAYBE_FirstRunTabsPromoAllowed FirstRunTabsPromoAllowed
-#endif
-IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorFirstRunTest,
-                       MAYBE_FirstRunTabsPromoAllowed) {
-  if (!PlatformSupportsSyncPromo())
-    return;
-  // Simulate the following master_preferences:
-  // {
-  //  "first_run_tabs" : [
-  //    "/title1.html"
-  //  ],
-  //  "sync_promo": {
-  //    "show_on_first_run_allowed": true
-  //  }
-  // }
+IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorFirstRunTest, AddFirstRunTab) {
   ASSERT_TRUE(embedded_test_server()->Start());
   StartupBrowserCreator browser_creator;
   browser_creator.AddFirstRunTab(
       embedded_test_server()->GetURL("/title1.html"));
-  browser()->profile()->GetPrefs()->SetBoolean(
-      prefs::kSignInPromoShowOnFirstRunAllowed, true);
-
-  // Do a process-startup browser launch.
-  base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
-  StartupBrowserCreatorImpl launch(base::FilePath(), dummy, &browser_creator,
-                                   chrome::startup::IS_FIRST_RUN);
-  ASSERT_TRUE(launch.Launch(browser()->profile(), std::vector<GURL>(), true));
-
-  // This should have created a new browser window.
-  Browser* new_browser = FindOneOtherBrowser(browser());
-  ASSERT_TRUE(new_browser);
-
-  // Verify that the first-run tab is shown and the sync promo has been added.
-  TabStripModel* tab_strip = new_browser->tab_strip_model();
-  ASSERT_EQ(2, tab_strip->count());
-  EXPECT_EQ(GetSigninPromoURL(), tab_strip->GetWebContentsAt(0)->GetURL());
-  EXPECT_EQ("title1.html",
-            tab_strip->GetWebContentsAt(1)->GetURL().ExtractFileName());
-}
-
-#if defined(GOOGLE_CHROME_BUILD) && defined(OS_MACOSX)
-// http://crbug.com/314819
-#define MAYBE_FirstRunTabsContainSyncPromo \
-    DISABLED_FirstRunTabsContainSyncPromo
-#else
-#define MAYBE_FirstRunTabsContainSyncPromo FirstRunTabsContainSyncPromo
-#endif
-IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorFirstRunTest,
-                       MAYBE_FirstRunTabsContainSyncPromo) {
-  if (!PlatformSupportsSyncPromo())
-    return;
-  // Simulate the following master_preferences:
-  // {
-  //  "first_run_tabs" : [
-  //    "/title1.html",
-  //    "chrome://signin/?source=0&next_page=chrome%3A%2F%2Fnewtab%2F"
-  //  ],
-  //  "sync_promo": {
-  //    "show_on_first_run_allowed": true
-  //  }
-  // }
-  ASSERT_TRUE(embedded_test_server()->Start());
-  StartupBrowserCreator browser_creator;
   browser_creator.AddFirstRunTab(
-      embedded_test_server()->GetURL("/title1.html"));
-  browser_creator.AddFirstRunTab(GetSigninPromoURL());
-  browser()->profile()->GetPrefs()->SetBoolean(
-      prefs::kSignInPromoShowOnFirstRunAllowed, true);
+      embedded_test_server()->GetURL("/title2.html"));
 
-  // Do a process-startup browser launch.
+  // Do a simple non-process-startup browser launch.
   base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
+
   StartupBrowserCreatorImpl launch(base::FilePath(), dummy, &browser_creator,
                                    chrome::startup::IS_FIRST_RUN);
-  ASSERT_TRUE(launch.Launch(browser()->profile(), std::vector<GURL>(), true));
+  ASSERT_TRUE(launch.Launch(browser()->profile(), std::vector<GURL>(), false));
 
   // This should have created a new browser window.
   Browser* new_browser = FindOneOtherBrowser(browser());
   ASSERT_TRUE(new_browser);
 
-  // Verify that the first-run tabs are shown and no sync promo has been added
-  // as the first-run tabs contain it already.
   TabStripModel* tab_strip = new_browser->tab_strip_model();
-  ASSERT_EQ(2, tab_strip->count());
+
+  EXPECT_EQ(2, tab_strip->count());
+
   EXPECT_EQ("title1.html",
             tab_strip->GetWebContentsAt(0)->GetURL().ExtractFileName());
-  EXPECT_EQ(GetSigninPromoURL(), tab_strip->GetWebContentsAt(1)->GetURL());
-}
-
-#if defined(GOOGLE_CHROME_BUILD) && defined(OS_MACOSX)
-// http://crbug.com/314819
-#define MAYBE_FirstRunTabsContainNTPSyncPromoAllowed \
-    DISABLED_FirstRunTabsContainNTPSyncPromoAllowed
-#else
-#define MAYBE_FirstRunTabsContainNTPSyncPromoAllowed \
-    FirstRunTabsContainNTPSyncPromoAllowed
-#endif
-IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorFirstRunTest,
-                       MAYBE_FirstRunTabsContainNTPSyncPromoAllowed) {
-  if (!PlatformSupportsSyncPromo())
-    return;
-  // Simulate the following master_preferences:
-  // {
-  //  "first_run_tabs" : [
-  //    "new_tab_page",
-  //    "/title1.html"
-  //  ],
-  //  "sync_promo": {
-  //    "show_on_first_run_allowed": true
-  //  }
-  // }
-  ASSERT_TRUE(embedded_test_server()->Start());
-  StartupBrowserCreator browser_creator;
-  browser_creator.AddFirstRunTab(GURL("http://new_tab_page"));
-  browser_creator.AddFirstRunTab(
-      embedded_test_server()->GetURL("/title1.html"));
-  browser()->profile()->GetPrefs()->SetBoolean(
-      prefs::kSignInPromoShowOnFirstRunAllowed, true);
-
-  // Do a process-startup browser launch.
-  base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
-  StartupBrowserCreatorImpl launch(base::FilePath(), dummy, &browser_creator,
-                                   chrome::startup::IS_FIRST_RUN);
-  ASSERT_TRUE(launch.Launch(browser()->profile(), std::vector<GURL>(), true));
-
-  // This should have created a new browser window.
-  Browser* new_browser = FindOneOtherBrowser(browser());
-  ASSERT_TRUE(new_browser);
-
-  // Verify that the first-run tabs are shown but the NTP that they contain has
-  // been replaced by the sync promo.
-  TabStripModel* tab_strip = new_browser->tab_strip_model();
-  ASSERT_EQ(2, tab_strip->count());
-  EXPECT_EQ(GetSigninPromoURL(), tab_strip->GetWebContentsAt(0)->GetURL());
-  EXPECT_EQ("title1.html",
+  EXPECT_EQ("title2.html",
             tab_strip->GetWebContentsAt(1)->GetURL().ExtractFileName());
 }
 
 #if defined(GOOGLE_CHROME_BUILD) && defined(OS_MACOSX)
 // http://crbug.com/314819
-#define MAYBE_FirstRunTabsContainNTPSyncPromoForbidden \
-    DISABLED_FirstRunTabsContainNTPSyncPromoForbidden
-#else
-#define MAYBE_FirstRunTabsContainNTPSyncPromoForbidden \
-    FirstRunTabsContainNTPSyncPromoForbidden
-#endif
-IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorFirstRunTest,
-                       MAYBE_FirstRunTabsContainNTPSyncPromoForbidden) {
-  if (!PlatformSupportsSyncPromo())
-    return;
-  // Simulate the following master_preferences:
-  // {
-  //  "first_run_tabs" : [
-  //    "new_tab_page",
-  //    "/title1.html"
-  //  ],
-  //  "sync_promo": {
-  //    "show_on_first_run_allowed": false
-  //  }
-  // }
-  ASSERT_TRUE(embedded_test_server()->Start());
-  StartupBrowserCreator browser_creator;
-  browser_creator.AddFirstRunTab(GURL("http://new_tab_page"));
-  browser_creator.AddFirstRunTab(
-      embedded_test_server()->GetURL("/title1.html"));
-  browser()->profile()->GetPrefs()->SetBoolean(
-      prefs::kSignInPromoShowOnFirstRunAllowed, false);
-
-  // Do a process-startup browser launch.
-  base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
-  StartupBrowserCreatorImpl launch(base::FilePath(), dummy, &browser_creator,
-                                   chrome::startup::IS_FIRST_RUN);
-  ASSERT_TRUE(launch.Launch(browser()->profile(), std::vector<GURL>(), true));
-
-  // This should have created a new browser window.
-  Browser* new_browser = FindOneOtherBrowser(browser());
-  ASSERT_TRUE(new_browser);
-
-  // Verify that the first-run tabs are shown, the NTP that they contain has not
-  // not been replaced by the sync promo and no sync promo has been added.
-  TabStripModel* tab_strip = new_browser->tab_strip_model();
-  ASSERT_EQ(2, tab_strip->count());
-  EXPECT_EQ(GURL(chrome::kChromeUINewTabURL),
-            tab_strip->GetWebContentsAt(0)->GetURL());
-  EXPECT_EQ("title1.html",
-            tab_strip->GetWebContentsAt(1)->GetURL().ExtractFileName());
-}
-
-#if defined(GOOGLE_CHROME_BUILD) && defined(OS_MACOSX)
-// http://crbug.com/314819
-#define MAYBE_FirstRunTabsSyncPromoForbidden \
-    DISABLED_FirstRunTabsSyncPromoForbidden
-#else
-#define MAYBE_FirstRunTabsSyncPromoForbidden FirstRunTabsSyncPromoForbidden
-#endif
-IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorFirstRunTest,
-                       MAYBE_FirstRunTabsSyncPromoForbidden) {
-  if (!PlatformSupportsSyncPromo())
-    return;
-  // Simulate the following master_preferences:
-  // {
-  //  "first_run_tabs" : [
-  //    "/title1.html"
-  //  ],
-  //  "sync_promo": {
-  //    "show_on_first_run_allowed": false
-  //  }
-  // }
-  ASSERT_TRUE(embedded_test_server()->Start());
-  StartupBrowserCreator browser_creator;
-  browser_creator.AddFirstRunTab(
-      embedded_test_server()->GetURL("/title1.html"));
-  browser()->profile()->GetPrefs()->SetBoolean(
-      prefs::kSignInPromoShowOnFirstRunAllowed, false);
-
-  // Do a process-startup browser launch.
-  base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
-  StartupBrowserCreatorImpl launch(base::FilePath(), dummy, &browser_creator,
-                                   chrome::startup::IS_FIRST_RUN);
-  ASSERT_TRUE(launch.Launch(browser()->profile(), std::vector<GURL>(), true));
-
-  // This should have created a new browser window.
-  Browser* new_browser = FindOneOtherBrowser(browser());
-  ASSERT_TRUE(new_browser);
-
-  // Verify that the first-run tab is shown and no sync promo has been added.
-  TabStripModel* tab_strip = new_browser->tab_strip_model();
-  ASSERT_EQ(1, tab_strip->count());
-  EXPECT_EQ("title1.html",
-            tab_strip->GetWebContentsAt(0)->GetURL().ExtractFileName());
-}
-
-#if defined(GOOGLE_CHROME_BUILD) && defined(OS_MACOSX)
-// http://crbug.com/314819
 #define MAYBE_RestoreOnStartupURLsPolicySpecified \
     DISABLED_RestoreOnStartupURLsPolicySpecified
 #else
@@ -1526,18 +1026,12 @@
 #endif
 IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorFirstRunTest,
                        MAYBE_RestoreOnStartupURLsPolicySpecified) {
-  if (!PlatformSupportsSyncPromo())
-    return;
-  // Simulate the following master_preferences:
-  // {
-  //  "sync_promo": {
-  //    "show_on_first_run_allowed": true
-  //  }
-  // }
   ASSERT_TRUE(embedded_test_server()->Start());
   StartupBrowserCreator browser_creator;
-  browser()->profile()->GetPrefs()->SetBoolean(
-      prefs::kSignInPromoShowOnFirstRunAllowed, true);
+
+  // Avoid showing the Welcome page.
+  browser()->profile()->GetPrefs()->SetBoolean(prefs::kHasSeenWelcomePage,
+                                               true);
 
   // Set the following user policies:
   // * RestoreOnStartup = RestoreOnStartupIsURLs
@@ -1558,6 +1052,9 @@
   provider_.UpdateChromePolicy(policy_map_);
   base::RunLoop().RunUntilIdle();
 
+  // Close the browser.
+  CloseBrowserAsynchronously(browser());
+
   // Do a process-startup browser launch.
   base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
   StartupBrowserCreatorImpl launch(base::FilePath(), dummy, &browser_creator,
diff --git a/chrome/browser/ui/startup/startup_browser_creator_triggered_reset_browsertest_win.cc b/chrome/browser/ui/startup/startup_browser_creator_triggered_reset_browsertest_win.cc
index 73b1186..1063a26c 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_triggered_reset_browsertest_win.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_triggered_reset_browsertest_win.cc
@@ -24,10 +24,13 @@
 #include "chrome/browser/ui/startup/startup_browser_creator.h"
 #include "chrome/browser/ui/startup/startup_browser_creator_impl.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "components/prefs/pref_service.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -108,6 +111,9 @@
 
   Profile* profile = browser()->profile();
 
+  // Avoid showing the Welcome page.
+  profile->GetPrefs()->SetBoolean(prefs::kHasSeenWelcomePage, true);
+
   // Set the startup preference to open these URLs.
   SessionStartupPref pref(SessionStartupPref::URLS);
   pref.urls = urls;
@@ -146,20 +152,33 @@
     EXPECT_EQ(expected_urls[i], tab_strip->GetWebContentsAt(i)->GetURL());
 }
 
-IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorTriggeredResetTest,
+class StartupBrowserCreatorTriggeredResetFirstRunTest
+    : public StartupBrowserCreatorTriggeredResetTest {
+ public:
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    command_line->AppendSwitch(switches::kForceFirstRun);
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorTriggeredResetFirstRunTest,
                        TestTriggeredResetDoesNotShowWithFirstRunURLs) {
   // The presence of First Run tabs (in production code, these commonly come
   // from master_preferences) should suppress the reset UI. Check that this is
   // the case.
   ASSERT_TRUE(embedded_test_server()->Start());
   StartupBrowserCreator browser_creator;
-  browser_creator.AddFirstRunTab(GURL("http://new_tab_page"));
   browser_creator.AddFirstRunTab(
       embedded_test_server()->GetURL("/title1.html"));
+  browser_creator.AddFirstRunTab(
+      embedded_test_server()->GetURL("/title2.html"));
 
   // Prep the next launch to be offered a reset prompt.
   MockTriggeredProfileResetter::SetHasResetTrigger(true);
 
+  // Avoid showing the Welcome page.
+  browser()->profile()->GetPrefs()->SetBoolean(prefs::kHasSeenWelcomePage,
+                                               true);
+
   // Do a process-startup browser launch.
   base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
   StartupBrowserCreatorImpl launch(base::FilePath(), dummy, &browser_creator,
@@ -174,15 +193,9 @@
   TabStripModel* tab_strip = new_browser->tab_strip_model();
   ASSERT_EQ(2, tab_strip->count());
 
-  GURL expected_first_tab_url =
-      signin::ShouldShowPromoAtStartup(browser()->profile(), true)
-          ? signin::GetPromoURL(
-                signin_metrics::AccessPoint::ACCESS_POINT_START_PAGE,
-                signin_metrics::Reason::REASON_SIGNIN_PRIMARY_ACCOUNT, false)
-          : GURL(chrome::kChromeUINewTabURL);
-  EXPECT_EQ(expected_first_tab_url, tab_strip->GetWebContentsAt(0)->GetURL());
-
   EXPECT_EQ("title1.html",
+            tab_strip->GetWebContentsAt(0)->GetURL().ExtractFileName());
+  EXPECT_EQ("title2.html",
             tab_strip->GetWebContentsAt(1)->GetURL().ExtractFileName());
 }
 
diff --git a/chrome/browser/ui/startup/startup_features.cc b/chrome/browser/ui/startup/startup_features.cc
index 3fd0c9f..7c1bc55 100644
--- a/chrome/browser/ui/startup/startup_features.cc
+++ b/chrome/browser/ui/startup/startup_features.cc
@@ -7,7 +7,7 @@
 namespace features {
 
 const base::Feature kUseConsolidatedStartupFlow{
-    "UseConsolidatedStartupFlow", base::FEATURE_DISABLED_BY_DEFAULT};
+    "UseConsolidatedStartupFlow", base::FEATURE_ENABLED_BY_DEFAULT};
 
 #if defined(OS_WIN)
 const base::Feature kWelcomeWin10InlineStyle{"WelcomeWin10InlineStyle",
diff --git a/chrome/browser/ui/startup/startup_tab_provider.cc b/chrome/browser/ui/startup/startup_tab_provider.cc
index 7ba2072..c3aaac70 100644
--- a/chrome/browser/ui/startup/startup_tab_provider.cc
+++ b/chrome/browser/ui/startup/startup_tab_provider.cc
@@ -9,8 +9,11 @@
 #include "chrome/browser/profile_resetter/triggered_profile_resetter.h"
 #include "chrome/browser/profile_resetter/triggered_profile_resetter_factory.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/tabs/pinned_tab_codec.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/locale_settings.h"
@@ -26,6 +29,10 @@
 #endif
 
 StartupTabs StartupTabProviderImpl::GetOnboardingTabs(Profile* profile) const {
+// Onboarding content has not been launched on Chrome OS.
+#if defined(OS_CHROMEOS)
+  return StartupTabs();
+#else
   if (!profile)
     return StartupTabs();
 
@@ -50,10 +57,11 @@
                                          has_seen_win10_promo, is_signed_in,
                                          is_default_browser);
   }
-#endif
+#endif  // defined(OS_WIN)
 
   return CheckStandardOnboardingTabPolicy(is_first_run, has_seen_welcome_page,
                                           is_signed_in);
+#endif  // defined(OS_CHROMEOS)
 }
 
 StartupTabs StartupTabProviderImpl::GetDistributionFirstRunTabs(
@@ -86,8 +94,20 @@
 StartupTabs StartupTabProviderImpl::GetPreferencesTabs(
     const base::CommandLine& command_line,
     Profile* profile) const {
+  // Attempt to find an existing, non-empty tabbed browser for this profile. If
+  // one exists, preferences tabs are not used.
+  BrowserList* browser_list = BrowserList::GetInstance();
+  auto other_tabbed_browser = std::find_if(
+      browser_list->begin(), browser_list->end(), [profile](Browser* browser) {
+        return browser->profile() == profile && browser->is_type_tabbed() &&
+               !browser->tab_strip_model()->empty();
+      });
+  bool profile_has_other_tabbed_browser =
+      other_tabbed_browser != browser_list->end();
+
   return CheckPreferencesTabPolicy(
-      StartupBrowserCreator::GetSessionStartupPref(command_line, profile));
+      StartupBrowserCreator::GetSessionStartupPref(command_line, profile),
+      profile_has_other_tabbed_browser);
 }
 
 StartupTabs StartupTabProviderImpl::GetNewTabPageTabs(
@@ -167,9 +187,11 @@
 
 // static
 StartupTabs StartupTabProviderImpl::CheckPreferencesTabPolicy(
-    const SessionStartupPref& pref) {
+    const SessionStartupPref& pref,
+    bool profile_has_other_tabbed_browser) {
   StartupTabs tabs;
-  if (pref.type == SessionStartupPref::Type::URLS && !pref.urls.empty()) {
+  if (pref.type == SessionStartupPref::Type::URLS && !pref.urls.empty() &&
+      !profile_has_other_tabbed_browser) {
     for (const auto& url : pref.urls)
       tabs.push_back(StartupTab(url, false));
   }
diff --git a/chrome/browser/ui/startup/startup_tab_provider.h b/chrome/browser/ui/startup/startup_tab_provider.h
index 582509e..633ee02 100644
--- a/chrome/browser/ui/startup/startup_tab_provider.h
+++ b/chrome/browser/ui/startup/startup_tab_provider.h
@@ -91,10 +91,12 @@
   static StartupTabs CheckPinnedTabPolicy(const SessionStartupPref& pref,
                                           const StartupTabs& pinned_tabs);
 
-  // Determines whether preferences indicate that user-specified tabs should be
-  // shown as the default new window content, and returns the specified tabs if
-  // so.
-  static StartupTabs CheckPreferencesTabPolicy(const SessionStartupPref& pref);
+  // Determines whether preferences and window state indicate that
+  // user-specified tabs should be shown as the default new window content, and
+  // returns the specified tabs if so.
+  static StartupTabs CheckPreferencesTabPolicy(
+      const SessionStartupPref& pref,
+      bool profile_has_other_tabbed_browser);
 
   // Determines whether startup preferences require the New Tab Page to be
   // explicitly specified. Session Restore does not expect the NTP to be passed.
diff --git a/chrome/browser/ui/startup/startup_tab_provider_unittest.cc b/chrome/browser/ui/startup/startup_tab_provider_unittest.cc
index 98139b9..226f0b79b 100644
--- a/chrome/browser/ui/startup/startup_tab_provider_unittest.cc
+++ b/chrome/browser/ui/startup/startup_tab_provider_unittest.cc
@@ -192,25 +192,36 @@
   SessionStartupPref pref(SessionStartupPref::Type::URLS);
   pref.urls = {GURL(base::ASCIIToUTF16("https://www.google.com"))};
 
-  StartupTabs output = StartupTabProviderImpl::CheckPreferencesTabPolicy(pref);
+  StartupTabs output =
+      StartupTabProviderImpl::CheckPreferencesTabPolicy(pref, false);
 
   ASSERT_EQ(1U, output.size());
   EXPECT_EQ("www.google.com", output[0].url.host());
 }
 
-TEST(StartupTabProviderTest, CheckPreferencesTabPolicy_Negative) {
+TEST(StartupTabProviderTest, CheckPreferencesTabPolicy_WrongType) {
   SessionStartupPref pref_default(SessionStartupPref::Type::DEFAULT);
   pref_default.urls = {GURL(base::ASCIIToUTF16("https://www.google.com"))};
 
   StartupTabs output =
-      StartupTabProviderImpl::CheckPreferencesTabPolicy(pref_default);
+      StartupTabProviderImpl::CheckPreferencesTabPolicy(pref_default, false);
 
   EXPECT_TRUE(output.empty());
 
   SessionStartupPref pref_last(SessionStartupPref::Type::LAST);
   pref_last.urls = {GURL(base::ASCIIToUTF16("https://www.google.com"))};
 
-  output = StartupTabProviderImpl::CheckPreferencesTabPolicy(pref_last);
+  output = StartupTabProviderImpl::CheckPreferencesTabPolicy(pref_last, false);
+
+  EXPECT_TRUE(output.empty());
+}
+
+TEST(StartupTabProviderTest, CheckPreferencesTabPolicy_NotFirstBrowser) {
+  SessionStartupPref pref(SessionStartupPref::Type::URLS);
+  pref.urls = {GURL(base::ASCIIToUTF16("https://www.google.com"))};
+
+  StartupTabs output =
+      StartupTabProviderImpl::CheckPreferencesTabPolicy(pref, true);
 
   EXPECT_TRUE(output.empty());
 }
diff --git a/chrome/browser/ui/tabs/tab_utils.cc b/chrome/browser/ui/tabs/tab_utils.cc
index bfaa2744..4c198704 100644
--- a/chrome/browser/ui/tabs/tab_utils.cc
+++ b/chrome/browser/ui/tabs/tab_utils.cc
@@ -9,6 +9,7 @@
 #include "base/command_line.h"
 #include "base/strings/string16.h"
 #include "build/build_config.h"
+#include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
 #include "chrome/browser/media/webrtc/media_stream_capture_indicator.h"
 #include "chrome/browser/themes/theme_properties.h"
@@ -23,7 +24,6 @@
 #include "ui/gfx/animation/multi_animation.h"
 #include "ui/gfx/image/image.h"
 #include "ui/gfx/paint_vector_icon.h"
-#include "ui/gfx/vector_icons_public.h"
 #include "ui/native_theme/common_theme.h"
 #include "ui/native_theme/native_theme.h"
 
@@ -177,34 +177,31 @@
 
 gfx::Image GetTabAlertIndicatorImage(TabAlertState alert_state,
                                      SkColor button_color) {
-  gfx::VectorIconId icon_id = gfx::VectorIconId::VECTOR_ICON_NONE;
+  const gfx::VectorIcon* icon = nullptr;
   switch (alert_state) {
     case TabAlertState::AUDIO_PLAYING:
-      icon_id = gfx::VectorIconId::TAB_AUDIO;
+      icon = &kTabAudioIcon;
       break;
     case TabAlertState::AUDIO_MUTING:
-      icon_id = gfx::VectorIconId::TAB_AUDIO_MUTING;
+      icon = &kTabAudioMutingIcon;
       break;
     case TabAlertState::MEDIA_RECORDING:
-      icon_id = gfx::VectorIconId::TAB_MEDIA_RECORDING;
+      icon = &kTabMediaRecordingIcon;
       break;
     case TabAlertState::TAB_CAPTURING:
-      icon_id = gfx::VectorIconId::TAB_MEDIA_CAPTURING;
+      icon = &kTabMediaCapturingIcon;
       break;
     case TabAlertState::BLUETOOTH_CONNECTED:
-      icon_id = gfx::VectorIconId::TAB_BLUETOOTH_CONNECTED;
+      icon = &kTabBluetoothConnectedIcon;
       break;
     case TabAlertState::USB_CONNECTED:
-      icon_id = gfx::VectorIconId::TAB_USB_CONNECTED;
+      icon = &kTabUsbConnectedIcon;
       break;
     case TabAlertState::NONE:
-      break;
+      return gfx::Image();
   }
-  if (icon_id != gfx::VectorIconId::VECTOR_ICON_NONE)
-    return gfx::Image(gfx::CreateVectorIcon(icon_id, 16, button_color));
-
-  NOTREACHED();
-  return gfx::Image();
+  DCHECK(icon);
+  return gfx::Image(gfx::CreateVectorIcon(*icon, 16, button_color));
 }
 
 gfx::Image GetTabAlertIndicatorAffordanceImage(TabAlertState alert_state,
diff --git a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
index 68f0fbf..1cd8dbb 100644
--- a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
+++ b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
@@ -40,9 +40,9 @@
 #include "ui/resources/grit/ui_resources.h"
 
 #if !defined(OS_MACOSX)
+#include "chrome/app/vector_icons/vector_icons.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/paint_vector_icon.h"
-#include "ui/gfx/vector_icons_public.h"
 #endif
 
 #if defined(USE_ASH)
@@ -131,8 +131,8 @@
 }
 
 #if !defined(OS_MACOSX)
-gfx::Image CreateFavicon(gfx::VectorIconId id) {
-  return gfx::Image(gfx::CreateVectorIcon(id, 16, gfx::kChromeIconGrey));
+gfx::Image CreateFavicon(const gfx::VectorIcon& icon) {
+  return gfx::Image(gfx::CreateVectorIcon(icon, 16, gfx::kChromeIconGrey));
 }
 #endif
 
@@ -439,7 +439,7 @@
     SetIcon(last_local_model_index_,
             rb.GetNativeImageNamed(IDR_RECENTLY_CLOSED_WINDOW));
 #else
-    SetIcon(last_local_model_index_, CreateFavicon(gfx::VectorIconId::TAB));
+    SetIcon(last_local_model_index_, CreateFavicon(kTabIcon));
 #endif
 
     int added_count = 0;
@@ -552,7 +552,7 @@
   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
   SetIcon(curr_model_index, rb.GetNativeImageNamed(IDR_RECENTLY_CLOSED_WINDOW));
 #else
-  SetIcon(curr_model_index, CreateFavicon(gfx::VectorIconId::TAB));
+  SetIcon(curr_model_index, CreateFavicon(kTabIcon));
 #endif
   local_window_items_.push_back(window_id);
 }
@@ -604,14 +604,14 @@
   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
   SetIcon(index_in_menu, rb.GetNativeImageNamed(favicon_id));
 #else
-  gfx::VectorIconId favicon_id = gfx::VectorIconId::VECTOR_ICON_NONE;
+  const gfx::VectorIcon* favicon = nullptr;
   switch (device_type) {
     case sync_sessions::SyncedSession::TYPE_PHONE:
-      favicon_id = gfx::VectorIconId::SMARTPHONE;
+      favicon = &kSmartphoneIcon;
       break;
 
     case sync_sessions::SyncedSession::TYPE_TABLET:
-      favicon_id = gfx::VectorIconId::TABLET;
+      favicon = &kTabletIcon;
       break;
 
     case sync_sessions::SyncedSession::TYPE_CHROMEOS:
@@ -620,11 +620,11 @@
     case sync_sessions::SyncedSession::TYPE_LINUX:
     case sync_sessions::SyncedSession::TYPE_OTHER:
     case sync_sessions::SyncedSession::TYPE_UNSET:
-      favicon_id = gfx::VectorIconId::LAPTOP;
+      favicon = &kLaptopIcon;
       break;
   }
 
-  SetIcon(index_in_menu, CreateFavicon(favicon_id));
+  SetIcon(index_in_menu, CreateFavicon(*favicon));
 #endif
 }
 
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 64683b57..81133c1 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
@@ -6,7 +6,11 @@
 
 #include "ash/root_window_controller.h"
 #include "ash/shell.h"
+#include "base/command_line.h"
+#include "base/lazy_instance.h"
+#include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "build/build_config.h"
 #include "chrome/browser/chrome_browser_main.h"
 #include "chrome/browser/ui/ash/ash_init.h"
 #include "chrome/browser/ui/ash/ash_util.h"
@@ -14,21 +18,26 @@
 #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/ash/session_controller_client.h"
-#include "chrome/browser/ui/ash/system_tray_client.h"
-#include "chrome/browser/ui/ash/volume_controller.h"
-#include "chrome/browser/ui/ash/vpn_list_forwarder.h"
 #include "chrome/browser/ui/views/ash/tab_scrubber.h"
 #include "chrome/browser/ui/views/chrome_browser_main_extra_parts_views.h"
 #include "chrome/browser/ui/views/frame/immersive_context_mus.h"
 #include "chrome/browser/ui/views/frame/immersive_handler_factory_mus.h"
-#include "chrome/browser/ui/views/select_file_dialog_extension.h"
-#include "chrome/browser/ui/views/select_file_dialog_extension_factory.h"
+#include "chrome/common/chrome_switches.h"
+#include "ui/aura/env.h"
 #include "ui/keyboard/content/keyboard.h"
 #include "ui/keyboard/keyboard_controller.h"
 #include "ui/wm/core/capture_controller.h"
 #include "ui/wm/core/wm_state.h"
 
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/ui/ash/session_controller_client.h"
+#include "chrome/browser/ui/ash/system_tray_client.h"
+#include "chrome/browser/ui/ash/volume_controller.h"
+#include "chrome/browser/ui/ash/vpn_list_forwarder.h"
+#include "chrome/browser/ui/views/select_file_dialog_extension.h"
+#include "chrome/browser/ui/views/select_file_dialog_extension_factory.h"
+#endif  // defined(OS_CHROMEOS)
+
 ChromeBrowserMainExtraPartsAsh::ChromeBrowserMainExtraPartsAsh(
     ChromeBrowserMainExtraPartsViews* extra_parts_views)
     : extra_parts_views_(extra_parts_views) {}
@@ -45,7 +54,10 @@
     immersive_handler_factory_ = base::MakeUnique<ImmersiveHandlerFactoryMus>();
   }
 
-  session_controller_client_ = base::MakeUnique<SessionControllerClient>();
+#if defined(OS_CHROMEOS)
+  // TODO(xiyuan): Update after SesssionStateDelegate is deprecated.
+  if (chrome::IsRunningInMash())
+    session_controller_client_ = base::MakeUnique<SessionControllerClient>();
 
   // Must be available at login screen, so initialize before profile.
   system_tray_client_ = base::MakeUnique<SystemTrayClient>();
@@ -59,6 +71,7 @@
   keyboard::InitializeKeyboard();
 
   ui::SelectFileDialog::SetFactory(new SelectFileDialogExtensionFactory);
+#endif  // defined(OS_CHROMEOS)
 }
 
 void ChromeBrowserMainExtraPartsAsh::PostProfileInit() {
@@ -86,6 +99,7 @@
 }
 
 void ChromeBrowserMainExtraPartsAsh::PostMainMessageLoopRun() {
+#if defined(OS_CHROMEOS)
   vpn_list_forwarder_.reset();
   volume_controller_.reset();
   new_window_client_.reset();
@@ -93,6 +107,6 @@
   media_client_.reset();
   cast_config_client_media_router_.reset();
   session_controller_client_.reset();
-
+#endif
   chrome::CloseAsh();
 }
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 ccc19ee..a8c56d5 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
@@ -22,8 +22,6 @@
 class VolumeController;
 class VpnListForwarder;
 
-// Browser initialization for Ash. Only runs on Chrome OS.
-// TODO(jamescook): Fold this into ChromeBrowserMainPartsChromeOS.
 class ChromeBrowserMainExtraPartsAsh : public ChromeBrowserMainExtraParts {
  public:
   explicit ChromeBrowserMainExtraPartsAsh(
diff --git a/chrome/browser/ui/views/frame/browser_header_painter_ash.cc b/chrome/browser/ui/views/frame/browser_header_painter_ash.cc
index 45d2a559..c61cb3f 100644
--- a/chrome/browser/ui/views/frame/browser_header_painter_ash.cc
+++ b/chrome/browser/ui/views/frame/browser_header_painter_ash.cc
@@ -7,6 +7,7 @@
 #include "ash/common/ash_layout_constants.h"
 #include "ash/common/frame/caption_buttons/frame_caption_button_container_view.h"
 #include "ash/common/frame/header_painter_util.h"
+#include "ash/resources/vector_icons/vector_icons.h"
 #include "base/logging.h"  // DCHECK
 #include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/ui/browser.h"
@@ -22,7 +23,6 @@
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/skia_util.h"
-#include "ui/gfx/vector_icons_public.h"
 #include "ui/views/view.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_delegate.h"
@@ -285,29 +285,27 @@
 }
 
 void BrowserHeaderPainterAsh::UpdateCaptionButtons() {
-  caption_button_container_->SetButtonImage(
-      ash::CAPTION_BUTTON_ICON_MINIMIZE,
-      gfx::VectorIconId::WINDOW_CONTROL_MINIMIZE);
-  caption_button_container_->SetButtonImage(
-      ash::CAPTION_BUTTON_ICON_CLOSE, gfx::VectorIconId::WINDOW_CONTROL_CLOSE);
+  caption_button_container_->SetButtonImage(ash::CAPTION_BUTTON_ICON_MINIMIZE,
+                                            ash::kWindowControlMinimizeIcon);
+  caption_button_container_->SetButtonImage(ash::CAPTION_BUTTON_ICON_CLOSE,
+                                            ash::kWindowControlCloseIcon);
   caption_button_container_->SetButtonImage(
       ash::CAPTION_BUTTON_ICON_LEFT_SNAPPED,
-      gfx::VectorIconId::WINDOW_CONTROL_LEFT_SNAPPED);
+      ash::kWindowControlLeftSnappedIcon);
   caption_button_container_->SetButtonImage(
       ash::CAPTION_BUTTON_ICON_RIGHT_SNAPPED,
-      gfx::VectorIconId::WINDOW_CONTROL_RIGHT_SNAPPED);
+      ash::kWindowControlRightSnappedIcon);
 
-  gfx::VectorIconId size_icon_id = gfx::VectorIconId::WINDOW_CONTROL_MAXIMIZE;
+  const gfx::VectorIcon* size_icon = &ash::kWindowControlMaximizeIcon;
   gfx::Size button_size(
       GetAshLayoutSize(AshLayoutSize::BROWSER_RESTORED_CAPTION_BUTTON));
   if (frame_->IsMaximized() || frame_->IsFullscreen()) {
-    size_icon_id = gfx::VectorIconId::WINDOW_CONTROL_RESTORE;
+    size_icon = &ash::kWindowControlRestoreIcon;
     button_size =
         GetAshLayoutSize(AshLayoutSize::BROWSER_MAXIMIZED_CAPTION_BUTTON);
   }
   caption_button_container_->SetButtonImage(
-      ash::CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE,
-      size_icon_id);
+      ash::CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE, *size_icon);
   caption_button_container_->SetButtonSize(button_size);
 }
 
diff --git a/chrome/browser/ui/views/global_error_bubble_view.cc b/chrome/browser/ui/views/global_error_bubble_view.cc
index db0ed5a0..62789d9 100644
--- a/chrome/browser/ui/views/global_error_bubble_view.cc
+++ b/chrome/browser/ui/views/global_error_bubble_view.cc
@@ -14,10 +14,10 @@
 #include "chrome/browser/ui/global_error/global_error_service_factory.h"
 #include "chrome/browser/ui/layout_constants.h"
 #include "chrome/browser/ui/views/elevation_icon_setter.h"
-#include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/toolbar/app_menu_button.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
 #include "ui/base/resource/resource_bundle.h"
+#include "ui/base/ui_features.h"
 #include "ui/gfx/image/image.h"
 #include "ui/views/bubble/bubble_frame_view.h"
 #include "ui/views/controls/button/blue_button.h"
@@ -28,6 +28,10 @@
 #include "ui/views/layout/layout_constants.h"
 #include "ui/views/window/dialog_client_view.h"
 
+#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#endif
+
 namespace {
 
 const int kMaxBubbleViewWidth = 362;
@@ -36,29 +40,36 @@
 
 // GlobalErrorBubbleViewBase ---------------------------------------------------
 
+#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
 // static
 GlobalErrorBubbleViewBase* GlobalErrorBubbleViewBase::ShowStandardBubbleView(
     Browser* browser,
     const base::WeakPtr<GlobalErrorWithStandardBubble>& error) {
   BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser);
   views::View* app_menu_button = browser_view->toolbar()->app_menu_button();
-  GlobalErrorBubbleView* bubble_view = new GlobalErrorBubbleView(
-      app_menu_button, views::BubbleBorder::TOP_RIGHT, browser, error);
+  GlobalErrorBubbleView* bubble_view =
+      new GlobalErrorBubbleView(app_menu_button, gfx::Point(),
+                                views::BubbleBorder::TOP_RIGHT, browser, error);
   views::BubbleDialogDelegateView::CreateBubble(bubble_view);
   bubble_view->GetWidget()->Show();
   return bubble_view;
 }
+#endif  // !OS_MACOSX || MAC_VIEWS_BROWSER
 
 // GlobalErrorBubbleView -------------------------------------------------------
 
 GlobalErrorBubbleView::GlobalErrorBubbleView(
     views::View* anchor_view,
+    const gfx::Point& anchor_point,
     views::BubbleBorder::Arrow arrow,
     Browser* browser,
     const base::WeakPtr<GlobalErrorWithStandardBubble>& error)
     : BubbleDialogDelegateView(anchor_view, arrow),
       browser_(browser),
-      error_(error) {}
+      error_(error) {
+  if (!anchor_view)
+    SetAnchorRect(gfx::Rect(anchor_point, gfx::Size()));
+}
 
 GlobalErrorBubbleView::~GlobalErrorBubbleView() {}
 
diff --git a/chrome/browser/ui/views/global_error_bubble_view.h b/chrome/browser/ui/views/global_error_bubble_view.h
index 5d3dbff7..db08a6d 100644
--- a/chrome/browser/ui/views/global_error_bubble_view.h
+++ b/chrome/browser/ui/views/global_error_bubble_view.h
@@ -20,6 +20,7 @@
  public:
   GlobalErrorBubbleView(
       views::View* anchor_view,
+      const gfx::Point& anchor_point,
       views::BubbleBorder::Arrow arrow,
       Browser* browser,
       const base::WeakPtr<GlobalErrorWithStandardBubble>& error);
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc
index d88bfdfe..c209ad6a 100644
--- a/chrome/browser/ui/views/tabs/tab.cc
+++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -13,6 +13,7 @@
 #include "base/macros.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/layout_constants.h"
@@ -51,7 +52,6 @@
 #include "ui/gfx/path.h"
 #include "ui/gfx/scoped_canvas.h"
 #include "ui/gfx/skia_util.h"
-#include "ui/gfx/vector_icons_public.h"
 #include "ui/resources/grit/ui_resources.h"
 #include "ui/views/border.h"
 #include "ui/views/controls/button/image_button.h"
@@ -587,11 +587,9 @@
   // on the current theme and active state.  The hovered and pressed images
   // don't depend on the these, so we can set them here.
   const gfx::ImageSkia& hovered = gfx::CreateVectorIcon(
-      gfx::VectorIconId::TAB_CLOSE_HOVERED_PRESSED,
-      SkColorSetRGB(0xDB, 0x44, 0x37));
+      kTabCloseHoveredPressedIcon, SkColorSetRGB(0xDB, 0x44, 0x37));
   const gfx::ImageSkia& pressed = gfx::CreateVectorIcon(
-      gfx::VectorIconId::TAB_CLOSE_HOVERED_PRESSED,
-      SkColorSetRGB(0xA8, 0x35, 0x2A));
+      kTabCloseHoveredPressedIcon, SkColorSetRGB(0xA8, 0x35, 0x2A));
   close_button_->SetImage(views::CustomButton::STATE_HOVERED, &hovered);
   close_button_->SetImage(views::CustomButton::STATE_PRESSED, &pressed);
 
@@ -1565,8 +1563,8 @@
     button_color_ = new_button_color;
     title_->SetEnabledColor(title_color);
     alert_indicator_button_->OnParentTabButtonColorChanged();
-    const gfx::ImageSkia& close_button_normal_image = gfx::CreateVectorIcon(
-        gfx::VectorIconId::TAB_CLOSE_NORMAL, button_color_);
+    const gfx::ImageSkia& close_button_normal_image =
+        gfx::CreateVectorIcon(kTabCloseNormalIcon, button_color_);
     close_button_->SetImage(views::CustomButton::STATE_NORMAL,
                             &close_button_normal_image);
   }
diff --git a/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc b/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc
index 0c03939..cbe9fea 100644
--- a/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc
+++ b/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc
@@ -32,8 +32,14 @@
       content::WebUIDataSource::Create(chrome::kChromeUIBookmarksHost);
 
   // Localized strings (alphabetical order).
+  AddLocalizedString(source, "cancelEdit", IDS_CANCEL);
   AddLocalizedString(source, "clearSearch",
                      IDS_MD_BOOKMARK_MANAGER_CLEAR_SEARCH);
+  AddLocalizedString(source, "editBookmarkTitle", IDS_BOOKMARK_EDITOR_TITLE);
+  AddLocalizedString(source, "editDialogNameInput",
+                     IDS_BOOKMARK_MANAGER_NAME_INPUT_PLACE_HOLDER);
+  AddLocalizedString(source, "editDialogUrlInput",
+                             IDS_BOOKMARK_MANAGER_URL_INPUT_PLACE_HOLDER);
   AddLocalizedString(source, "emptyList",
                      IDS_MD_BOOKMARK_MANAGER_EMPTY_LIST);
   AddLocalizedString(source, "menuAddBookmark",
@@ -51,6 +57,7 @@
   AddLocalizedString(source, "menuSort", IDS_MD_BOOKMARK_MANAGER_MENU_SORT);
   AddLocalizedString(source, "searchPrompt",
                      IDS_BOOKMARK_MANAGER_SEARCH_BUTTON);
+  AddLocalizedString(source, "saveEdit", IDS_SAVE);
   AddLocalizedString(source, "title", IDS_MD_BOOKMARK_MANAGER_TITLE);
 
   // Resources.
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index e8344dc..fc8d9b2 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -4494,6 +4494,7 @@
         "../browser/ui/cocoa/browser_window_controller_unittest.mm",
         "../browser/ui/cocoa/browser_window_layout_unittest.mm",
         "../browser/ui/cocoa/browser_window_utils_unittest.mm",
+        "../browser/ui/cocoa/bubble_anchor_helper_views_unittest.mm",
         "../browser/ui/cocoa/bubble_view_unittest.mm",
         "../browser/ui/cocoa/chrome_browser_window_unittest.mm",
         "../browser/ui/cocoa/clickhold_button_cell_unittest.mm",
diff --git a/chrome/test/data/webui/md_bookmarks/store_test.js b/chrome/test/data/webui/md_bookmarks/store_test.js
index 1322a78..ebc1563 100644
--- a/chrome/test/data/webui/md_bookmarks/store_test.js
+++ b/chrome/test/data/webui/md_bookmarks/store_test.js
@@ -167,4 +167,24 @@
     assertTrue(store.idToNodeMap_['0'].isSelected);
     assertEquals('0', store.selectedId);
   });
+
+  test('bookmark gets updated after editing', function() {
+    // Edit title updates idToNodeMap_ properly.
+    store.onBookmarkChanged_('4', {'title': 'test'});
+    assertEquals('test', store.idToNodeMap_['4'].title);
+    assertEquals('link4', store.idToNodeMap_['4'].url);
+
+    // Edit url updates idToNodeMap_ properly.
+    store.onBookmarkChanged_('5', {'url': 'http://www.google.com'});
+    assertEquals('', store.idToNodeMap_['5'].title);
+    assertEquals('http://www.google.com', store.idToNodeMap_['5'].url);
+
+    // Edit url and title updates idToNodeMap_ properly.
+    store.onBookmarkChanged_('2', {
+      'title': 'test',
+      'url': 'http://www.google.com',
+    });
+    assertEquals('test', store.idToNodeMap_['2'].title);
+    assertEquals('http://www.google.com', store.idToNodeMap_['2'].url);
+  });
 });
diff --git a/chromeos/chromeos.gyp b/chromeos/chromeos.gyp
index 4f72786c..a02a49b 100644
--- a/chromeos/chromeos.gyp
+++ b/chromeos/chromeos.gyp
@@ -390,6 +390,8 @@
       'settings/timezone_settings.h',
       'settings/timezone_settings_helper.cc',
       'settings/timezone_settings_helper.h',
+      'system/devicemode.cc',
+      'system/devicemode.h',
       'system/devicetype.cc',
       'system/devicetype.h',
 
diff --git a/chromeos/chromeos_switches.cc b/chromeos/chromeos_switches.cc
index 4a6bdfa..68023d82 100644
--- a/chromeos/chromeos_switches.cc
+++ b/chromeos/chromeos_switches.cc
@@ -418,6 +418,9 @@
 // of network packets from whitelisted sources.
 const char kWakeOnWifiPacket[] = "wake-on-wifi-packet";
 
+// Force system compositor mode when set.
+const char kForceSystemCompositorMode[] = "force-system-compositor-mode";
+
 bool WakeOnWifiEnabled() {
   return !base::CommandLine::ForCurrentProcess()->HasSwitch(kDisableWakeOnWifi);
 }
diff --git a/chromeos/chromeos_switches.h b/chromeos/chromeos_switches.h
index 64c60aa..46ae9e7 100644
--- a/chromeos/chromeos_switches.h
+++ b/chromeos/chromeos_switches.h
@@ -126,6 +126,7 @@
 CHROMEOS_EXPORT extern const char kTestAutoUpdateUI[];
 CHROMEOS_EXPORT extern const char kAttestationServer[];
 CHROMEOS_EXPORT extern const char kWakeOnWifiPacket[];
+CHROMEOS_EXPORT extern const char kForceSystemCompositorMode[];
 
 // Returns true if the system should wake in response to wifi traffic.
 CHROMEOS_EXPORT bool WakeOnWifiEnabled();
diff --git a/chromeos/system/devicemode.cc b/chromeos/system/devicemode.cc
new file mode 100644
index 0000000..01b82fd5
--- /dev/null
+++ b/chromeos/system/devicemode.cc
@@ -0,0 +1,21 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/system/devicemode.h"
+
+#include "base/command_line.h"
+#include "base/sys_info.h"
+#include "chromeos/chromeos_switches.h"
+
+namespace chromeos {
+
+bool IsRunningAsSystemCompositor() {
+  static bool is_running_as_system_compositor =
+      base::SysInfo::IsRunningOnChromeOS() ||
+      base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kForceSystemCompositorMode);
+  return is_running_as_system_compositor;
+}
+
+}  // namespace chromeos
diff --git a/chromeos/system/devicemode.h b/chromeos/system/devicemode.h
new file mode 100644
index 0000000..edc3799
--- /dev/null
+++ b/chromeos/system/devicemode.h
@@ -0,0 +1,18 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_SYSTEM_DEVICEMODE_H_
+#define CHROMEOS_SYSTEM_DEVICEMODE_H_
+
+#include "chromeos/chromeos_export.h"
+
+namespace chromeos {
+
+// Returns true when running as system compositor. Ie. using libudev, kms and
+// evdev for input and output.
+CHROMEOS_EXPORT bool IsRunningAsSystemCompositor();
+
+}  // namespace chromeos
+
+#endif  // CHROMEOS_SYSTEM_DEVICEMODE_H_
diff --git a/components/bookmark_component_strings.grdp b/components/bookmark_component_strings.grdp
index 6acef33..efd4777 100644
--- a/components/bookmark_component_strings.grdp
+++ b/components/bookmark_component_strings.grdp
@@ -7,7 +7,7 @@
     New folder
   </message>
   <message name="IDS_BOOKMARK_EDITOR_TITLE" desc="Title of the window the bookmark editor is in.">
-    Edit Bookmark
+    Edit bookmark
   </message>
   <if expr="not use_titlecase">
     <message name="IDS_BOOKMARK_MANAGER_NAME_INPUT_PLACE_HOLDER" desc="Text to show in the URL input field when editing or creating bookmarks.">
diff --git a/components/payments/BUILD.gn b/components/payments/BUILD.gn
index 22ae5283..bbdd5f5 100644
--- a/components/payments/BUILD.gn
+++ b/components/payments/BUILD.gn
@@ -20,7 +20,9 @@
   ]
 
   public_deps = [
+    ":payment_request",
     "//mojo/common:common_custom_types",
+    "//url/mojo:url_mojom_gurl",
   ]
 }
 
diff --git a/components/payments/payment_app.mojom b/components/payments/payment_app.mojom
index a12d53b..a3e9715b 100644
--- a/components/payments/payment_app.mojom
+++ b/components/payments/payment_app.mojom
@@ -4,6 +4,9 @@
 
 module payments.mojom;
 
+import "components/payments/payment_request.mojom";
+import "url/mojo/url.mojom";
+
 enum PaymentAppManifestError {
   NONE,
   NOT_IMPLEMENTED,
@@ -31,3 +34,11 @@
   GetManifest()
       => (PaymentAppManifest payment_app_manifest, PaymentAppManifestError error);
 };
+
+struct PaymentAppRequestData {
+  url.mojom.Url origin;
+  array<PaymentMethodData> methodData;
+  PaymentItem total;
+  array<PaymentDetailsModifier> modifiers;
+  string optionId;
+};
diff --git a/components/safe_browsing_db/v4_store.cc b/components/safe_browsing_db/v4_store.cc
index 34eaa27..c46dc58 100644
--- a/components/safe_browsing_db/v4_store.cc
+++ b/components/safe_browsing_db/v4_store.cc
@@ -764,7 +764,7 @@
   // It should never be the case that more than one hash prefixes match a given
   // full hash. However, if that happens, this method returns any one of them.
   // It does not guarantee which one of those will be returned.
-  DCHECK_EQ(32u, full_hash.size());
+  DCHECK(full_hash.size() == 32u || full_hash.size() == 21u);
   for (const auto& pair : hash_prefix_map_) {
     const PrefixSize& prefix_size = pair.first;
     const HashPrefixes& hash_prefixes = pair.second;
diff --git a/components/safe_browsing_db/v4_store.h b/components/safe_browsing_db/v4_store.h
index ac990b3..0deb76a2 100644
--- a/components/safe_browsing_db/v4_store.h
+++ b/components/safe_browsing_db/v4_store.h
@@ -267,6 +267,7 @@
                            TestHashPrefixExistsInMapWithDifferentSizes);
   FRIEND_TEST_ALL_PREFIXES(V4StoreTest,
                            TestHashPrefixDoesNotExistInMapWithDifferentSizes);
+  FRIEND_TEST_ALL_PREFIXES(V4StoreTest, GetMatchingHashPrefixSize32Or21);
   FRIEND_TEST_ALL_PREFIXES(V4StoreTest,
                            TestAdditionsWithRiceEncodingFailsWithInvalidInput);
   FRIEND_TEST_ALL_PREFIXES(V4StoreTest, TestAdditionsWithRiceEncodingSucceeds);
diff --git a/components/safe_browsing_db/v4_store_unittest.cc b/components/safe_browsing_db/v4_store_unittest.cc
index 2922a7a..575b340 100644
--- a/components/safe_browsing_db/v4_store_unittest.cc
+++ b/components/safe_browsing_db/v4_store_unittest.cc
@@ -673,6 +673,22 @@
   EXPECT_TRUE(store.GetMatchingHashPrefix(full_hash).empty());
 }
 
+TEST_F(V4StoreTest, GetMatchingHashPrefixSize32Or21) {
+  HashPrefix prefix = "0123";
+  V4Store store(task_runner_, store_path_);
+  store.hash_prefix_map_[4] = prefix;
+
+  FullHash full_hash_21 = "0123456789ABCDEF01234";
+  EXPECT_EQ(prefix, store.GetMatchingHashPrefix(full_hash_21));
+  FullHash full_hash_32 = "0123456789ABCDEF0123456789ABCDEF";
+  EXPECT_EQ(prefix, store.GetMatchingHashPrefix(full_hash_32));
+#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
+  // This hits a DCHECK so it is release mode only.
+  FullHash full_hash_22 = "0123456789ABCDEF012345";
+  EXPECT_EQ(prefix, store.GetMatchingHashPrefix(full_hash_22));
+#endif
+}
+
 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
 // This test hits a NOTREACHED so it is a release mode only test.
 TEST_F(V4StoreTest, TestAdditionsWithRiceEncodingFailsWithInvalidInput) {
diff --git a/content/browser/memory/memory_coordinator_impl_unittest.cc b/content/browser/memory/memory_coordinator_impl_unittest.cc
index 795d18b..9c3c992 100644
--- a/content/browser/memory/memory_coordinator_impl_unittest.cc
+++ b/content/browser/memory/memory_coordinator_impl_unittest.cc
@@ -473,7 +473,14 @@
   EXPECT_EQ(base::MemoryState::THROTTLED, coordinator_->GetGlobalMemoryState());
 }
 
-TEST_F(MemoryCoordinatorImplTest, GetStateForProcess) {
+
+#if defined(OS_ANDROID)
+// TODO(jcivelli): Broken on Android. http://crbug.com/678665
+#define MAYBE_GetStateForProcess DISABLED_GetStateForProcess
+#else
+#define MAYBE_GetStateForProcess GetStateForProcess
+#endif
+TEST_F(MemoryCoordinatorImplTest, MAYBE_GetStateForProcess) {
   EXPECT_EQ(base::MemoryState::UNKNOWN,
             coordinator_->GetStateForProcess(base::kNullProcessHandle));
   EXPECT_EQ(base::MemoryState::NORMAL,
diff --git a/content/browser/payments/payment_app_provider_impl.cc b/content/browser/payments/payment_app_provider_impl.cc
index 0d88e87..5f90d1c 100644
--- a/content/browser/payments/payment_app_provider_impl.cc
+++ b/content/browser/payments/payment_app_provider_impl.cc
@@ -57,6 +57,13 @@
       base::Bind(&GetAllManifestsOnIO, payment_app_context, callback));
 }
 
+void PaymentAppProviderImpl::InvokePaymentApp(
+    BrowserContext* browser_context,
+    int64_t registration_id,
+    payments::mojom::PaymentAppRequestDataPtr data) {
+  NOTIMPLEMENTED();
+}
+
 PaymentAppProviderImpl::PaymentAppProviderImpl() {}
 
 PaymentAppProviderImpl::~PaymentAppProviderImpl() {}
diff --git a/content/browser/payments/payment_app_provider_impl.h b/content/browser/payments/payment_app_provider_impl.h
index 127e181e..5a5a128 100644
--- a/content/browser/payments/payment_app_provider_impl.h
+++ b/content/browser/payments/payment_app_provider_impl.h
@@ -25,6 +25,10 @@
   // Should be accessed only on the UI thread.
   void GetAllManifests(BrowserContext* browser_context,
                        const GetAllManifestsCallback& callback) override;
+  void InvokePaymentApp(
+      BrowserContext* browser_context,
+      int64_t registration_id,
+      payments::mojom::PaymentAppRequestDataPtr data) override;
 
  private:
   PaymentAppProviderImpl();
diff --git a/content/browser/service_worker/embedded_worker_instance_unittest.cc b/content/browser/service_worker/embedded_worker_instance_unittest.cc
index 723f6f1..1f89e03 100644
--- a/content/browser/service_worker/embedded_worker_instance_unittest.cc
+++ b/content/browser/service_worker/embedded_worker_instance_unittest.cc
@@ -146,9 +146,6 @@
   DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerInstanceTest);
 };
 
-class EmbeddedWorkerInstanceTestP
-    : public MojoServiceWorkerTestP<EmbeddedWorkerInstanceTest> {};
-
 // A helper to simulate the start worker sequence is stalled in a worker
 // process.
 class StalledInStartWorkerHelper : public EmbeddedWorkerTestHelper {
@@ -178,18 +175,7 @@
   bool force_stall_in_start_ = true;
 };
 
-class FailToSendIPCHelper : public EmbeddedWorkerTestHelper {
- public:
-  FailToSendIPCHelper() : EmbeddedWorkerTestHelper(base::FilePath()) {}
-  ~FailToSendIPCHelper() override {}
-
-  bool Send(IPC::Message* message) override {
-    delete message;
-    return false;
-  }
-};
-
-TEST_P(EmbeddedWorkerInstanceTestP, StartAndStop) {
+TEST_F(EmbeddedWorkerInstanceTest, StartAndStop) {
   std::unique_ptr<EmbeddedWorkerInstance> worker =
       embedded_worker_registry()->CreateWorker();
   EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
@@ -229,15 +215,6 @@
   // EmbeddedWorkerTestHelper.
   EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
 
-  if (!is_mojo_enabled()) {
-    // Verify that we've sent two messages via chromium IPC to start and
-    // terminate the worker.
-    ASSERT_TRUE(ipc_sink()->GetUniqueMessageMatching(
-        EmbeddedWorkerMsg_StartWorker::ID));
-    ASSERT_TRUE(
-        ipc_sink()->GetUniqueMessageMatching(EmbeddedWorkerMsg_StopWorker::ID));
-  }
-
   // Check if the IPCs are fired in expected order.
   ASSERT_EQ(4u, events_.size());
   EXPECT_EQ(PROCESS_ALLOCATED, events_[0].type);
@@ -248,7 +225,7 @@
 
 // Test that a worker that failed twice will use a new render process
 // on the next attempt.
-TEST_P(EmbeddedWorkerInstanceTestP, ForceNewProcess) {
+TEST_F(EmbeddedWorkerInstanceTest, ForceNewProcess) {
   std::unique_ptr<EmbeddedWorkerInstance> worker =
       embedded_worker_registry()->CreateWorker();
   EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
@@ -314,7 +291,7 @@
   }
 }
 
-TEST_P(EmbeddedWorkerInstanceTestP, StopWhenDevToolsAttached) {
+TEST_F(EmbeddedWorkerInstanceTest, StopWhenDevToolsAttached) {
   std::unique_ptr<EmbeddedWorkerInstance> worker =
       embedded_worker_registry()->CreateWorker();
   EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
@@ -361,7 +338,7 @@
 
 // Test that the removal of a worker from the registry doesn't remove
 // other workers in the same process.
-TEST_P(EmbeddedWorkerInstanceTestP, RemoveWorkerInSharedProcess) {
+TEST_F(EmbeddedWorkerInstanceTest, RemoveWorkerInSharedProcess) {
   std::unique_ptr<EmbeddedWorkerInstance> worker1 =
       embedded_worker_registry()->CreateWorker();
   std::unique_ptr<EmbeddedWorkerInstance> worker2 =
@@ -418,7 +395,7 @@
   worker2->Stop();
 }
 
-TEST_P(EmbeddedWorkerInstanceTestP, DetachDuringProcessAllocation) {
+TEST_F(EmbeddedWorkerInstanceTest, DetachDuringProcessAllocation) {
   const int64_t version_id = 55L;
   const GURL scope("http://example.com/");
   const GURL url("http://example.com/worker.js");
@@ -450,7 +427,7 @@
   EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[0].status);
 }
 
-TEST_P(EmbeddedWorkerInstanceTestP, DetachAfterSendingStartWorkerMessage) {
+TEST_F(EmbeddedWorkerInstanceTest, DetachAfterSendingStartWorkerMessage) {
   const int64_t version_id = 55L;
   const GURL scope("http://example.com/");
   const GURL url("http://example.com/worker.js");
@@ -490,7 +467,7 @@
   EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[0].status);
 }
 
-TEST_P(EmbeddedWorkerInstanceTestP, StopDuringProcessAllocation) {
+TEST_F(EmbeddedWorkerInstanceTest, StopDuringProcessAllocation) {
   const int64_t version_id = 55L;
   const GURL scope("http://example.com/");
   const GURL url("http://example.com/worker.js");
@@ -542,7 +519,7 @@
   worker->Stop();
 }
 
-TEST_P(EmbeddedWorkerInstanceTestP, StopDuringPausedAfterDownload) {
+TEST_F(EmbeddedWorkerInstanceTest, StopDuringPausedAfterDownload) {
   const int64_t version_id = 55L;
   const GURL scope("http://example.com/");
   const GURL url("http://example.com/worker.js");
@@ -574,7 +551,7 @@
       EmbeddedWorkerMsg_ResumeAfterDownload::ID));
 }
 
-TEST_P(EmbeddedWorkerInstanceTestP, StopAfterSendingStartWorkerMessage) {
+TEST_F(EmbeddedWorkerInstanceTest, StopAfterSendingStartWorkerMessage) {
   const int64_t version_id = 55L;
   const GURL scope("http://example.com/");
   const GURL url("http://example.com/worker.js");
@@ -637,7 +614,7 @@
   worker->Stop();
 }
 
-TEST_P(EmbeddedWorkerInstanceTestP, Detach) {
+TEST_F(EmbeddedWorkerInstanceTest, Detach) {
   const int64_t version_id = 55L;
   const GURL pattern("http://example.com/");
   const GURL url("http://example.com/worker.js");
@@ -670,56 +647,33 @@
 }
 
 // Test for when sending the start IPC failed.
-TEST_P(EmbeddedWorkerInstanceTestP, FailToSendStartIPC) {
+TEST_F(EmbeddedWorkerInstanceTest, FailToSendStartIPC) {
   const int64_t version_id = 55L;
   const GURL pattern("http://example.com/");
   const GURL url("http://example.com/worker.js");
 
-  if (is_mojo_enabled()) {
-    // Let StartWorker fail; mojo IPC fails to connect to a remote interface.
-    helper_->RegisterMockInstanceClient(nullptr);
-  } else {
-    helper_.reset(new FailToSendIPCHelper());
-  }
+  // Let StartWorker fail; mojo IPC fails to connect to a remote interface.
+  helper_->RegisterMockInstanceClient(nullptr);
 
   std::unique_ptr<EmbeddedWorkerInstance> worker =
       embedded_worker_registry()->CreateWorker();
   helper_->SimulateAddProcessToPattern(pattern,
                                        helper_->mock_render_process_id());
-  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
   worker->AddListener(this);
 
   // Attempt to start the worker.
   std::unique_ptr<EmbeddedWorkerStartParams> params =
       CreateStartParams(version_id, pattern, url);
-  if (is_mojo_enabled()) {
-    worker->Start(std::move(params), CreateEventDispatcher(),
-                  base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
-    base::RunLoop().RunUntilIdle();
-  } else {
-    base::RunLoop run_loop;
-    worker->Start(
-        std::move(params), CreateEventDispatcher(),
-        base::Bind(&SaveStatusAndCall, &status, run_loop.QuitClosure()));
-    run_loop.Run();
-  }
+  worker->Start(std::move(params), CreateEventDispatcher(),
+                base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+  base::RunLoop().RunUntilIdle();
 
-  if (is_mojo_enabled()) {
-    // Worker should handle the failure of binding as detach.
-    ASSERT_EQ(3u, events_.size());
-    EXPECT_EQ(PROCESS_ALLOCATED, events_[0].type);
-    EXPECT_EQ(START_WORKER_MESSAGE_SENT, events_[1].type);
-    EXPECT_EQ(DETACHED, events_[2].type);
-    EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[2].status);
-  } else {
-    // The callback should have run, and we should have got an OnStopped
-    // message.
-    EXPECT_EQ(SERVICE_WORKER_ERROR_IPC_FAILED, status);
-    ASSERT_EQ(2u, events_.size());
-    EXPECT_EQ(PROCESS_ALLOCATED, events_[0].type);
-    EXPECT_EQ(STOPPED, events_[1].type);
-    EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[1].status);
-  }
+  // Worker should handle the failure of binding as detach.
+  ASSERT_EQ(3u, events_.size());
+  EXPECT_EQ(PROCESS_ALLOCATED, events_[0].type);
+  EXPECT_EQ(START_WORKER_MESSAGE_SENT, events_[1].type);
+  EXPECT_EQ(DETACHED, events_[2].type);
+  EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[2].status);
 }
 
 class FailEmbeddedWorkerInstanceClientImpl
@@ -737,10 +691,7 @@
   }
 };
 
-TEST_P(EmbeddedWorkerInstanceTestP, RemoveRemoteInterface) {
-  if (!is_mojo_enabled())
-    return;
-
+TEST_F(EmbeddedWorkerInstanceTest, RemoveRemoteInterface) {
   const int64_t version_id = 55L;
   const GURL pattern("http://example.com/");
   const GURL url("http://example.com/worker.js");
@@ -772,8 +723,4 @@
   EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[2].status);
 }
 
-INSTANTIATE_TEST_CASE_P(EmbeddedWorkerInstanceTest,
-                        EmbeddedWorkerInstanceTestP,
-                        ::testing::Values(false, true));
-
 }  // namespace content
diff --git a/content/browser/service_worker/embedded_worker_registry.h b/content/browser/service_worker/embedded_worker_registry.h
index 80ce9b3..5b374f7 100644
--- a/content/browser/service_worker/embedded_worker_registry.h
+++ b/content/browser/service_worker/embedded_worker_registry.h
@@ -112,7 +112,7 @@
   friend class MojoEmbeddedWorkerInstanceTest;
   friend class EmbeddedWorkerInstance;
   friend class EmbeddedWorkerInstanceTest;
-  FRIEND_TEST_ALL_PREFIXES(EmbeddedWorkerInstanceTestP,
+  FRIEND_TEST_ALL_PREFIXES(EmbeddedWorkerInstanceTest,
                            RemoveWorkerInSharedProcess);
 
   using WorkerInstanceMap = std::map<int, EmbeddedWorkerInstance*>;
diff --git a/content/browser/service_worker/embedded_worker_test_helper.cc b/content/browser/service_worker/embedded_worker_test_helper.cc
index 0ef4127..b2f80213 100644
--- a/content/browser/service_worker/embedded_worker_test_helper.cc
+++ b/content/browser/service_worker/embedded_worker_test_helper.cc
@@ -186,6 +186,12 @@
     NOTIMPLEMENTED();
   }
 
+  void DispatchPaymentRequestEvent(
+      payments::mojom::PaymentAppRequestDataPtr data,
+      const DispatchPaymentRequestEventCallback& callback) override {
+    NOTIMPLEMENTED();
+  }
+
   void DispatchExtendableMessageEvent(
       mojom::ExtendableMessageEventPtr event,
       const DispatchExtendableMessageEventCallback& callback) override {
diff --git a/content/browser/service_worker/link_header_support_unittest.cc b/content/browser/service_worker/link_header_support_unittest.cc
index 1b0598b..9179802 100644
--- a/content/browser/service_worker/link_header_support_unittest.cc
+++ b/content/browser/service_worker/link_header_support_unittest.cc
@@ -155,10 +155,7 @@
   storage::BlobStorageContext blob_storage_context_;
 };
 
-class LinkHeaderServiceWorkerTestP
-    : public MojoServiceWorkerTestP<LinkHeaderServiceWorkerTest> {};
-
-TEST_P(LinkHeaderServiceWorkerTestP, InstallServiceWorker_Basic) {
+TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_Basic) {
   ProcessLinkHeaderForRequest(
       CreateSubresourceRequest(GURL("https://example.com/foo/bar/")).get(),
       "<../foo.js>; rel=serviceworker", context_wrapper());
@@ -171,7 +168,7 @@
             registrations[0].active_version.script_url);
 }
 
-TEST_P(LinkHeaderServiceWorkerTestP, InstallServiceWorker_ScopeWithFragment) {
+TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeWithFragment) {
   ProcessLinkHeaderForRequest(
       CreateSubresourceRequest(GURL("https://example.com/foo/bar/")).get(),
       "<../bar.js>; rel=serviceworker; scope=\"scope#ref\"", context_wrapper());
@@ -185,7 +182,7 @@
             registrations[0].active_version.script_url);
 }
 
-TEST_P(LinkHeaderServiceWorkerTestP, InstallServiceWorker_ScopeAbsoluteUrl) {
+TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeAbsoluteUrl) {
   ProcessLinkHeaderForRequest(
       CreateSubresourceRequest(GURL("https://example.com/foo/bar/")).get(),
       "<bar.js>; rel=serviceworker; "
@@ -201,8 +198,7 @@
             registrations[0].active_version.script_url);
 }
 
-TEST_P(LinkHeaderServiceWorkerTestP,
-       InstallServiceWorker_ScopeDifferentOrigin) {
+TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeDifferentOrigin) {
   ProcessLinkHeaderForRequest(
       CreateSubresourceRequest(GURL("https://example.com/foobar/")).get(),
       "<bar.js>; rel=serviceworker; scope=\"https://google.com/scope\"",
@@ -213,8 +209,7 @@
   ASSERT_EQ(0u, registrations.size());
 }
 
-TEST_P(LinkHeaderServiceWorkerTestP,
-       InstallServiceWorker_ScopeUrlEncodedSlash) {
+TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeUrlEncodedSlash) {
   ProcessLinkHeaderForRequest(
       CreateSubresourceRequest(GURL("https://example.com/foobar/")).get(),
       "<bar.js>; rel=serviceworker; scope=\"./foo%2Fbar\"", context_wrapper());
@@ -224,7 +219,7 @@
   ASSERT_EQ(0u, registrations.size());
 }
 
-TEST_P(LinkHeaderServiceWorkerTestP,
+TEST_F(LinkHeaderServiceWorkerTest,
        InstallServiceWorker_ScriptUrlEncodedSlash) {
   ProcessLinkHeaderForRequest(
       CreateSubresourceRequest(GURL("https://example.com/foobar/")).get(),
@@ -235,7 +230,7 @@
   ASSERT_EQ(0u, registrations.size());
 }
 
-TEST_P(LinkHeaderServiceWorkerTestP, InstallServiceWorker_ScriptAbsoluteUrl) {
+TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScriptAbsoluteUrl) {
   ProcessLinkHeaderForRequest(
       CreateSubresourceRequest(GURL("https://example.com/foobar/")).get(),
       "<https://example.com/bar.js>; rel=serviceworker; scope=foo",
@@ -249,7 +244,7 @@
             registrations[0].active_version.script_url);
 }
 
-TEST_P(LinkHeaderServiceWorkerTestP,
+TEST_F(LinkHeaderServiceWorkerTest,
        InstallServiceWorker_ScriptDifferentOrigin) {
   ProcessLinkHeaderForRequest(
       CreateSubresourceRequest(GURL("https://example.com/foobar/")).get(),
@@ -261,7 +256,7 @@
   ASSERT_EQ(0u, registrations.size());
 }
 
-TEST_P(LinkHeaderServiceWorkerTestP, InstallServiceWorker_MultipleWorkers) {
+TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_MultipleWorkers) {
   ProcessLinkHeaderForRequest(
       CreateSubresourceRequest(GURL("https://example.com/foobar/")).get(),
       "<bar.js>; rel=serviceworker; scope=foo, <baz.js>; "
@@ -279,7 +274,7 @@
             registrations[1].active_version.script_url);
 }
 
-TEST_P(LinkHeaderServiceWorkerTestP,
+TEST_F(LinkHeaderServiceWorkerTest,
        InstallServiceWorker_ValidAndInvalidValues) {
   ProcessLinkHeaderForRequest(
       CreateSubresourceRequest(GURL("https://example.com/foobar/")).get(),
@@ -295,7 +290,7 @@
             registrations[0].active_version.script_url);
 }
 
-TEST_P(LinkHeaderServiceWorkerTestP, InstallServiceWorker_InsecureContext) {
+TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_InsecureContext) {
   std::unique_ptr<net::URLRequest> request =
       CreateSubresourceRequest(GURL("https://example.com/foo/bar/"));
   ResourceRequestInfoImpl::ForRequest(request.get())
@@ -308,7 +303,7 @@
   ASSERT_EQ(0u, registrations.size());
 }
 
-TEST_P(LinkHeaderServiceWorkerTestP,
+TEST_F(LinkHeaderServiceWorkerTest,
        InstallServiceWorker_NavigationFromInsecureContextToSecureContext) {
   std::unique_ptr<net::URLRequest> request = CreateRequest(
       GURL("https://example.com/foo/bar/"), RESOURCE_TYPE_MAIN_FRAME);
@@ -329,7 +324,7 @@
             registrations[0].active_version.script_url);
 }
 
-TEST_P(LinkHeaderServiceWorkerTestP,
+TEST_F(LinkHeaderServiceWorkerTest,
        InstallServiceWorker_NavigationToInsecureContext) {
   provider_host()->SetDocumentUrl(GURL("http://example.com/foo/bar/"));
   provider_host()->set_parent_frame_secure(true);
@@ -344,7 +339,7 @@
   ASSERT_EQ(0u, registrations.size());
 }
 
-TEST_P(LinkHeaderServiceWorkerTestP,
+TEST_F(LinkHeaderServiceWorkerTest,
        InstallServiceWorker_NavigationToInsecureHttpsContext) {
   provider_host()->SetDocumentUrl(GURL("https://example.com/foo/bar/"));
   provider_host()->set_parent_frame_secure(false);
@@ -359,7 +354,7 @@
   ASSERT_EQ(0u, registrations.size());
 }
 
-TEST_P(LinkHeaderServiceWorkerTestP,
+TEST_F(LinkHeaderServiceWorkerTest,
        InstallServiceWorker_FromWorkerWithoutControllees) {
   CreateServiceWorkerProviderHost();
   ProcessLinkHeaderForRequest(
@@ -371,7 +366,7 @@
   ASSERT_EQ(0u, registrations.size());
 }
 
-TEST_P(LinkHeaderServiceWorkerTestP,
+TEST_F(LinkHeaderServiceWorkerTest,
        InstallServiceWorker_FromWorkerWithControllees) {
   CreateServiceWorkerProviderHost();
 
@@ -392,8 +387,4 @@
   ASSERT_EQ(1u, registrations.size());
 }
 
-INSTANTIATE_TEST_CASE_P(LinkHeaderServiceWorkerTest,
-                        LinkHeaderServiceWorkerTestP,
-                        testing::Bool());
-
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc
index 3333a8a..02af1cc 100644
--- a/content/browser/service_worker/service_worker_browsertest.cc
+++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -68,6 +68,7 @@
 #include "content/shell/browser/shell.h"
 #include "content/shell/browser/shell_content_browser_client.h"
 #include "content/test/test_content_browser_client.h"
+#include "net/cert/cert_status_flags.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/http/http_response_info.h"
 #include "net/log/net_log_with_source.h"
@@ -400,8 +401,7 @@
 
 }  // namespace
 
-class ServiceWorkerBrowserTest
-    : public MojoServiceWorkerTestP<ContentBrowserTest> {
+class ServiceWorkerBrowserTest : public ContentBrowserTest {
  protected:
   using self = ServiceWorkerBrowserTest;
 
@@ -862,7 +862,7 @@
   std::unique_ptr<ServiceWorkerFetchDispatcher> fetch_dispatcher_;
 };
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, StartAndStop) {
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartAndStop) {
   StartServerAndNavigateToSetup();
   RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread,
                            base::Unretained(this),
@@ -889,7 +889,7 @@
   ASSERT_EQ(SERVICE_WORKER_OK, status);
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, StartNotFound) {
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartNotFound) {
   StartServerAndNavigateToSetup();
   RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread,
                            base::Unretained(this),
@@ -899,7 +899,7 @@
   StartWorker(SERVICE_WORKER_ERROR_NETWORK);
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, ReadResourceFailure) {
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, ReadResourceFailure) {
   StartServerAndNavigateToSetup();
   // Create a registration.
   RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread,
@@ -931,7 +931,7 @@
                         SERVICE_WORKER_ERROR_NOT_FOUND);
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
                        ReadResourceFailure_WaitingWorker) {
   StartServerAndNavigateToSetup();
   // Create a registration and active version.
@@ -981,19 +981,19 @@
                         SERVICE_WORKER_OK);
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, Install) {
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, Install) {
   StartServerAndNavigateToSetup();
   InstallTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK);
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
                        InstallWithWaitUntil_Fulfilled) {
   StartServerAndNavigateToSetup();
   InstallTestHelper("/service_worker/worker_install_fulfilled.js",
                     SERVICE_WORKER_OK);
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
                        InstallWithFetchHandler) {
   StartServerAndNavigateToSetup();
   InstallTestHelper("/service_worker/fetch_event.js", SERVICE_WORKER_OK);
@@ -1001,7 +1001,7 @@
             version_->fetch_handler_existence());
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
                        InstallWithoutFetchHandler) {
   StartServerAndNavigateToSetup();
   InstallTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK);
@@ -1011,7 +1011,7 @@
 
 // Check that ServiceWorker script requests set a "Service-Worker: script"
 // header.
-IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
                        ServiceWorkerScriptHeader) {
   embedded_test_server()->RegisterRequestHandler(
       base::Bind(&VerifyServiceWorkerHeaderInRequest));
@@ -1019,27 +1019,27 @@
   InstallTestHelper("/service_worker/generated_sw.js", SERVICE_WORKER_OK);
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
                        Activate_NoEventListener) {
   StartServerAndNavigateToSetup();
   ActivateTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK);
   ASSERT_EQ(ServiceWorkerVersion::ACTIVATING, version_->status());
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, Activate_Rejected) {
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, Activate_Rejected) {
   StartServerAndNavigateToSetup();
   ActivateTestHelper("/service_worker/worker_activate_rejected.js",
                      SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED);
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
                        InstallWithWaitUntil_Rejected) {
   StartServerAndNavigateToSetup();
   InstallTestHelper("/service_worker/worker_install_rejected.js",
                     SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED);
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
                        InstallWithWaitUntil_RejectConsoleMessage) {
   StartServerAndNavigateToSetup();
   RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread,
@@ -1085,7 +1085,7 @@
   base::Closure quit_;
 };
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, TimeoutStartingWorker) {
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutStartingWorker) {
   StartServerAndNavigateToSetup();
   RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread,
                            base::Unretained(this),
@@ -1123,7 +1123,7 @@
   EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, status);
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, TimeoutWorkerInEvent) {
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutWorkerInEvent) {
   StartServerAndNavigateToSetup();
   RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread,
                            base::Unretained(this),
@@ -1159,7 +1159,7 @@
   EXPECT_EQ(SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED, status);
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, FetchEvent_Response) {
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, FetchEvent_Response) {
   StartServerAndNavigateToSetup();
   ServiceWorkerFetchEventResult result;
   ServiceWorkerResponse response;
@@ -1182,7 +1182,7 @@
   EXPECT_EQ("This resource is gone. Gone, gone, gone.", body);
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
                        FetchEvent_ResponseViaCache) {
   StartServerAndNavigateToSetup();
   ServiceWorkerFetchEventResult result;
@@ -1210,7 +1210,7 @@
   EXPECT_EQ("cache_name", response2.cache_storage_cache_name);
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
                        FetchEvent_respondWithRejection) {
   StartServerAndNavigateToSetup();
   ServiceWorkerFetchEventResult result;
@@ -1266,7 +1266,7 @@
   bool data_saver_enabled_;
 };
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, FetchWithSaveData) {
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, FetchWithSaveData) {
   embedded_test_server()->RegisterRequestHandler(
       base::Bind(&VerifySaveDataHeaderInRequest));
   StartServerAndNavigateToSetup();
@@ -1278,7 +1278,7 @@
   SetBrowserClientForTesting(old_client);
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
                        RequestWorkerScriptWithSaveData) {
   embedded_test_server()->RegisterRequestHandler(
       base::Bind(&VerifySaveDataHeaderInRequest));
@@ -1291,7 +1291,7 @@
   SetBrowserClientForTesting(old_client);
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, FetchWithoutSaveData) {
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, FetchWithoutSaveData) {
   embedded_test_server()->RegisterRequestHandler(
       base::Bind(&VerifySaveDataHeaderNotInRequest));
   StartServerAndNavigateToSetup();
@@ -1302,7 +1302,7 @@
   SetBrowserClientForTesting(old_client);
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest, FetchPageWithSaveData) {
+IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, FetchPageWithSaveData) {
   StartServerAndNavigateToSetup();
   const char kPageUrl[] = "/service_worker/handle_fetch.html";
   const char kWorkerUrl[] = "/service_worker/add_save_data_to_title.js";
@@ -1338,7 +1338,7 @@
 // Tests that when data saver is enabled and a cross-origin fetch by a webpage
 // is intercepted by a serviceworker, and the serviceworker does a fetch, the
 // preflight request does not have save-data in Access-Control-Request-Headers.
-IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest, CrossOriginFetchWithSaveData) {
+IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, CrossOriginFetchWithSaveData) {
   StartServerAndNavigateToSetup();
   const char kPageUrl[] = "/service_worker/fetch_cross_origin.html";
   const char kWorkerUrl[] = "/service_worker/fetch_event_pass_through.js";
@@ -1382,7 +1382,7 @@
   run_loop.Run();
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest,
+IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest,
                        FetchPageWithSaveDataPassThroughOnFetch) {
   const char kPageUrl[] = "/service_worker/pass_through_fetch.html";
   const char kWorkerUrl[] = "/service_worker/fetch_event_pass_through.js";
@@ -1418,7 +1418,7 @@
   run_loop.Run();
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest, Reload) {
+IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, Reload) {
   StartServerAndNavigateToSetup();
   const char kPageUrl[] = "/service_worker/reload.html";
   const char kWorkerUrl[] = "/service_worker/fetch_event_reload.js";
@@ -1677,7 +1677,7 @@
         "            result => event.source.postMessage(result)));\n"
         "  });";
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest, NetworkFallback) {
+IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest, NetworkFallback) {
   const char kPageUrl[] = "/service_worker/navigation_preload.html";
   const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
   const char kPage[] = "<title>PASS</title>Hello world.";
@@ -1718,7 +1718,7 @@
   }
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest, SetHeaderValue) {
+IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest, SetHeaderValue) {
   const std::string kPageUrl = "/service_worker/navigation_preload.html";
   const std::string kWorkerUrl = "/service_worker/navigation_preload.js";
   const std::string kPage = "<title>FROM_SERVER</title>";
@@ -1803,7 +1803,7 @@
   ASSERT_EQ(0, GetRequestCount(kPageUrl4));
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest,
+IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
                        RespondWithNavigationPreload) {
   const char kPageUrl[] = "/service_worker/navigation_preload.html";
   const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
@@ -1842,7 +1842,7 @@
             request_log_[kPageUrl][0].headers[kNavigationPreloadHeaderName]);
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest, GetResponseText) {
+IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest, GetResponseText) {
   const char kPageUrl[] = "/service_worker/navigation_preload.html";
   const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
   const char kPage[] = "<title>PASS</title>Hello world.";
@@ -1877,7 +1877,7 @@
   EXPECT_EQ(1, GetRequestCount(kPageUrl));
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest,
+IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
                        AbortPreloadRequest) {
   const char kPageUrl[] = "/service_worker/navigation_preload.html";
   const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
@@ -1937,7 +1937,7 @@
       GetTextContent());
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest, NetworkError) {
+IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest, NetworkError) {
   const char kPageUrl[] = "/service_worker/navigation_preload.html";
   const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
   const GURL page_url = embedded_test_server()->GetURL(kPageUrl);
@@ -1961,7 +1961,7 @@
             GetTextContent());
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest,
+IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
                        CanceledByInterceptor) {
   content::ResourceDispatcherHost::Get()->RegisterInterceptor(
       kNavigationPreloadHeaderName, "",
@@ -1988,7 +1988,7 @@
             GetTextContent());
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest,
+IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
                        PreloadHeadersSimple) {
   const char kPageUrl[] = "/service_worker/navigation_preload.html";
   const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
@@ -2028,7 +2028,7 @@
                           base::IntToString(sizeof(kPage) - 1)));
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest, NotEnabled) {
+IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest, NotEnabled) {
   const char kPageUrl[] = "/service_worker/navigation_preload.html";
   const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
   const char kPage[] = "<title>ERROR</title>Hello world.";
@@ -2054,7 +2054,7 @@
   EXPECT_EQ("Resolved with undefined.", GetTextContent());
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest,
+IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
                        PreloadHeadersCustom) {
   const char kPageUrl[] = "/service_worker/navigation_preload.html";
   const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
@@ -2107,7 +2107,7 @@
   EXPECT_FALSE(dict->HasKey("set-cookie2"));
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest, RejectRedirects) {
+IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest, RejectRedirects) {
   const char kPageUrl[] = "/service_worker/navigation_preload.html";
   const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
   const char kRedirectedPageUrl[] =
@@ -2151,7 +2151,7 @@
 
 // Tests responding with the navigation preload response when the navigation
 // occurred after a redirect.
-IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest,
+IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
                        RedirectAndRespondWithNavigationPreload) {
   const std::string kPageUrl = "/service_worker/navigation_preload.html";
   const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
@@ -2221,7 +2221,7 @@
 // OnReceiveResponse(). This behavior is caused by MimeSniffingResourceHandler.
 // This test checks that even if the MimeSniffingResourceHandler is triggered
 // navigation preload must be handled correctly.
-IN_PROC_BROWSER_TEST_P(ServiceWorkerNavigationPreloadTest,
+IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
                        RespondWithNavigationPreloadWithMimeSniffing) {
   const char kPageUrl[] = "/service_worker/navigation_preload.html";
   const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
@@ -2258,7 +2258,7 @@
 #else
 #define MAYBE_ResponseFromHTTPSServiceWorkerIsMarkedAsSecure ResponseFromHTTPSServiceWorkerIsMarkedAsSecure
 #endif
-IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest,
+IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest,
                        MAYBE_ResponseFromHTTPSServiceWorkerIsMarkedAsSecure) {
   StartServerAndNavigateToSetup();
   const char kPageUrl[] = "/service_worker/fetch_event_blob.html";
@@ -2287,7 +2287,7 @@
                   SSLStatus::DISPLAYED_INSECURE_CONTENT));
   EXPECT_TRUE(
       https_server.GetCertificate()->Equals(entry->GetSSL().certificate.get()));
-  EXPECT_EQ(0u, entry->GetSSL().cert_status);
+  EXPECT_FALSE(net::IsCertStatusError(entry->GetSSL().cert_status));
 
   shell()->Close();
 
@@ -2298,7 +2298,7 @@
   run_loop.Run();
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest,
+IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest,
                        ResponseFromHTTPServiceWorkerIsNotMarkedAsSecure) {
   StartServerAndNavigateToSetup();
   const char kPageUrl[] = "/service_worker/fetch_event_blob.html";
@@ -2332,7 +2332,7 @@
   run_loop.Run();
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest, ImportsBustMemcache) {
+IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, ImportsBustMemcache) {
   StartServerAndNavigateToSetup();
   const char kScopeUrl[] = "/service_worker/imports_bust_memcache_scope/";
   const char kPageUrl[] = "/service_worker/imports_bust_memcache.html";
@@ -2398,7 +2398,7 @@
   return result;
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerBlackBoxBrowserTest, Registration) {
+IN_PROC_BROWSER_TEST_F(ServiceWorkerBlackBoxBrowserTest, Registration) {
   StartServerAndNavigateToSetup();
   // Close the only window to be sure we're not re-using its RenderProcessHost.
   shell()->Close();
@@ -2481,7 +2481,7 @@
 #else
 #define MAYBE_CrossSiteTransfer CrossSiteTransfer
 #endif
-IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest, MAYBE_CrossSiteTransfer) {
+IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, MAYBE_CrossSiteTransfer) {
   StartServerAndNavigateToSetup();
   // The first page registers a service worker.
   const char kRegisterPageUrl[] = "/service_worker/cross_site_xfer.html";
@@ -2536,7 +2536,7 @@
   base::Closure cache_updated_closure_;
 };
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserV8CacheTest, Restart) {
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserV8CacheTest, Restart) {
   StartServerAndNavigateToSetup();
   RunOnIOThread(base::Bind(&self::SetUpRegistrationAndListenerOnIOThread,
                            base::Unretained(this),
@@ -2809,7 +2809,7 @@
 const int ServiceWorkerV8CacheStrategiesTest::kV8CacheTimeStampDataSize =
     sizeof(unsigned) + sizeof(double);
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerV8CacheStrategiesTest,
+IN_PROC_BROWSER_TEST_F(ServiceWorkerV8CacheStrategiesTest,
                        V8CacheOnCacheStorage) {
   // The strategy is "aggressive" on default.
   CheckStrategyIsAggressive();
@@ -2829,7 +2829,7 @@
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerV8CacheStrategiesNoneTest);
 };
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerV8CacheStrategiesNoneTest,
+IN_PROC_BROWSER_TEST_F(ServiceWorkerV8CacheStrategiesNoneTest,
                        V8CacheOnCacheStorage) {
   CheckStrategyIsNone();
 }
@@ -2848,7 +2848,7 @@
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerV8CacheStrategiesNormalTest);
 };
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerV8CacheStrategiesNormalTest,
+IN_PROC_BROWSER_TEST_F(ServiceWorkerV8CacheStrategiesNormalTest,
                        V8CacheOnCacheStorage) {
   CheckStrategyIsNormal();
 }
@@ -2867,7 +2867,7 @@
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerV8CacheStrategiesAggressiveTest);
 };
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerV8CacheStrategiesAggressiveTest,
+IN_PROC_BROWSER_TEST_F(ServiceWorkerV8CacheStrategiesAggressiveTest,
                        V8CacheOnCacheStorage) {
   CheckStrategyIsAggressive();
 }
@@ -2918,7 +2918,7 @@
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerDisableWebSecurityTest);
 };
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerDisableWebSecurityTest,
+IN_PROC_BROWSER_TEST_F(ServiceWorkerDisableWebSecurityTest,
                        GetRegistrationNoCrash) {
   StartServerAndNavigateToSetup();
   const char kPageUrl[] =
@@ -2927,14 +2927,14 @@
   RunTestWithCrossOriginURL(kPageUrl, kScopeUrl);
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerDisableWebSecurityTest, RegisterNoCrash) {
+IN_PROC_BROWSER_TEST_F(ServiceWorkerDisableWebSecurityTest, RegisterNoCrash) {
   StartServerAndNavigateToSetup();
   const char kPageUrl[] = "/service_worker/disable_web_security_register.html";
   const char kScopeUrl[] = "/service_worker/";
   RunTestWithCrossOriginURL(kPageUrl, kScopeUrl);
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerDisableWebSecurityTest, UnregisterNoCrash) {
+IN_PROC_BROWSER_TEST_F(ServiceWorkerDisableWebSecurityTest, UnregisterNoCrash) {
   StartServerAndNavigateToSetup();
   const char kPageUrl[] =
       "/service_worker/disable_web_security_unregister.html";
@@ -2944,7 +2944,7 @@
   RunTestWithCrossOriginURL(kPageUrl, kScopeUrl);
 }
 
-IN_PROC_BROWSER_TEST_P(ServiceWorkerDisableWebSecurityTest, UpdateNoCrash) {
+IN_PROC_BROWSER_TEST_F(ServiceWorkerDisableWebSecurityTest, UpdateNoCrash) {
   StartServerAndNavigateToSetup();
   const char kPageUrl[] = "/service_worker/disable_web_security_update.html";
   const char kScopeUrl[] = "/service_worker/scope/";
@@ -2987,7 +2987,7 @@
 // TODO(shimazu): Enable these tests on macos when MemoryMonitorMac is
 // implemented.
 #if !defined(OS_MACOSX)
-IN_PROC_BROWSER_TEST_P(MemoryCoordinatorWithServiceWorkerTest,
+IN_PROC_BROWSER_TEST_F(MemoryCoordinatorWithServiceWorkerTest,
                        CannotSuspendRendererWithServiceWorker) {
   StartServerAndNavigateToSetup();
   ActivateTestHelper("/service_worker/fetch_event.js", SERVICE_WORKER_OK);
@@ -3014,40 +3014,6 @@
   // The process which has service worker thread shouldn't be suspended.
   EXPECT_FALSE(memory_coordinator->CanSuspendRenderer(render_process_id));
 }
-INSTANTIATE_TEST_CASE_P(ServiceWorkerBrowserTest,
-                        MemoryCoordinatorWithServiceWorkerTest,
-                        ::testing::Bool());
 #endif
 
-INSTANTIATE_TEST_CASE_P(ServiceWorkerBrowserTest,
-                        ServiceWorkerBrowserTest,
-                        ::testing::Values(true, false));
-INSTANTIATE_TEST_CASE_P(ServiceWorkerBrowserTest,
-                        ServiceWorkerVersionBrowserV8CacheTest,
-                        ::testing::Values(true, false));
-INSTANTIATE_TEST_CASE_P(ServiceWorkerBrowserTest,
-                        ServiceWorkerVersionBrowserTest,
-                        ::testing::Values(true, false));
-INSTANTIATE_TEST_CASE_P(ServiceWorkerBrowserTest,
-                        ServiceWorkerBlackBoxBrowserTest,
-                        ::testing::Values(true, false));
-INSTANTIATE_TEST_CASE_P(ServiceWorkerBrowserTest,
-                        ServiceWorkerNavigationPreloadTest,
-                        ::testing::Values(true, false));
-INSTANTIATE_TEST_CASE_P(ServiceWorkerBrowserTest,
-                        ServiceWorkerV8CacheStrategiesTest,
-                        ::testing::Values(true, false));
-INSTANTIATE_TEST_CASE_P(ServiceWorkerBrowserTest,
-                        ServiceWorkerV8CacheStrategiesNoneTest,
-                        ::testing::Values(true, false));
-INSTANTIATE_TEST_CASE_P(ServiceWorkerBrowserTest,
-                        ServiceWorkerV8CacheStrategiesNormalTest,
-                        ::testing::Values(true, false));
-INSTANTIATE_TEST_CASE_P(ServiceWorkerBrowserTest,
-                        ServiceWorkerV8CacheStrategiesAggressiveTest,
-                        ::testing::Values(true, false));
-INSTANTIATE_TEST_CASE_P(ServiceWorkerBrowserTest,
-                        ServiceWorkerDisableWebSecurityTest,
-                        ::testing::Values(true, false));
-
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_cache_writer_unittest.cc b/content/browser/service_worker/service_worker_cache_writer_unittest.cc
index 2a9b464e..00d03893 100644
--- a/content/browser/service_worker/service_worker_cache_writer_unittest.cc
+++ b/content/browser/service_worker/service_worker_cache_writer_unittest.cc
@@ -400,16 +400,13 @@
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerCacheWriterTest);
 };
 
-class ServiceWorkerCacheWriterTestP
-    : public MojoServiceWorkerTestP<ServiceWorkerCacheWriterTest> {};
-
 // Passthrough tests:
 // In these tests, the ServiceWorkerCacheWriter under test has no existing
 // reader, since no calls to ExpectReader() have been made; this means that
 // there is no existing cached response and the incoming data is written back to
 // the cache directly.
 
-TEST_P(ServiceWorkerCacheWriterTestP, PassthroughHeadersSync) {
+TEST_F(ServiceWorkerCacheWriterTest, PassthroughHeadersSync) {
   const size_t kHeaderSize = 16;
   MockServiceWorkerResponseWriter* writer = ExpectWriter();
   writer->ExpectWriteInfoOk(kHeaderSize, false);
@@ -422,7 +419,7 @@
   EXPECT_EQ(0U, cache_writer_->bytes_written());
 }
 
-TEST_P(ServiceWorkerCacheWriterTestP, PassthroughHeadersAsync) {
+TEST_F(ServiceWorkerCacheWriterTest, PassthroughHeadersAsync) {
   size_t kHeaderSize = 16;
   MockServiceWorkerResponseWriter* writer = ExpectWriter();
   writer->ExpectWriteInfoOk(kHeaderSize, true);
@@ -438,7 +435,7 @@
   EXPECT_EQ(0U, cache_writer_->bytes_written());
 }
 
-TEST_P(ServiceWorkerCacheWriterTestP, PassthroughDataSync) {
+TEST_F(ServiceWorkerCacheWriterTest, PassthroughDataSync) {
   const std::string data1 = "abcdef";
   const std::string data2 = "ghijklmno";
   size_t response_size = data1.size() + data2.size();
@@ -460,7 +457,7 @@
   EXPECT_TRUE(writer->AllExpectedWritesDone());
 }
 
-TEST_P(ServiceWorkerCacheWriterTestP, PassthroughDataAsync) {
+TEST_F(ServiceWorkerCacheWriterTest, PassthroughDataAsync) {
   const std::string data1 = "abcdef";
   const std::string data2 = "ghijklmno";
   size_t response_size = data1.size() + data2.size();
@@ -488,7 +485,7 @@
   EXPECT_TRUE(writer->AllExpectedWritesDone());
 }
 
-TEST_P(ServiceWorkerCacheWriterTestP, PassthroughHeadersFailSync) {
+TEST_F(ServiceWorkerCacheWriterTest, PassthroughHeadersFailSync) {
   const size_t kHeaderSize = 16;
   MockServiceWorkerResponseWriter* writer = ExpectWriter();
   writer->ExpectWriteInfo(kHeaderSize, false, net::ERR_FAILED);
@@ -501,7 +498,7 @@
   EXPECT_EQ(0U, cache_writer_->bytes_written());
 }
 
-TEST_P(ServiceWorkerCacheWriterTestP, PassthroughHeadersFailAsync) {
+TEST_F(ServiceWorkerCacheWriterTest, PassthroughHeadersFailAsync) {
   size_t kHeaderSize = 16;
   MockServiceWorkerResponseWriter* writer = ExpectWriter();
   writer->ExpectWriteInfo(kHeaderSize, true, net::ERR_FAILED);
@@ -517,7 +514,7 @@
   EXPECT_EQ(0U, cache_writer_->bytes_written());
 }
 
-TEST_P(ServiceWorkerCacheWriterTestP, PassthroughDataFailSync) {
+TEST_F(ServiceWorkerCacheWriterTest, PassthroughDataFailSync) {
   const std::string data = "abcdef";
 
   MockServiceWorkerResponseWriter* writer = ExpectWriter();
@@ -530,7 +527,7 @@
   EXPECT_TRUE(writer->AllExpectedWritesDone());
 }
 
-TEST_P(ServiceWorkerCacheWriterTestP, PassthroughDataFailAsync) {
+TEST_F(ServiceWorkerCacheWriterTest, PassthroughDataFailAsync) {
   const std::string data = "abcdef";
 
   MockServiceWorkerResponseWriter* writer = ExpectWriter();
@@ -552,7 +549,7 @@
 // reader for an existing cached response, so it will compare the response being
 // written to it against the existing cached response.
 
-TEST_P(ServiceWorkerCacheWriterTestP, CompareHeadersSync) {
+TEST_F(ServiceWorkerCacheWriterTest, CompareHeadersSync) {
   size_t response_size = 3;
   MockServiceWorkerResponseWriter* writer = ExpectWriter();
   MockServiceWorkerResponseReader* reader = ExpectReader();
@@ -566,7 +563,7 @@
   EXPECT_TRUE(reader->AllExpectedReadsDone());
 }
 
-TEST_P(ServiceWorkerCacheWriterTestP, CompareDataOkSync) {
+TEST_F(ServiceWorkerCacheWriterTest, CompareDataOkSync) {
   const std::string data1 = "abcdef";
   size_t response_size = data1.size();
 
@@ -588,7 +585,7 @@
   EXPECT_EQ(0U, cache_writer_->bytes_written());
 }
 
-TEST_P(ServiceWorkerCacheWriterTestP, CompareHeadersFailSync) {
+TEST_F(ServiceWorkerCacheWriterTest, CompareHeadersFailSync) {
   size_t response_size = 3;
   MockServiceWorkerResponseWriter* writer = ExpectWriter();
   MockServiceWorkerResponseReader* reader = ExpectReader();
@@ -601,7 +598,7 @@
   EXPECT_TRUE(reader->AllExpectedReadsDone());
 }
 
-TEST_P(ServiceWorkerCacheWriterTestP, CompareDataFailSync) {
+TEST_F(ServiceWorkerCacheWriterTest, CompareDataFailSync) {
   const std::string data1 = "abcdef";
   size_t response_size = data1.size();
 
@@ -622,7 +619,7 @@
   EXPECT_EQ(0U, cache_writer_->bytes_written());
 }
 
-TEST_P(ServiceWorkerCacheWriterTestP, CompareShortCacheReads) {
+TEST_F(ServiceWorkerCacheWriterTest, CompareShortCacheReads) {
   const size_t kHeaderSize = 16;
   const std::string& data1 = "abcdef";
   const std::string& cache_data2 = "ghi";
@@ -652,7 +649,7 @@
   EXPECT_EQ(0U, cache_writer_->bytes_written());
 }
 
-TEST_P(ServiceWorkerCacheWriterTestP, CompareDataOkAsync) {
+TEST_F(ServiceWorkerCacheWriterTest, CompareDataOkAsync) {
   const std::string data1 = "abcdef";
   size_t response_size = data1.size();
 
@@ -674,7 +671,7 @@
   EXPECT_EQ(0U, cache_writer_->bytes_written());
 }
 
-TEST_P(ServiceWorkerCacheWriterTestP, CompareDataManyOkAsync) {
+TEST_F(ServiceWorkerCacheWriterTest, CompareDataManyOkAsync) {
   const std::string expected_data[] = {
       "abcdef", "ghijkl", "mnopqr", "stuvwxyz",
   };
@@ -709,7 +706,7 @@
 // differs in the cached version. The writer should be asked to rewrite the
 // headers and body with the new value, and the copy reader should be asked to
 // read the header and data1.
-TEST_P(ServiceWorkerCacheWriterTestP, CompareFailedCopySync) {
+TEST_F(ServiceWorkerCacheWriterTest, CompareFailedCopySync) {
   std::string data1 = "abcdef";
   std::string cache_data2 = "ghijkl";
   std::string net_data2 = "mnopqr";
@@ -750,7 +747,7 @@
 }
 
 // Tests behavior when the cached data is shorter than the network data.
-TEST_P(ServiceWorkerCacheWriterTestP, CompareFailedCopyShort) {
+TEST_F(ServiceWorkerCacheWriterTest, CompareFailedCopyShort) {
   std::string data1 = "abcdef";
   std::string cache_data2 = "mnop";
   std::string net_data2 = "mnopqr";
@@ -792,7 +789,7 @@
 }
 
 // Tests behavior when the cached data is longer than the network data.
-TEST_P(ServiceWorkerCacheWriterTestP, CompareFailedCopyLong) {
+TEST_F(ServiceWorkerCacheWriterTest, CompareFailedCopyLong) {
   std::string data1 = "abcdef";
   std::string cache_data2 = "mnop";
   std::string net_data2 = "mnop";
@@ -835,9 +832,5 @@
   EXPECT_TRUE(copy_reader->AllExpectedReadsDone());
 }
 
-INSTANTIATE_TEST_CASE_P(ServiceWorkerCacheWriterTest,
-                        ServiceWorkerCacheWriterTestP,
-                        testing::Bool());
-
 }  // namespace
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_context_core.h b/content/browser/service_worker/service_worker_context_core.h
index e0c7d79..4832b8c4 100644
--- a/content/browser/service_worker/service_worker_context_core.h
+++ b/content/browser/service_worker/service_worker_context_core.h
@@ -292,8 +292,8 @@
   }
 
  private:
-  friend class ServiceWorkerContextCoreTestP;
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextCoreTestP, FailureInfo);
+  friend class ServiceWorkerContextCoreTest;
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextCoreTest, FailureInfo);
 
   typedef std::map<int64_t, ServiceWorkerRegistration*> RegistrationsMap;
   typedef std::map<int64_t, ServiceWorkerVersion*> VersionMap;
diff --git a/content/browser/service_worker/service_worker_context_core_unittest.cc b/content/browser/service_worker/service_worker_context_core_unittest.cc
index e0e5c69f..42658be 100644
--- a/content/browser/service_worker/service_worker_context_core_unittest.cc
+++ b/content/browser/service_worker/service_worker_context_core_unittest.cc
@@ -34,10 +34,7 @@
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerContextCoreTest);
 };
 
-class ServiceWorkerContextCoreTestP
-    : public MojoServiceWorkerTestP<ServiceWorkerContextCoreTest> {};
-
-TEST_P(ServiceWorkerContextCoreTestP, FailureInfo) {
+TEST_F(ServiceWorkerContextCoreTest, FailureInfo) {
   const int64_t kVersionId = 55;  // dummy value
 
   EXPECT_EQ(0, context()->GetVersionFailureCount(kVersionId));
@@ -62,8 +59,4 @@
   EXPECT_FALSE(base::ContainsKey(context()->failure_counts_, kVersionId));
 }
 
-INSTANTIATE_TEST_CASE_P(ServiceWorkerContextCoreTest,
-                        ServiceWorkerContextCoreTestP,
-                        testing::Bool());
-
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_context_request_handler_unittest.cc b/content/browser/service_worker/service_worker_context_request_handler_unittest.cc
index 5c6a1d7..93583b3 100644
--- a/content/browser/service_worker/service_worker_context_request_handler_unittest.cc
+++ b/content/browser/service_worker/service_worker_context_request_handler_unittest.cc
@@ -85,10 +85,7 @@
   storage::BlobStorageContext blob_storage_context_;
 };
 
-class ServiceWorkerContextRequestHandlerTestP
-    : public MojoServiceWorkerTestP<ServiceWorkerContextRequestHandlerTest> {};
-
-TEST_P(ServiceWorkerContextRequestHandlerTestP, UpdateBefore24Hours) {
+TEST_F(ServiceWorkerContextRequestHandlerTest, UpdateBefore24Hours) {
   // Give the registration a very recent last update time and pretend
   // we're installing a new version.
   registration_->set_last_update_check(base::Time::Now());
@@ -114,7 +111,7 @@
   EXPECT_FALSE(sw_job->net_request_->load_flags() & net::LOAD_BYPASS_CACHE);
 }
 
-TEST_P(ServiceWorkerContextRequestHandlerTestP, UpdateAfter24Hours) {
+TEST_F(ServiceWorkerContextRequestHandlerTest, UpdateAfter24Hours) {
   // Give the registration a old update time and pretend
   // we're installing a new version.
   registration_->set_last_update_check(
@@ -141,7 +138,7 @@
   EXPECT_TRUE(sw_job->net_request_->load_flags() & net::LOAD_BYPASS_CACHE);
 }
 
-TEST_P(ServiceWorkerContextRequestHandlerTestP, UpdateForceBypassCache) {
+TEST_F(ServiceWorkerContextRequestHandlerTest, UpdateForceBypassCache) {
   // Give the registration a very recent last update time and pretend
   // we're installing a new version.
   registration_->set_last_update_check(base::Time::Now());
@@ -168,7 +165,7 @@
   EXPECT_TRUE(sw_job->net_request_->load_flags() & net::LOAD_BYPASS_CACHE);
 }
 
-TEST_P(ServiceWorkerContextRequestHandlerTestP,
+TEST_F(ServiceWorkerContextRequestHandlerTest,
        ServiceWorkerDataRequestAnnotation) {
   version_->SetStatus(ServiceWorkerVersion::NEW);
   provider_host_->running_hosted_version_ = version_;
@@ -196,7 +193,7 @@
 
 // Tests starting a service worker when the skip_service_worker flag is on. The
 // flag should be ignored.
-TEST_P(ServiceWorkerContextRequestHandlerTestP,
+TEST_F(ServiceWorkerContextRequestHandlerTest,
        SkipServiceWorkerForServiceWorkerRequest) {
   // Conduct a resource fetch for the main script.
   version_->SetStatus(ServiceWorkerVersion::NEW);
@@ -217,8 +214,4 @@
   EXPECT_TRUE(handler);
 }
 
-INSTANTIATE_TEST_CASE_P(ServiceWorkerContextRequestHandlerTest,
-                        ServiceWorkerContextRequestHandlerTestP,
-                        testing::Bool());
-
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_context_unittest.cc b/content/browser/service_worker/service_worker_context_unittest.cc
index c12be51..88870e2 100644
--- a/content/browser/service_worker/service_worker_context_unittest.cc
+++ b/content/browser/service_worker/service_worker_context_unittest.cc
@@ -162,9 +162,6 @@
   std::vector<NotificationLog> notifications_;
 };
 
-class ServiceWorkerContextTestP
-    : public MojoServiceWorkerTestP<ServiceWorkerContextTest> {};
-
 class RecordableEmbeddedWorkerInstanceClient
     : public EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient {
  public:
@@ -198,15 +195,13 @@
 };
 
 // Make sure basic registration is working.
-TEST_P(ServiceWorkerContextTestP, Register) {
+TEST_F(ServiceWorkerContextTest, Register) {
   GURL pattern("http://www.example.com/");
   GURL script_url("http://www.example.com/service_worker.js");
 
   RecordableEmbeddedWorkerInstanceClient* client = nullptr;
-  if (is_mojo_enabled()) {
-    client = helper_->CreateAndRegisterMockInstanceClient<
-        RecordableEmbeddedWorkerInstanceClient>(helper_->AsWeakPtr());
-  }
+  client = helper_->CreateAndRegisterMockInstanceClient<
+      RecordableEmbeddedWorkerInstanceClient>(helper_->AsWeakPtr());
 
   int64_t registration_id = kInvalidServiceWorkerRegistrationId;
   bool called = false;
@@ -220,28 +215,17 @@
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(called);
 
-  if (is_mojo_enabled()) {
-    EXPECT_EQ(2UL, helper_->ipc_sink()->message_count());
-    ASSERT_EQ(2UL, client->events().size());
-    EXPECT_EQ(RecordableEmbeddedWorkerInstanceClient::Message::StartWorker,
-              client->events()[0]);
-    EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
-        ServiceWorkerMsg_InstallEvent::ID));
-    EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
-        ServiceWorkerMsg_ActivateEvent::ID));
-    EXPECT_EQ(RecordableEmbeddedWorkerInstanceClient::Message::StopWorker,
-              client->events()[1]);
-  } else {
-    EXPECT_EQ(4UL, helper_->ipc_sink()->message_count());
-    EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
-        EmbeddedWorkerMsg_StartWorker::ID));
-    EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
-        ServiceWorkerMsg_InstallEvent::ID));
-    EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
-        ServiceWorkerMsg_ActivateEvent::ID));
-    EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
-        EmbeddedWorkerMsg_StopWorker::ID));
-  }
+  EXPECT_EQ(2UL, helper_->ipc_sink()->message_count());
+  ASSERT_EQ(2UL, client->events().size());
+  EXPECT_EQ(RecordableEmbeddedWorkerInstanceClient::Message::StartWorker,
+            client->events()[0]);
+  EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
+      ServiceWorkerMsg_InstallEvent::ID));
+  EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
+      ServiceWorkerMsg_ActivateEvent::ID));
+  EXPECT_EQ(RecordableEmbeddedWorkerInstanceClient::Message::StopWorker,
+            client->events()[1]);
+
   EXPECT_NE(kInvalidServiceWorkerRegistrationId, registration_id);
 
   ASSERT_EQ(1u, notifications_.size());
@@ -262,7 +246,7 @@
 // Test registration when the service worker rejects the install event. The
 // registration callback should indicate success, but there should be no waiting
 // or active worker in the registration.
-TEST_P(ServiceWorkerContextTestP, Register_RejectInstall) {
+TEST_F(ServiceWorkerContextTest, Register_RejectInstall) {
   GURL pattern("http://www.example.com/");
   GURL script_url("http://www.example.com/service_worker.js");
 
@@ -271,10 +255,8 @@
   helper_->context_wrapper()->AddObserver(this);
 
   RecordableEmbeddedWorkerInstanceClient* client = nullptr;
-  if (is_mojo_enabled()) {
-    client = helper_->CreateAndRegisterMockInstanceClient<
-        RecordableEmbeddedWorkerInstanceClient>(helper_->AsWeakPtr());
-  }
+  client = helper_->CreateAndRegisterMockInstanceClient<
+      RecordableEmbeddedWorkerInstanceClient>(helper_->AsWeakPtr());
 
   int64_t registration_id = kInvalidServiceWorkerRegistrationId;
   bool called = false;
@@ -288,28 +270,17 @@
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(called);
 
-  if (is_mojo_enabled()) {
-    EXPECT_EQ(1UL, helper_->ipc_sink()->message_count());
-    ASSERT_EQ(2UL, client->events().size());
-    EXPECT_EQ(RecordableEmbeddedWorkerInstanceClient::Message::StartWorker,
-              client->events()[0]);
-    EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
-        ServiceWorkerMsg_InstallEvent::ID));
-    EXPECT_FALSE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
-        ServiceWorkerMsg_ActivateEvent::ID));
-    EXPECT_EQ(RecordableEmbeddedWorkerInstanceClient::Message::StopWorker,
-              client->events()[1]);
-  } else {
-    EXPECT_EQ(3UL, helper_->ipc_sink()->message_count());
-    EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
-        EmbeddedWorkerMsg_StartWorker::ID));
-    EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
-        ServiceWorkerMsg_InstallEvent::ID));
-    EXPECT_FALSE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
-        ServiceWorkerMsg_ActivateEvent::ID));
-    EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
-        EmbeddedWorkerMsg_StopWorker::ID));
-  }
+  EXPECT_EQ(1UL, helper_->ipc_sink()->message_count());
+  ASSERT_EQ(2UL, client->events().size());
+  EXPECT_EQ(RecordableEmbeddedWorkerInstanceClient::Message::StartWorker,
+            client->events()[0]);
+  EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
+      ServiceWorkerMsg_InstallEvent::ID));
+  EXPECT_FALSE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
+      ServiceWorkerMsg_ActivateEvent::ID));
+  EXPECT_EQ(RecordableEmbeddedWorkerInstanceClient::Message::StopWorker,
+            client->events()[1]);
+
   EXPECT_NE(kInvalidServiceWorkerRegistrationId, registration_id);
 
   ASSERT_EQ(1u, notifications_.size());
@@ -329,7 +300,7 @@
 
 // Test registration when the service worker rejects the activate event. The
 // worker should be activated anyway.
-TEST_P(ServiceWorkerContextTestP, Register_RejectActivate) {
+TEST_F(ServiceWorkerContextTest, Register_RejectActivate) {
   GURL pattern("http://www.example.com/");
   GURL script_url("http://www.example.com/service_worker.js");
 
@@ -338,10 +309,8 @@
   helper_->context_wrapper()->AddObserver(this);
 
   RecordableEmbeddedWorkerInstanceClient* client = nullptr;
-  if (is_mojo_enabled()) {
-    client = helper_->CreateAndRegisterMockInstanceClient<
-        RecordableEmbeddedWorkerInstanceClient>(helper_->AsWeakPtr());
-  }
+  client = helper_->CreateAndRegisterMockInstanceClient<
+      RecordableEmbeddedWorkerInstanceClient>(helper_->AsWeakPtr());
 
   int64_t registration_id = kInvalidServiceWorkerRegistrationId;
   bool called = false;
@@ -353,28 +322,17 @@
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(called);
 
-  if (is_mojo_enabled()) {
-    EXPECT_EQ(2UL, helper_->ipc_sink()->message_count());
-    ASSERT_EQ(2UL, client->events().size());
-    EXPECT_EQ(RecordableEmbeddedWorkerInstanceClient::Message::StartWorker,
-              client->events()[0]);
-    EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
-        ServiceWorkerMsg_InstallEvent::ID));
-    EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
-        ServiceWorkerMsg_ActivateEvent::ID));
-    EXPECT_EQ(RecordableEmbeddedWorkerInstanceClient::Message::StopWorker,
-              client->events()[1]);
-  } else {
-    EXPECT_EQ(4UL, helper_->ipc_sink()->message_count());
-    EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
-        EmbeddedWorkerMsg_StartWorker::ID));
-    EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
-        ServiceWorkerMsg_InstallEvent::ID));
-    EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
-        ServiceWorkerMsg_ActivateEvent::ID));
-    EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
-        EmbeddedWorkerMsg_StopWorker::ID));
-  }
+  EXPECT_EQ(2UL, helper_->ipc_sink()->message_count());
+  ASSERT_EQ(2UL, client->events().size());
+  EXPECT_EQ(RecordableEmbeddedWorkerInstanceClient::Message::StartWorker,
+            client->events()[0]);
+  EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
+      ServiceWorkerMsg_InstallEvent::ID));
+  EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
+      ServiceWorkerMsg_ActivateEvent::ID));
+  EXPECT_EQ(RecordableEmbeddedWorkerInstanceClient::Message::StopWorker,
+            client->events()[1]);
+
   EXPECT_NE(kInvalidServiceWorkerRegistrationId, registration_id);
 
   ASSERT_EQ(1u, notifications_.size());
@@ -390,7 +348,7 @@
 }
 
 // Make sure registrations are cleaned up when they are unregistered.
-TEST_P(ServiceWorkerContextTestP, Unregister) {
+TEST_F(ServiceWorkerContextTest, Unregister) {
   GURL pattern("http://www.example.com/");
 
   bool called = false;
@@ -433,7 +391,7 @@
 }
 
 // Make sure registrations are cleaned up when they are unregistered in bulk.
-TEST_P(ServiceWorkerContextTestP, UnregisterMultiple) {
+TEST_F(ServiceWorkerContextTest, UnregisterMultiple) {
   GURL origin1_p1("http://www.example.com/test");
   GURL origin1_p2("http://www.example.com/hello");
   GURL origin2_p1("http://www.example.com:8080/again");
@@ -536,7 +494,7 @@
 }
 
 // Make sure registering a new script shares an existing registration.
-TEST_P(ServiceWorkerContextTestP, RegisterNewScript) {
+TEST_F(ServiceWorkerContextTest, RegisterNewScript) {
   GURL pattern("http://www.example.com/");
 
   bool called = false;
@@ -578,7 +536,7 @@
 
 // Make sure that when registering a duplicate pattern+script_url
 // combination, that the same registration is used.
-TEST_P(ServiceWorkerContextTestP, RegisterDuplicateScript) {
+TEST_F(ServiceWorkerContextTest, RegisterDuplicateScript) {
   GURL pattern("http://www.example.com/");
   GURL script_url("http://www.example.com/service_worker.js");
 
@@ -617,7 +575,7 @@
   EXPECT_EQ(old_registration_id, notifications_[1].registration_id);
 }
 
-TEST_P(ServiceWorkerContextTestP, ProviderHostIterator) {
+TEST_F(ServiceWorkerContextTest, ProviderHostIterator) {
   const int kRenderProcessId1 = 1;
   const int kRenderProcessId2 = 2;
   const GURL kOrigin1 = GURL("http://www.example.com/");
@@ -701,22 +659,13 @@
 
 class ServiceWorkerContextRecoveryTest
     : public ServiceWorkerContextTest,
-      public testing::WithParamInterface<testing::tuple<bool, bool>> {
+      public testing::WithParamInterface<bool> {
  public:
   ServiceWorkerContextRecoveryTest() {}
   virtual ~ServiceWorkerContextRecoveryTest() {}
 
  protected:
-  void SetUp() override {
-    if (!is_mojo_enabled()) {
-      base::CommandLine::ForCurrentProcess()->AppendSwitch(
-          switches::kDisableMojoServiceWorker);
-    }
-    ServiceWorkerContextTest::SetUp();
-  }
-
-  bool is_mojo_enabled() const { return testing::get<0>(GetParam()); }
-  bool is_storage_on_disk() const { return testing::get<1>(GetParam()); }
+  bool is_storage_on_disk() const { return GetParam(); }
 };
 
 TEST_P(ServiceWorkerContextRecoveryTest, DeleteAndStartOver) {
@@ -811,12 +760,8 @@
   EXPECT_EQ(registration_id, notifications_[2].registration_id);
 }
 
-INSTANTIATE_TEST_CASE_P(ServiceWorkerContextTest,
-                        ServiceWorkerContextTestP,
-                        testing::Bool());
-
 INSTANTIATE_TEST_CASE_P(ServiceWorkerContextRecoveryTest,
                         ServiceWorkerContextRecoveryTest,
-                        testing::Combine(testing::Bool(), testing::Bool()));
+                        testing::Bool());
 
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc b/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
index 8132f4d9..eb826b2 100644
--- a/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
+++ b/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
@@ -157,10 +157,6 @@
   GURL script_url_;
 };
 
-class ServiceWorkerControlleeRequestHandlerTestP
-    : public MojoServiceWorkerTestP<ServiceWorkerControlleeRequestHandlerTest> {
-};
-
 class ServiceWorkerTestContentBrowserClient : public TestContentBrowserClient {
  public:
   ServiceWorkerTestContentBrowserClient() {}
@@ -173,7 +169,7 @@
   }
 };
 
-TEST_P(ServiceWorkerControlleeRequestHandlerTestP, DisallowServiceWorker) {
+TEST_F(ServiceWorkerControlleeRequestHandlerTest, DisallowServiceWorker) {
   ServiceWorkerTestContentBrowserClient test_browser_client;
   ContentBrowserClient* old_browser_client =
       SetBrowserClientForTesting(&test_browser_client);
@@ -207,7 +203,7 @@
   SetBrowserClientForTesting(old_browser_client);
 }
 
-TEST_P(ServiceWorkerControlleeRequestHandlerTestP, ActivateWaitingVersion) {
+TEST_F(ServiceWorkerControlleeRequestHandlerTest, ActivateWaitingVersion) {
   // Store a registration that is installed but not activated yet.
   version_->set_fetch_handler_existence(
       ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
@@ -242,7 +238,7 @@
 }
 
 // Test that an installing registration is associated with a provider host.
-TEST_P(ServiceWorkerControlleeRequestHandlerTestP, InstallingRegistration) {
+TEST_F(ServiceWorkerControlleeRequestHandlerTest, InstallingRegistration) {
   // Create an installing registration.
   version_->SetStatus(ServiceWorkerVersion::INSTALLING);
   version_->set_fetch_handler_existence(
@@ -268,7 +264,7 @@
 }
 
 // Test to not regress crbug/414118.
-TEST_P(ServiceWorkerControlleeRequestHandlerTestP, DeletedProviderHost) {
+TEST_F(ServiceWorkerControlleeRequestHandlerTest, DeletedProviderHost) {
   // Store a registration so the call to FindRegistrationForDocument will read
   // from the database.
   version_->set_fetch_handler_existence(
@@ -304,7 +300,7 @@
 // Tests the scenario where a controllee request handler was created
 // for a subresource request, but before MaybeCreateJob() is run, the
 // controller/active version becomes null.
-TEST_P(ServiceWorkerControlleeRequestHandlerTestP, LostActiveVersion) {
+TEST_F(ServiceWorkerControlleeRequestHandlerTest, LostActiveVersion) {
   // Store an activated worker.
   version_->set_fetch_handler_existence(
       ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
@@ -343,7 +339,7 @@
       sub_job->response_type_);
 }
 
-TEST_P(ServiceWorkerControlleeRequestHandlerTestP, FallbackWithNoFetchHandler) {
+TEST_F(ServiceWorkerControlleeRequestHandlerTest, FallbackWithNoFetchHandler) {
   version_->set_fetch_handler_existence(
       ServiceWorkerVersion::FetchHandlerExistence::DOES_NOT_EXIST);
   version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
@@ -393,8 +389,4 @@
   EXPECT_FALSE(sub_cors_job->ShouldForwardToServiceWorker());
 }
 
-INSTANTIATE_TEST_CASE_P(ServiceWorkerControlleeRequestHandlerTest,
-                        ServiceWorkerControlleeRequestHandlerTestP,
-                        testing::Bool());
-
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc b/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
index a40598601..b4385433 100644
--- a/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
+++ b/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
@@ -261,9 +261,6 @@
   ServiceWorkerProviderHost* provider_host_;
 };
 
-class ServiceWorkerDispatcherHostTestP
-    : public MojoServiceWorkerTestP<ServiceWorkerDispatcherHostTest> {};
-
 class ServiceWorkerTestContentBrowserClient : public TestContentBrowserClient {
  public:
   ServiceWorkerTestContentBrowserClient() {}
@@ -276,7 +273,7 @@
   }
 };
 
-TEST_P(ServiceWorkerDispatcherHostTestP,
+TEST_F(ServiceWorkerDispatcherHostTest,
        Register_ContentSettingsDisallowsServiceWorker) {
   ServiceWorkerTestContentBrowserClient test_browser_client;
   ContentBrowserClient* old_browser_client =
@@ -310,7 +307,7 @@
   SetBrowserClientForTesting(old_browser_client);
 }
 
-TEST_P(ServiceWorkerDispatcherHostTestP, Register_HTTPS) {
+TEST_F(ServiceWorkerDispatcherHostTest, Register_HTTPS) {
   const int64_t kProviderId = 99;  // Dummy value
   std::unique_ptr<ServiceWorkerProviderHost> host(
       CreateServiceWorkerProviderHost(kProviderId));
@@ -323,7 +320,7 @@
            ServiceWorkerMsg_ServiceWorkerRegistered::ID);
 }
 
-TEST_P(ServiceWorkerDispatcherHostTestP, Register_NonSecureTransportLocalhost) {
+TEST_F(ServiceWorkerDispatcherHostTest, Register_NonSecureTransportLocalhost) {
   const int64_t kProviderId = 99;  // Dummy value
   std::unique_ptr<ServiceWorkerProviderHost> host(
       CreateServiceWorkerProviderHost(kProviderId));
@@ -336,7 +333,7 @@
            ServiceWorkerMsg_ServiceWorkerRegistered::ID);
 }
 
-TEST_P(ServiceWorkerDispatcherHostTestP, Register_InvalidScopeShouldFail) {
+TEST_F(ServiceWorkerDispatcherHostTest, Register_InvalidScopeShouldFail) {
   const int64_t kProviderId = 99;  // Dummy value
   std::unique_ptr<ServiceWorkerProviderHost> host(
       CreateServiceWorkerProviderHost(kProviderId));
@@ -348,7 +345,7 @@
   EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
 }
 
-TEST_P(ServiceWorkerDispatcherHostTestP, Register_InvalidScriptShouldFail) {
+TEST_F(ServiceWorkerDispatcherHostTest, Register_InvalidScriptShouldFail) {
   const int64_t kProviderId = 99;  // Dummy value
   std::unique_ptr<ServiceWorkerProviderHost> host(
       CreateServiceWorkerProviderHost(kProviderId));
@@ -359,7 +356,7 @@
   EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
 }
 
-TEST_P(ServiceWorkerDispatcherHostTestP, Register_NonSecureOriginShouldFail) {
+TEST_F(ServiceWorkerDispatcherHostTest, Register_NonSecureOriginShouldFail) {
   const int64_t kProviderId = 99;  // Dummy value
   std::unique_ptr<ServiceWorkerProviderHost> host(
       CreateServiceWorkerProviderHost(kProviderId));
@@ -372,7 +369,7 @@
   EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
 }
 
-TEST_P(ServiceWorkerDispatcherHostTestP, Register_CrossOriginShouldFail) {
+TEST_F(ServiceWorkerDispatcherHostTest, Register_CrossOriginShouldFail) {
   const int64_t kProviderId = 99;  // Dummy value
   std::unique_ptr<ServiceWorkerProviderHost> host(
       CreateServiceWorkerProviderHost(kProviderId));
@@ -416,7 +413,7 @@
   EXPECT_EQ(6, dispatcher_host_->bad_messages_received_count_);
 }
 
-TEST_P(ServiceWorkerDispatcherHostTestP, Register_BadCharactersShouldFail) {
+TEST_F(ServiceWorkerDispatcherHostTest, Register_BadCharactersShouldFail) {
   const int64_t kProviderId = 99;  // Dummy value
   std::unique_ptr<ServiceWorkerProviderHost> host(
       CreateServiceWorkerProviderHost(kProviderId));
@@ -448,8 +445,7 @@
   EXPECT_EQ(6, dispatcher_host_->bad_messages_received_count_);
 }
 
-TEST_P(ServiceWorkerDispatcherHostTestP,
-       Register_FileSystemDocumentShouldFail) {
+TEST_F(ServiceWorkerDispatcherHostTest, Register_FileSystemDocumentShouldFail) {
   const int64_t kProviderId = 99;  // Dummy value
   std::unique_ptr<ServiceWorkerProviderHost> host(
       CreateServiceWorkerProviderHost(kProviderId));
@@ -472,7 +468,7 @@
   EXPECT_EQ(3, dispatcher_host_->bad_messages_received_count_);
 }
 
-TEST_P(ServiceWorkerDispatcherHostTestP,
+TEST_F(ServiceWorkerDispatcherHostTest,
        Register_FileSystemScriptOrScopeShouldFail) {
   const int64_t kProviderId = 99;  // Dummy value
   std::unique_ptr<ServiceWorkerProviderHost> host(
@@ -496,7 +492,7 @@
   EXPECT_EQ(3, dispatcher_host_->bad_messages_received_count_);
 }
 
-TEST_P(ServiceWorkerDispatcherHostTestP, EarlyContextDeletion) {
+TEST_F(ServiceWorkerDispatcherHostTest, EarlyContextDeletion) {
   helper_->ShutdownContext();
 
   // Let the shutdown reach the simulated IO thread.
@@ -508,7 +504,7 @@
            ServiceWorkerMsg_ServiceWorkerRegistrationError::ID);
 }
 
-TEST_P(ServiceWorkerDispatcherHostTestP, ProviderCreatedAndDestroyed) {
+TEST_F(ServiceWorkerDispatcherHostTest, ProviderCreatedAndDestroyed) {
   const int kProviderId = 1001;
   int process_id = helper_->mock_render_process_id();
 
@@ -543,7 +539,7 @@
   EXPECT_FALSE(context()->GetProviderHost(process_id, kProviderId));
 }
 
-TEST_P(ServiceWorkerDispatcherHostTestP, GetRegistration_SameOrigin) {
+TEST_F(ServiceWorkerDispatcherHostTest, GetRegistration_SameOrigin) {
   const int64_t kProviderId = 99;  // Dummy value
   std::unique_ptr<ServiceWorkerProviderHost> host(
       CreateServiceWorkerProviderHost(kProviderId));
@@ -555,8 +551,7 @@
                   ServiceWorkerMsg_DidGetRegistration::ID);
 }
 
-TEST_P(ServiceWorkerDispatcherHostTestP,
-       GetRegistration_CrossOriginShouldFail) {
+TEST_F(ServiceWorkerDispatcherHostTest, GetRegistration_CrossOriginShouldFail) {
   const int64_t kProviderId = 99;  // Dummy value
   std::unique_ptr<ServiceWorkerProviderHost> host(
       CreateServiceWorkerProviderHost(kProviderId));
@@ -567,7 +562,7 @@
   EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
 }
 
-TEST_P(ServiceWorkerDispatcherHostTestP,
+TEST_F(ServiceWorkerDispatcherHostTest,
        GetRegistration_InvalidScopeShouldFail) {
   const int64_t kProviderId = 99;  // Dummy value
   std::unique_ptr<ServiceWorkerProviderHost> host(
@@ -579,7 +574,7 @@
   EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
 }
 
-TEST_P(ServiceWorkerDispatcherHostTestP,
+TEST_F(ServiceWorkerDispatcherHostTest,
        GetRegistration_NonSecureOriginShouldFail) {
   const int64_t kProviderId = 99;  // Dummy value
   std::unique_ptr<ServiceWorkerProviderHost> host(
@@ -591,7 +586,7 @@
   EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
 }
 
-TEST_P(ServiceWorkerDispatcherHostTestP, GetRegistration_EarlyContextDeletion) {
+TEST_F(ServiceWorkerDispatcherHostTest, GetRegistration_EarlyContextDeletion) {
   helper_->ShutdownContext();
 
   // Let the shutdown reach the simulated IO thread.
@@ -602,7 +597,7 @@
                   ServiceWorkerMsg_ServiceWorkerGetRegistrationError::ID);
 }
 
-TEST_P(ServiceWorkerDispatcherHostTestP, GetRegistrations_SecureOrigin) {
+TEST_F(ServiceWorkerDispatcherHostTest, GetRegistrations_SecureOrigin) {
   const int64_t kProviderId = 99;  // Dummy value
   std::unique_ptr<ServiceWorkerProviderHost> host(
       CreateServiceWorkerProviderHost(kProviderId));
@@ -612,7 +607,7 @@
   GetRegistrations(kProviderId, ServiceWorkerMsg_DidGetRegistrations::ID);
 }
 
-TEST_P(ServiceWorkerDispatcherHostTestP,
+TEST_F(ServiceWorkerDispatcherHostTest,
        GetRegistrations_NonSecureOriginShouldFail) {
   const int64_t kProviderId = 99;  // Dummy value
   std::unique_ptr<ServiceWorkerProviderHost> host(
@@ -624,8 +619,7 @@
   EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
 }
 
-TEST_P(ServiceWorkerDispatcherHostTestP,
-       GetRegistrations_EarlyContextDeletion) {
+TEST_F(ServiceWorkerDispatcherHostTest, GetRegistrations_EarlyContextDeletion) {
   helper_->ShutdownContext();
 
   // Let the shutdown reach the simulated IO thread.
@@ -634,7 +628,7 @@
   GetRegistrations(-1, ServiceWorkerMsg_ServiceWorkerGetRegistrationsError::ID);
 }
 
-TEST_P(ServiceWorkerDispatcherHostTestP, CleanupOnRendererCrash) {
+TEST_F(ServiceWorkerDispatcherHostTest, CleanupOnRendererCrash) {
   GURL pattern = GURL("http://www.example.com/");
   GURL script_url = GURL("http://www.example.com/service_worker.js");
   int process_id = helper_->mock_render_process_id();
@@ -679,7 +673,7 @@
   EXPECT_EQ(0, new_dispatcher_host->bad_messages_received_count_);
 }
 
-TEST_P(ServiceWorkerDispatcherHostTestP, DispatchExtendableMessageEvent) {
+TEST_F(ServiceWorkerDispatcherHostTest, DispatchExtendableMessageEvent) {
   GURL pattern = GURL("http://www.example.com/");
   GURL script_url = GURL("http://www.example.com/service_worker.js");
 
@@ -745,7 +739,7 @@
   EXPECT_EQ(remaining_time, version_->remaining_timeout());
 }
 
-TEST_P(ServiceWorkerDispatcherHostTestP, DispatchExtendableMessageEvent_Fail) {
+TEST_F(ServiceWorkerDispatcherHostTest, DispatchExtendableMessageEvent_Fail) {
   GURL pattern = GURL("http://www.example.com/");
   GURL script_url = GURL("http://www.example.com/service_worker.js");
 
@@ -773,7 +767,7 @@
     EXPECT_FALSE(MessagePortService::GetInstance()->AreMessagesHeld(port));
 }
 
-TEST_P(ServiceWorkerDispatcherHostTestP, OnSetHostedVersionId) {
+TEST_F(ServiceWorkerDispatcherHostTest, OnSetHostedVersionId) {
   GURL pattern = GURL("http://www.example.com/");
   GURL script_url = GURL("http://www.example.com/service_worker.js");
 
@@ -801,7 +795,7 @@
   EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
 }
 
-TEST_P(ServiceWorkerDispatcherHostTestP, OnSetHostedVersionId_DetachedWorker) {
+TEST_F(ServiceWorkerDispatcherHostTest, OnSetHostedVersionId_DetachedWorker) {
   GURL pattern = GURL("http://www.example.com/");
   GURL script_url = GURL("http://www.example.com/service_worker.js");
 
@@ -829,7 +823,7 @@
   EXPECT_EQ(0, dispatcher_host_->bad_messages_received_count_);
 }
 
-TEST_P(ServiceWorkerDispatcherHostTestP, ReceivedTimedOutRequestResponse) {
+TEST_F(ServiceWorkerDispatcherHostTest, ReceivedTimedOutRequestResponse) {
   GURL pattern = GURL("https://www.example.com/");
   GURL script_url = GURL("https://www.example.com/service_worker.js");
 
@@ -856,8 +850,4 @@
   EXPECT_EQ(0, dispatcher_host_->bad_messages_received_count_);
 }
 
-INSTANTIATE_TEST_CASE_P(ServiceWorkerDispatcherHostTest,
-                        ServiceWorkerDispatcherHostTestP,
-                        testing::Bool());
-
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_handle_unittest.cc b/content/browser/service_worker/service_worker_handle_unittest.cc
index cf853e15..32716e1 100644
--- a/content/browser/service_worker/service_worker_handle_unittest.cc
+++ b/content/browser/service_worker/service_worker_handle_unittest.cc
@@ -143,10 +143,7 @@
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerHandleTest);
 };
 
-class ServiceWorkerHandleTestP
-    : public MojoServiceWorkerTestP<ServiceWorkerHandleTest> {};
-
-TEST_P(ServiceWorkerHandleTestP, OnVersionStateChanged) {
+TEST_F(ServiceWorkerHandleTest, OnVersionStateChanged) {
   std::unique_ptr<ServiceWorkerHandle> handle =
       ServiceWorkerHandle::Create(helper_->context()->AsWeakPtr(),
                                   provider_host_->AsWeakPtr(), version_.get());
@@ -164,24 +161,13 @@
   ASSERT_EQ(0L, dispatcher_host_->bad_message_received_count_);
 
   const IPC::Message* message = nullptr;
-  if (is_mojo_enabled()) {
-    // StartWorker shouldn't be recorded here.
-    ASSERT_EQ(1UL, ipc_sink()->message_count());
-    message = ipc_sink()->GetMessageAt(0);
-  } else {
-    ASSERT_EQ(2UL, ipc_sink()->message_count());
-    // We should be sending 1. StartWorker,
-    EXPECT_EQ(EmbeddedWorkerMsg_StartWorker::ID,
-              ipc_sink()->GetMessageAt(0)->type());
-    message = ipc_sink()->GetMessageAt(1);
-  }
+  // StartWorker shouldn't be recorded here.
+  ASSERT_EQ(1UL, ipc_sink()->message_count());
+  message = ipc_sink()->GetMessageAt(0);
+
   // StateChanged (state == Installed).
   VerifyStateChangedMessage(handle->handle_id(),
                             blink::WebServiceWorkerStateInstalled, message);
 }
 
-INSTANTIATE_TEST_CASE_P(ServiceWorkerHandleTest,
-                        ServiceWorkerHandleTestP,
-                        ::testing::Values(false, true));
-
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_job_unittest.cc b/content/browser/service_worker/service_worker_job_unittest.cc
index 72740fb0..363722f 100644
--- a/content/browser/service_worker/service_worker_job_unittest.cc
+++ b/content/browser/service_worker/service_worker_job_unittest.cc
@@ -143,9 +143,6 @@
   std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
 };
 
-class ServiceWorkerJobTestP
-    : public MojoServiceWorkerTestP<ServiceWorkerJobTest> {};
-
 scoped_refptr<ServiceWorkerRegistration> ServiceWorkerJobTest::RunRegisterJob(
     const GURL& pattern,
     const GURL& script_url,
@@ -199,7 +196,7 @@
           helper_->context()->AsWeakPtr(), NULL));
 }
 
-TEST_P(ServiceWorkerJobTestP, SameDocumentSameRegistration) {
+TEST_F(ServiceWorkerJobTest, SameDocumentSameRegistration) {
   scoped_refptr<ServiceWorkerRegistration> original_registration =
       RunRegisterJob(GURL("http://www.example.com/"),
                      GURL("http://www.example.com/service_worker.js"));
@@ -219,7 +216,7 @@
   ASSERT_EQ(registration1, registration2);
 }
 
-TEST_P(ServiceWorkerJobTestP, SameMatchSameRegistration) {
+TEST_F(ServiceWorkerJobTest, SameMatchSameRegistration) {
   bool called;
   scoped_refptr<ServiceWorkerRegistration> original_registration =
       RunRegisterJob(GURL("http://www.example.com/"),
@@ -244,7 +241,7 @@
   ASSERT_EQ(registration1, registration2);
 }
 
-TEST_P(ServiceWorkerJobTestP, DifferentMatchDifferentRegistration) {
+TEST_F(ServiceWorkerJobTest, DifferentMatchDifferentRegistration) {
   bool called1;
   scoped_refptr<ServiceWorkerRegistration> original_registration1;
   job_coordinator()->Register(
@@ -283,7 +280,7 @@
 }
 
 // Make sure basic registration is working.
-TEST_P(ServiceWorkerJobTestP, Register) {
+TEST_F(ServiceWorkerJobTest, Register) {
   scoped_refptr<ServiceWorkerRegistration> registration =
       RunRegisterJob(GURL("http://www.example.com/"),
                      GURL("http://www.example.com/service_worker.js"));
@@ -294,7 +291,7 @@
 }
 
 // Make sure registrations are cleaned up when they are unregistered.
-TEST_P(ServiceWorkerJobTestP, Unregister) {
+TEST_F(ServiceWorkerJobTest, Unregister) {
   GURL pattern("http://www.example.com/");
 
   scoped_refptr<ServiceWorkerRegistration> registration =
@@ -310,7 +307,7 @@
   ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(NULL), registration);
 }
 
-TEST_P(ServiceWorkerJobTestP, Unregister_NothingRegistered) {
+TEST_F(ServiceWorkerJobTest, Unregister_NothingRegistered) {
   GURL pattern("http://www.example.com/");
 
   RunUnregisterJob(pattern, SERVICE_WORKER_ERROR_NOT_FOUND);
@@ -318,7 +315,7 @@
 
 // Make sure registering a new script creates a new version and shares an
 // existing registration.
-TEST_P(ServiceWorkerJobTestP, RegisterNewScript) {
+TEST_F(ServiceWorkerJobTest, RegisterNewScript) {
   GURL pattern("http://www.example.com/");
 
   scoped_refptr<ServiceWorkerRegistration> old_registration =
@@ -344,7 +341,7 @@
 
 // Make sure that when registering a duplicate pattern+script_url
 // combination, that the same registration is used.
-TEST_P(ServiceWorkerJobTestP, RegisterDuplicateScript) {
+TEST_F(ServiceWorkerJobTest, RegisterDuplicateScript) {
   GURL pattern("http://www.example.com/");
   GURL script_url("http://www.example.com/service_worker.js");
 
@@ -383,7 +380,7 @@
   }
 };
 
-TEST_P(ServiceWorkerJobTestP, Register_FailToStartWorker) {
+TEST_F(ServiceWorkerJobTest, Register_FailToStartWorker) {
   helper_.reset(new FailToStartWorkerTestHelper);
 
   scoped_refptr<ServiceWorkerRegistration> registration =
@@ -396,7 +393,7 @@
 
 // Register and then unregister the pattern, in parallel. Job coordinator should
 // process jobs until the last job.
-TEST_P(ServiceWorkerJobTestP, ParallelRegUnreg) {
+TEST_F(ServiceWorkerJobTest, ParallelRegUnreg) {
   GURL pattern("http://www.example.com/");
   GURL script_url("http://www.example.com/service_worker.js");
 
@@ -428,7 +425,7 @@
 // Register conflicting scripts for the same pattern. The most recent
 // registration should win, and the old registration should have been
 // shutdown.
-TEST_P(ServiceWorkerJobTestP, ParallelRegNewScript) {
+TEST_F(ServiceWorkerJobTest, ParallelRegNewScript) {
   GURL pattern("http://www.example.com/");
 
   GURL script_url1("http://www.example.com/service_worker1.js");
@@ -466,7 +463,7 @@
 // Register the exact same pattern + script. Requests should be
 // coalesced such that both callers get the exact same registration
 // object.
-TEST_P(ServiceWorkerJobTestP, ParallelRegSameScript) {
+TEST_F(ServiceWorkerJobTest, ParallelRegSameScript) {
   GURL pattern("http://www.example.com/");
 
   GURL script_url("http://www.example.com/service_worker1.js");
@@ -503,7 +500,7 @@
 }
 
 // Call simulataneous unregister calls.
-TEST_P(ServiceWorkerJobTestP, ParallelUnreg) {
+TEST_F(ServiceWorkerJobTest, ParallelUnreg) {
   GURL pattern("http://www.example.com/");
 
   GURL script_url("http://www.example.com/service_worker.js");
@@ -534,7 +531,7 @@
   ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration);
 }
 
-TEST_P(ServiceWorkerJobTestP, AbortAll_Register) {
+TEST_F(ServiceWorkerJobTest, AbortAll_Register) {
   GURL pattern1("http://www1.example.com/");
   GURL pattern2("http://www2.example.com/");
   GURL script_url1("http://www1.example.com/service_worker.js");
@@ -585,7 +582,7 @@
   EXPECT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration2);
 }
 
-TEST_P(ServiceWorkerJobTestP, AbortAll_Unregister) {
+TEST_F(ServiceWorkerJobTest, AbortAll_Unregister) {
   GURL pattern1("http://www1.example.com/");
   GURL pattern2("http://www2.example.com/");
 
@@ -611,7 +608,7 @@
   ASSERT_TRUE(unregistration_called2);
 }
 
-TEST_P(ServiceWorkerJobTestP, AbortAll_RegUnreg) {
+TEST_F(ServiceWorkerJobTest, AbortAll_RegUnreg) {
   GURL pattern("http://www.example.com/");
   GURL script_url("http://www.example.com/service_worker.js");
 
@@ -646,7 +643,7 @@
 
 // Tests that the waiting worker enters the 'redundant' state upon
 // unregistration.
-TEST_P(ServiceWorkerJobTestP, UnregisterWaitingSetsRedundant) {
+TEST_F(ServiceWorkerJobTest, UnregisterWaitingSetsRedundant) {
   GURL script_url("http://www.example.com/service_worker.js");
   scoped_refptr<ServiceWorkerRegistration> registration =
       RunRegisterJob(GURL("http://www.example.com/"), script_url);
@@ -679,7 +676,7 @@
 
 // Tests that the active worker enters the 'redundant' state upon
 // unregistration.
-TEST_P(ServiceWorkerJobTestP, UnregisterActiveSetsRedundant) {
+TEST_F(ServiceWorkerJobTest, UnregisterActiveSetsRedundant) {
   scoped_refptr<ServiceWorkerRegistration> registration =
       RunRegisterJob(GURL("http://www.example.com/"),
                      GURL("http://www.example.com/service_worker.js"));
@@ -699,7 +696,7 @@
 
 // Tests that the active worker enters the 'redundant' state upon
 // unregistration.
-TEST_P(ServiceWorkerJobTestP,
+TEST_F(ServiceWorkerJobTest,
        UnregisterActiveSetsRedundant_WaitForNoControllee) {
   scoped_refptr<ServiceWorkerRegistration> registration =
       RunRegisterJob(GURL("http://www.example.com/"),
@@ -971,7 +968,7 @@
 
 }  // namespace
 
-TEST_P(ServiceWorkerJobTestP, Update_NoChange) {
+TEST_F(ServiceWorkerJobTest, Update_NoChange) {
   UpdateJobTestHelper* update_helper = new UpdateJobTestHelper;
   helper_.reset(update_helper);
   scoped_refptr<ServiceWorkerRegistration> registration =
@@ -1009,7 +1006,7 @@
   EXPECT_FALSE(update_helper->update_found_);
 }
 
-TEST_P(ServiceWorkerJobTestP, Update_BumpLastUpdateCheckTime) {
+TEST_F(ServiceWorkerJobTest, Update_BumpLastUpdateCheckTime) {
   const base::Time kToday = base::Time::Now();
   const base::Time kYesterday =
       kToday - base::TimeDelta::FromDays(1) - base::TimeDelta::FromHours(1);
@@ -1058,7 +1055,7 @@
   EXPECT_LT(kYesterday, registration->last_update_check());
 }
 
-TEST_P(ServiceWorkerJobTestP, Update_NewVersion) {
+TEST_F(ServiceWorkerJobTest, Update_NewVersion) {
   UpdateJobTestHelper* update_helper = new UpdateJobTestHelper;
   helper_.reset(update_helper);
   scoped_refptr<ServiceWorkerRegistration> registration =
@@ -1150,7 +1147,7 @@
 
 // Test that the update job uses the script URL of the newest worker when the
 // job starts, rather than when it is scheduled.
-TEST_P(ServiceWorkerJobTestP, Update_ScriptUrlChanged) {
+TEST_F(ServiceWorkerJobTest, Update_ScriptUrlChanged) {
   // Create a registration with an active version.
   scoped_refptr<ServiceWorkerRegistration> registration =
       RunRegisterJob(GURL("http://www.example.com/one/"),
@@ -1178,7 +1175,7 @@
 
 // Test that update succeeds if the incumbent worker was evicted
 // during the update job (this can happen on disk cache failure).
-TEST_P(ServiceWorkerJobTestP, Update_EvictedIncumbent) {
+TEST_F(ServiceWorkerJobTest, Update_EvictedIncumbent) {
   EvictIncumbentVersionHelper* update_helper = new EvictIncumbentVersionHelper;
   helper_.reset(update_helper);
   scoped_refptr<ServiceWorkerRegistration> registration =
@@ -1207,7 +1204,7 @@
   EXPECT_FALSE(registration->is_uninstalled());
 }
 
-TEST_P(ServiceWorkerJobTestP, Update_UninstallingRegistration) {
+TEST_F(ServiceWorkerJobTest, Update_UninstallingRegistration) {
   bool called;
   scoped_refptr<ServiceWorkerRegistration> registration =
       RunRegisterJob(GURL("http://www.example.com/one/"),
@@ -1234,7 +1231,7 @@
   EXPECT_EQ(NULL, registration->installing_version());
 }
 
-TEST_P(ServiceWorkerJobTestP, RegisterWhileUninstalling) {
+TEST_F(ServiceWorkerJobTest, RegisterWhileUninstalling) {
   GURL pattern("http://www.example.com/one/");
   GURL script1("http://www.example.com/service_worker.js");
   GURL script2("http://www.example.com/service_worker.js?new");
@@ -1285,7 +1282,7 @@
   EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, new_version->status());
 }
 
-TEST_P(ServiceWorkerJobTestP, RegisterAndUnregisterWhileUninstalling) {
+TEST_F(ServiceWorkerJobTest, RegisterAndUnregisterWhileUninstalling) {
   GURL pattern("http://www.example.com/one/");
   GURL script1("http://www.example.com/service_worker.js");
   GURL script2("http://www.example.com/service_worker.js?new");
@@ -1333,8 +1330,7 @@
   EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, new_version->status());
 }
 
-TEST_P(ServiceWorkerJobTestP,
-       RegisterSameScriptMultipleTimesWhileUninstalling) {
+TEST_F(ServiceWorkerJobTest, RegisterSameScriptMultipleTimesWhileUninstalling) {
   GURL pattern("http://www.example.com/one/");
   GURL script1("http://www.example.com/service_worker.js");
   GURL script2("http://www.example.com/service_worker.js?new");
@@ -1385,7 +1381,7 @@
   EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, new_version->status());
 }
 
-TEST_P(ServiceWorkerJobTestP, RegisterMultipleTimesWhileUninstalling) {
+TEST_F(ServiceWorkerJobTest, RegisterMultipleTimesWhileUninstalling) {
   GURL pattern("http://www.example.com/one/");
   GURL script1("http://www.example.com/service_worker.js?first");
   GURL script2("http://www.example.com/service_worker.js?second");
@@ -1482,7 +1478,7 @@
   bool has_fetch_handler_ = true;
 };
 
-TEST_P(ServiceWorkerJobTestP, RemoveControlleeDuringInstall) {
+TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringInstall) {
   EventCallbackHelper* helper = new EventCallbackHelper;
   helper_.reset(helper);
 
@@ -1522,7 +1518,7 @@
   EXPECT_EQ(registration, FindRegistrationForPattern(pattern));
 }
 
-TEST_P(ServiceWorkerJobTestP, RemoveControlleeDuringRejectedInstall) {
+TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringRejectedInstall) {
   EventCallbackHelper* helper = new EventCallbackHelper;
   helper_.reset(helper);
 
@@ -1558,7 +1554,7 @@
   FindRegistrationForPattern(pattern, SERVICE_WORKER_ERROR_NOT_FOUND);
 }
 
-TEST_P(ServiceWorkerJobTestP, RemoveControlleeDuringInstall_RejectActivate) {
+TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringInstall_RejectActivate) {
   EventCallbackHelper* helper = new EventCallbackHelper;
   helper_.reset(helper);
 
@@ -1594,7 +1590,7 @@
   FindRegistrationForPattern(pattern, SERVICE_WORKER_OK);
 }
 
-TEST_P(ServiceWorkerJobTestP, HasFetchHandler) {
+TEST_F(ServiceWorkerJobTest, HasFetchHandler) {
   EventCallbackHelper* helper = new EventCallbackHelper;
   helper_.reset(helper);
 
@@ -1645,62 +1641,35 @@
   DISALLOW_COPY_AND_ASSIGN(CheckPauseAfterDownloadEmbeddedWorkerInstanceClient);
 };
 
-TEST_P(ServiceWorkerJobTestP, Update_PauseAfterDownload) {
+TEST_F(ServiceWorkerJobTest, Update_PauseAfterDownload) {
   UpdateJobTestHelper* update_helper = new UpdateJobTestHelper;
   helper_.reset(update_helper);
-  IPC::TestSink* sink = update_helper->ipc_sink();
 
   std::vector<CheckPauseAfterDownloadEmbeddedWorkerInstanceClient*> clients;
-  if (is_mojo_enabled()) {
-    clients.push_back(helper_->CreateAndRegisterMockInstanceClient<
-                      CheckPauseAfterDownloadEmbeddedWorkerInstanceClient>(
-        helper_->AsWeakPtr()));
-    clients.push_back(helper_->CreateAndRegisterMockInstanceClient<
-                      CheckPauseAfterDownloadEmbeddedWorkerInstanceClient>(
-        helper_->AsWeakPtr()));
-  }
+  clients.push_back(helper_->CreateAndRegisterMockInstanceClient<
+                    CheckPauseAfterDownloadEmbeddedWorkerInstanceClient>(
+      helper_->AsWeakPtr()));
+  clients.push_back(helper_->CreateAndRegisterMockInstanceClient<
+                    CheckPauseAfterDownloadEmbeddedWorkerInstanceClient>(
+      helper_->AsWeakPtr()));
 
   // The initial version should not pause after download.
-  if (is_mojo_enabled())
-    clients[0]->set_next_pause_after_download(false);
+  clients[0]->set_next_pause_after_download(false);
   scoped_refptr<ServiceWorkerRegistration> registration =
       update_helper->SetupInitialRegistration(kNewVersionOrigin);
-  if (is_mojo_enabled()) {
-    ASSERT_EQ(1, clients[0]->num_of_startworker());
-  } else {
-    const IPC::Message* start_msg =
-        sink->GetUniqueMessageMatching(EmbeddedWorkerMsg_StartWorker::ID);
-    ASSERT_TRUE(start_msg);
-    EmbeddedWorkerMsg_StartWorker::Param param;
-    EmbeddedWorkerMsg_StartWorker::Read(start_msg, &param);
-    const EmbeddedWorkerStartParams& start_params = std::get<0>(param);
-    EXPECT_FALSE(start_params.pause_after_download);
-    sink->ClearMessages();
-  }
+  ASSERT_EQ(1, clients[0]->num_of_startworker());
 
   // The updated version should pause after download.
-  if (is_mojo_enabled())
-    clients[1]->set_next_pause_after_download(true);
+  clients[1]->set_next_pause_after_download(true);
   registration->AddListener(update_helper);
   registration->active_version()->StartUpdate();
   base::RunLoop().RunUntilIdle();
-  if (is_mojo_enabled()) {
-    ASSERT_EQ(1, clients[1]->num_of_startworker());
-  } else {
-    const IPC::Message* start_msg =
-        sink->GetUniqueMessageMatching(EmbeddedWorkerMsg_StartWorker::ID);
-    ASSERT_TRUE(start_msg);
-    EmbeddedWorkerMsg_StartWorker::Param param;
-    EmbeddedWorkerMsg_StartWorker::Read(start_msg, &param);
-    const EmbeddedWorkerStartParams& start_params = std::get<0>(param);
-    EXPECT_TRUE(start_params.pause_after_download);
-    sink->ClearMessages();
-  }
+  ASSERT_EQ(1, clients[1]->num_of_startworker());
 }
 
 // Test that activation doesn't complete if it's triggered by removing a
 // controllee and starting the worker failed due to shutdown.
-TEST_P(ServiceWorkerJobTestP, ActivateCancelsOnShutdown) {
+TEST_F(ServiceWorkerJobTest, ActivateCancelsOnShutdown) {
   UpdateJobTestHelper* update_helper = new UpdateJobTestHelper;
   helper_.reset(update_helper);
   GURL pattern("http://www.example.com/");
@@ -1755,8 +1724,4 @@
   registration->RemoveListener(update_helper);
 }
 
-INSTANTIATE_TEST_CASE_P(ServiceWorkerJobTest,
-                        ServiceWorkerJobTestP,
-                        ::testing::Values(false, true));
-
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_process_manager.h b/content/browser/service_worker/service_worker_process_manager.h
index a45fb87..da8443f 100644
--- a/content/browser/service_worker/service_worker_process_manager.h
+++ b/content/browser/service_worker/service_worker_process_manager.h
@@ -86,12 +86,12 @@
   bool PatternHasProcessToRun(const GURL& pattern) const;
 
  private:
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProcessManagerTestP, SortProcess);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProcessManagerTestP,
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProcessManagerTest, SortProcess);
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProcessManagerTest,
                            FindAvailableProcess);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProcessManagerTestP,
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProcessManagerTest,
                            AllocateWorkerProcess_FindAvailableProcess);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProcessManagerTestP,
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProcessManagerTest,
                            AllocateWorkerProcess_InShutdown);
 
   // Information about the process for an EmbeddedWorkerInstance.
diff --git a/content/browser/service_worker/service_worker_process_manager_unittest.cc b/content/browser/service_worker/service_worker_process_manager_unittest.cc
index efc77ff..ee6ea10 100644
--- a/content/browser/service_worker/service_worker_process_manager_unittest.cc
+++ b/content/browser/service_worker/service_worker_process_manager_unittest.cc
@@ -70,10 +70,7 @@
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerProcessManagerTest);
 };
 
-class ServiceWorkerProcessManagerTestP
-    : public MojoServiceWorkerTestP<ServiceWorkerProcessManagerTest> {};
-
-TEST_P(ServiceWorkerProcessManagerTestP, SortProcess) {
+TEST_F(ServiceWorkerProcessManagerTest, SortProcess) {
   // Process 1 has 2 refs, 2 has 3 refs and 3 has 1 ref.
   process_manager_->AddProcessReferenceToPattern(pattern_, 1);
   process_manager_->AddProcessReferenceToPattern(pattern_, 1);
@@ -93,7 +90,7 @@
               testing::ElementsAre(2, 3));
 }
 
-TEST_P(ServiceWorkerProcessManagerTestP, FindAvailableProcess) {
+TEST_F(ServiceWorkerProcessManagerTest, FindAvailableProcess) {
   std::unique_ptr<MockRenderProcessHost> host1(CreateRenderProcessHost());
   std::unique_ptr<MockRenderProcessHost> host2(CreateRenderProcessHost());
   std::unique_ptr<MockRenderProcessHost> host3(CreateRenderProcessHost());
@@ -125,7 +122,7 @@
   EXPECT_EQ(host3->GetID(), process_manager_->FindAvailableProcess(pattern_));
 }
 
-TEST_P(ServiceWorkerProcessManagerTestP,
+TEST_F(ServiceWorkerProcessManagerTest,
        AllocateWorkerProcess_FindAvailableProcess) {
   const int kEmbeddedWorkerId1 = 100;
   const int kEmbeddedWorkerId2 = 200;
@@ -236,7 +233,7 @@
   EXPECT_TRUE(instance_info.empty());
 }
 
-TEST_P(ServiceWorkerProcessManagerTestP, AllocateWorkerProcess_InShutdown) {
+TEST_F(ServiceWorkerProcessManagerTest, AllocateWorkerProcess_InShutdown) {
   process_manager_->Shutdown();
   ASSERT_TRUE(process_manager_->IsShutdown());
 
@@ -257,8 +254,4 @@
   EXPECT_TRUE(process_manager_->instance_info_.empty());
 }
 
-INSTANTIATE_TEST_CASE_P(ServiceWorkerProcessManagerTest,
-                        ServiceWorkerProcessManagerTestP,
-                        testing::Bool());
-
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_provider_host.h b/content/browser/service_worker/service_worker_provider_host.h
index 4879e4f..33df5b2 100644
--- a/content/browser/service_worker/service_worker_provider_host.h
+++ b/content/browser/service_worker/service_worker_provider_host.h
@@ -297,7 +297,7 @@
  private:
   friend class ForeignFetchRequestHandlerTest;
   friend class LinkHeaderServiceWorkerTest;
-  friend class ServiceWorkerProviderHostTestP;
+  friend class ServiceWorkerProviderHostTest;
   friend class ServiceWorkerWriteToCacheJobTest;
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerWriteToCacheJobTest, Update_SameScript);
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerWriteToCacheJobTest,
@@ -308,21 +308,21 @@
                            Update_ElongatedScript);
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerWriteToCacheJobTest,
                            Update_EmptyScript);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDispatcherHostTestP,
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDispatcherHostTest,
                            DispatchExtendableMessageEvent);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDispatcherHostTestP,
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDispatcherHostTest,
                            DispatchExtendableMessageEvent_Fail);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTestP,
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
                            UpdateBefore24Hours);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTestP,
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
                            UpdateAfter24Hours);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTestP,
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
                            UpdateForceBypassCache);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTestP,
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
                            ServiceWorkerDataRequestAnnotation);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTestP,
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
                            SkipServiceWorkerForServiceWorkerRequest);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProviderHostTestP, ContextSecurity);
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProviderHostTest, ContextSecurity);
 
   struct OneShotGetReadyCallback {
     GetRegistrationForReadyCallback callback;
diff --git a/content/browser/service_worker/service_worker_provider_host_unittest.cc b/content/browser/service_worker/service_worker_provider_host_unittest.cc
index 184d661..799c36d 100644
--- a/content/browser/service_worker/service_worker_provider_host_unittest.cc
+++ b/content/browser/service_worker/service_worker_provider_host_unittest.cc
@@ -102,10 +102,7 @@
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerProviderHostTest);
 };
 
-class ServiceWorkerProviderHostTestP
-    : public MojoServiceWorkerTestP<ServiceWorkerProviderHostTest> {};
-
-TEST_P(ServiceWorkerProviderHostTestP, PotentialRegistration_ProcessStatus) {
+TEST_F(ServiceWorkerProviderHostTest, PotentialRegistration_ProcessStatus) {
   // Matching registrations have already been set by SetDocumentUrl.
   ASSERT_TRUE(PatternHasProcessToRun(registration1_->pattern()));
 
@@ -134,7 +131,7 @@
   ASSERT_TRUE(PatternHasProcessToRun(registration3_->pattern()));   // host1,2
 }
 
-TEST_P(ServiceWorkerProviderHostTestP, AssociatedRegistration_ProcessStatus) {
+TEST_F(ServiceWorkerProviderHostTest, AssociatedRegistration_ProcessStatus) {
   // Associating the registration will also increase the process refs for
   // the registration's pattern.
   provider_host1_->AssociateRegistration(registration1_.get(),
@@ -147,7 +144,7 @@
   ASSERT_TRUE(PatternHasProcessToRun(registration1_->pattern()));
 }
 
-TEST_P(ServiceWorkerProviderHostTestP, MatchRegistration) {
+TEST_F(ServiceWorkerProviderHostTest, MatchRegistration) {
   // Match registration should return the longest matching one.
   ASSERT_EQ(registration2_, provider_host1_->MatchRegistration());
   provider_host1_->RemoveMatchingRegistration(registration2_.get());
@@ -170,7 +167,7 @@
   ASSERT_EQ(nullptr, provider_host1_->MatchRegistration());
 }
 
-TEST_P(ServiceWorkerProviderHostTestP, ContextSecurity) {
+TEST_F(ServiceWorkerProviderHostTest, ContextSecurity) {
   using FrameSecurityLevel = ServiceWorkerProviderHost::FrameSecurityLevel;
   content::ResetSchemesAndOriginsWhitelistForTesting();
 
@@ -203,8 +200,4 @@
   EXPECT_FALSE(provider_host1_->IsContextSecureForServiceWorker());
 }
 
-INSTANTIATE_TEST_CASE_P(ServiceWorkerProviderHostTest,
-                        ServiceWorkerProviderHostTestP,
-                        ::testing::Values(false, true));
-
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc b/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc
index 852c7a2..b0fb55e 100644
--- a/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc
+++ b/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc
@@ -189,10 +189,7 @@
   MockURLRequestDelegate delegate_;
 };
 
-class ServiceWorkerReadFromCacheJobTestP
-    : public MojoServiceWorkerTestP<ServiceWorkerReadFromCacheJobTest> {};
-
-TEST_P(ServiceWorkerReadFromCacheJobTestP, ReadMainScript) {
+TEST_F(ServiceWorkerReadFromCacheJobTest, ReadMainScript) {
   // Read the main script from the diskcache.
   std::unique_ptr<net::URLRequest> request =
       url_request_context_->CreateRequest(main_script_.url,
@@ -210,7 +207,7 @@
             DeduceStartWorkerFailureReason(SERVICE_WORKER_OK));
 }
 
-TEST_P(ServiceWorkerReadFromCacheJobTestP, ReadImportedScript) {
+TEST_F(ServiceWorkerReadFromCacheJobTest, ReadImportedScript) {
   // Read the imported script from the diskcache.
   std::unique_ptr<net::URLRequest> request =
       url_request_context_->CreateRequest(imported_script_.url,
@@ -227,7 +224,7 @@
             DeduceStartWorkerFailureReason(SERVICE_WORKER_OK));
 }
 
-TEST_P(ServiceWorkerReadFromCacheJobTestP, ResourceNotFound) {
+TEST_F(ServiceWorkerReadFromCacheJobTest, ResourceNotFound) {
   ASSERT_EQ(SERVICE_WORKER_OK, FindRegistration());
 
   // Try to read a nonexistent resource from the diskcache.
@@ -253,8 +250,4 @@
   EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND, FindRegistration());
 }
 
-INSTANTIATE_TEST_CASE_P(ServiceWorkerReadFromCacheJobTest,
-                        ServiceWorkerReadFromCacheJobTestP,
-                        testing::Bool());
-
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_registration_unittest.cc b/content/browser/service_worker/service_worker_registration_unittest.cc
index 593519b..9e87cab 100644
--- a/content/browser/service_worker/service_worker_registration_unittest.cc
+++ b/content/browser/service_worker/service_worker_registration_unittest.cc
@@ -99,10 +99,7 @@
   TestBrowserThreadBundle thread_bundle_;
 };
 
-class ServiceWorkerRegistrationTestP
-    : public MojoServiceWorkerTestP<ServiceWorkerRegistrationTest> {};
-
-TEST_P(ServiceWorkerRegistrationTestP, SetAndUnsetVersions) {
+TEST_F(ServiceWorkerRegistrationTest, SetAndUnsetVersions) {
   const GURL kScope("http://www.example.not/");
   const GURL kScript("http://www.example.not/service_worker.js");
   int64_t kRegistrationId = 1L;
@@ -170,7 +167,7 @@
             kInvalidServiceWorkerVersionId);
 }
 
-TEST_P(ServiceWorkerRegistrationTestP, FailedRegistrationNoCrash) {
+TEST_F(ServiceWorkerRegistrationTest, FailedRegistrationNoCrash) {
   const GURL kScope("http://www.example.not/");
   int64_t kRegistrationId = 1L;
   scoped_refptr<ServiceWorkerRegistration> registration =
@@ -184,7 +181,7 @@
   // Don't crash when handle gets destructed.
 }
 
-TEST_P(ServiceWorkerRegistrationTestP, NavigationPreload) {
+TEST_F(ServiceWorkerRegistrationTest, NavigationPreload) {
   const GURL kScope("http://www.example.not/");
   const GURL kScript("https://www.example.not/service_worker.js");
   // Setup.
@@ -222,9 +219,9 @@
 
 // Sets up a registration with a waiting worker, and an active worker
 // with a controllee and an inflight request.
-class ServiceWorkerActivationTest : public ServiceWorkerRegistrationTestP {
+class ServiceWorkerActivationTest : public ServiceWorkerRegistrationTest {
  public:
-  ServiceWorkerActivationTest() : ServiceWorkerRegistrationTestP() {}
+  ServiceWorkerActivationTest() : ServiceWorkerRegistrationTest() {}
 
   void SetUp() override {
     ServiceWorkerRegistrationTest::SetUp();
@@ -302,7 +299,7 @@
 };
 
 // Test activation triggered by finishing all requests.
-TEST_P(ServiceWorkerActivationTest, NoInflightRequest) {
+TEST_F(ServiceWorkerActivationTest, NoInflightRequest) {
   scoped_refptr<ServiceWorkerRegistration> reg = registration();
   scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version();
   scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version();
@@ -321,7 +318,7 @@
 }
 
 // Test activation triggered by loss of controllee.
-TEST_P(ServiceWorkerActivationTest, NoControllee) {
+TEST_F(ServiceWorkerActivationTest, NoControllee) {
   scoped_refptr<ServiceWorkerRegistration> reg = registration();
   scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version();
   scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version();
@@ -340,7 +337,7 @@
 }
 
 // Test activation triggered by skipWaiting.
-TEST_P(ServiceWorkerActivationTest, SkipWaiting) {
+TEST_F(ServiceWorkerActivationTest, SkipWaiting) {
   scoped_refptr<ServiceWorkerRegistration> reg = registration();
   scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version();
   scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version();
@@ -359,7 +356,7 @@
 }
 
 // Test activation triggered by skipWaiting and finishing requests.
-TEST_P(ServiceWorkerActivationTest, SkipWaitingWithInflightRequest) {
+TEST_F(ServiceWorkerActivationTest, SkipWaitingWithInflightRequest) {
   scoped_refptr<ServiceWorkerRegistration> reg = registration();
   scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version();
   scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version();
@@ -377,12 +374,4 @@
   EXPECT_EQ(version_2.get(), reg->active_version());
 }
 
-INSTANTIATE_TEST_CASE_P(ServiceWorkerRegistrationTest,
-                        ServiceWorkerRegistrationTestP,
-                        testing::Bool());
-
-INSTANTIATE_TEST_CASE_P(ServiceWorkerActivationTest,
-                        ServiceWorkerActivationTest,
-                        testing::Bool());
-
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_request_handler_unittest.cc b/content/browser/service_worker/service_worker_request_handler_unittest.cc
index 1c243f1b..cdac7ba 100644
--- a/content/browser/service_worker/service_worker_request_handler_unittest.cc
+++ b/content/browser/service_worker/service_worker_request_handler_unittest.cc
@@ -114,10 +114,7 @@
   storage::BlobStorageContext blob_storage_context_;
 };
 
-class ServiceWorkerRequestHandlerTestP
-    : public MojoServiceWorkerTestP<ServiceWorkerRequestHandlerTest> {};
-
-TEST_P(ServiceWorkerRequestHandlerTestP, InitializeHandler_FTP) {
+TEST_F(ServiceWorkerRequestHandlerTest, InitializeHandler_FTP) {
   std::unique_ptr<net::URLRequest> request =
       CreateRequest("ftp://host/scope/doc", "GET");
   InitializeHandler(request.get(), false, RESOURCE_TYPE_MAIN_FRAME);
@@ -125,42 +122,42 @@
   EXPECT_FALSE(GetHandler(request.get()));
 }
 
-TEST_P(ServiceWorkerRequestHandlerTestP, InitializeHandler_HTTP_MAIN_FRAME) {
+TEST_F(ServiceWorkerRequestHandlerTest, InitializeHandler_HTTP_MAIN_FRAME) {
   // HTTP should have the handler because the response is possible to be a
   // redirect to HTTPS.
   InitializeHandlerSimpleTest("http://host/scope/doc", "GET", false,
                               RESOURCE_TYPE_MAIN_FRAME);
 }
 
-TEST_P(ServiceWorkerRequestHandlerTestP, InitializeHandler_HTTPS_MAIN_FRAME) {
+TEST_F(ServiceWorkerRequestHandlerTest, InitializeHandler_HTTPS_MAIN_FRAME) {
   InitializeHandlerSimpleTest("https://host/scope/doc", "GET", false,
                               RESOURCE_TYPE_MAIN_FRAME);
 }
 
-TEST_P(ServiceWorkerRequestHandlerTestP, InitializeHandler_HTTP_SUB_FRAME) {
+TEST_F(ServiceWorkerRequestHandlerTest, InitializeHandler_HTTP_SUB_FRAME) {
   // HTTP should have the handler because the response is possible to be a
   // redirect to HTTPS.
   InitializeHandlerSimpleTest("http://host/scope/doc", "GET", false,
                               RESOURCE_TYPE_SUB_FRAME);
 }
 
-TEST_P(ServiceWorkerRequestHandlerTestP, InitializeHandler_HTTPS_SUB_FRAME) {
+TEST_F(ServiceWorkerRequestHandlerTest, InitializeHandler_HTTPS_SUB_FRAME) {
   InitializeHandlerSimpleTest("https://host/scope/doc", "GET", false,
                               RESOURCE_TYPE_SUB_FRAME);
 }
 
-TEST_P(ServiceWorkerRequestHandlerTestP, InitializeHandler_HTTPS_OPTIONS) {
+TEST_F(ServiceWorkerRequestHandlerTest, InitializeHandler_HTTPS_OPTIONS) {
   // OPTIONS is also supported. See crbug.com/434660.
   InitializeHandlerSimpleTest("https://host/scope/doc", "OPTIONS", false,
                               RESOURCE_TYPE_MAIN_FRAME);
 }
 
-TEST_P(ServiceWorkerRequestHandlerTestP, InitializeHandler_HTTPS_SKIP) {
+TEST_F(ServiceWorkerRequestHandlerTest, InitializeHandler_HTTPS_SKIP) {
   InitializeHandlerSimpleTest("https://host/scope/doc", "GET", true,
                               RESOURCE_TYPE_MAIN_FRAME);
 }
 
-TEST_P(ServiceWorkerRequestHandlerTestP, InitializeHandler_IMAGE) {
+TEST_F(ServiceWorkerRequestHandlerTest, InitializeHandler_IMAGE) {
   // Check provider host's URL after initializing a handler for an image.
   provider_host_->SetDocumentUrl(GURL("https://host/scope/doc"));
   std::unique_ptr<net::URLRequest> request =
@@ -170,8 +167,4 @@
   EXPECT_EQ(GURL("https://host/scope/doc"), provider_host_->document_url());
 }
 
-INSTANTIATE_TEST_CASE_P(ServiceWorkerRequestHandlerTest,
-                        ServiceWorkerRequestHandlerTestP,
-                        testing::Bool());
-
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_storage_unittest.cc b/content/browser/service_worker/service_worker_storage_unittest.cc
index fb743e9..9598586 100644
--- a/content/browser/service_worker/service_worker_storage_unittest.cc
+++ b/content/browser/service_worker/service_worker_storage_unittest.cc
@@ -545,10 +545,7 @@
   TestBrowserThreadBundle browser_thread_bundle_;
 };
 
-class ServiceWorkerStorageTestP
-    : public MojoServiceWorkerTestP<ServiceWorkerStorageTest> {};
-
-TEST_P(ServiceWorkerStorageTestP, DisabledStorage) {
+TEST_F(ServiceWorkerStorageTest, DisabledStorage) {
   const GURL kScope("http://www.example.com/scope/");
   const GURL kScript("http://www.example.com/script.js");
   const GURL kDocumentUrl("http://www.example.com/scope/document.html");
@@ -626,7 +623,7 @@
   EXPECT_EQ(kInvalidServiceWorkerResourceId, storage()->NewRegistrationId());
 }
 
-TEST_P(ServiceWorkerStorageTestP, StoreFindUpdateDeleteRegistration) {
+TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
   const GURL kScope("http://www.test.not/scope/");
   const GURL kDocumentUrl("http://www.test.not/scope/document.html");
   const GURL kResource1("http://www.test.not/scope/resource1.js");
@@ -828,7 +825,7 @@
             DeleteRegistration(kRegistrationId + 1, kScope.GetOrigin()));
 }
 
-TEST_P(ServiceWorkerStorageTestP, InstallingRegistrationsAreFindable) {
+TEST_F(ServiceWorkerStorageTest, InstallingRegistrationsAreFindable) {
   const GURL kScope("http://www.test.not/scope/");
   const GURL kScript("http://www.test.not/script.js");
   const GURL kDocumentUrl("http://www.test.not/scope/document.html");
@@ -957,7 +954,7 @@
   EXPECT_TRUE(registrations_for_origin.empty());
 }
 
-TEST_P(ServiceWorkerStorageTestP, StoreUserData) {
+TEST_F(ServiceWorkerStorageTest, StoreUserData) {
   const GURL kScope("http://www.test.not/scope/");
   const GURL kScript("http://www.test.not/script.js");
   const int64_t kRegistrationId = 0;
@@ -1098,26 +1095,26 @@
 
 // The *_BeforeInitialize tests exercise the API before LazyInitialize() is
 // called.
-TEST_P(ServiceWorkerStorageTestP, StoreUserData_BeforeInitialize) {
+TEST_F(ServiceWorkerStorageTest, StoreUserData_BeforeInitialize) {
   const int kRegistrationId = 0;
   EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
             StoreUserData(kRegistrationId, GURL("https://example.com"),
                           {{"key", "data"}}));
 }
 
-TEST_P(ServiceWorkerStorageTestP, GetUserData_BeforeInitialize) {
+TEST_F(ServiceWorkerStorageTest, GetUserData_BeforeInitialize) {
   const int kRegistrationId = 0;
   std::vector<std::string> data_out;
   EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
             GetUserData(kRegistrationId, {"key"}, &data_out));
 }
 
-TEST_P(ServiceWorkerStorageTestP, ClearUserData_BeforeInitialize) {
+TEST_F(ServiceWorkerStorageTest, ClearUserData_BeforeInitialize) {
   const int kRegistrationId = 0;
   EXPECT_EQ(SERVICE_WORKER_OK, ClearUserData(kRegistrationId, {"key"}));
 }
 
-TEST_P(ServiceWorkerStorageTestP,
+TEST_F(ServiceWorkerStorageTest,
        GetUserDataForAllRegistrations_BeforeInitialize) {
   std::vector<std::pair<int64_t, std::string>> data_list_out;
   EXPECT_EQ(SERVICE_WORKER_OK,
@@ -1125,10 +1122,10 @@
   EXPECT_TRUE(data_list_out.empty());
 }
 
-class ServiceWorkerResourceStorageTest : public ServiceWorkerStorageTestP {
+class ServiceWorkerResourceStorageTest : public ServiceWorkerStorageTest {
  public:
   void SetUp() override {
-    ServiceWorkerStorageTestP::SetUp();
+    ServiceWorkerStorageTest::SetUp();
     LazyInitialize();
 
     scope_ = GURL("http://www.test.not/scope/");
@@ -1207,7 +1204,7 @@
 
 };
 
-TEST_P(ServiceWorkerResourceStorageTest,
+TEST_F(ServiceWorkerResourceStorageTest,
        WriteMetadataWithServiceWorkerResponseMetadataWriter) {
   const char kMetadata1[] = "Test metadata";
   const char kMetadata2[] = "small";
@@ -1233,7 +1230,7 @@
   EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));
 }
 
-TEST_P(ServiceWorkerResourceStorageTest,
+TEST_F(ServiceWorkerResourceStorageTest,
        WriteMetadataWithServiceWorkerScriptCacheMap) {
   const char kMetadata1[] = "Test metadata";
   const char kMetadata2[] = "small";
@@ -1266,7 +1263,7 @@
   EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));
 }
 
-TEST_P(ServiceWorkerResourceStorageTest, DeleteRegistration_NoLiveVersion) {
+TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_NoLiveVersion) {
   bool was_called = false;
   ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
   std::set<int64_t> verify_ids;
@@ -1298,7 +1295,7 @@
   EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
 }
 
-TEST_P(ServiceWorkerResourceStorageTest, DeleteRegistration_WaitingVersion) {
+TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_WaitingVersion) {
   bool was_called = false;
   ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
   std::set<int64_t> verify_ids;
@@ -1340,7 +1337,7 @@
   EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
 }
 
-TEST_P(ServiceWorkerResourceStorageTest, DeleteRegistration_ActiveVersion) {
+TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_ActiveVersion) {
   // Promote the worker to active and add a controllee.
   registration_->SetActiveVersion(registration_->waiting_version());
   storage()->UpdateToActiveState(
@@ -1391,7 +1388,7 @@
   EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
 }
 
-TEST_P(ServiceWorkerResourceStorageDiskTest, CleanupOnRestart) {
+TEST_F(ServiceWorkerResourceStorageDiskTest, CleanupOnRestart) {
   // Promote the worker to active and add a controllee.
   registration_->SetActiveVersion(registration_->waiting_version());
   registration_->SetWaitingVersion(NULL);
@@ -1476,7 +1473,7 @@
   EXPECT_TRUE(VerifyBasicResponse(storage(), kNewResourceId, true));
 }
 
-TEST_P(ServiceWorkerResourceStorageDiskTest, DeleteAndStartOver) {
+TEST_F(ServiceWorkerResourceStorageDiskTest, DeleteAndStartOver) {
   EXPECT_FALSE(storage()->IsDisabled());
   ASSERT_TRUE(base::DirectoryExists(storage()->GetDiskCachePath()));
   ASSERT_TRUE(base::DirectoryExists(storage()->GetDatabasePath()));
@@ -1493,7 +1490,7 @@
   EXPECT_FALSE(base::DirectoryExists(storage()->GetDatabasePath()));
 }
 
-TEST_P(ServiceWorkerResourceStorageDiskTest,
+TEST_F(ServiceWorkerResourceStorageDiskTest,
        DeleteAndStartOver_UnrelatedFileExists) {
   EXPECT_FALSE(storage()->IsDisabled());
   ASSERT_TRUE(base::DirectoryExists(storage()->GetDiskCachePath()));
@@ -1518,7 +1515,7 @@
   EXPECT_FALSE(base::DirectoryExists(storage()->GetDatabasePath()));
 }
 
-TEST_P(ServiceWorkerResourceStorageDiskTest,
+TEST_F(ServiceWorkerResourceStorageDiskTest,
        DeleteAndStartOver_OpenedFileExists) {
   EXPECT_FALSE(storage()->IsDisabled());
   ASSERT_TRUE(base::DirectoryExists(storage()->GetDiskCachePath()));
@@ -1552,7 +1549,7 @@
 #endif
 }
 
-TEST_P(ServiceWorkerResourceStorageTest, UpdateRegistration) {
+TEST_F(ServiceWorkerResourceStorageTest, UpdateRegistration) {
   // Promote the worker to active worker and add a controllee.
   registration_->SetActiveVersion(registration_->waiting_version());
   storage()->UpdateToActiveState(
@@ -1617,7 +1614,7 @@
   EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
 }
 
-TEST_P(ServiceWorkerStorageTestP, FindRegistration_LongestScopeMatch) {
+TEST_F(ServiceWorkerStorageTest, FindRegistration_LongestScopeMatch) {
   const GURL kDocumentUrl("http://www.example.com/scope/foo");
   scoped_refptr<ServiceWorkerRegistration> found_registration;
 
@@ -1713,15 +1710,15 @@
 
 // Test fixture that uses disk storage, rather than memory. Useful for tests
 // that test persistence by simulating browser shutdown and restart.
-class ServiceWorkerStorageDiskTest : public ServiceWorkerStorageTestP {
+class ServiceWorkerStorageDiskTest : public ServiceWorkerStorageTest {
  public:
   void SetUp() override {
     ASSERT_TRUE(InitUserDataDirectory());
-    ServiceWorkerStorageTestP::SetUp();
+    ServiceWorkerStorageTest::SetUp();
   }
 };
 
-TEST_P(ServiceWorkerStorageDiskTest, OriginHasForeignFetchRegistrations) {
+TEST_F(ServiceWorkerStorageDiskTest, OriginHasForeignFetchRegistrations) {
   LazyInitialize();
 
   // Registration 1 for http://www.example.com
@@ -1832,7 +1829,7 @@
   EXPECT_FALSE(storage()->OriginHasForeignFetchRegistrations(kOrigin2));
 }
 
-TEST_P(ServiceWorkerStorageTestP, OriginTrialsAbsentEntryAndEmptyEntry) {
+TEST_F(ServiceWorkerStorageTest, OriginTrialsAbsentEntryAndEmptyEntry) {
   const GURL origin1("http://www1.example.com");
   const GURL scope1("http://www1.example.com/foo/");
   RegistrationData data1;
@@ -1882,7 +1879,7 @@
 }
 
 class ServiceWorkerStorageOriginTrialsDiskTest
-    : public ServiceWorkerStorageTestP {
+    : public ServiceWorkerStorageTest {
  public:
   ServiceWorkerStorageOriginTrialsDiskTest() {
     SetContentClient(&test_content_client_);
@@ -1892,7 +1889,7 @@
   }
   void SetUp() override {
     ASSERT_TRUE(InitUserDataDirectory());
-    ServiceWorkerStorageTestP::SetUp();
+    ServiceWorkerStorageTest::SetUp();
   }
 
  private:
@@ -1919,7 +1916,7 @@
   TestContentClient test_content_client_;
 };
 
-TEST_P(ServiceWorkerStorageOriginTrialsDiskTest, FromMainScript) {
+TEST_F(ServiceWorkerStorageOriginTrialsDiskTest, FromMainScript) {
   LazyInitialize();
   const GURL kScope("https://valid.example.com/scope");
   const GURL kScript("https://valid.example.com/script.js");
@@ -2015,7 +2012,7 @@
 }
 
 // Tests loading a registration that has no navigation preload state.
-TEST_P(ServiceWorkerStorageTestP, AbsentNavigationPreloadState) {
+TEST_F(ServiceWorkerStorageTest, AbsentNavigationPreloadState) {
   const GURL origin1("http://www1.example.com");
   const GURL scope1("http://www1.example.com/foo/");
   RegistrationData data1;
@@ -2047,7 +2044,7 @@
 
 // Tests loading a registration with a disabled navigation preload
 // state.
-TEST_P(ServiceWorkerStorageDiskTest, DisabledNavigationPreloadState) {
+TEST_F(ServiceWorkerStorageDiskTest, DisabledNavigationPreloadState) {
   LazyInitialize();
   const GURL kScope("https://valid.example.com/scope");
   const GURL kScript("https://valid.example.com/script.js");
@@ -2092,7 +2089,7 @@
 
 // Tests loading a registration with an enabled navigation preload state, as
 // well as a custom header value.
-TEST_P(ServiceWorkerStorageDiskTest, EnabledNavigationPreloadState) {
+TEST_F(ServiceWorkerStorageDiskTest, EnabledNavigationPreloadState) {
   LazyInitialize();
   const GURL kScope("https://valid.example.com/scope");
   const GURL kScript("https://valid.example.com/script.js");
@@ -2137,20 +2134,4 @@
   EXPECT_EQ(kHeaderValue, state.header);
 }
 
-INSTANTIATE_TEST_CASE_P(ServiceWorkerResourceStorageDiskTest,
-                        ServiceWorkerResourceStorageDiskTest,
-                        testing::Bool());
-INSTANTIATE_TEST_CASE_P(ServiceWorkerResourceStorageTest,
-                        ServiceWorkerResourceStorageTest,
-                        testing::Bool());
-INSTANTIATE_TEST_CASE_P(ServiceWorkerStorageDiskTest,
-                        ServiceWorkerStorageDiskTest,
-                        testing::Bool());
-INSTANTIATE_TEST_CASE_P(ServiceWorkerStorageOriginTrialsDiskTest,
-                        ServiceWorkerStorageOriginTrialsDiskTest,
-                        testing::Bool());
-INSTANTIATE_TEST_CASE_P(ServiceWorkerStorageTestP,
-                        ServiceWorkerStorageTestP,
-                        testing::Bool());
-
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_test_utils.h b/content/browser/service_worker/service_worker_test_utils.h
index 8aa67ed..467eaf03 100644
--- a/content/browser/service_worker/service_worker_test_utils.h
+++ b/content/browser/service_worker/service_worker_test_utils.h
@@ -14,21 +14,6 @@
 
 namespace content {
 
-template <class TestClass>
-class MojoServiceWorkerTestP : public TestClass,
-                               public testing::WithParamInterface<bool> {
- protected:
-  void SetUp() override {
-    if (!is_mojo_enabled()) {
-      base::CommandLine::ForCurrentProcess()->AppendSwitch(
-          switches::kDisableMojoServiceWorker);
-    }
-    TestClass::SetUp();
-  }
-
-  bool is_mojo_enabled() const { return GetParam(); }
-};
-
 template <typename Arg>
 void ReceiveResult(BrowserThread::ID run_quit_thread,
                    const base::Closure& quit,
diff --git a/content/browser/service_worker/service_worker_url_request_job.h b/content/browser/service_worker/service_worker_url_request_job.h
index 89703fe..d02d417 100644
--- a/content/browser/service_worker/service_worker_url_request_job.h
+++ b/content/browser/service_worker/service_worker_url_request_job.h
@@ -149,7 +149,7 @@
 
  private:
   class FileSizeResolver;
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerControlleeRequestHandlerTestP,
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerControlleeRequestHandlerTest,
                            LostActiveVersion);
 
   enum ResponseType {
diff --git a/content/browser/service_worker/service_worker_url_request_job_unittest.cc b/content/browser/service_worker/service_worker_url_request_job_unittest.cc
index 0ce78e4..fb9c2996 100644
--- a/content/browser/service_worker/service_worker_url_request_job_unittest.cc
+++ b/content/browser/service_worker/service_worker_url_request_job_unittest.cc
@@ -342,10 +342,7 @@
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerURLRequestJobTest);
 };
 
-class ServiceWorkerURLRequestJobTestP
-    : public MojoServiceWorkerTestP<ServiceWorkerURLRequestJobTest> {};
-
-TEST_P(ServiceWorkerURLRequestJobTestP, Simple) {
+TEST_F(ServiceWorkerURLRequestJobTest, Simple) {
   version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
   TestRequest(200, "OK", std::string(), true /* expect_valid_ssl */);
 
@@ -364,7 +361,7 @@
   EXPECT_EQ(std::string(), info->response_cache_storage_cache_name());
 }
 
-TEST_P(ServiceWorkerURLRequestJobTestP, CustomTimeout) {
+TEST_F(ServiceWorkerURLRequestJobTest, CustomTimeout) {
   version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
 
   // Set mock clock on version_ to check timeout behavior.
@@ -409,7 +406,7 @@
   DISALLOW_COPY_AND_ASSIGN(ProviderDeleteHelper);
 };
 
-TEST_P(ServiceWorkerURLRequestJobTestP, DeletedProviderHostOnFetchEvent) {
+TEST_F(ServiceWorkerURLRequestJobTest, DeletedProviderHostOnFetchEvent) {
   version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
   // Shouldn't crash if the ProviderHost is deleted prior to completion of
   // the fetch event.
@@ -432,7 +429,7 @@
   EXPECT_FALSE(info->service_worker_ready_time().is_null());
 }
 
-TEST_P(ServiceWorkerURLRequestJobTestP, DeletedProviderHostBeforeFetchEvent) {
+TEST_F(ServiceWorkerURLRequestJobTest, DeletedProviderHostBeforeFetchEvent) {
   version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
   request_ = url_request_context_.CreateRequest(
       GURL("https://example.com/foo.html"), net::DEFAULT_PRIORITY,
@@ -497,7 +494,7 @@
   DISALLOW_COPY_AND_ASSIGN(BlobResponder);
 };
 
-TEST_P(ServiceWorkerURLRequestJobTestP, BlobResponse) {
+TEST_F(ServiceWorkerURLRequestJobTest, BlobResponse) {
   ChromeBlobStorageContext* blob_storage_context =
       ChromeBlobStorageContext::GetFor(browser_context_.get());
   std::string expected_response;
@@ -527,7 +524,7 @@
   EXPECT_FALSE(info->service_worker_ready_time().is_null());
 }
 
-TEST_P(ServiceWorkerURLRequestJobTestP, NonExistentBlobUUIDResponse) {
+TEST_F(ServiceWorkerURLRequestJobTest, NonExistentBlobUUIDResponse) {
   SetUpWithHelper(new BlobResponder("blob-id:nothing-is-here", 0));
   version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
   TestRequest(500, "Service Worker Response Error", std::string(),
@@ -581,7 +578,7 @@
   DISALLOW_COPY_AND_ASSIGN(StreamResponder);
 };
 
-TEST_P(ServiceWorkerURLRequestJobTestP, StreamResponse) {
+TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse) {
   const GURL stream_url("blob://stream");
   StreamContext* stream_context =
       GetStreamContextForResourceContext(
@@ -630,7 +627,7 @@
   EXPECT_FALSE(HasWork());
 }
 
-TEST_P(ServiceWorkerURLRequestJobTestP, StreamResponse_DelayedRegistration) {
+TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse_DelayedRegistration) {
   const GURL stream_url("blob://stream");
   StreamContext* stream_context =
       GetStreamContextForResourceContext(
@@ -680,7 +677,7 @@
   EXPECT_FALSE(HasWork());
 }
 
-TEST_P(ServiceWorkerURLRequestJobTestP, StreamResponse_QuickFinalize) {
+TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse_QuickFinalize) {
   const GURL stream_url("blob://stream");
   StreamContext* stream_context =
       GetStreamContextForResourceContext(
@@ -728,7 +725,7 @@
   EXPECT_FALSE(HasWork());
 }
 
-TEST_P(ServiceWorkerURLRequestJobTestP, StreamResponse_Flush) {
+TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse_Flush) {
   const GURL stream_url("blob://stream");
   StreamContext* stream_context =
       GetStreamContextForResourceContext(
@@ -774,7 +771,7 @@
   EXPECT_FALSE(info->service_worker_ready_time().is_null());
 }
 
-TEST_P(ServiceWorkerURLRequestJobTestP, StreamResponseAndCancel) {
+TEST_F(ServiceWorkerURLRequestJobTest, StreamResponseAndCancel) {
   const GURL stream_url("blob://stream");
   StreamContext* stream_context =
       GetStreamContextForResourceContext(
@@ -827,7 +824,7 @@
   EXPECT_FALSE(info->service_worker_ready_time().is_null());
 }
 
-TEST_P(ServiceWorkerURLRequestJobTestP,
+TEST_F(ServiceWorkerURLRequestJobTest,
        StreamResponse_DelayedRegistrationAndCancel) {
   const GURL stream_url("blob://stream");
   StreamContext* stream_context =
@@ -882,7 +879,7 @@
   DISALLOW_COPY_AND_ASSIGN(FailFetchHelper);
 };
 
-TEST_P(ServiceWorkerURLRequestJobTestP, FailFetchDispatch) {
+TEST_F(ServiceWorkerURLRequestJobTest, FailFetchDispatch) {
   SetUpWithHelper(new FailFetchHelper);
 
   version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
@@ -911,7 +908,7 @@
   EXPECT_FALSE(info->service_worker_ready_time().is_null());
 }
 
-TEST_P(ServiceWorkerURLRequestJobTestP, FailToActivate_MainResource) {
+TEST_F(ServiceWorkerURLRequestJobTest, FailToActivate_MainResource) {
   RunFailToActivateTest(RESOURCE_TYPE_MAIN_FRAME);
 
   // The load should fail and we should have fallen back to network because
@@ -927,7 +924,7 @@
   EXPECT_EQ(host->controlling_version(), nullptr);
 }
 
-TEST_P(ServiceWorkerURLRequestJobTestP, FailToActivate_Subresource) {
+TEST_F(ServiceWorkerURLRequestJobTest, FailToActivate_Subresource) {
   RunFailToActivateTest(RESOURCE_TYPE_IMAGE);
 
   // The load should fail and we should not fall back to network because
@@ -982,7 +979,7 @@
 
 // This simulates the case when a response is returned and the fetch event is
 // still in flight.
-TEST_P(ServiceWorkerURLRequestJobTestP, EarlyResponse) {
+TEST_F(ServiceWorkerURLRequestJobTest, EarlyResponse) {
   EarlyResponseHelper* helper = new EarlyResponseHelper;
   SetUpWithHelper(helper);
 
@@ -1051,7 +1048,7 @@
 };
 
 // Test cancelling the URLRequest while the fetch event is in flight.
-TEST_P(ServiceWorkerURLRequestJobTestP, CancelRequest) {
+TEST_F(ServiceWorkerURLRequestJobTest, CancelRequest) {
   DelayedResponseHelper* helper = new DelayedResponseHelper;
   SetUpWithHelper(helper);
 
@@ -1081,8 +1078,4 @@
 // TODO(kinuko): Add more tests with different response data and also for
 // FallbackToNetwork case.
 
-INSTANTIATE_TEST_CASE_P(ServiceWorkerURLRequestJobTest,
-                        ServiceWorkerURLRequestJobTestP,
-                        testing::Bool());
-
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h
index 1c72ae8..0e26f68 100644
--- a/content/browser/service_worker/service_worker_version.h
+++ b/content/browser/service_worker/service_worker_version.h
@@ -434,23 +434,22 @@
   friend class ServiceWorkerStallInStoppingTest;
   friend class ServiceWorkerURLRequestJobTest;
   friend class ServiceWorkerVersionBrowserTest;
-  friend class ServiceWorkerVersionTestP;
+  friend class ServiceWorkerVersionTest;
 
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerControlleeRequestHandlerTestP,
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerControlleeRequestHandlerTest,
                            ActivateWaitingVersion);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerControlleeRequestHandlerTestP,
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerControlleeRequestHandlerTest,
                            FallbackWithNoFetchHandler);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTestP, IdleTimeout);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTestP, SetDevToolsAttached);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTestP, StaleUpdate_FreshWorker);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTestP,
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, IdleTimeout);
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, SetDevToolsAttached);
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, StaleUpdate_FreshWorker);
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest,
                            StaleUpdate_NonActiveWorker);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTestP, StaleUpdate_StartWorker);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTestP,
-                           StaleUpdate_RunningWorker);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTestP,
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, StaleUpdate_StartWorker);
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, StaleUpdate_RunningWorker);
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest,
                            StaleUpdate_DoNotDeferTimer);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTestP, RequestTimeout);
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, RequestTimeout);
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerFailToStartTest, Timeout);
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionBrowserTest,
                            TimeoutStartingWorker);
@@ -458,12 +457,12 @@
                            TimeoutWorkerInEvent);
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerStallInStoppingTest, DetachThenStart);
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerStallInStoppingTest, DetachThenRestart);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTestP,
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest,
                            RegisterForeignFetchScopes);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTestP, RequestNowTimeout);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTestP, RequestNowTimeoutKill);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTestP, RequestCustomizedTimeout);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTestP, MixedRequestTimeouts);
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, RequestNowTimeout);
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, RequestNowTimeoutKill);
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, RequestCustomizedTimeout);
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, MixedRequestTimeouts);
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerURLRequestJobTest, EarlyResponse);
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerURLRequestJobTest, CancelRequest);
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerActivationTest, SkipWaiting);
diff --git a/content/browser/service_worker/service_worker_version_unittest.cc b/content/browser/service_worker/service_worker_version_unittest.cc
index 066f2bf..c63ee7c 100644
--- a/content/browser/service_worker/service_worker_version_unittest.cc
+++ b/content/browser/service_worker/service_worker_version_unittest.cc
@@ -300,13 +300,9 @@
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerVersionTest);
 };
 
-class ServiceWorkerVersionTestP
-    : public MojoServiceWorkerTestP<ServiceWorkerVersionTest> {};
-
 class MessageReceiverDisallowStart : public MessageReceiver {
  public:
-  MessageReceiverDisallowStart(bool is_mojo_enabled)
-      : MessageReceiver(), is_mojo_enabled_(is_mojo_enabled) {}
+  MessageReceiverDisallowStart() : MessageReceiver() {}
   ~MessageReceiverDisallowStart() override {}
 
   enum class StartMode { STALL, FAIL, SUCCEED };
@@ -320,14 +316,10 @@
       case StartMode::STALL:
         break;  // Do nothing.
       case StartMode::FAIL:
-        if (is_mojo_enabled_) {
-          ASSERT_EQ(current_mock_instance_index_ + 1,
-                    mock_instance_clients()->size());
-          // Remove the connection by peer
-          mock_instance_clients()->at(current_mock_instance_index_).reset();
-        } else {
-          OnStopWorker(embedded_worker_id);
-        }
+        ASSERT_EQ(current_mock_instance_index_ + 1,
+                  mock_instance_clients()->size());
+        // Remove the connection by peer
+        mock_instance_clients()->at(current_mock_instance_index_).reset();
         break;
       case StartMode::SUCCEED:
         MessageReceiver::OnStartWorker(embedded_worker_id,
@@ -341,15 +333,14 @@
   void set_start_mode(StartMode mode) { mode_ = mode; }
 
  private:
-  const bool is_mojo_enabled_;
   uint32_t current_mock_instance_index_ = 0;
   StartMode mode_ = StartMode::STALL;
   DISALLOW_COPY_AND_ASSIGN(MessageReceiverDisallowStart);
 };
 
-class ServiceWorkerFailToStartTest : public ServiceWorkerVersionTestP {
+class ServiceWorkerFailToStartTest : public ServiceWorkerVersionTest {
  protected:
-  ServiceWorkerFailToStartTest() : ServiceWorkerVersionTestP() {}
+  ServiceWorkerFailToStartTest() : ServiceWorkerVersionTest() {}
 
   void set_start_mode(MessageReceiverDisallowStart::StartMode mode) {
     MessageReceiverDisallowStart* helper =
@@ -358,7 +349,7 @@
   }
 
   std::unique_ptr<MessageReceiver> GetMessageReceiver() override {
-    return base::MakeUnique<MessageReceiverDisallowStart>(is_mojo_enabled());
+    return base::MakeUnique<MessageReceiverDisallowStart>();
   }
 
  private:
@@ -405,9 +396,9 @@
   DISALLOW_COPY_AND_ASSIGN(MessageReceiverDisallowStop);
 };
 
-class ServiceWorkerStallInStoppingTest : public ServiceWorkerVersionTestP {
+class ServiceWorkerStallInStoppingTest : public ServiceWorkerVersionTest {
  protected:
-  ServiceWorkerStallInStoppingTest() : ServiceWorkerVersionTestP() {}
+  ServiceWorkerStallInStoppingTest() : ServiceWorkerVersionTest() {}
 
   std::unique_ptr<MessageReceiver> GetMessageReceiver() override {
     return base::MakeUnique<MessageReceiverDisallowStop>();
@@ -417,7 +408,7 @@
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerStallInStoppingTest);
 };
 
-TEST_P(ServiceWorkerVersionTestP, ConcurrentStartAndStop) {
+TEST_F(ServiceWorkerVersionTest, ConcurrentStartAndStop) {
   // Call StartWorker() multiple times.
   ServiceWorkerStatusCode status1 = SERVICE_WORKER_ERROR_FAILED;
   ServiceWorkerStatusCode status2 = SERVICE_WORKER_ERROR_FAILED;
@@ -485,7 +476,7 @@
   EXPECT_EQ(SERVICE_WORKER_OK, status3);
 }
 
-TEST_P(ServiceWorkerVersionTestP, DispatchEventToStoppedWorker) {
+TEST_F(ServiceWorkerVersionTest, DispatchEventToStoppedWorker) {
   EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
 
   // Dispatch an event without starting the worker.
@@ -505,7 +496,7 @@
   EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
 }
 
-TEST_P(ServiceWorkerVersionTestP, StartUnregisteredButStillLiveWorker) {
+TEST_F(ServiceWorkerVersionTest, StartUnregisteredButStillLiveWorker) {
   // Start the worker.
   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
   version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
@@ -539,7 +530,7 @@
   EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
 }
 
-TEST_P(ServiceWorkerVersionTestP, ReceiveMessageFromWorker) {
+TEST_F(ServiceWorkerVersionTest, ReceiveMessageFromWorker) {
   // Start worker.
   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
   version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
@@ -563,7 +554,7 @@
   EXPECT_EQ(777, receiver.received_values()[1]);
 }
 
-TEST_P(ServiceWorkerVersionTestP, InstallAndWaitCompletion) {
+TEST_F(ServiceWorkerVersionTest, InstallAndWaitCompletion) {
   version_->SetStatus(ServiceWorkerVersion::INSTALLING);
 
   // Wait for the completion.
@@ -579,7 +570,7 @@
   EXPECT_EQ(ServiceWorkerVersion::INSTALLING, version_->status());
 }
 
-TEST_P(ServiceWorkerVersionTestP, ActivateAndWaitCompletion) {
+TEST_F(ServiceWorkerVersionTest, ActivateAndWaitCompletion) {
   // TODO(mek): This test (and the one above for the install event) made more
   // sense back when ServiceWorkerVersion was responsible for updating the
   // status. Now a better version of this test should probably be added to
@@ -600,7 +591,7 @@
   EXPECT_EQ(ServiceWorkerVersion::ACTIVATING, version_->status());
 }
 
-TEST_P(ServiceWorkerVersionTestP, RepeatedlyObserveStatusChanges) {
+TEST_F(ServiceWorkerVersionTest, RepeatedlyObserveStatusChanges) {
   EXPECT_EQ(ServiceWorkerVersion::NEW, version_->status());
 
   // Repeatedly observe status changes (the callback re-registers itself).
@@ -623,7 +614,7 @@
   ASSERT_EQ(ServiceWorkerVersion::REDUNDANT, statuses[4]);
 }
 
-TEST_P(ServiceWorkerVersionTestP, IdleTimeout) {
+TEST_F(ServiceWorkerVersionTest, IdleTimeout) {
   // Used to reliably test when the idle time gets reset regardless of clock
   // granularity.
   const base::TimeDelta kOneSecond = base::TimeDelta::FromSeconds(1);
@@ -688,7 +679,7 @@
   EXPECT_LT(idle_time, version_->idle_time_);
 }
 
-TEST_P(ServiceWorkerVersionTestP, SetDevToolsAttached) {
+TEST_F(ServiceWorkerVersionTest, SetDevToolsAttached) {
   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
   version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                         CreateReceiverOnCurrentThread(&status));
@@ -718,7 +709,7 @@
   EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
 }
 
-TEST_P(ServiceWorkerVersionTestP, StoppingBeforeDestruct) {
+TEST_F(ServiceWorkerVersionTest, StoppingBeforeDestruct) {
   RunningStateListener listener;
   version_->AddListener(&listener);
 
@@ -735,7 +726,7 @@
 }
 
 // Test that update isn't triggered for a non-stale worker.
-TEST_P(ServiceWorkerVersionTestP, StaleUpdate_FreshWorker) {
+TEST_F(ServiceWorkerVersionTest, StaleUpdate_FreshWorker) {
   version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
   registration_->SetActiveVersion(version_);
   registration_->set_last_update_check(base::Time::Now());
@@ -746,7 +737,7 @@
 }
 
 // Test that update isn't triggered for a non-active worker.
-TEST_P(ServiceWorkerVersionTestP, StaleUpdate_NonActiveWorker) {
+TEST_F(ServiceWorkerVersionTest, StaleUpdate_NonActiveWorker) {
   version_->SetStatus(ServiceWorkerVersion::INSTALLING);
   registration_->SetInstallingVersion(version_);
   registration_->set_last_update_check(GetYesterday());
@@ -757,7 +748,7 @@
 }
 
 // Test that staleness is detected when starting a worker.
-TEST_P(ServiceWorkerVersionTestP, StaleUpdate_StartWorker) {
+TEST_F(ServiceWorkerVersionTest, StaleUpdate_StartWorker) {
   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
 
   // Starting the worker marks it as stale.
@@ -777,7 +768,7 @@
 }
 
 // Test that staleness is detected on a running worker.
-TEST_P(ServiceWorkerVersionTestP, StaleUpdate_RunningWorker) {
+TEST_F(ServiceWorkerVersionTest, StaleUpdate_RunningWorker) {
   // Start a fresh worker.
   version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
   registration_->SetActiveVersion(version_);
@@ -803,7 +794,7 @@
 }
 
 // Test that a stream of events doesn't restart the timer.
-TEST_P(ServiceWorkerVersionTestP, StaleUpdate_DoNotDeferTimer) {
+TEST_F(ServiceWorkerVersionTest, StaleUpdate_DoNotDeferTimer) {
   // Make a stale worker.
   version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
   registration_->SetActiveVersion(version_);
@@ -839,7 +830,7 @@
   EXPECT_EQ(run_time, version_->update_timer_.desired_run_time());
 }
 
-TEST_P(ServiceWorkerVersionTestP, RequestTimeout) {
+TEST_F(ServiceWorkerVersionTest, RequestTimeout) {
   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK;  // dummy value
   version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
 
@@ -868,7 +859,7 @@
                                        base::Time::Now()));
 }
 
-TEST_P(ServiceWorkerVersionTestP, RequestNowTimeout) {
+TEST_F(ServiceWorkerVersionTest, RequestNowTimeout) {
   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK;  // dummy value
   version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
 
@@ -895,7 +886,7 @@
   EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
 }
 
-TEST_P(ServiceWorkerVersionTestP, RequestNowTimeoutKill) {
+TEST_F(ServiceWorkerVersionTest, RequestNowTimeoutKill) {
   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK;  // dummy value
   version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
 
@@ -922,7 +913,7 @@
   EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
 }
 
-TEST_P(ServiceWorkerVersionTestP, RequestCustomizedTimeout) {
+TEST_F(ServiceWorkerVersionTest, RequestCustomizedTimeout) {
   ServiceWorkerStatusCode first_status =
       SERVICE_WORKER_ERROR_MAX_VALUE;  // dummy value
   ServiceWorkerStatusCode second_status =
@@ -984,7 +975,7 @@
   EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
 }
 
-TEST_P(ServiceWorkerVersionTestP, MixedRequestTimeouts) {
+TEST_F(ServiceWorkerVersionTest, MixedRequestTimeouts) {
   ServiceWorkerStatusCode sync_status =
       SERVICE_WORKER_ERROR_NETWORK;  // dummy value
   ServiceWorkerStatusCode fetch_status =
@@ -1035,7 +1026,7 @@
   EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
 }
 
-TEST_P(ServiceWorkerFailToStartTest, RendererCrash) {
+TEST_F(ServiceWorkerFailToStartTest, RendererCrash) {
   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK;  // dummy value
   version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
                         CreateReceiverOnCurrentThread(&status));
@@ -1058,7 +1049,7 @@
   EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
 }
 
-TEST_P(ServiceWorkerFailToStartTest, Timeout) {
+TEST_F(ServiceWorkerFailToStartTest, Timeout) {
   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK;  // dummy value
 
   // Start starting the worker.
@@ -1084,7 +1075,7 @@
 
 // Test that a service worker stalled in stopping will timeout and not get in a
 // sticky error state.
-TEST_P(ServiceWorkerStallInStoppingTest, DetachThenStart) {
+TEST_F(ServiceWorkerStallInStoppingTest, DetachThenStart) {
   // Start a worker.
   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
   version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
@@ -1132,7 +1123,7 @@
 
 // Test that a service worker stalled in stopping with a start worker
 // request queued up will timeout and restart.
-TEST_P(ServiceWorkerStallInStoppingTest, DetachThenRestart) {
+TEST_F(ServiceWorkerStallInStoppingTest, DetachThenRestart) {
   // Start a worker.
   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
   version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
@@ -1164,7 +1155,7 @@
   EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
 }
 
-TEST_P(ServiceWorkerVersionTestP, RegisterForeignFetchScopes) {
+TEST_F(ServiceWorkerVersionTest, RegisterForeignFetchScopes) {
   version_->SetStatus(ServiceWorkerVersion::INSTALLING);
   // Start a worker.
   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
@@ -1240,7 +1231,7 @@
   EXPECT_EQ(valid_origin, version_->foreign_fetch_origins_[0]);
 }
 
-TEST_P(ServiceWorkerVersionTestP, RendererCrashDuringEvent) {
+TEST_F(ServiceWorkerVersionTest, RendererCrashDuringEvent) {
   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK;  // dummy value
 
   version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
@@ -1275,7 +1266,7 @@
                                        base::Time::Now()));
 }
 
-TEST_P(ServiceWorkerVersionTestP, DispatchEvent) {
+TEST_F(ServiceWorkerVersionTest, DispatchEvent) {
   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK;  // dummy value
 
   // Activate and start worker.
@@ -1321,7 +1312,7 @@
                                       base::Time::Now()));
 }
 
-TEST_P(ServiceWorkerFailToStartTest, FailingWorkerUsesNewRendererProcess) {
+TEST_F(ServiceWorkerFailToStartTest, FailingWorkerUsesNewRendererProcess) {
   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
 
   helper_->SimulateAddProcessToPattern(pattern_,
@@ -1380,7 +1371,7 @@
   base::RunLoop().RunUntilIdle();
 }
 
-TEST_P(ServiceWorkerFailToStartTest, RestartStalledWorker) {
+TEST_F(ServiceWorkerFailToStartTest, RestartStalledWorker) {
   ServiceWorkerStatusCode status1 = SERVICE_WORKER_ERROR_MAX_VALUE;
   ServiceWorkerStatusCode status2 = SERVICE_WORKER_ERROR_MAX_VALUE;
   version_->StartWorker(ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME,
@@ -1403,7 +1394,7 @@
   EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
 }
 
-TEST_P(ServiceWorkerVersionTestP, DispatchConcurrentEvent) {
+TEST_F(ServiceWorkerVersionTest, DispatchConcurrentEvent) {
   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK;  // dummy value
 
   // Activate and start worker.
@@ -1482,7 +1473,7 @@
                                       base::Time::Now()));
 }
 
-TEST_P(ServiceWorkerVersionTestP, DispatchSimpleEvent_Completed) {
+TEST_F(ServiceWorkerVersionTest, DispatchSimpleEvent_Completed) {
   ServiceWorkerStatusCode status =
       SERVICE_WORKER_ERROR_MAX_VALUE;  // dummy value
 
@@ -1519,7 +1510,7 @@
   EXPECT_EQ(SERVICE_WORKER_OK, status);
 }
 
-TEST_P(ServiceWorkerVersionTestP, DispatchSimpleEvent_Rejected) {
+TEST_F(ServiceWorkerVersionTest, DispatchSimpleEvent_Rejected) {
   ServiceWorkerStatusCode status =
       SERVICE_WORKER_ERROR_MAX_VALUE;  // dummy value
 
@@ -1556,7 +1547,7 @@
   EXPECT_EQ(SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED, status);
 }
 
-TEST_P(ServiceWorkerVersionTestP, DispatchEvent_MultipleResponse) {
+TEST_F(ServiceWorkerVersionTest, DispatchEvent_MultipleResponse) {
   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
 
   // Activate and start worker.
@@ -1625,9 +1616,9 @@
                                       base::Time::Now()));
 }
 
-class ServiceWorkerNavigationHintUMATest : public ServiceWorkerVersionTestP {
+class ServiceWorkerNavigationHintUMATest : public ServiceWorkerVersionTest {
  protected:
-  ServiceWorkerNavigationHintUMATest() : ServiceWorkerVersionTestP() {}
+  ServiceWorkerNavigationHintUMATest() : ServiceWorkerVersionTest() {}
 
   void StartWorker(ServiceWorkerMetrics::EventType purpose) {
     ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
@@ -1708,25 +1699,25 @@
 const char ServiceWorkerNavigationHintUMATest::kLinkTapDown[] =
     "ServiceWorker.NavigationHintPrecision.LINK_TAP_DOWN";
 
-TEST_P(ServiceWorkerNavigationHintUMATest, LinkMouseDown) {
+TEST_F(ServiceWorkerNavigationHintUMATest, LinkMouseDown) {
   SimpleNavigationHintTest(
       ServiceWorkerMetrics::EventType::NAVIGATION_HINT_LINK_MOUSE_DOWN,
       kLinkMouseDown, {kLinkTapUnconfirmed, kLinkTapDown});
 }
 
-TEST_P(ServiceWorkerNavigationHintUMATest, LinkTapUnconfirmed) {
+TEST_F(ServiceWorkerNavigationHintUMATest, LinkTapUnconfirmed) {
   SimpleNavigationHintTest(
       ServiceWorkerMetrics::EventType::NAVIGATION_HINT_LINK_TAP_UNCONFIRMED,
       kLinkTapUnconfirmed, {kLinkMouseDown, kLinkTapDown});
 }
 
-TEST_P(ServiceWorkerNavigationHintUMATest, LinkTapDown) {
+TEST_F(ServiceWorkerNavigationHintUMATest, LinkTapDown) {
   SimpleNavigationHintTest(
       ServiceWorkerMetrics::EventType::NAVIGATION_HINT_LINK_TAP_DOWN,
       kLinkTapDown, {kLinkMouseDown, kLinkTapUnconfirmed});
 }
 
-TEST_P(ServiceWorkerNavigationHintUMATest, ConcurrentStart) {
+TEST_F(ServiceWorkerNavigationHintUMATest, ConcurrentStart) {
   version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
   ServiceWorkerStatusCode status1 = SERVICE_WORKER_ERROR_MAX_VALUE;
   ServiceWorkerStatusCode status2 = SERVICE_WORKER_ERROR_MAX_VALUE;
@@ -1760,7 +1751,7 @@
   histogram_tester_.ExpectBucketCount(kNavigationHintPrecision, false, 0);
 }
 
-TEST_P(ServiceWorkerNavigationHintUMATest, StartWhileStopping) {
+TEST_F(ServiceWorkerNavigationHintUMATest, StartWhileStopping) {
   StartWorker(ServiceWorkerMetrics::EventType::NAVIGATION_HINT_LINK_MOUSE_DOWN);
   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
   version_->StopWorker(CreateReceiverOnCurrentThread(&status));
@@ -1778,16 +1769,4 @@
   histogram_tester_.ExpectTotalCount(kLinkTapDown, 1);
 }
 
-INSTANTIATE_TEST_CASE_P(ServiceWorkerVersionTestP,
-                        ServiceWorkerVersionTestP,
-                        testing::Bool());
-INSTANTIATE_TEST_CASE_P(ServiceWorkerFailToStartTest,
-                        ServiceWorkerFailToStartTest,
-                        testing::Bool());
-INSTANTIATE_TEST_CASE_P(ServiceWorkerNavigationHintUMATest,
-                        ServiceWorkerNavigationHintUMATest,
-                        testing::Bool());
-INSTANTIATE_TEST_CASE_P(ServiceWorkerStallInStoppingTest,
-                        ServiceWorkerStallInStoppingTest,
-                        testing::Bool());
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_write_to_cache_job.h b/content/browser/service_worker/service_worker_write_to_cache_job.h
index 011559e..da5016b 100644
--- a/content/browser/service_worker/service_worker_write_to_cache_job.h
+++ b/content/browser/service_worker/service_worker_write_to_cache_job.h
@@ -60,13 +60,13 @@
   const static net::Error kIdenticalScriptError;
 
  private:
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTestP,
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
                            UpdateBefore24Hours);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTestP,
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
                            UpdateAfter24Hours);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTestP,
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
                            UpdateForceBypassCache);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTestP,
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
                            ServiceWorkerDataRequestAnnotation);
 
   ~ServiceWorkerWriteToCacheJob() override;
diff --git a/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc b/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc
index d1e2328f2..494dee53 100644
--- a/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc
+++ b/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc
@@ -448,10 +448,7 @@
   int64_t next_version_id_ = 1L;
 };
 
-class ServiceWorkerWriteToCacheJobTestP
-    : public MojoServiceWorkerTestP<ServiceWorkerWriteToCacheJobTest> {};
-
-TEST_P(ServiceWorkerWriteToCacheJobTestP, Normal) {
+TEST_F(ServiceWorkerWriteToCacheJobTest, Normal) {
   mock_protocol_handler_->SetCreateJobCallback(
       base::Bind(&CreateNormalURLRequestJob));
   request_->Start();
@@ -461,7 +458,7 @@
             version_->script_cache_map()->LookupResourceId(script_url_));
 }
 
-TEST_P(ServiceWorkerWriteToCacheJobTestP, InvalidMimeType) {
+TEST_F(ServiceWorkerWriteToCacheJobTest, InvalidMimeType) {
   mock_protocol_handler_->SetCreateJobCallback(
       base::Bind(&CreateInvalidMimeTypeJob));
   request_->Start();
@@ -472,7 +469,7 @@
             version_->script_cache_map()->LookupResourceId(script_url_));
 }
 
-TEST_P(ServiceWorkerWriteToCacheJobTestP, SSLCertificateError) {
+TEST_F(ServiceWorkerWriteToCacheJobTest, SSLCertificateError) {
   mock_protocol_handler_->SetCreateJobCallback(
       base::Bind(&CreateSSLCertificateErrorJob));
   request_->Start();
@@ -492,10 +489,7 @@
   ~ServiceWorkerWriteToCacheLocalhostTest() override {}
 };
 
-class ServiceWorkerWriteToCacheLocalhostTestP
-    : public MojoServiceWorkerTestP<ServiceWorkerWriteToCacheLocalhostTest> {};
-
-TEST_P(ServiceWorkerWriteToCacheLocalhostTestP,
+TEST_F(ServiceWorkerWriteToCacheLocalhostTest,
        SSLCertificateError_AllowInsecureLocalhost) {
   base::CommandLine::ForCurrentProcess()->AppendSwitch(
       switches::kAllowInsecureLocalhost);
@@ -510,7 +504,7 @@
             version_->script_cache_map()->LookupResourceId(script_url_));
 }
 
-TEST_P(ServiceWorkerWriteToCacheLocalhostTestP, SSLCertificateError) {
+TEST_F(ServiceWorkerWriteToCacheLocalhostTest, SSLCertificateError) {
   mock_protocol_handler_->SetCreateJobCallback(
       base::Bind(&CreateSSLCertificateErrorJob));
   request_->Start();
@@ -521,7 +515,7 @@
             version_->script_cache_map()->LookupResourceId(script_url_));
 }
 
-TEST_P(ServiceWorkerWriteToCacheLocalhostTestP,
+TEST_F(ServiceWorkerWriteToCacheLocalhostTest,
        CertStatusError_AllowInsecureLocalhost) {
   base::CommandLine::ForCurrentProcess()->AppendSwitch(
       switches::kAllowInsecureLocalhost);
@@ -536,7 +530,7 @@
             version_->script_cache_map()->LookupResourceId(script_url_));
 }
 
-TEST_P(ServiceWorkerWriteToCacheLocalhostTestP, CertStatusError) {
+TEST_F(ServiceWorkerWriteToCacheLocalhostTest, CertStatusError) {
   mock_protocol_handler_->SetCreateJobCallback(
       base::Bind(&CreateCertStatusErrorJob));
   request_->Start();
@@ -547,7 +541,7 @@
             version_->script_cache_map()->LookupResourceId(script_url_));
 }
 
-TEST_P(ServiceWorkerWriteToCacheJobTestP, CertStatusError) {
+TEST_F(ServiceWorkerWriteToCacheJobTest, CertStatusError) {
   mock_protocol_handler_->SetCreateJobCallback(
       base::Bind(&CreateCertStatusErrorJob));
   request_->Start();
@@ -558,14 +552,14 @@
             version_->script_cache_map()->LookupResourceId(script_url_));
 }
 
-TEST_P(ServiceWorkerWriteToCacheJobTestP, Update_SameScript) {
+TEST_F(ServiceWorkerWriteToCacheJobTest, Update_SameScript) {
   std::string response = GenerateLongResponse();
   CreateIncumbent(response);
   scoped_refptr<ServiceWorkerVersion> version = UpdateScript(response);
   EXPECT_EQ(kInvalidServiceWorkerResourceId, GetResourceId(version.get()));
 }
 
-TEST_P(ServiceWorkerWriteToCacheJobTestP, Update_SameSizeScript) {
+TEST_F(ServiceWorkerWriteToCacheJobTest, Update_SameSizeScript) {
   std::string response = GenerateLongResponse();
   CreateIncumbent(response);
 
@@ -600,7 +594,7 @@
   registration_->SetWaitingVersion(version);
 }
 
-TEST_P(ServiceWorkerWriteToCacheJobTestP, Update_TruncatedScript) {
+TEST_F(ServiceWorkerWriteToCacheJobTest, Update_TruncatedScript) {
   std::string response = GenerateLongResponse();
   CreateIncumbent(response);
 
@@ -629,7 +623,7 @@
   registration_->SetWaitingVersion(version);
 }
 
-TEST_P(ServiceWorkerWriteToCacheJobTestP, Update_ElongatedScript) {
+TEST_F(ServiceWorkerWriteToCacheJobTest, Update_ElongatedScript) {
   std::string original_response = GenerateLongResponse();
   CreateIncumbent(original_response);
 
@@ -652,7 +646,7 @@
   registration_->SetWaitingVersion(version);
 }
 
-TEST_P(ServiceWorkerWriteToCacheJobTestP, Update_EmptyScript) {
+TEST_F(ServiceWorkerWriteToCacheJobTest, Update_EmptyScript) {
   // Create empty incumbent.
   CreateIncumbent(std::string());
 
@@ -672,7 +666,7 @@
   EXPECT_EQ(kInvalidServiceWorkerResourceId, GetResourceId(version.get()));
 }
 
-TEST_P(ServiceWorkerWriteToCacheJobTestP, Error) {
+TEST_F(ServiceWorkerWriteToCacheJobTest, Error) {
   mock_protocol_handler_->SetCreateJobCallback(
       base::Bind(&CreateFailedURLRequestJob));
   request_->Start();
@@ -683,7 +677,7 @@
             version_->script_cache_map()->LookupResourceId(script_url_));
 }
 
-TEST_P(ServiceWorkerWriteToCacheJobTestP, FailedWriteHeadersToCache) {
+TEST_F(ServiceWorkerWriteToCacheJobTest, FailedWriteHeadersToCache) {
   mock_protocol_handler_->SetCreateJobCallback(
       base::Bind(&CreateNormalURLRequestJob));
   DisableCache();
@@ -693,11 +687,4 @@
   EXPECT_EQ(net::ERR_FAILED, request_->status().error());
 }
 
-INSTANTIATE_TEST_CASE_P(ServiceWorkerWriteToCacheJobTest,
-                        ServiceWorkerWriteToCacheJobTestP,
-                        testing::Bool());
-INSTANTIATE_TEST_CASE_P(ServiceWorkerWriteToCacheLocalhostTest,
-                        ServiceWorkerWriteToCacheLocalhostTestP,
-                        testing::Bool());
-
 }  // namespace content
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn
index 0d16324..e4f12fc 100644
--- a/content/common/BUILD.gn
+++ b/content/common/BUILD.gn
@@ -354,6 +354,7 @@
     "//cc/ipc",
     "//cc/surfaces",
     "//components/discardable_memory/common",
+    "//components/payments:payment_app",
     "//components/tracing",
     "//components/tracing:startup_tracing",
     "//content:resources",
diff --git a/content/common/service_worker/service_worker_event_dispatcher.mojom b/content/common/service_worker/service_worker_event_dispatcher.mojom
index d878916e..df445a8 100644
--- a/content/common/service_worker/service_worker_event_dispatcher.mojom
+++ b/content/common/service_worker/service_worker_event_dispatcher.mojom
@@ -4,6 +4,7 @@
 
 module content.mojom;
 
+import "components/payments/payment_app.mojom";
 import "content/common/url_loader.mojom";
 import "mojo/common/string16.mojom";
 import "mojo/common/time.mojom";
@@ -45,6 +46,9 @@
                     blink.mojom.BackgroundSyncEventLastChance last_chance)
       => (blink.mojom.ServiceWorkerEventStatus status,
           mojo.common.mojom.Time dispatch_event_time);
+  DispatchPaymentRequestEvent(payments.mojom.PaymentAppRequestData data)
+      => (blink.mojom.ServiceWorkerEventStatus status,
+          mojo.common.mojom.Time dispatch_event_time);
   DispatchExtendableMessageEvent(ExtendableMessageEvent event)
       => (blink.mojom.ServiceWorkerEventStatus status,
           mojo.common.mojom.Time dispatch_event_time);
diff --git a/content/common/service_worker/service_worker_utils.cc b/content/common/service_worker/service_worker_utils.cc
index 9abc8588..9834b83 100644
--- a/content/common/service_worker/service_worker_utils.cc
+++ b/content/common/service_worker/service_worker_utils.cc
@@ -134,8 +134,7 @@
 
 // static
 bool ServiceWorkerUtils::IsMojoForServiceWorkerEnabled() {
-  return !base::CommandLine::ForCurrentProcess()->HasSwitch(
-      switches::kDisableMojoServiceWorker);
+  return true;
 }
 
 bool LongestScopeMatcher::MatchLongest(const GURL& scope) {
diff --git a/content/public/browser/payment_app_provider.h b/content/public/browser/payment_app_provider.h
index 022e8c6..b772e8b 100644
--- a/content/public/browser/payment_app_provider.h
+++ b/content/public/browser/payment_app_provider.h
@@ -35,6 +35,10 @@
   // Should be accessed only on the UI thread.
   virtual void GetAllManifests(BrowserContext* browser_context,
                                const GetAllManifestsCallback& callback) = 0;
+  virtual void InvokePaymentApp(
+      BrowserContext* browser_context,
+      int64_t registration_id,
+      payments::mojom::PaymentAppRequestDataPtr data) = 0;
 
  protected:
   virtual ~PaymentAppProvider() {}
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index 773f254..bd57ea2 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -404,6 +404,7 @@
     "//cc/surfaces:surface_id",
     "//cc/surfaces:surfaces",
     "//components/discardable_memory/client",
+    "//components/payments:payment_app",
     "//components/url_formatter",
     "//content:resources",
     "//content/child",
diff --git a/content/renderer/DEPS b/content/renderer/DEPS
index c5de582..98c4ec9 100644
--- a/content/renderer/DEPS
+++ b/content/renderer/DEPS
@@ -2,6 +2,7 @@
   # Allow inclusion of specific components that we depend on.
   # See comment in content/DEPS for which components are allowed.
   "+components/discardable_memory/client",
+  "+components/payments",
   "+components/scheduler",
   "+components/url_formatter",
 
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc
index 14a008f..12a94c7 100644
--- a/content/renderer/gpu/render_widget_compositor.cc
+++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -5,6 +5,8 @@
 #include "content/renderer/gpu/render_widget_compositor.h"
 
 #include <stddef.h>
+
+#include <cmath>
 #include <limits>
 #include <string>
 #include <utility>
@@ -49,6 +51,7 @@
 #include "content/common/layer_tree_settings_factory.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_switches.h"
+#include "content/public/common/screen_info.h"
 #include "content/public/renderer/content_renderer_client.h"
 #include "content/renderer/gpu/render_widget_compositor_delegate.h"
 #include "content/renderer/input/input_handler_manager.h"
@@ -67,11 +70,6 @@
 #include "ui/native_theme/native_theme_switches.h"
 #include "ui/native_theme/overlay_scrollbar_constants_aura.h"
 
-#if defined(OS_ANDROID)
-#include "base/android/build_info.h"
-#include "ui/gfx/android/device_display_info.h"
-#endif
-
 namespace base {
 class Value;
 }
@@ -143,49 +141,29 @@
   return cc_selection;
 }
 
-gfx::Size CalculateDefaultTileSize(float initial_device_scale_factor) {
+gfx::Size CalculateDefaultTileSize(float initial_device_scale_factor,
+                                   const ScreenInfo& screen_info) {
   int default_tile_size = 256;
 #if defined(OS_ANDROID)
-  // TODO(epenner): unify this for all platforms if it
-  // makes sense (http://crbug.com/159524)
+  const gfx::Size screen_size = gfx::ScaleToFlooredSize(
+      screen_info.rect.size(), screen_info.device_scale_factor);
+  int display_width = screen_size.width();
+  int display_height = screen_size.height();
+  int numTiles = (display_width * display_height) / (256 * 256);
+  if (numTiles > 16)
+    default_tile_size = 384;
+  if (numTiles >= 40)
+    default_tile_size = 512;
 
-  gfx::DeviceDisplayInfo info;
-  bool real_size_supported = true;
-  int display_width = info.GetPhysicalDisplayWidth();
-  int display_height = info.GetPhysicalDisplayHeight();
-  if (display_width == 0 || display_height == 0) {
-    real_size_supported = false;
-    display_width = info.GetDisplayWidth();
-    display_height = info.GetDisplayHeight();
-  }
-
+  // Adjust for some resolutions that barely straddle an extra
+  // tile when in portrait mode. This helps worst case scroll/raster
+  // by not needing a full extra tile for each row.
+  constexpr int tolerance = 10;  // To avoid rounding errors.
   int portrait_width = std::min(display_width, display_height);
-  int landscape_width = std::max(display_width, display_height);
-
-  if (real_size_supported) {
-    // Maximum HD dimensions should be 768x1280
-    // Maximum FHD dimensions should be 1200x1920
-    if (portrait_width > 768 || landscape_width > 1280)
-      default_tile_size = 384;
-    if (portrait_width > 1200 || landscape_width > 1920)
-      default_tile_size = 512;
-
-    // Adjust for some resolutions that barely straddle an extra
-    // tile when in portrait mode. This helps worst case scroll/raster
-    // by not needing a full extra tile for each row.
-    if (default_tile_size == 256 && portrait_width == 768)
-      default_tile_size += 32;
-    if (default_tile_size == 384 && portrait_width == 1200)
-      default_tile_size += 32;
-  } else {
-    // We don't know the exact resolution due to screen controls etc.
-    // So this just estimates the values above using tile counts.
-    int numTiles = (display_width * display_height) / (256 * 256);
-    if (numTiles > 16)
-      default_tile_size = 384;
-    if (numTiles >= 40)
-      default_tile_size = 512;
-  }
+  if (default_tile_size == 256 && std::abs(portrait_width - 768) < tolerance)
+    default_tile_size += 32;
+  if (default_tile_size == 384 && std::abs(portrait_width - 1200) < tolerance)
+    default_tile_size += 32;
 #elif defined(OS_CHROMEOS) || defined(OS_MACOSX)
   // Use 512 for high DPI (dsf=2.0f) devices.
   if (initial_device_scale_factor >= 2.0f)
@@ -215,10 +193,11 @@
 std::unique_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create(
     RenderWidgetCompositorDelegate* delegate,
     float device_scale_factor,
+    const ScreenInfo& screen_info,
     CompositorDependencies* compositor_deps) {
   std::unique_ptr<RenderWidgetCompositor> compositor(
       new RenderWidgetCompositor(delegate, compositor_deps));
-  compositor->Initialize(device_scale_factor);
+  compositor->Initialize(device_scale_factor, screen_info);
   return compositor;
 }
 
@@ -234,10 +213,11 @@
       remote_proto_channel_receiver_(nullptr),
       weak_factory_(this) {}
 
-void RenderWidgetCompositor::Initialize(float device_scale_factor) {
+void RenderWidgetCompositor::Initialize(float device_scale_factor,
+                                        const ScreenInfo& screen_info) {
   base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
-  cc::LayerTreeSettings settings =
-      GenerateLayerTreeSettings(*cmd, compositor_deps_, device_scale_factor);
+  cc::LayerTreeSettings settings = GenerateLayerTreeSettings(
+      *cmd, compositor_deps_, device_scale_factor, screen_info);
 
   animation_host_ = cc::AnimationHost::CreateMainInstance();
 
@@ -284,7 +264,8 @@
 cc::LayerTreeSettings RenderWidgetCompositor::GenerateLayerTreeSettings(
     const base::CommandLine& cmd,
     CompositorDependencies* compositor_deps,
-    float device_scale_factor) {
+    float device_scale_factor,
+    const ScreenInfo& screen_info) {
   cc::LayerTreeSettings settings;
 
   // For web contents, layer transforms should scale up the contents of layers
@@ -296,7 +277,8 @@
 
   // TODO(danakj): This should not be a setting O_O; it should change when the
   // device scale factor on LayerTreeHost changes.
-  settings.default_tile_size = CalculateDefaultTileSize(device_scale_factor);
+  settings.default_tile_size =
+      CalculateDefaultTileSize(device_scale_factor, screen_info);
   if (cmd.HasSwitch(switches::kDefaultTileWidth)) {
     int tile_width = 0;
     GetSwitchValueAsInt(cmd, switches::kDefaultTileWidth, 1,
diff --git a/content/renderer/gpu/render_widget_compositor.h b/content/renderer/gpu/render_widget_compositor.h
index 1bd9b6b4..f14063a9 100644
--- a/content/renderer/gpu/render_widget_compositor.h
+++ b/content/renderer/gpu/render_widget_compositor.h
@@ -50,6 +50,7 @@
 namespace content {
 
 class RenderWidgetCompositorDelegate;
+struct ScreenInfo;
 
 class CONTENT_EXPORT RenderWidgetCompositor
     : NON_EXPORTED_BASE(public blink::WebLayerTreeView),
@@ -62,6 +63,7 @@
   static std::unique_ptr<RenderWidgetCompositor> Create(
       RenderWidgetCompositorDelegate* delegate,
       float device_scale_factor,
+      const ScreenInfo& screen_info,
       CompositorDependencies* compositor_deps);
 
   ~RenderWidgetCompositor() override;
@@ -69,7 +71,8 @@
   static cc::LayerTreeSettings GenerateLayerTreeSettings(
       const base::CommandLine& cmd,
       CompositorDependencies* compositor_deps,
-      float device_scale_factor);
+      float device_scale_factor,
+      const ScreenInfo& screen_info);
   static cc::ManagedMemoryPolicy GetGpuMemoryPolicy(
       const cc::ManagedMemoryPolicy& policy);
 
@@ -209,7 +212,7 @@
   RenderWidgetCompositor(RenderWidgetCompositorDelegate* delegate,
                          CompositorDependencies* compositor_deps);
 
-  void Initialize(float device_scale_factor);
+  void Initialize(float device_scale_factor, const ScreenInfo& screen_info);
   cc::LayerTreeHost* layer_tree_host() { return layer_tree_host_.get(); }
 
  private:
diff --git a/content/renderer/gpu/render_widget_compositor_unittest.cc b/content/renderer/gpu/render_widget_compositor_unittest.cc
index b4ec6b3..f09b64e 100644
--- a/content/renderer/gpu/render_widget_compositor_unittest.cc
+++ b/content/renderer/gpu/render_widget_compositor_unittest.cc
@@ -18,6 +18,7 @@
 #include "cc/test/test_context_provider.h"
 #include "cc/test/test_web_graphics_context_3d.h"
 #include "cc/trees/layer_tree_host.h"
+#include "content/public/common/screen_info.h"
 #include "content/public/test/mock_render_thread.h"
 #include "content/renderer/render_widget.h"
 #include "content/test/fake_compositor_dependencies.h"
@@ -217,7 +218,9 @@
  public:
   RenderWidgetCompositorFrameSinkTest()
       : render_widget_compositor_(&compositor_delegate_, &compositor_deps_) {
-    render_widget_compositor_.Initialize(1.f /* initial_device_scale_factor */);
+    ScreenInfo dummy_screen_info;
+    render_widget_compositor_.Initialize(1.f /* initial_device_scale_factor */,
+                                         dummy_screen_info);
   }
 
   void RunTest(bool use_null_compositor_frame_sink,
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index 1fff8df..59b1d939 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -1226,7 +1226,7 @@
   DCHECK(!host_closing_);
 
   compositor_ = RenderWidgetCompositor::Create(this, device_scale_factor_,
-                                               compositor_deps_);
+                                               screen_info_, compositor_deps_);
   compositor_->setViewportSize(physical_backing_size_);
   OnDeviceScaleFactorChanged();
   compositor_->SetDeviceColorSpace(screen_info_.icc_profile.GetColorSpace());
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc
index 715a35e..43a660e2 100644
--- a/content/renderer/service_worker/service_worker_context_client.cc
+++ b/content/renderer/service_worker/service_worker_context_client.cc
@@ -904,6 +904,12 @@
                             web_last_chance);
 }
 
+void ServiceWorkerContextClient::DispatchPaymentRequestEvent(
+    payments::mojom::PaymentAppRequestDataPtr data,
+    const DispatchPaymentRequestEventCallback& callback) {
+  NOTIMPLEMENTED();
+}
+
 void ServiceWorkerContextClient::Send(IPC::Message* message) {
   sender_->Send(message);
 }
diff --git a/content/renderer/service_worker/service_worker_context_client.h b/content/renderer/service_worker/service_worker_context_client.h
index 2686e31..4bbcc32 100644
--- a/content/renderer/service_worker/service_worker_context_client.h
+++ b/content/renderer/service_worker/service_worker_context_client.h
@@ -19,6 +19,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/strings/string16.h"
 #include "base/time/time.h"
+#include "components/payments/payment_app.mojom.h"
 #include "content/child/webmessageportchannel_impl.h"
 #include "content/common/service_worker/service_worker_event_dispatcher.mojom.h"
 #include "content/common/service_worker/service_worker_status_code.h"
@@ -68,6 +69,9 @@
   using SyncCallback =
       base::Callback<void(ServiceWorkerStatusCode,
                           base::Time /* dispatch_event_time */)>;
+  using PaymentRequestEventCallback =
+      base::Callback<void(ServiceWorkerStatusCode,
+                          base::Time /* dispatch_event_time */)>;
   using FetchCallback =
       base::Callback<void(ServiceWorkerStatusCode,
                           base::Time /* dispatch_event_time */)>;
@@ -224,6 +228,9 @@
       const std::string& tag,
       blink::mojom::BackgroundSyncEventLastChance last_chance,
       const DispatchSyncEventCallback& callback) override;
+  void DispatchPaymentRequestEvent(
+      payments::mojom::PaymentAppRequestDataPtr data,
+      const DispatchPaymentRequestEventCallback& callback) override;
 
   void OnActivateEvent(int request_id);
   void OnInstallEvent(int request_id);
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 1fd0646..0dbf9fef 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1406,6 +1406,7 @@
     "//components/display_compositor",
     "//components/leveldb/public/cpp",
     "//components/payments:payment_app",
+    "//components/payments:payment_request",
     "//components/rappor:test_support",
     "//content:resources",
     "//content/app:both_for_content_tests",
diff --git a/content/test/gpu/generate_buildbot_json.py b/content/test/gpu/generate_buildbot_json.py
index 5e6e4484..c8af5304 100755
--- a/content/test/gpu/generate_buildbot_json.py
+++ b/content/test/gpu/generate_buildbot_json.py
@@ -232,19 +232,6 @@
       'swarming': False,
       'os_type': 'win',
     },
-    'Win7 Release (New Intel)': {
-      'swarming_dimensions': [
-        {
-          'gpu': '8086:0412',
-          'os': 'Windows-2008ServerR2-SP1'
-        },
-      ],
-      'build_config': 'Release',
-      # This bot is a one-off and doesn't have similar slaves in the
-      # swarming pool.
-      'swarming': False,
-      'os_type': 'win',
-    },
     'Win10 Release (New Intel)': {
       'swarming_dimensions': [
         {
@@ -258,11 +245,11 @@
       'swarming': False,
       'os_type': 'win',
     },
-    'Win7 Debug (New Intel)': {
+    'Win10 Debug (New Intel)': {
       'swarming_dimensions': [
         {
           'gpu': '8086:0412',
-          'os': 'Windows-2008ServerR2-SP1'
+          'os': 'Windows-10',
         },
       ],
       'build_config': 'Debug',
@@ -271,10 +258,23 @@
       'swarming': False,
       'os_type': 'win',
     },
-    'Win10 Debug (New Intel)': {
+    'Win10 Release (Intel HD 530)': {
       'swarming_dimensions': [
         {
-          'gpu': '8086:0412',
+          'gpu': '8086:1912',
+          'os': 'Windows-10',
+        },
+      ],
+      'build_config': 'Release',
+      # This bot is a one-off and doesn't have similar slaves in the
+      # swarming pool.
+      'swarming': False,
+      'os_type': 'win',
+    },
+    'Win10 Debug (Intel HD 530)': {
+      'swarming_dimensions': [
+        {
+          'gpu': '8086:1912',
           'os': 'Windows-10',
         },
       ],
@@ -532,6 +532,32 @@
       'swarming': False,
       'os_type': 'linux',
     },
+    'Linux Release (Intel HD 530)': {
+      'swarming_dimensions': [
+        {
+          'gpu': '8086:1912',
+          'os': 'Linux'
+        },
+      ],
+      'build_config': 'Release',
+      # This bot is a one-off and doesn't have similar slaves in the
+      # swarming pool.
+      'swarming': False,
+      'os_type': 'linux',
+    },
+    'Linux Debug (Intel HD 530)': {
+      'swarming_dimensions': [
+        {
+          'gpu': '8086:1912',
+          'os': 'Linux'
+        },
+      ],
+      'build_config': 'Debug',
+      # This bot is a one-off and doesn't have similar slaves in the
+      # swarming pool.
+      'swarming': False,
+      'os_type': 'linux',
+    },
     'Linux Release (AMD R7 240)': {
       'swarming_dimensions': [
         {
diff --git a/content/test/layouttest_support.cc b/content/test/layouttest_support.cc
index fefd00e..c23f1a1 100644
--- a/content/test/layouttest_support.cc
+++ b/content/test/layouttest_support.cc
@@ -26,6 +26,7 @@
 #include "content/common/renderer.mojom.h"
 #include "content/common/site_isolation_policy.h"
 #include "content/public/common/page_state.h"
+#include "content/public/common/screen_info.h"
 #include "content/public/renderer/renderer_gamepad_provider.h"
 #include "content/renderer/fetchers/manifest_fetcher.h"
 #include "content/renderer/gpu/render_widget_compositor.h"
@@ -347,9 +348,11 @@
     if (!task_runner)
       task_runner = base::ThreadTaskRunnerHandle::Get().get();
 
+    ScreenInfo dummy_screen_info;
     cc::LayerTreeSettings settings =
         RenderWidgetCompositor::GenerateLayerTreeSettings(
-            *base::CommandLine::ForCurrentProcess(), deps, 1.f);
+            *base::CommandLine::ForCurrentProcess(), deps, 1.f,
+            dummy_screen_info);
 
     auto compositor_frame_sink = base::MakeUnique<cc::TestCompositorFrameSink>(
         std::move(compositor_context_provider),
diff --git a/ipc/run_all_unittests.cc b/ipc/run_all_unittests.cc
index a9d2133..5646c67 100644
--- a/ipc/run_all_unittests.cc
+++ b/ipc/run_all_unittests.cc
@@ -16,9 +16,6 @@
 #endif
 
 int main(int argc, char** argv) {
-#if defined(OS_ANDROID)
-  base::InitAndroidMultiProcessTestHelper(main);
-#endif
   base::TestSuite test_suite(argc, argv);
   mojo::edk::Init();
   base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart);
diff --git a/mojo/android/BUILD.gn b/mojo/android/BUILD.gn
index 527b1cfa..1a8cdbd 100644
--- a/mojo/android/BUILD.gn
+++ b/mojo/android/BUILD.gn
@@ -131,7 +131,7 @@
     ":libsystem_java",
     ":system_java_jni_headers",
     "//base",
-    "//base/test/:test_support",
+    "//base/test:test_support",
     "//build/config/sanitizers:deps",
     "//mojo/edk/system",
     "//mojo/public/cpp/bindings/tests:mojo_public_bindings_test_utils",
diff --git a/mojo/edk/embedder/platform_channel_pair.h b/mojo/edk/embedder/platform_channel_pair.h
index f80de89..9c93f76 100644
--- a/mojo/edk/embedder/platform_channel_pair.h
+++ b/mojo/edk/embedder/platform_channel_pair.h
@@ -69,6 +69,7 @@
   // |PrepareToPassClientHandleToChildProcess()| and launched the child (using
   // the provided data), to create a client handle connected to the server
   // handle (in the parent process).
+  // TODO(jcivelli): remove the command_line param. http://crbug.com/670106
   static ScopedPlatformHandle PassClientHandleFromParentProcess(
       const base::CommandLine& command_line);
 
diff --git a/mojo/edk/embedder/platform_channel_pair_posix.cc b/mojo/edk/embedder/platform_channel_pair_posix.cc
index 55f3ae24..4760e95 100644
--- a/mojo/edk/embedder/platform_channel_pair_posix.cc
+++ b/mojo/edk/embedder/platform_channel_pair_posix.cc
@@ -35,6 +35,15 @@
 
 namespace {
 
+#if defined(OS_ANDROID)
+enum {
+  // Leave room for any other descriptors defined in content for example.
+  // TODO(jcivelli): consider changing base::GlobalDescriptors to generate a
+  //   key when setting the file descriptor (http://crbug.com/676442).
+  kAndroidClientHandleDescriptor =
+      base::GlobalDescriptors::kBaseDescriptor + 10000,
+};
+#else
 bool IsTargetDescriptorUsed(
     const base::FileHandleMappingVector& file_handle_mapping,
     int target_fd) {
@@ -44,6 +53,7 @@
   }
   return false;
 }
+#endif
 
 }  // namespace
 
@@ -92,13 +102,21 @@
 PlatformChannelPair::PassClientHandleFromParentProcessFromString(
     const std::string& value) {
   int client_fd = -1;
+#if defined(OS_ANDROID)
+  base::GlobalDescriptors::Key key = -1;
+  if (value.empty() || !base::StringToUint(value, &key)) {
+    LOG(ERROR) << "Missing or invalid --" << kMojoPlatformChannelHandleSwitch;
+    return ScopedPlatformHandle();
+  }
+  client_fd = base::GlobalDescriptors::GetInstance()->Get(key);
+#else
   if (value.empty() ||
       !base::StringToInt(value, &client_fd) ||
       client_fd < base::GlobalDescriptors::kBaseDescriptor) {
     LOG(ERROR) << "Missing or invalid --" << kMojoPlatformChannelHandleSwitch;
     return ScopedPlatformHandle();
   }
-
+#endif
   return ScopedPlatformHandle(PlatformHandle(client_fd));
 }
 
@@ -124,6 +142,12 @@
 std::string
 PlatformChannelPair::PrepareToPassClientHandleToChildProcessAsString(
       HandlePassingInformation* handle_passing_info) const {
+#if defined(OS_ANDROID)
+  int fd = client_handle_.get().handle;
+  handle_passing_info->push_back(
+      std::pair<int, int>(fd, kAndroidClientHandleDescriptor));
+  return base::UintToString(kAndroidClientHandleDescriptor);
+#else
   DCHECK(handle_passing_info);
   // This is an arbitrary sanity check. (Note that this guarantees that the loop
   // below will terminate sanely.)
@@ -141,6 +165,7 @@
   handle_passing_info->push_back(
       std::pair<int, int>(client_handle_.get().handle, target_fd));
   return base::IntToString(target_fd);
+#endif
 }
 
 }  // namespace edk
diff --git a/mojo/edk/test/multiprocess_test_helper.cc b/mojo/edk/test/multiprocess_test_helper.cc
index 9aa9b0c..f5f9ce61a1 100644
--- a/mojo/edk/test/multiprocess_test_helper.cc
+++ b/mojo/edk/test/multiprocess_test_helper.cc
@@ -182,14 +182,8 @@
   CHECK(test_child_.IsValid());
 
   int rv = -1;
-#if defined(OS_ANDROID)
-  // On Android, we need to use a special function to wait for the child.
-  CHECK(AndroidWaitForChildExitWithTimeout(
-      test_child_, TestTimeouts::action_timeout(), &rv));
-#else
-  CHECK(
-      test_child_.WaitForExitWithTimeout(TestTimeouts::action_timeout(), &rv));
-#endif
+  WaitForMultiprocessTestChildExit(test_child_, TestTimeouts::action_timeout(),
+                                   &rv);
   test_child_.Close();
   return rv;
 }
diff --git a/mojo/edk/test/run_all_perftests.cc b/mojo/edk/test/run_all_perftests.cc
index f426a2a..8f2511f 100644
--- a/mojo/edk/test/run_all_perftests.cc
+++ b/mojo/edk/test/run_all_perftests.cc
@@ -13,10 +13,6 @@
 #include "mojo/public/tests/test_support_private.h"
 
 int main(int argc, char** argv) {
-#if defined(OS_ANDROID)
-  base::InitAndroidMultiProcessTestHelper(main);
-#endif
-
   base::PerfTestSuite test(argc, argv);
 
   mojo::edk::Init();
diff --git a/mojo/edk/test/run_all_unittests.cc b/mojo/edk/test/run_all_unittests.cc
index cd6b241..0b0663b 100644
--- a/mojo/edk/test/run_all_unittests.cc
+++ b/mojo/edk/test/run_all_unittests.cc
@@ -26,10 +26,6 @@
   testing::GTEST_FLAG(death_test_style) = "threadsafe";
 #endif
 #if defined(OS_ANDROID)
-  // Enable the alternate test child implementation. This is needed because Mojo
-  // tests need to spawn test children after initialising the Mojo system.
-  base::InitAndroidMultiProcessTestHelper(main);
-
   // On android, the test framework has a signal handler that will print a
   // [ CRASH ] line when the application crashes. This breaks death test has the
   // test runner will consider the death of the child process a test failure.
diff --git a/mojo/public/cpp/bindings/BUILD.gn b/mojo/public/cpp/bindings/BUILD.gn
index 70cec5ea..0244d3a 100644
--- a/mojo/public/cpp/bindings/BUILD.gn
+++ b/mojo/public/cpp/bindings/BUILD.gn
@@ -170,7 +170,6 @@
   # TODO(yzshen): crbug.com/617718 Consider moving this into blink.
   source_set("wtf_support") {
     sources = [
-      "array_traits_wtf.h",
       "array_traits_wtf_vector.h",
       "lib/string_traits_wtf.cc",
       "lib/wtf_clone_equals_util.h",
@@ -178,7 +177,6 @@
       "lib/wtf_serialization.h",
       "map_traits_wtf_hash_map.h",
       "string_traits_wtf.h",
-      "wtf_array.h",
     ]
 
     public_deps = [
diff --git a/mojo/public/cpp/bindings/array_traits_wtf.h b/mojo/public/cpp/bindings/array_traits_wtf.h
deleted file mode 100644
index 7e773fc..0000000
--- a/mojo/public/cpp/bindings/array_traits_wtf.h
+++ /dev/null
@@ -1,40 +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 MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_WTF_H_
-#define MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_WTF_H_
-
-#include "mojo/public/cpp/bindings/array_traits.h"
-#include "mojo/public/cpp/bindings/wtf_array.h"
-
-namespace mojo {
-
-template <typename U>
-struct ArrayTraits<WTFArray<U>> {
-  using Element = U;
-
-  static bool IsNull(const WTFArray<U>& input) { return input.is_null(); }
-  static void SetToNull(WTFArray<U>* output) { *output = nullptr; }
-
-  static size_t GetSize(const WTFArray<U>& input) { return input.size(); }
-
-  static U* GetData(WTFArray<U>& input) { return &input.front(); }
-
-  static const U* GetData(const WTFArray<U>& input) { return &input.front(); }
-
-  static U& GetAt(WTFArray<U>& input, size_t index) { return input[index]; }
-
-  static const U& GetAt(const WTFArray<U>& input, size_t index) {
-    return input[index];
-  }
-
-  static bool Resize(WTFArray<U>& input, size_t size) {
-    input.resize(size);
-    return true;
-  }
-};
-
-}  // namespace mojo
-
-#endif  // MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_WTF_H_
diff --git a/mojo/public/cpp/bindings/lib/wtf_serialization.h b/mojo/public/cpp/bindings/lib/wtf_serialization.h
index 40766bb..0f112b9 100644
--- a/mojo/public/cpp/bindings/lib/wtf_serialization.h
+++ b/mojo/public/cpp/bindings/lib/wtf_serialization.h
@@ -5,7 +5,6 @@
 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_SERIALIZATION_H_
 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_SERIALIZATION_H_
 
-#include "mojo/public/cpp/bindings/array_traits_wtf.h"
 #include "mojo/public/cpp/bindings/array_traits_wtf_vector.h"
 #include "mojo/public/cpp/bindings/map_traits_wtf_hash_map.h"
 #include "mojo/public/cpp/bindings/string_traits_wtf.h"
diff --git a/mojo/public/cpp/bindings/struct_traits.h b/mojo/public/cpp/bindings/struct_traits.h
index 0b48681..443ce149 100644
--- a/mojo/public/cpp/bindings/struct_traits.h
+++ b/mojo/public/cpp/bindings/struct_traits.h
@@ -34,7 +34,7 @@
 //        - array:
 //          Value or reference of any type that has an ArrayTraits defined.
 //          Supported by default: std::vector, CArray, mojo::Array, WTF::Vector
-//          (in blink), mojo::WTFArray (in blink).
+//          (in blink).
 //
 //        - map:
 //          Value or reference of any type that has a MapTraits defined.
diff --git a/mojo/public/cpp/bindings/tests/BUILD.gn b/mojo/public/cpp/bindings/tests/BUILD.gn
index f2697c6..f3a64b6 100644
--- a/mojo/public/cpp/bindings/tests/BUILD.gn
+++ b/mojo/public/cpp/bindings/tests/BUILD.gn
@@ -77,11 +77,9 @@
     testonly = true
 
     sources = [
-      "array_common_test.h",
       "container_test_util.cc",
       "container_test_util.h",
       "variant_test_util.h",
-      "wtf_array_unittest.cc",
       "wtf_hash_unittest.cc",
       "wtf_types_unittest.cc",
     ]
diff --git a/mojo/public/cpp/bindings/tests/wtf_array_unittest.cc b/mojo/public/cpp/bindings/tests/wtf_array_unittest.cc
deleted file mode 100644
index bb54b9c9..0000000
--- a/mojo/public/cpp/bindings/tests/wtf_array_unittest.cc
+++ /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 "mojo/public/cpp/bindings/wtf_array.h"
-
-#include "mojo/public/cpp/bindings/lib/serialization.h"
-#include "mojo/public/cpp/bindings/lib/wtf_serialization.h"
-#include "mojo/public/cpp/bindings/tests/array_common_test.h"
-#include "mojo/public/cpp/bindings/tests/container_test_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace test {
-namespace {
-
-using WTFArrayTest = testing::Test;
-
-ARRAY_COMMON_TEST(WTFArray, NullAndEmpty)
-ARRAY_COMMON_TEST(WTFArray, Basic)
-ARRAY_COMMON_TEST(WTFArray, Bool)
-ARRAY_COMMON_TEST(WTFArray, Handle)
-ARRAY_COMMON_TEST(WTFArray, HandlesAreClosed)
-ARRAY_COMMON_TEST(WTFArray, Clone)
-ARRAY_COMMON_TEST(WTFArray, Serialization_ArrayOfPOD)
-ARRAY_COMMON_TEST(WTFArray, Serialization_EmptyArrayOfPOD)
-ARRAY_COMMON_TEST(WTFArray, Serialization_ArrayOfArrayOfPOD)
-ARRAY_COMMON_TEST(WTFArray, Serialization_ArrayOfBool)
-ARRAY_COMMON_TEST(WTFArray, Serialization_ArrayOfString)
-ARRAY_COMMON_TEST(WTFArray, Resize_Copyable)
-ARRAY_COMMON_TEST(WTFArray, Resize_MoveOnly)
-
-TEST_F(WTFArrayTest, MoveFromAndToWTFVector_Copyable) {
-  WTF::Vector<CopyableType> vec1(1);
-  WTFArray<CopyableType> arr(std::move(vec1));
-  ASSERT_EQ(1u, arr.size());
-  ASSERT_FALSE(arr[0].copied());
-
-  WTF::Vector<CopyableType> vec2(arr.PassStorage());
-  ASSERT_EQ(1u, vec2.size());
-  ASSERT_FALSE(vec2[0].copied());
-
-  ASSERT_EQ(0u, arr.size());
-  ASSERT_TRUE(arr.is_null());
-}
-
-TEST_F(WTFArrayTest, MoveFromAndToWTFVector_MoveOnly) {
-  WTF::Vector<MoveOnlyType> vec1(1);
-  WTFArray<MoveOnlyType> arr(std::move(vec1));
-
-  ASSERT_EQ(1u, arr.size());
-
-  WTF::Vector<MoveOnlyType> vec2(arr.PassStorage());
-  ASSERT_EQ(1u, vec2.size());
-
-  ASSERT_EQ(0u, arr.size());
-  ASSERT_TRUE(arr.is_null());
-}
-
-}  // namespace
-}  // namespace test
-}  // namespace mojo
diff --git a/mojo/public/cpp/bindings/tests/wtf_types_unittest.cc b/mojo/public/cpp/bindings/tests/wtf_types_unittest.cc
index 8d9709c..9a20cc45 100644
--- a/mojo/public/cpp/bindings/tests/wtf_types_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/wtf_types_unittest.cc
@@ -106,29 +106,6 @@
 
 }  // namespace
 
-TEST_F(WTFTypesTest, Serialization_WTFArrayToWTFArray) {
-  using MojomType = ArrayDataView<StringDataView>;
-
-  WTFArray<WTF::String> strs = ConstructStringArray();
-  auto cloned_strs = strs.Clone();
-
-  mojo::internal::SerializationContext context;
-  size_t size =
-      mojo::internal::PrepareToSerialize<MojomType>(cloned_strs, &context);
-
-  mojo::internal::FixedBufferForTesting buf(size);
-  typename mojo::internal::MojomTypeTraits<MojomType>::Data* data;
-  mojo::internal::ContainerValidateParams validate_params(
-      0, true, new mojo::internal::ContainerValidateParams(0, false, nullptr));
-  mojo::internal::Serialize<MojomType>(cloned_strs, &buf, &data,
-                                       &validate_params, &context);
-
-  WTFArray<WTF::String> strs2;
-  mojo::internal::Deserialize<MojomType>(data, &strs2, &context);
-
-  EXPECT_TRUE(strs.Equals(strs2));
-}
-
 TEST_F(WTFTypesTest, Serialization_WTFVectorToWTFVector) {
   using MojomType = ArrayDataView<StringDataView>;
 
@@ -152,22 +129,24 @@
   EXPECT_EQ(strs, strs2);
 }
 
-TEST_F(WTFTypesTest, Serialization_WTFArrayToMojoArray) {
+TEST_F(WTFTypesTest, Serialization_WTFVectorToStlVector) {
   using MojomType = ArrayDataView<StringDataView>;
 
-  WTFArray<WTF::String> strs = ConstructStringArray();
+  WTF::Vector<WTF::String> strs = ConstructStringArray();
+  auto cloned_strs = strs;
 
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<MojomType>(strs, &context);
+  size_t size =
+      mojo::internal::PrepareToSerialize<MojomType>(cloned_strs, &context);
 
   mojo::internal::FixedBufferForTesting buf(size);
   typename mojo::internal::MojomTypeTraits<MojomType>::Data* data;
   mojo::internal::ContainerValidateParams validate_params(
       0, true, new mojo::internal::ContainerValidateParams(0, false, nullptr));
-  mojo::internal::Serialize<MojomType>(strs, &buf, &data, &validate_params,
-                                       &context);
+  mojo::internal::Serialize<MojomType>(cloned_strs, &buf, &data,
+                                       &validate_params, &context);
 
-  Array<base::Optional<std::string>> strs2;
+  std::vector<base::Optional<std::string>> strs2;
   mojo::internal::Deserialize<MojomType>(data, &strs2, &context);
 
   ASSERT_EQ(4u, strs2.size());
diff --git a/mojo/public/cpp/bindings/wtf_array.h b/mojo/public/cpp/bindings/wtf_array.h
deleted file mode 100644
index 5964f2a..0000000
--- a/mojo/public/cpp/bindings/wtf_array.h
+++ /dev/null
@@ -1,197 +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 MOJO_PUBLIC_CPP_BINDINGS_WTF_ARRAY_H_
-#define MOJO_PUBLIC_CPP_BINDINGS_WTF_ARRAY_H_
-
-#include <stddef.h>
-#include <utility>
-
-#include "base/macros.h"
-#include "mojo/public/cpp/bindings/lib/array_internal.h"
-#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
-#include "mojo/public/cpp/bindings/lib/template_util.h"
-#include "mojo/public/cpp/bindings/lib/wtf_clone_equals_util.h"
-#include "mojo/public/cpp/bindings/type_converter.h"
-#include "third_party/WebKit/Source/wtf/Vector.h"
-
-namespace mojo {
-
-// Represents an array backed by WTF::Vector. Comparing with WTF::Vector,
-// mojo::WTFArray is move-only and can be null.
-// It is easy to convert between WTF::Vector<T> and mojo::WTFArray<T>:
-//   - constructor WTFArray(WTF::Vector<T>&&) takes the contents of a
-//     WTF::Vector<T>;
-//   - method PassStorage() passes the underlying WTF::Vector.
-template <typename T>
-class WTFArray {
- public:
-  // Constructs an empty array.
-  WTFArray() : is_null_(false) {}
-  // Constructs a null array.
-  WTFArray(std::nullptr_t null_pointer) : is_null_(true) {}
-
-  // Constructs a new non-null array of the specified size. The elements will
-  // be value-initialized (meaning that they will be initialized by their
-  // default constructor, if any, or else zero-initialized).
-  explicit WTFArray(size_t size) : vec_(size), is_null_(false) {}
-  ~WTFArray() {}
-
-  // Moves the contents of |other| into this array.
-  WTFArray(WTF::Vector<T>&& other) : vec_(std::move(other)), is_null_(false) {}
-  WTFArray(WTFArray&& other) : is_null_(true) { Take(&other); }
-
-  WTFArray& operator=(WTF::Vector<T>&& other) {
-    vec_ = std::move(other);
-    is_null_ = false;
-    return *this;
-  }
-  WTFArray& operator=(WTFArray&& other) {
-    Take(&other);
-    return *this;
-  }
-
-  WTFArray& operator=(std::nullptr_t null_pointer) {
-    is_null_ = true;
-    vec_.clear();
-    return *this;
-  }
-
-  // Creates a non-null array of the specified size. The elements will be
-  // value-initialized (meaning that they will be initialized by their default
-  // constructor, if any, or else zero-initialized).
-  static WTFArray New(size_t size) { return WTFArray(size); }
-
-  // Creates a new array with a copy of the contents of |other|.
-  template <typename U>
-  static WTFArray From(const U& other) {
-    return TypeConverter<WTFArray, U>::Convert(other);
-  }
-
-  // Copies the contents of this array to a new object of type |U|.
-  template <typename U>
-  U To() const {
-    return TypeConverter<U, WTFArray>::Convert(*this);
-  }
-
-  // Indicates whether the array is null (which is distinct from empty).
-  bool is_null() const {
-    // When the array is set to null, the underlying storage |vec_| shouldn't
-    // contain any elements.
-    DCHECK(!is_null_ || vec_.isEmpty());
-    return is_null_;
-  }
-
-  // Indicates whether the array is empty (which is distinct from null).
-  bool empty() const { return vec_.isEmpty() && !is_null_; }
-
-  // Returns a reference to the first element of the array. Calling this on a
-  // null or empty array causes undefined behavior.
-  const T& front() const { return vec_.front(); }
-  T& front() { return vec_.front(); }
-
-  // Returns the size of the array, which will be zero if the array is null.
-  size_t size() const { return vec_.size(); }
-
-  // Returns a reference to the element at zero-based |offset|. Calling this on
-  // an array with size less than |offset|+1 causes undefined behavior.
-  const T& at(size_t offset) const { return vec_.at(offset); }
-  const T& operator[](size_t offset) const { return at(offset); }
-  T& at(size_t offset) { return vec_.at(offset); }
-  T& operator[](size_t offset) { return at(offset); }
-
-  // Resizes the array to |size| and makes it non-null. Otherwise, works just
-  // like the resize method of |WTF::Vector|.
-  void resize(size_t size) {
-    is_null_ = false;
-    vec_.resize(size);
-  }
-
-  // Sets the array to empty (even if previously it was null.)
-  void SetToEmpty() { resize(0); }
-
-  // Returns a const reference to the |WTF::Vector| managed by this class. If
-  // the array is null, this will be an empty vector.
-  const WTF::Vector<T>& storage() const { return vec_; }
-
-  // Passes the underlying storage and resets this array to null.
-  //
-  // TODO(yzshen): Consider changing this to a rvalue-ref-qualified conversion
-  // to WTF::Vector<T> after we move to MSVC 2015.
-  WTF::Vector<T> PassStorage() {
-    is_null_ = true;
-    return std::move(vec_);
-  }
-
-  void Swap(WTFArray* other) {
-    std::swap(is_null_, other->is_null_);
-    vec_.swap(other->vec_);
-  }
-
-  // Swaps the contents of this array with the specified vector, making this
-  // array non-null. Since the vector cannot represent null, it will just be
-  // made empty if this array is null.
-  void Swap(WTF::Vector<T>* other) {
-    is_null_ = false;
-    vec_.swap(*other);
-  }
-
-  // Returns a copy of the array where each value of the new array has been
-  // "cloned" from the corresponding value of this array. If the element type
-  // defines a Clone() method, it will be used; otherwise copy
-  // constructor/assignment will be used.
-  //
-  // Please note that calling this method will fail compilation if the element
-  // type cannot be cloned (which usually means that it is a Mojo handle type or
-  // a type containing Mojo handles).
-  WTFArray Clone() const {
-    WTFArray result;
-    result.is_null_ = is_null_;
-    result.vec_ = internal::Clone(vec_);
-    return result;
-  }
-
-  // Indicates whether the contents of this array are equal to |other|. A null
-  // array is only equal to another null array. If the element type defines an
-  // Equals() method, it will be used; otherwise == operator will be used.
-  bool Equals(const WTFArray& other) const {
-    if (is_null() != other.is_null())
-      return false;
-    return internal::Equals(vec_, other.vec_);
-  }
-
- private:
-  // TODO(dcheng): Use an explicit conversion operator.
-  typedef WTF::Vector<T> WTFArray::*Testable;
-
- public:
-  operator Testable() const {
-    // When the array is set to null, the underlying storage |vec_| shouldn't
-    // contain any elements.
-    DCHECK(!is_null_ || vec_.isEmpty());
-    return is_null_ ? 0 : &WTFArray::vec_;
-  }
-
- private:
-  // Forbid the == and != operators explicitly, otherwise WTFArray will be
-  // converted to Testable to do == or != comparison.
-  template <typename U>
-  bool operator==(const WTFArray<U>& other) const = delete;
-  template <typename U>
-  bool operator!=(const WTFArray<U>& other) const = delete;
-
-  void Take(WTFArray* other) {
-    operator=(nullptr);
-    Swap(other);
-  }
-
-  WTF::Vector<T> vec_;
-  bool is_null_;
-
-  DISALLOW_COPY_AND_ASSIGN(WTFArray);
-};
-
-}  // namespace mojo
-
-#endif  // MOJO_PUBLIC_CPP_BINDINGS_WTF_ARRAY_H_
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl
index 031e21d5..cc55f8e 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl
@@ -71,7 +71,6 @@
 {# hash_util.h includes template specializations that should be present for
    every use of {Inlined}StructPtr. #}
 #include "mojo/public/cpp/bindings/lib/wtf_hash_util.h"
-#include "mojo/public/cpp/bindings/wtf_array.h"
 #include "third_party/WebKit/Source/wtf/HashFunctions.h"
 #include "third_party/WebKit/Source/wtf/Optional.h"
 #include "third_party/WebKit/Source/wtf/text/WTFString.h"
diff --git a/net/cert/cert_verify_proc.h b/net/cert/cert_verify_proc.h
index 5befe24..81cebd6 100644
--- a/net/cert/cert_verify_proc.h
+++ b/net/cert/cert_verify_proc.h
@@ -89,9 +89,17 @@
                            VerifyRejectsSHA1AfterDeprecationLegacyMode);
 
   // Performs the actual verification using the desired underlying
-  // cryptographic library. On entry, |verify_result->verified_cert|
-  // is set to |cert|, the unverified chain. If no chain is built, the
-  // value must be left untouched.
+  //
+  // On entry, |verify_result| will be default-initialized as a successful
+  // validation, with |verify_result->verified_cert| set to |cert|.
+  //
+  // Implementations are expected to fill in all applicable fields, excluding
+  // |ocsp_result|, which will be filled in by |Verify()|. If an error code is
+  // returned, |verify_result->cert_status| should be non-zero, indicating an
+  // error occurred.
+  //
+  // On success, net::OK should be returned, with |verify_result| updated to
+  // reflect the successfully verified chain.
   virtual int VerifyInternal(X509Certificate* cert,
                              const std::string& hostname,
                              const std::string& ocsp_response,
diff --git a/net/cert/cert_verify_result.h b/net/cert/cert_verify_result.h
index 29c0675..f8e0ded 100644
--- a/net/cert/cert_verify_result.h
+++ b/net/cert/cert_verify_result.h
@@ -26,14 +26,25 @@
 
   void Reset();
 
+  // Comparing CertVerifyResult with a nullptr |verified_cert| is invalid.
   bool operator==(const CertVerifyResult& other) const;
 
-  // The certificate and chain that was constructed during verification.
-  // Note that the though the verified certificate will match the originally
-  // supplied certificate, the intermediate certificates stored within may
-  // be substantially different. In the event of a verification failure, this
-  // will contain the chain as supplied by the server. This may be NULL if
-  // running within the sandbox.
+  // The certificate chain that was constructed during verification.
+  //
+  // Note: Although |verified_cert| will match the originally supplied
+  // certificate to be validated, the results of GetIntermediateCertificates()
+  // may be substantially different, both in order and in content, then the
+  // originally supplied intermediates.
+  //
+  // In the event of validation failures, this may contain the originally
+  // supplied certificate chain or a partially constructed path, depending on
+  // the implementation.
+  //
+  // In the event of validation success, the trust anchor will be
+  // |verified_cert->GetIntermediateCertificates().back()| if
+  // there was a certificate chain to the trust anchor, and will
+  // be |verified_cert->os_cert_handle()| if the certificate was
+  // the trust anchor.
   scoped_refptr<X509Certificate> verified_cert;
 
   // Bitmask of CERT_STATUS_* from net/cert/cert_status_flags.h. Note that
diff --git a/services/ui/DEPS b/services/ui/DEPS
index d2bf7702..f94329ae 100644
--- a/services/ui/DEPS
+++ b/services/ui/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
   "+cc",
+  "+chromeos/system",
   "+components/discardable_memory/service",
   "+components/discardable_memory/public",
   "+ipc",
diff --git a/services/ui/display/BUILD.gn b/services/ui/display/BUILD.gn
index 0e05b07..cda9627f 100644
--- a/services/ui/display/BUILD.gn
+++ b/services/ui/display/BUILD.gn
@@ -28,6 +28,7 @@
     ]
 
     deps += [
+      "//chromeos",
       "//services/ui/public/interfaces/display",
       "//skia",
       "//ui/display/manager",
diff --git a/services/ui/display/screen_manager_ozone.cc b/services/ui/display/screen_manager_ozone.cc
index 0a106f3..e48d6a1 100644
--- a/services/ui/display/screen_manager_ozone.cc
+++ b/services/ui/display/screen_manager_ozone.cc
@@ -9,8 +9,8 @@
 
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
-#include "base/sys_info.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "chromeos/system/devicemode.h"
 #include "services/service_manager/public/cpp/interface_registry.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/display/manager/chromeos/display_change_observer.h"
@@ -148,7 +148,7 @@
 
   // The FakeDisplayController gives us a way to make the NativeDisplayDelegate
   // pretend something display related has happened.
-  if (!base::SysInfo::IsRunningOnChromeOS()) {
+  if (!chromeos::IsRunningAsSystemCompositor()) {
     fake_display_controller_ =
         native_display_delegate_->GetFakeDisplayController();
   }
diff --git a/services/ui/public/interfaces/mus_constants.mojom b/services/ui/public/interfaces/mus_constants.mojom
index 4897e42..e3f9af2 100644
--- a/services/ui/public/interfaces/mus_constants.mojom
+++ b/services/ui/public/interfaces/mus_constants.mojom
@@ -7,9 +7,4 @@
 enum OrderDirection {
   ABOVE = 1,
   BELOW,
-};
-
-// If this property is present on a window then the window is only shown once
-// the underlay has been provided. This property is only checked once at
-// construction time.
-const string kWaitForUnderlay_Property = "property:wait-for-underlay";
+};
\ No newline at end of file
diff --git a/services/ui/ws/frame_generator.cc b/services/ui/ws/frame_generator.cc
index c4c309b..7f8e788 100644
--- a/services/ui/ws/frame_generator.cc
+++ b/services/ui/ws/frame_generator.cc
@@ -159,8 +159,7 @@
   if (!window || !window->visible())
     return;
 
-  if (!window->compositor_frame_sink_manager() ||
-      !window->compositor_frame_sink_manager()->ShouldDraw())
+  if (!window->compositor_frame_sink_manager())
     return;
 
   cc::SurfaceId default_surface_id =
diff --git a/services/ui/ws/server_window_compositor_frame_sink_manager.cc b/services/ui/ws/server_window_compositor_frame_sink_manager.cc
index b55d0a89..c3410b3b 100644
--- a/services/ui/ws/server_window_compositor_frame_sink_manager.cc
+++ b/services/ui/ws/server_window_compositor_frame_sink_manager.cc
@@ -15,24 +15,12 @@
 
 ServerWindowCompositorFrameSinkManager::ServerWindowCompositorFrameSinkManager(
     ServerWindow* window)
-    : window_(window),
-      waiting_for_initial_frames_(
-          window_->properties().count(ui::mojom::kWaitForUnderlay_Property) >
-          0) {}
+    : window_(window) {}
 
 ServerWindowCompositorFrameSinkManager::
     ~ServerWindowCompositorFrameSinkManager() {
 }
 
-bool ServerWindowCompositorFrameSinkManager::ShouldDraw() {
-  if (!waiting_for_initial_frames_)
-    return true;
-
-  waiting_for_initial_frames_ = !IsCompositorFrameSinkReadyAndNonEmpty(
-      mojom::CompositorFrameSinkType::DEFAULT);
-  return !waiting_for_initial_frames_;
-}
-
 void ServerWindowCompositorFrameSinkManager::CreateDisplayCompositorFrameSink(
     gfx::AcceleratedWidget widget,
     cc::mojom::MojoCompositorFrameSinkRequest request,
diff --git a/services/ui/ws/server_window_compositor_frame_sink_manager.h b/services/ui/ws/server_window_compositor_frame_sink_manager.h
index eb21737..69055d56 100644
--- a/services/ui/ws/server_window_compositor_frame_sink_manager.h
+++ b/services/ui/ws/server_window_compositor_frame_sink_manager.h
@@ -45,9 +45,6 @@
   explicit ServerWindowCompositorFrameSinkManager(ServerWindow* window);
   ~ServerWindowCompositorFrameSinkManager();
 
-  // Returns true if the CompositorFrameSinks from this manager should be drawn.
-  bool ShouldDraw();
-
   // Creates a new CompositorFrameSink of the specified type, replacing the
   // existing one of the specified type.
   void CreateDisplayCompositorFrameSink(
@@ -109,15 +106,6 @@
 
   TypeToCompositorFrameSinkMap type_to_compositor_frame_sink_map_;
 
-  // TODO(mfomitchev): This is currently always false. Confirm if we still need
-  // this.
-  // While true the window is not drawn. This is initially true if the window
-  // has the property |kWaitForUnderlay_Property|. This is set to false once
-  // the underlay and default surface have been set *and* their size is at
-  // least that of the window. Ideally we would wait for sizes to match, but
-  // the underlay is not necessarily as big as the window.
-  bool waiting_for_initial_frames_;
-
   DISALLOW_COPY_AND_ASSIGN(ServerWindowCompositorFrameSinkManager);
 };
 
diff --git a/testing/android/native_test/BUILD.gn b/testing/android/native_test/BUILD.gn
index f08a8d1..728cec0 100644
--- a/testing/android/native_test/BUILD.gn
+++ b/testing/android/native_test/BUILD.gn
@@ -7,6 +7,8 @@
 source_set("native_test_support") {
   testonly = true
   sources = [
+    "main_runner.cc",
+    "main_runner.h",
     "native_test_launcher.cc",
     "native_test_launcher.h",
     "native_test_util.cc",
@@ -33,9 +35,18 @@
   ]
 }
 
+android_library("native_main_runner_java") {
+  testonly = true
+  java_files = [ "java/src/org/chromium/native_test/MainRunner.java" ]
+  deps = [
+    "//base:base_java",
+  ]
+}
+
 android_library("native_test_java") {
   testonly = true
   deps = [
+    ":native_main_runner_java",
     "//base:base_java",
     "//base:base_java_test_support",
     "//testing/android/appurify_support:appurify_support_java",
@@ -53,6 +64,7 @@
 
 generate_jni("native_test_jni_headers") {
   sources = [
+    "java/src/org/chromium/native_test/MainRunner.java",
     "java/src/org/chromium/native_test/NativeTest.java",
   ]
   jni_package = "testing"
diff --git a/testing/android/native_test/java/AndroidManifest.xml.jinja2 b/testing/android/native_test/java/AndroidManifest.xml.jinja2
index cdd7b544..c465cac7 100644
--- a/testing/android/native_test/java/AndroidManifest.xml.jinja2
+++ b/testing/android/native_test/java/AndroidManifest.xml.jinja2
@@ -47,6 +47,18 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
+
+        <!-- If you change the number below, make sure to add/remove actual service classes
+             org/chromium/base/MultiprocessTestClientService*.java -->
+        {% set num_test_client_services = 5 %}
+        <meta-data android:name="org.chromium.native_test.NUM_TEST_CLIENT_SERVICES"
+                   android:value="{{ num_test_client_services }}"/>
+        {% for i in range(num_test_client_services) %}
+        <service android:name="org.chromium.base.MultiprocessTestClientService{{ i }}"
+                 android:process=":test_client_process{{ i }}"
+                 android:isolatedProcess="false"
+                 android:exported="false" />
+        {% endfor %}
     </application>
 
     <instrumentation android:name="org.chromium.native_test.NativeTestInstrumentationTestRunner"
diff --git a/testing/android/native_test/java/src/org/chromium/native_test/MainRunner.java b/testing/android/native_test/java/src/org/chromium/native_test/MainRunner.java
new file mode 100644
index 0000000..94aaeef12
--- /dev/null
+++ b/testing/android/native_test/java/src/org/chromium/native_test/MainRunner.java
@@ -0,0 +1,27 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.native_test;
+
+import org.chromium.base.annotations.JNINamespace;
+
+/**
+ * This class provides a way to run the native main method.
+ * It is used in the multi-process test case, so that the child process can call
+ * the main method without //base/test:test_support's linkage requiring the
+ * main() symbol.
+ */
+@JNINamespace("testing::android")
+public final class MainRunner {
+    // Prevent instanciation.
+    private MainRunner() {
+    }
+
+    // Maps the file descriptors and executes the main method with the passed in command line.
+    public static int runMain(String[] commandLine, int[] fdsToMapKeys, int[] fdsToMapFds) {
+        return nativeRunMain(commandLine, fdsToMapKeys, fdsToMapFds);
+    }
+    private static native int nativeRunMain(
+            String[] commandLine, int[] fdsToMapKeys, int[] fdsToMapFds);
+}
\ No newline at end of file
diff --git a/testing/android/native_test/main_runner.cc b/testing/android/native_test/main_runner.cc
new file mode 100644
index 0000000..629721f
--- /dev/null
+++ b/testing/android/native_test/main_runner.cc
@@ -0,0 +1,56 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <vector>
+
+#include "base/android/jni_array.h"
+#include "base/logging.h"
+#include "base/posix/global_descriptors.h"
+#include "jni/MainRunner_jni.h"
+
+extern int main(int argc, char** argv);
+
+namespace testing {
+namespace android {
+
+bool RegisterMainRunnerJni(JNIEnv* env) {
+  return RegisterNativesImpl(env);
+}
+
+static jint RunMain(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jclass>& jcaller,
+    const base::android::JavaParamRef<jobjectArray>& command_line,
+    const base::android::JavaParamRef<jintArray>& fds_to_map_keys,
+    const base::android::JavaParamRef<jintArray>& fds_to_map_fds) {
+  // Guards against process being reused.
+  // In most cases, running main again will cause problems (static variables,
+  // singletons, lazy instances won't be in the same state as a clean run).
+  static bool alreadyRun = false;
+  CHECK(!alreadyRun);
+  alreadyRun = true;
+
+  std::vector<int> keys;
+  base::android::JavaIntArrayToIntVector(env, fds_to_map_keys, &keys);
+  std::vector<int> fds;
+  base::android::JavaIntArrayToIntVector(env, fds_to_map_fds, &fds);
+  CHECK_EQ(keys.size(), fds.size());
+
+  for (size_t i = 0; i < keys.size(); i++) {
+    base::GlobalDescriptors::GetInstance()->Set(keys[i], fds[i]);
+  }
+
+  std::vector<std::string> cpp_command_line;
+  AppendJavaStringArrayToStringVector(env, command_line, &cpp_command_line);
+
+  std::vector<char*> c_command_line;
+  for (auto& entry : cpp_command_line) {
+    c_command_line.push_back(&entry[0]);
+  }
+
+  return main(c_command_line.size(), &c_command_line[0]);
+}
+
+}  // namespace android
+}  // namespace testing
diff --git a/testing/android/native_test/main_runner.h b/testing/android/native_test/main_runner.h
new file mode 100644
index 0000000..acd499b
--- /dev/null
+++ b/testing/android/native_test/main_runner.h
@@ -0,0 +1,18 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TESTING_ANDROID_NATIVE_TEST_MAIN_RUNNER_H_
+#define TESTING_ANDROID_NATIVE_TEST_MAIN_RUNNER_H_
+
+#include <jni.h>
+
+namespace testing {
+namespace android {
+
+bool RegisterMainRunnerJni(JNIEnv* env);
+
+}  // namespace android
+}  // namespace testing
+
+#endif  // TESTING_ANDROID_NATIVE_TEST_MAIN_RUNNER_H_
diff --git a/testing/android/native_test/native_test_launcher.cc b/testing/android/native_test/native_test_launcher.cc
index 9547216..72e75db7 100644
--- a/testing/android/native_test/native_test_launcher.cc
+++ b/testing/android/native_test/native_test_launcher.cc
@@ -26,6 +26,7 @@
 #include "base/test/test_support_android.h"
 #include "gtest/gtest.h"
 #include "jni/NativeTest_jni.h"
+#include "testing/android/native_test/main_runner.h"
 #include "testing/android/native_test/native_test_util.h"
 
 using base::android::JavaParamRef;
@@ -127,9 +128,10 @@
 }
 
 bool RegisterNativeTestJNI(JNIEnv* env) {
-  if (!base::android::RegisterJni(env)) {
+  if (!base::android::RegisterJni(env))
     return false;
-  }
+  if (!RegisterMainRunnerJni(env))
+    return false;
   return RegisterNativesImpl(env);
 }
 
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json
index 8083fda..d355317a 100644
--- a/testing/buildbot/chromium.gpu.fyi.json
+++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -2086,6 +2086,360 @@
       "All"
     ]
   },
+  "Linux Debug (Intel HD 530)": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--use-gpu-in-tests",
+          "--test-launcher-retry-limit=0"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        },
+        "test": "angle_end2end_tests",
+        "use_xvfb": false
+      },
+      {
+        "args": [
+          "--use-gpu-in-tests",
+          "--test-launcher-retry-limit=0"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        },
+        "test": "angle_unittests",
+        "use_xvfb": false
+      },
+      {
+        "args": [
+          "--use-gpu-in-tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        },
+        "test": "audio_unittests",
+        "use_xvfb": false
+      },
+      {
+        "args": [
+          "--use-gpu-in-tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        },
+        "test": "gl_tests",
+        "use_xvfb": false
+      },
+      {
+        "args": [
+          "--use-gpu-in-tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        },
+        "test": "gl_unittests",
+        "use_xvfb": false
+      },
+      {
+        "args": [
+          "--use-gpu-in-tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        },
+        "test": "gles2_conform_test",
+        "use_xvfb": false
+      }
+    ],
+    "isolated_scripts": [
+      {
+        "args": [
+          "context_lost",
+          "--show-stdout",
+          "--browser=debug",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "context_lost_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "depth_capture",
+          "--show-stdout",
+          "--browser=debug",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "depth_capture_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "gpu_process",
+          "--show-stdout",
+          "--browser=debug",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "gpu_process_launch_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "hardware_accelerated_feature",
+          "--show-stdout",
+          "--browser=debug",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "hardware_accelerated_feature_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "maps",
+          "--show-stdout",
+          "--browser=debug",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--os-type",
+          "linux",
+          "--build-revision",
+          "${got_revision}",
+          "--test-machine-name",
+          "${buildername}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "maps_pixel_test",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "pixel",
+          "--show-stdout",
+          "--browser=debug",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--refimg-cloud-storage-bucket",
+          "chromium-gpu-archive/reference-images",
+          "--os-type",
+          "linux",
+          "--build-revision",
+          "${got_revision}",
+          "--test-machine-name",
+          "${buildername}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "pixel_test",
+        "non_precommit_args": [
+          "--upload-refimg-to-cloud-storage"
+        ],
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "precommit_args": [
+          "--download-refimg-from-cloud-storage"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "screenshot_sync",
+          "--show-stdout",
+          "--browser=debug",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "screenshot_sync_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "trace_test",
+          "--show-stdout",
+          "--browser=debug",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "trace_test",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=debug",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "webgl_conformance_angle_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=debug",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "webgl_conformance_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        }
+      }
+    ]
+  },
   "Linux Debug (NVIDIA)": {
     "gtest_tests": [
       {
@@ -3973,6 +4327,399 @@
       }
     ]
   },
+  "Linux Release (Intel HD 530)": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--use-gpu-in-tests",
+          "--test-launcher-retry-limit=0"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        },
+        "test": "angle_end2end_tests",
+        "use_xvfb": false
+      },
+      {
+        "args": [
+          "--use-gpu-in-tests",
+          "--test-launcher-retry-limit=0"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        },
+        "test": "angle_unittests",
+        "use_xvfb": false
+      },
+      {
+        "args": [
+          "--use-gpu-in-tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        },
+        "test": "audio_unittests",
+        "use_xvfb": false
+      },
+      {
+        "args": [
+          "--enable-gpu",
+          "--test-launcher-jobs=1",
+          "--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*"
+        ],
+        "name": "tab_capture_end2end_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "browser_tests",
+        "use_xvfb": false
+      },
+      {
+        "args": [
+          "--use-gpu-in-tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        },
+        "test": "gl_tests",
+        "use_xvfb": false
+      },
+      {
+        "args": [
+          "--use-gpu-in-tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        },
+        "test": "gl_unittests",
+        "use_xvfb": false
+      },
+      {
+        "args": [
+          "--use-gpu-in-tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        },
+        "test": "gles2_conform_test",
+        "use_xvfb": false
+      }
+    ],
+    "isolated_scripts": [
+      {
+        "args": [
+          "context_lost",
+          "--show-stdout",
+          "--browser=release",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "context_lost_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "depth_capture",
+          "--show-stdout",
+          "--browser=release",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "depth_capture_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "gpu_process",
+          "--show-stdout",
+          "--browser=release",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "gpu_process_launch_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "hardware_accelerated_feature",
+          "--show-stdout",
+          "--browser=release",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "hardware_accelerated_feature_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "maps",
+          "--show-stdout",
+          "--browser=release",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--os-type",
+          "linux",
+          "--build-revision",
+          "${got_revision}",
+          "--test-machine-name",
+          "${buildername}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "maps_pixel_test",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "pixel",
+          "--show-stdout",
+          "--browser=release",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--refimg-cloud-storage-bucket",
+          "chromium-gpu-archive/reference-images",
+          "--os-type",
+          "linux",
+          "--build-revision",
+          "${got_revision}",
+          "--test-machine-name",
+          "${buildername}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "pixel_test",
+        "non_precommit_args": [
+          "--upload-refimg-to-cloud-storage"
+        ],
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "precommit_args": [
+          "--download-refimg-from-cloud-storage"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "screenshot_sync",
+          "--show-stdout",
+          "--browser=release",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "screenshot_sync_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "trace_test",
+          "--show-stdout",
+          "--browser=release",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "trace_test",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=release",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--webgl-conformance-version=2.0.1",
+          "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "webgl2_conformance_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ],
+          "shards": 15
+        }
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=release",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "webgl_conformance_angle_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=release",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "webgl_conformance_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Linux"
+            }
+          ]
+        }
+      }
+    ]
+  },
   "Linux Release (NVIDIA GeForce 730)": {
     "gtest_tests": [
       {
@@ -9666,6 +10413,459 @@
       }
     ]
   },
+  "Win10 Debug (Intel HD 530)": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--use-gpu-in-tests",
+          "--test-launcher-retry-limit=0"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        },
+        "test": "angle_end2end_tests",
+        "use_xvfb": false
+      },
+      {
+        "args": [
+          "--use-gpu-in-tests",
+          "--test-launcher-retry-limit=0"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        },
+        "test": "angle_unittests",
+        "use_xvfb": false
+      },
+      {
+        "args": [
+          "--use-gpu-in-tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        },
+        "test": "audio_unittests",
+        "use_xvfb": false
+      },
+      {
+        "args": [
+          "--use-gpu-in-tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        },
+        "test": "gl_tests",
+        "use_xvfb": false
+      },
+      {
+        "args": [
+          "--use-gpu-in-tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        },
+        "test": "gl_unittests",
+        "use_xvfb": false
+      },
+      {
+        "args": [
+          "--use-gpu-in-tests",
+          "--use-angle=d3d9"
+        ],
+        "name": "gles2_conform_d3d9_test",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        },
+        "test": "gles2_conform_test",
+        "use_xvfb": false
+      },
+      {
+        "args": [
+          "--use-gpu-in-tests",
+          "--use-angle=gl",
+          "--disable-gpu-sandbox"
+        ],
+        "name": "gles2_conform_gl_test",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        },
+        "test": "gles2_conform_test",
+        "use_xvfb": false
+      },
+      {
+        "args": [
+          "--use-gpu-in-tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        },
+        "test": "gles2_conform_test",
+        "use_xvfb": false
+      },
+      {
+        "args": [
+          "--use-test-data-path"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        },
+        "test": "video_decode_accelerator_unittest",
+        "use_xvfb": false
+      }
+    ],
+    "isolated_scripts": [
+      {
+        "args": [
+          "context_lost",
+          "--show-stdout",
+          "--browser=debug",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "context_lost_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "depth_capture",
+          "--show-stdout",
+          "--browser=debug",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "depth_capture_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "gpu_process",
+          "--show-stdout",
+          "--browser=debug",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "gpu_process_launch_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "hardware_accelerated_feature",
+          "--show-stdout",
+          "--browser=debug",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "hardware_accelerated_feature_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "maps",
+          "--show-stdout",
+          "--browser=debug",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--os-type",
+          "win",
+          "--build-revision",
+          "${got_revision}",
+          "--test-machine-name",
+          "${buildername}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "maps_pixel_test",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "pixel",
+          "--show-stdout",
+          "--browser=debug",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--refimg-cloud-storage-bucket",
+          "chromium-gpu-archive/reference-images",
+          "--os-type",
+          "win",
+          "--build-revision",
+          "${got_revision}",
+          "--test-machine-name",
+          "${buildername}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "pixel_test",
+        "non_precommit_args": [
+          "--upload-refimg-to-cloud-storage"
+        ],
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "precommit_args": [
+          "--download-refimg-from-cloud-storage"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "screenshot_sync",
+          "--show-stdout",
+          "--browser=debug",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "screenshot_sync_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "trace_test",
+          "--show-stdout",
+          "--browser=debug",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "trace_test",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=debug",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d11 --use-passthrough-cmd-decoder"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "webgl_conformance_d3d11_passthrough_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=debug",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d9"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "webgl_conformance_d3d9_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=debug",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=gl"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "webgl_conformance_gl_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=debug",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "webgl_conformance_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        }
+      }
+    ]
+  },
   "Win10 Debug (NVIDIA)": {
     "gtest_tests": [
       {
@@ -10572,6 +11772,498 @@
       }
     ]
   },
+  "Win10 Release (Intel HD 530)": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--use-gpu-in-tests",
+          "--test-launcher-retry-limit=0"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        },
+        "test": "angle_end2end_tests",
+        "use_xvfb": false
+      },
+      {
+        "args": [
+          "--use-gpu-in-tests",
+          "--test-launcher-retry-limit=0"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        },
+        "test": "angle_unittests",
+        "use_xvfb": false
+      },
+      {
+        "args": [
+          "--use-gpu-in-tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        },
+        "test": "audio_unittests",
+        "use_xvfb": false
+      },
+      {
+        "args": [
+          "--enable-gpu",
+          "--test-launcher-jobs=1",
+          "--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*"
+        ],
+        "name": "tab_capture_end2end_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "browser_tests",
+        "use_xvfb": false
+      },
+      {
+        "args": [
+          "--use-gpu-in-tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        },
+        "test": "gl_tests",
+        "use_xvfb": false
+      },
+      {
+        "args": [
+          "--use-gpu-in-tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        },
+        "test": "gl_unittests",
+        "use_xvfb": false
+      },
+      {
+        "args": [
+          "--use-gpu-in-tests",
+          "--use-angle=d3d9"
+        ],
+        "name": "gles2_conform_d3d9_test",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        },
+        "test": "gles2_conform_test",
+        "use_xvfb": false
+      },
+      {
+        "args": [
+          "--use-gpu-in-tests",
+          "--use-angle=gl",
+          "--disable-gpu-sandbox"
+        ],
+        "name": "gles2_conform_gl_test",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        },
+        "test": "gles2_conform_test",
+        "use_xvfb": false
+      },
+      {
+        "args": [
+          "--use-gpu-in-tests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        },
+        "test": "gles2_conform_test",
+        "use_xvfb": false
+      },
+      {
+        "args": [
+          "--use-test-data-path"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        },
+        "test": "video_decode_accelerator_unittest",
+        "use_xvfb": false
+      }
+    ],
+    "isolated_scripts": [
+      {
+        "args": [
+          "context_lost",
+          "--show-stdout",
+          "--browser=release",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "context_lost_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "depth_capture",
+          "--show-stdout",
+          "--browser=release",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "depth_capture_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "gpu_process",
+          "--show-stdout",
+          "--browser=release",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "gpu_process_launch_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "hardware_accelerated_feature",
+          "--show-stdout",
+          "--browser=release",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "hardware_accelerated_feature_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "maps",
+          "--show-stdout",
+          "--browser=release",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--os-type",
+          "win",
+          "--build-revision",
+          "${got_revision}",
+          "--test-machine-name",
+          "${buildername}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "maps_pixel_test",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "pixel",
+          "--show-stdout",
+          "--browser=release",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--refimg-cloud-storage-bucket",
+          "chromium-gpu-archive/reference-images",
+          "--os-type",
+          "win",
+          "--build-revision",
+          "${got_revision}",
+          "--test-machine-name",
+          "${buildername}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "pixel_test",
+        "non_precommit_args": [
+          "--upload-refimg-to-cloud-storage"
+        ],
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "precommit_args": [
+          "--download-refimg-from-cloud-storage"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "screenshot_sync",
+          "--show-stdout",
+          "--browser=release",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "screenshot_sync_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "trace_test",
+          "--show-stdout",
+          "--browser=release",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "trace_test",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=release",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--webgl-conformance-version=2.0.1",
+          "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "webgl2_conformance_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ],
+          "shards": 15
+        }
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=release",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d11 --use-passthrough-cmd-decoder"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "webgl_conformance_d3d11_passthrough_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=release",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d9"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "webgl_conformance_d3d9_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=release",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=gl"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "webgl_conformance_gl_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=release",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "webgl_conformance_tests",
+        "override_compile_targets": [
+          "telemetry_gpu_integration_test_run"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:1912",
+              "os": "Windows-10"
+            }
+          ]
+        }
+      }
+    ]
+  },
   "Win10 Release (NVIDIA)": {
     "gtest_tests": [
       {
@@ -12442,436 +14134,6 @@
       }
     ]
   },
-  "Win7 Debug (New Intel)": {
-    "gtest_tests": [
-      {
-        "args": [
-          "--use-gpu-in-tests",
-          "--test-launcher-retry-limit=0"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        },
-        "test": "angle_end2end_tests",
-        "use_xvfb": false
-      },
-      {
-        "args": [
-          "--use-gpu-in-tests",
-          "--test-launcher-retry-limit=0"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        },
-        "test": "angle_unittests",
-        "use_xvfb": false
-      },
-      {
-        "args": [
-          "--use-gpu-in-tests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        },
-        "test": "audio_unittests",
-        "use_xvfb": false
-      },
-      {
-        "args": [
-          "--use-gpu-in-tests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        },
-        "test": "gl_tests",
-        "use_xvfb": false
-      },
-      {
-        "args": [
-          "--use-gpu-in-tests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        },
-        "test": "gl_unittests",
-        "use_xvfb": false
-      },
-      {
-        "args": [
-          "--use-gpu-in-tests",
-          "--use-angle=d3d9"
-        ],
-        "name": "gles2_conform_d3d9_test",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        },
-        "test": "gles2_conform_test",
-        "use_xvfb": false
-      },
-      {
-        "args": [
-          "--use-gpu-in-tests",
-          "--use-angle=gl",
-          "--disable-gpu-sandbox"
-        ],
-        "name": "gles2_conform_gl_test",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        },
-        "test": "gles2_conform_test",
-        "use_xvfb": false
-      },
-      {
-        "args": [
-          "--use-gpu-in-tests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        },
-        "test": "gles2_conform_test",
-        "use_xvfb": false
-      },
-      {
-        "args": [
-          "--use-test-data-path"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        },
-        "test": "video_decode_accelerator_unittest",
-        "use_xvfb": false
-      }
-    ],
-    "isolated_scripts": [
-      {
-        "args": [
-          "context_lost",
-          "--show-stdout",
-          "--browser=debug",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "name": "context_lost_tests",
-        "override_compile_targets": [
-          "telemetry_gpu_integration_test_run"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        }
-      },
-      {
-        "args": [
-          "depth_capture",
-          "--show-stdout",
-          "--browser=debug",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "name": "depth_capture_tests",
-        "override_compile_targets": [
-          "telemetry_gpu_integration_test_run"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        }
-      },
-      {
-        "args": [
-          "gpu_process",
-          "--show-stdout",
-          "--browser=debug",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "name": "gpu_process_launch_tests",
-        "override_compile_targets": [
-          "telemetry_gpu_integration_test_run"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        }
-      },
-      {
-        "args": [
-          "hardware_accelerated_feature",
-          "--show-stdout",
-          "--browser=debug",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "name": "hardware_accelerated_feature_tests",
-        "override_compile_targets": [
-          "telemetry_gpu_integration_test_run"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        }
-      },
-      {
-        "args": [
-          "maps",
-          "--show-stdout",
-          "--browser=debug",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
-          "--os-type",
-          "win",
-          "--build-revision",
-          "${got_revision}",
-          "--test-machine-name",
-          "${buildername}"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "name": "maps_pixel_test",
-        "override_compile_targets": [
-          "telemetry_gpu_integration_test_run"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        }
-      },
-      {
-        "args": [
-          "pixel",
-          "--show-stdout",
-          "--browser=debug",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
-          "--refimg-cloud-storage-bucket",
-          "chromium-gpu-archive/reference-images",
-          "--os-type",
-          "win",
-          "--build-revision",
-          "${got_revision}",
-          "--test-machine-name",
-          "${buildername}"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "name": "pixel_test",
-        "non_precommit_args": [
-          "--upload-refimg-to-cloud-storage"
-        ],
-        "override_compile_targets": [
-          "telemetry_gpu_integration_test_run"
-        ],
-        "precommit_args": [
-          "--download-refimg-from-cloud-storage"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        }
-      },
-      {
-        "args": [
-          "screenshot_sync",
-          "--show-stdout",
-          "--browser=debug",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "name": "screenshot_sync_tests",
-        "override_compile_targets": [
-          "telemetry_gpu_integration_test_run"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        }
-      },
-      {
-        "args": [
-          "trace_test",
-          "--show-stdout",
-          "--browser=debug",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "name": "trace_test",
-        "override_compile_targets": [
-          "telemetry_gpu_integration_test_run"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        }
-      },
-      {
-        "args": [
-          "webgl_conformance",
-          "--show-stdout",
-          "--browser=debug",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d11 --use-passthrough-cmd-decoder"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "name": "webgl_conformance_d3d11_passthrough_tests",
-        "override_compile_targets": [
-          "telemetry_gpu_integration_test_run"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        }
-      },
-      {
-        "args": [
-          "webgl_conformance",
-          "--show-stdout",
-          "--browser=debug",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d9"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "name": "webgl_conformance_d3d9_tests",
-        "override_compile_targets": [
-          "telemetry_gpu_integration_test_run"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        }
-      },
-      {
-        "args": [
-          "webgl_conformance",
-          "--show-stdout",
-          "--browser=debug",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "name": "webgl_conformance_tests",
-        "override_compile_targets": [
-          "telemetry_gpu_integration_test_run"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        }
-      }
-    ]
-  },
   "Win7 Release (AMD R5 230)": {
     "gtest_tests": [
       {
@@ -15382,475 +16644,6 @@
       }
     ]
   },
-  "Win7 Release (New Intel)": {
-    "gtest_tests": [
-      {
-        "args": [
-          "--use-gpu-in-tests",
-          "--test-launcher-retry-limit=0"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        },
-        "test": "angle_end2end_tests",
-        "use_xvfb": false
-      },
-      {
-        "args": [
-          "--use-gpu-in-tests",
-          "--test-launcher-retry-limit=0"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        },
-        "test": "angle_unittests",
-        "use_xvfb": false
-      },
-      {
-        "args": [
-          "--use-gpu-in-tests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        },
-        "test": "audio_unittests",
-        "use_xvfb": false
-      },
-      {
-        "args": [
-          "--enable-gpu",
-          "--test-launcher-jobs=1",
-          "--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*"
-        ],
-        "name": "tab_capture_end2end_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "browser_tests",
-        "use_xvfb": false
-      },
-      {
-        "args": [
-          "--use-gpu-in-tests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        },
-        "test": "gl_tests",
-        "use_xvfb": false
-      },
-      {
-        "args": [
-          "--use-gpu-in-tests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        },
-        "test": "gl_unittests",
-        "use_xvfb": false
-      },
-      {
-        "args": [
-          "--use-gpu-in-tests",
-          "--use-angle=d3d9"
-        ],
-        "name": "gles2_conform_d3d9_test",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        },
-        "test": "gles2_conform_test",
-        "use_xvfb": false
-      },
-      {
-        "args": [
-          "--use-gpu-in-tests",
-          "--use-angle=gl",
-          "--disable-gpu-sandbox"
-        ],
-        "name": "gles2_conform_gl_test",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        },
-        "test": "gles2_conform_test",
-        "use_xvfb": false
-      },
-      {
-        "args": [
-          "--use-gpu-in-tests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        },
-        "test": "gles2_conform_test",
-        "use_xvfb": false
-      },
-      {
-        "args": [
-          "--use-test-data-path"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        },
-        "test": "video_decode_accelerator_unittest",
-        "use_xvfb": false
-      }
-    ],
-    "isolated_scripts": [
-      {
-        "args": [
-          "context_lost",
-          "--show-stdout",
-          "--browser=release",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "name": "context_lost_tests",
-        "override_compile_targets": [
-          "telemetry_gpu_integration_test_run"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        }
-      },
-      {
-        "args": [
-          "depth_capture",
-          "--show-stdout",
-          "--browser=release",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "name": "depth_capture_tests",
-        "override_compile_targets": [
-          "telemetry_gpu_integration_test_run"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        }
-      },
-      {
-        "args": [
-          "gpu_process",
-          "--show-stdout",
-          "--browser=release",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "name": "gpu_process_launch_tests",
-        "override_compile_targets": [
-          "telemetry_gpu_integration_test_run"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        }
-      },
-      {
-        "args": [
-          "hardware_accelerated_feature",
-          "--show-stdout",
-          "--browser=release",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "name": "hardware_accelerated_feature_tests",
-        "override_compile_targets": [
-          "telemetry_gpu_integration_test_run"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        }
-      },
-      {
-        "args": [
-          "maps",
-          "--show-stdout",
-          "--browser=release",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
-          "--os-type",
-          "win",
-          "--build-revision",
-          "${got_revision}",
-          "--test-machine-name",
-          "${buildername}"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "name": "maps_pixel_test",
-        "override_compile_targets": [
-          "telemetry_gpu_integration_test_run"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        }
-      },
-      {
-        "args": [
-          "pixel",
-          "--show-stdout",
-          "--browser=release",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
-          "--refimg-cloud-storage-bucket",
-          "chromium-gpu-archive/reference-images",
-          "--os-type",
-          "win",
-          "--build-revision",
-          "${got_revision}",
-          "--test-machine-name",
-          "${buildername}"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "name": "pixel_test",
-        "non_precommit_args": [
-          "--upload-refimg-to-cloud-storage"
-        ],
-        "override_compile_targets": [
-          "telemetry_gpu_integration_test_run"
-        ],
-        "precommit_args": [
-          "--download-refimg-from-cloud-storage"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        }
-      },
-      {
-        "args": [
-          "screenshot_sync",
-          "--show-stdout",
-          "--browser=release",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "name": "screenshot_sync_tests",
-        "override_compile_targets": [
-          "telemetry_gpu_integration_test_run"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        }
-      },
-      {
-        "args": [
-          "trace_test",
-          "--show-stdout",
-          "--browser=release",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "name": "trace_test",
-        "override_compile_targets": [
-          "telemetry_gpu_integration_test_run"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        }
-      },
-      {
-        "args": [
-          "webgl_conformance",
-          "--show-stdout",
-          "--browser=release",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
-          "--webgl-conformance-version=2.0.1",
-          "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "name": "webgl2_conformance_tests",
-        "override_compile_targets": [
-          "telemetry_gpu_integration_test_run"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ],
-          "shards": 15
-        }
-      },
-      {
-        "args": [
-          "webgl_conformance",
-          "--show-stdout",
-          "--browser=release",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d11 --use-passthrough-cmd-decoder"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "name": "webgl_conformance_d3d11_passthrough_tests",
-        "override_compile_targets": [
-          "telemetry_gpu_integration_test_run"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        }
-      },
-      {
-        "args": [
-          "webgl_conformance",
-          "--show-stdout",
-          "--browser=release",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d9"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "name": "webgl_conformance_d3d9_tests",
-        "override_compile_targets": [
-          "telemetry_gpu_integration_test_run"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        }
-      },
-      {
-        "args": [
-          "webgl_conformance",
-          "--show-stdout",
-          "--browser=release",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "name": "webgl_conformance_tests",
-        "override_compile_targets": [
-          "telemetry_gpu_integration_test_run"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0412",
-              "os": "Windows-2008ServerR2-SP1"
-            }
-          ]
-        }
-      }
-    ]
-  },
   "Win7 x64 Debug (NVIDIA)": {
     "gtest_tests": [
       {
diff --git a/testing/test.gni b/testing/test.gni
index e4cce69a..9aa7cc47 100644
--- a/testing/test.gni
+++ b/testing/test.gni
@@ -6,6 +6,12 @@
 # TEST SETUP
 # ==============================================================================
 
+if (is_android) {
+  import("//build/config/android/config.gni")
+  import("//build/config/android/rules.gni")
+  import("//build/config/sanitizers/sanitizers.gni")
+}
+
 # Define a test as an executable (or apk on Android) with the "testonly" flag
 # set.
 # Variable:
@@ -13,10 +19,6 @@
 #   use_native_activity: Test implements ANativeActivity_onCreate().
 template("test") {
   if (is_android) {
-    import("//build/config/android/config.gni")
-    import("//build/config/android/rules.gni")
-    import("//build/config/sanitizers/sanitizers.gni")
-
     _use_raw_android_executable = defined(invoker.use_raw_android_executable) &&
                                   invoker.use_raw_android_executable
 
@@ -118,6 +120,9 @@
           install_script_name = "install_${invoker.output_name}"
         }
 
+        # Add the Java classes so that each target does not have to do it.
+        deps += [ "//base/test:test_support_java" ]
+
         # TODO(agrieve): Remove this data_dep once bots don't build the _apk
         #     target (post-GYP).
         # It's a bit backwards for the apk to depend on the runner script, since
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
index 5ca3a783..e2ae5ef 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
@@ -416,7 +416,6 @@
 Bug(none) compositing/squashing/squashing-sparsity-heuristic.html [ Failure ]
 Bug(none) compositing/tiled-layers-hidpi.html [ Failure ]
 Bug(none) compositing/update-paint-phases.html [ Failure ]
-Bug(none) compositing/video/video-controls-layer-creation.html [ Failure ]
 Bug(none) compositing/video/video-poster.html [ Crash Failure ]
 Bug(none) compositing/video/video-reflection.html [ Crash Failure  ]
 Bug(none) compositing/visibility/layer-visible-content.html [ Failure ]
@@ -431,23 +430,18 @@
 Bug(none) fast/backgrounds/animated-svg-as-mask.html [ Failure ]
 Bug(none) fast/backgrounds/background-inherit-color-bug.html [ Failure ]
 Bug(none) fast/backgrounds/background-leakage-transforms.html [ Failure ]
-Bug(none) fast/backgrounds/gradient-background-leakage-2.html [ Failure ]
-Bug(none) fast/backgrounds/gradient-background-leakage.html [ Failure ]
 Bug(none) fast/backgrounds/mask-box-image-zoomed.html [ Failure ]
 Bug(none) fast/backgrounds/mask-box-image.html [ Failure ]
 Bug(none) fast/backgrounds/mask-composite.html [ Failure ]
 Bug(none) fast/backgrounds/opacity-on-document-element.html [ Failure ]
 Bug(none) fast/backgrounds/repeat/mask-negative-offset-repeat.html [ Failure ]
-Bug(none) fast/backgrounds/repeat/negative-offset-repeat-transformed.html [ Failure ]
 Bug(none) fast/backgrounds/svg-as-mask.html [ Failure ]
 Bug(none) fast/backgrounds/transformed-body-background.html [ Failure ]
 Bug(none) fast/backgrounds/transformed-body-html-background.html [ Failure ]
 Bug(none) fast/backgrounds/transformed-html-body-background.html [ Failure ]
 Bug(none) fast/block/basic/016.html [ Failure ]
 Bug(none) fast/block/basic/fieldset-stretch-to-legend.html [ Failure ]
-Bug(none) fast/block/float/002.html [ Failure ]
 Bug(none) fast/block/float/008.html [ Failure ]
-Bug(none) fast/block/float/017.html [ Failure ]
 Bug(none) fast/block/float/021.html [ Failure ]
 Bug(none) fast/block/float/025.html [ Failure ]
 Bug(none) fast/block/float/026.html [ Failure ]
@@ -456,17 +450,13 @@
 Bug(none) fast/block/float/032.html [ Failure ]
 Bug(none) fast/block/float/033.html [ Failure ]
 Bug(none) fast/block/float/035.html [ Failure ]
-Bug(none) fast/block/float/avoiding-float-centered.html [ Failure ]
 Bug(none) fast/block/float/br-with-clear-2.html [ Failure ]
 Bug(none) fast/block/float/centered-float-avoidance-complexity.html [ Failure ]
 Bug(none) fast/block/float/float-avoidance.html [ Failure ]
 Bug(none) fast/block/float/float-in-float-painting.html [ Failure ]
-Bug(none) fast/block/float/max-width-clear-float-with-overflow-hidden.html [ Failure ]
 Bug(none) fast/block/float/nested-clearance.html [ Failure ]
-Bug(none) fast/block/float/nested-floats-expand-formatting-context.html [ Failure ]
 Bug(none) fast/block/float/relative-painted-twice.html [ Failure ]
 Bug(none) fast/block/float/shrink-to-avoid-float-complexity.html [ Failure ]
-Bug(none) fast/block/float/width-update-after-clear.html [ Failure ]
 crbug.com/667946 fast/block/float/float-change-composited-scrolling.html [ Failure ]
 Bug(none) fast/block/margin-collapse/103.html [ Failure ]
 Bug(none) fast/block/margin-collapse/104.html [ Failure ]
@@ -498,16 +488,12 @@
 Bug(none) fast/body-propagation/overflow/005-declarative.xhtml [ Failure ]
 Bug(none) fast/body-propagation/overflow/005-xhtml.xhtml [ Failure ]
 Bug(none) fast/body-propagation/overflow/005.html [ Failure ]
-Bug(none) fast/body-propagation/overflow/006-declarative.xhtml [ Failure ]
-Bug(none) fast/body-propagation/overflow/006-xhtml.xhtml [ Failure ]
-Bug(none) fast/body-propagation/overflow/006.html [ Failure ]
 Bug(none) fast/body-propagation/overflow/007-declarative.xhtml [ Failure ]
 Bug(none) fast/body-propagation/overflow/007-xhtml.xhtml [ Failure ]
 Bug(none) fast/body-propagation/overflow/007.html [ Failure ]
 Bug(none) fast/borders/block-mask-overlay-image-outset.html [ Failure ]
 Bug(none) fast/borders/block-mask-overlay-image.html [ Failure ]
 Bug(none) fast/borders/border-antialiasing.html [ Failure ]
-Bug(none) fast/borders/border-image-rotate-transform.html [ Failure ]
 Bug(none) fast/borders/border-inner-bleed.html [ Failure ]
 Bug(none) fast/borders/border-radius-mask-canvas-all.html [ Failure ]
 Bug(none) fast/borders/border-radius-mask-canvas-border.html [ Failure ]
@@ -527,22 +513,17 @@
 Bug(none) fast/borders/rtl-border-01.html [ Failure ]
 Bug(none) fast/borders/rtl-border-02.html [ Failure ]
 Bug(none) fast/borders/rtl-border-03.html [ Failure ]
-Bug(none) fast/borders/rtl-border-05.html [ Failure ]
-Bug(none) fast/borders/table-borders.html [ Failure ]
 Bug(none) fast/box-shadow/basic-shadows.html [ Failure ]
 Bug(none) fast/box-shadow/box-shadow-clipped-slices.html [ Failure Timeout ]
 Bug(none) fast/box-shadow/box-shadow-transformed.html [ Failure ]
 Bug(none) fast/box-shadow/box-shadow.html [ Failure ]
 Bug(none) fast/box-shadow/scaled-box-shadow.html [ Failure ]
 Bug(none) fast/box-sizing/box-sizing.html [ Failure ]
-Bug(none) fast/box-sizing/panels-one.html [ Failure ]
-Bug(none) fast/box-sizing/panels-two.html [ Failure ]
 Bug(none) fast/canvas/alpha.html [ Failure ]
 Bug(none) fast/canvas/canvas-composite-video.html [ Failure ]
 Bug(none) fast/canvas/canvas-css-clip-path.html [ Failure ]
 Bug(none) fast/canvas/webgl/pixelated.html [ Failure ]
 Bug(none) fast/clip/nestedTransparencyClip.html [ Failure ]
-Bug(none) fast/clip/outline-overflowClip.html [ Failure ]
 Bug(none) fast/clip/overflow-border-radius-clip.html [ Failure ]
 Bug(none) fast/clip/overflow-border-radius-combinations.html [ Failure ]
 Bug(none) fast/clip/overflow-border-radius-composited-parent.html [ Failure ]
@@ -551,65 +532,44 @@
 Bug(none) fast/clip/overflow-border-radius-transformed.html [ Failure ]
 Bug(none) fast/css-generated-content/014.html [ Failure ]
 Bug(none) fast/css-generated-content/table-parts-before-and-after.html [ Failure ]
-Bug(none) fast/css-grid-layout/min-width-height-auto-overflow.html [ Failure ]
-Bug(none) fast/css-grid-layout/scrolled-grid-painting-overflow.html [ Failure ]
-Bug(none) fast/css-grid-layout/scrolled-grid-painting.html [ Failure ]
-Bug(none) fast/css/acid2.html [ Failure ]
 Bug(none) fast/css/bidi-override-in-anonymous-block.html [ Failure ]
 Bug(none) fast/css/border-height.html [ Failure ]
 Bug(none) fast/css/color-correction-backgrounds-and-text.html [ Failure ]
 Bug(none) fast/css/color-correction-on-background-image.html [ Failure ]
-Bug(none) fast/css/continuationCrash.html [ Failure ]
 Bug(none) fast/css/empty-webkit-mask-crash.html [ Failure ]
 Bug(none) fast/css/first-child-pseudo-class.html [ Failure ]
 Bug(none) fast/css/first-of-type-pseudo-class.html [ Failure ]
 Bug(none) fast/css/hsl-color.html [ Failure ]
 Bug(none) fast/css/imageTileOpacity.html [ Failure ]
-Bug(none) fast/css/invalidation-errors-2.html [ Failure ]
-Bug(none) fast/css/invalidation-errors.html [ Failure ]
 Bug(none) fast/css/last-child-pseudo-class.html [ Failure ]
 Bug(none) fast/css/last-of-type-pseudo-class.html [ Failure ]
 Bug(none) fast/css/line-height-overflow.html [ Failure ]
-Bug(none) fast/css/line-height.html [ Failure ]
-Bug(none) fast/css/margin-top-bottom-dynamic.html [ Failure ]
 Bug(none) fast/css/nested-rounded-corners.html [ Failure ]
 Bug(none) fast/css/object-fit-img-svg.html [ Failure ]
 Bug(none) fast/css/object-fit-img-svg2.html [ Failure ]
-Bug(none) fast/css/object-position-svg.html [ Failure ]
 Bug(none) fast/css/only-child-pseudo-class.html [ Failure ]
 Bug(none) fast/css/only-of-type-pseudo-class.html [ Failure ]
 Bug(none) fast/css/outline-auto-empty-rects.html [ Failure ]
 Bug(none) fast/css/outline-offset-large.html [ Failure ]
-Bug(none) fast/css/resize-corner-tracking-transformed-iframe.html [ Failure ]
 Bug(none) fast/css/resize-corner-tracking-transformed.html [ Failure ]
-Bug(none) fast/css/rtl-ordering.html [ Failure ]
-Bug(none) fast/css/text-overflow-ellipsis-multiple-shadows.html [ Failure ]
-Bug(none) fast/css/text-overflow-ellipsis-strict.html [ Failure ]
 Bug(none) fast/css/text-overflow-ellipsis-text-align-center.html [ Failure ]
 Bug(none) fast/css/text-overflow-ellipsis-text-align-justify.html [ Failure ]
 Bug(none) fast/css/text-overflow-ellipsis-text-align-left.html [ Failure ]
 Bug(none) fast/css/text-overflow-ellipsis-text-align-right.html [ Failure ]
-Bug(none) fast/css/text-overflow-ellipsis.html [ Failure ]
-Bug(none) fast/css/text-overflow-input.html [ Failure ]
 Bug(none) fast/css/transformed-mask.html [ Crash Failure ]
 Bug(none) fast/css/vertical-text-overflow-ellipsis-text-align-center.html [ Failure ]
 Bug(none) fast/css/vertical-text-overflow-ellipsis-text-align-justify.html [ Failure ]
 Bug(none) fast/css/vertical-text-overflow-ellipsis-text-align-left.html [ Failure ]
 Bug(none) fast/css/vertical-text-overflow-ellipsis-text-align-right.html [ Failure ]
-Bug(none) fast/deprecated-flexbox/016.html [ Failure ]
 Bug(none) fast/dom/34176.html [ Failure ]
 Bug(none) fast/dom/52776.html [ Failure ]
 Bug(none) fast/dom/CompositorProxy/proxy-forces-layer.html [ Failure Timeout Pass ]
 Bug(none) fast/dom/focus-contenteditable.html [ Failure ]
 Bug(none) fast/dom/rtl-scroll-to-leftmost-and-resize.html [ Failure Crash ]
-Bug(none) fast/dom/Window/open-existing-pop-up-blocking.html [ Failure ]
 Bug(none) fast/dynamic/anchor-lock.html [ Failure ]
 Bug(none) fast/dynamic/first-letter-after-list-marker.html [ Failure ]
-Bug(none) fast/encoding/utf-16-big-endian.html [ Failure ]
-Bug(none) fast/encoding/utf-16-little-endian.html [ Failure ]
 Bug(none) fast/events/autoscroll.html [ Failure ]
 crbug.com/667946 fast/events/autoscroll-disabled-in-fix.html [ Skip ]
-Bug(none) fast/events/context-no-deselect.html [ Failure ]
 Bug(none) fast/events/gesture-pinch-zoom-scroll-bubble.html [ Failure ]
 Bug(none) fast/events/keyboard-scroll-by-page.html [ Failure ]
 Bug(none) fast/events/platform-wheelevent-paging-x-in-scrolling-page.html [ Failure ]
@@ -637,138 +597,40 @@
 Bug(none) fast/events/touch/touch-rect-crash-on-unpromote-layer.html [ Failure ]
 Bug(none) fast/events/wheel/wheelevent-in-horizontal-scrollbar-in-rtl.html [ Failure ]
 Bug(none) fast/events/wheel/wheelevent-in-vertical-scrollbar-in-rtl.html [ Failure ]
-Bug(none) fast/files/file-in-input-display.html [ Failure ]
-Bug(none) fast/forms/001.html [ Failure ]
-Bug(none) fast/forms/basic-buttons.html [ Failure ]
-Bug(none) fast/forms/basic-inputs.html [ Failure ]
-Bug(none) fast/forms/blankbuttons.html [ Failure ]
 Bug(none) fast/forms/button-default-title.html [ Failure ]
-Bug(none) fast/forms/button-positioned.html [ Failure ]
-Bug(none) fast/forms/button-sizes.html [ Failure ]
-Bug(none) fast/forms/button-style-color.html [ Failure ]
-Bug(none) fast/forms/button-table-styles.html [ Failure ]
-Bug(none) fast/forms/button-text-transform.html [ Failure ]
-Bug(none) fast/forms/control-clip-overflow.html [ Failure ]
-Bug(none) fast/forms/control-restrict-line-height.html [ Failure ]
-Bug(none) fast/forms/datalist/input-appearance-range-with-transform.html [ Failure ]
-Bug(none) fast/forms/date/date-appearance-basic.html [ Failure ]
-Bug(none) fast/forms/datetimelocal/datetimelocal-appearance-basic.html [ Failure ]
 Bug(none) fast/forms/fieldset/fieldset-align.html [ Failure ]
-Bug(none) fast/forms/file/file-input-direction.html [ Failure ]
-Bug(none) fast/forms/file/file-input-disabled.html [ Failure ]
-Bug(none) fast/forms/file/file-input-pressed-state.html [ Failure ]
-Bug(none) fast/forms/file/input-file-re-render.html [ Failure ]
-Bug(none) fast/forms/form-element-geometry.html [ Failure ]
-Bug(none) fast/forms/formmove3.html [ Failure ]
 Bug(none) fast/forms/huge-mac-input-clamped-height.html [ Failure ]
 Bug(none) fast/forms/huge-mac-input-clamped-width.html [ Failure ]
-Bug(none) fast/forms/input-appearance-height.html [ Failure ]
-Bug(none) fast/forms/input-button-sizes.html [ Failure ]
-Bug(none) fast/forms/input-value.html [ Failure ]
-Bug(none) fast/forms/month/month-appearance-basic.html [ Failure ]
-Bug(none) fast/forms/number/number-appearance-datalist.html [ Failure ]
-Bug(none) fast/forms/number/number-appearance-rtl.html [ Failure ]
-Bug(none) fast/forms/number/number-appearance-spinbutton-disabled-readonly.html [ Failure ]
 Bug(none) fast/forms/number/number-appearance-spinbutton-layer.html [ Failure ]
 Bug(none) fast/forms/placeholder-position.html [ Failure ]
-Bug(none) fast/forms/plaintext-mode-2.html [ Failure ]
-Bug(none) fast/forms/range/input-appearance-range.html [ Failure ]
-Bug(none) fast/forms/search/search-appearance-basic.html [ Failure ]
-Bug(none) fast/forms/search/search-cancel-button-style-sharing.html [ Failure ]
-Bug(none) fast/forms/search/search-rtl.html [ Failure ]
-Bug(none) fast/forms/select/003.html [ Failure ]
-Bug(none) fast/forms/select/004.html [ Failure ]
-Bug(none) fast/forms/select/basic-selects.html [ Failure ]
-Bug(none) fast/forms/select/disabled-select-change-index.html [ Failure ]
-Bug(none) fast/forms/select/HTMLOptionElement_label01.html [ Failure ]
-Bug(none) fast/forms/select/HTMLOptionElement_label02.html [ Failure ]
-Bug(none) fast/forms/select/HTMLOptionElement_label03.html [ Failure ]
-Bug(none) fast/forms/select/HTMLOptionElement_label04.html [ Failure ]
 Bug(none) fast/forms/select/listbox-appearance-basic.html [ Failure ]
-Bug(none) fast/forms/select/listbox-appearance-separator.html [ Failure ]
-Bug(none) fast/forms/select/listbox-bidi-align.html [ Failure ]
 Bug(none) fast/forms/select/listbox-scrollbar-incremental-load.html [ Failure ]
 Bug(none) fast/forms/select/menulist-appearance-basic.html [ Failure ]
-Bug(none) fast/forms/select/menulist-appearance-none.html [ Failure ]
 Bug(none) fast/forms/select/menulist-appearance-rtl.html [ Failure ]
-Bug(none) fast/forms/select/menulist-clip.html [ Failure ]
 Bug(none) fast/forms/select/menulist-deselect-update.html [ Crash Failure ]
-Bug(none) fast/forms/select/menulist-no-overflow.html [ Failure ]
-Bug(none) fast/forms/select/menulist-option-wrap.html [ Failure ]
-Bug(none) fast/forms/select/menulist-restrict-line-height.html [ Failure ]
-Bug(none) fast/forms/select/menulist-style-color.html [ Failure ]
 Bug(none) fast/forms/select/menulist-width-change.html [ Crash Failure ]
-Bug(none) fast/forms/select/optgroup-rendering.html [ Failure ]
-Bug(none) fast/forms/select/option-script.html [ Failure ]
-Bug(none) fast/forms/select/option-strip-whitespace.html [ Failure ]
-Bug(none) fast/forms/select/option-text-clip.html [ Failure ]
-Bug(none) fast/forms/select/select-align.html [ Failure ]
-Bug(none) fast/forms/select/select-autofilled.html [ Failure ]
-Bug(none) fast/forms/select/select-background-none.html [ Failure ]
-Bug(none) fast/forms/select/select-baseline.html [ Failure ]
-Bug(none) fast/forms/select/select-block-background.html [ Failure ]
 Bug(none) fast/forms/select/select-change-listbox-to-popup.html [ Crash Failure ]
-Bug(none) fast/forms/select/select-change-popup-to-listbox.html [ Failure ]
-Bug(none) fast/forms/select/select-dirty-parent-pref-widths.html [ Failure ]
-Bug(none) fast/forms/select/select-disabled-appearance.html [ Failure ]
 Bug(none) fast/forms/select/select-initial-position.html [ Failure ]
-Bug(none) fast/forms/select/select-listbox-multiple-no-focusring.html [ Failure ]
-Bug(none) fast/forms/select/select-selected.html [ Failure ]
-Bug(none) fast/forms/select/select-size-invalid.html [ Failure ]
-Bug(none) fast/forms/select/select-style.html [ Failure ]
-Bug(none) fast/forms/select/select-visual-hebrew.html [ Failure ]
 Bug(none) fast/forms/select/select-writing-direction-natural.html [ Crash Failure ]
-Bug(none) fast/forms/stuff-on-my-optgroup.html [ Failure ]
-Bug(none) fast/forms/submit/submit-appearance-basic.html [ Failure ]
-Bug(none) fast/forms/tabbing-input-iframe.html [ Failure ]
-Bug(none) fast/forms/targeted-frame-submission.html [ Failure ]
-Bug(none) fast/forms/text/input-appearance-bkcolor.html [ Failure ]
-Bug(none) fast/forms/text/input-appearance-disabled.html [ Failure ]
-Bug(none) fast/forms/text/input-appearance-focus.html [ Failure ]
-Bug(none) fast/forms/text/input-appearance-preventDefault.html [ Failure ]
-Bug(none) fast/forms/text/input-appearance-readonly.html [ Failure ]
 Bug(none) fast/forms/text/input-appearance-selection.html [ Failure ]
 Bug(none) fast/forms/text/input-disabled-color.html [ Failure ]
-Bug(none) fast/forms/text/input-double-click-selection-gap-bug.html [ Failure ]
-Bug(none) fast/forms/text/input-placeholder-visibility-1.html [ Failure ]
-Bug(none) fast/forms/text/input-placeholder-visibility-3.html [ Failure ]
 Bug(none) fast/forms/text/input-readonly-autoscroll.html [ Failure ]
 Bug(none) fast/forms/text/input-readonly-dimmed.html [ Failure ]
-Bug(none) fast/forms/text/input-tab-shows-caret.html [ Failure ]
 Bug(none) fast/forms/text/input-table.html [ Failure ]
-Bug(none) fast/forms/text/input-text-click-inside.html [ Failure ]
-Bug(none) fast/forms/text/input-text-double-click.html [ Failure ]
-Bug(none) fast/forms/text/input-text-drag-down.html [ Failure ]
-Bug(none) fast/forms/text/input-text-option-delete.html [ Failure ]
 Bug(none) fast/forms/text/input-text-scroll-left-on-blur.html [ Failure ]
-Bug(none) fast/forms/text/input-text-self-emptying-click.html [ Failure ]
-Bug(none) fast/forms/text/text-appearance-basic.html [ Failure ]
-Bug(none) fast/forms/text/text-appearance-datalist.html [ Failure ]
-Bug(none) fast/forms/text/textfield-focus-ring.html [ Failure ]
 Bug(none) fast/forms/text/textfield-outline.html [ Failure ]
 Bug(none) fast/forms/text/textfield-overflow.html [ Failure ]
 Bug(none) fast/forms/textarea/basic-textareas-quirks.html [ Failure ]
 Bug(none) fast/forms/textarea/basic-textareas.html [ Failure ]
-Bug(none) fast/forms/textarea/linebox-overflow-in-textarea-padding.html [ Failure ]
-Bug(none) fast/forms/textarea/reset-textarea.html [ Failure ]
-Bug(none) fast/forms/textarea/textarea-appearance-basic.html [ Failure ]
-Bug(none) fast/forms/textarea/textarea-placeholder-visibility-1.html [ Failure ]
-Bug(none) fast/forms/textarea/textarea-placeholder-visibility-2.html [ Failure ]
 Bug(none) fast/forms/textarea/textarea-scrollbar.html [ Failure ]
 Bug(none) fast/forms/textarea/textarea-scrolled-focus-ring.html [ Failure ]
 Bug(none) fast/forms/textarea/textarea-scrolled-mask.html [ Failure ]
 Bug(none) fast/forms/textarea/textarea-scrolled-type.html [ Failure ]
 Bug(none) fast/forms/textarea/textAreaLineHeight.html [ Failure ]
-Bug(none) fast/forms/time/time-appearance-basic.html [ Failure ]
-Bug(none) fast/forms/week/week-appearance-basic.html [ Failure ]
-Bug(none) fast/frames/frame-navigation.html [ Failure ]
 Bug(none) fast/frames/frame-set-rotation-hit.html [ Crash Timeout ]
-Bug(none) fast/frames/frame-set-scaling-centered.html [ Failure ]
 Bug(none) fast/frames/frame-set-scaling-hit.html [ Crash Timeout ]
 Bug(none) fast/frames/frame-set-scaling-rotate.html [ Failure ]
 Bug(none) fast/frames/frame-set-scaling-skew.html [ Failure ]
-Bug(none) fast/frames/frame-set-scaling.html [ Failure ]
-Bug(none) fast/frames/frameset-style-recalc.html [ Failure ]
 Bug(none) fast/frames/iframe-scaling-with-scroll.html [ Failure ]
 Bug(none) fast/frames/iframe-scrolling-attribute.html [ Failure ]
 Bug(none) fast/frames/transparent-scrollbar.html [ Failure ]
@@ -792,16 +654,7 @@
 Bug(none) fast/html/details-remove-summary-4-and-click.html [ Crash Failure ]
 Bug(none) fast/html/details-remove-summary-5-and-click.html [ Failure ]
 Bug(none) fast/html/details-remove-summary-6-and-click.html [ Failure ]
-Bug(none) fast/html/details-replace-summary-child.html [ Failure ]
-Bug(none) fast/html/details-replace-text.html [ Failure ]
-Bug(none) images/12-55.html [ Failure ]
 Bug(none) images/182.html [ Crash Failure ]
-Bug(none) images/2-dht.html [ Failure ]
-Bug(none) images/23-55.html [ Failure ]
-Bug(none) images/55.html [ Failure ]
-Bug(none) images/alt-text-wrapping.html [ Failure ]
-Bug(none) images/color-profile-background-image-cross-fade-png.html [ Failure ]
-Bug(none) images/color-profile-background-image-cross-fade.html [ Failure ]
 Bug(none) images/color-profile-border-fade.html [ Failure ]
 Bug(none) images/color-profile-border-radius.html [ Failure ]
 Bug(none) images/color-profile-filter.html [ Failure ]
@@ -810,23 +663,17 @@
 Bug(none) images/color-profile-layer.html [ Failure ]
 Bug(none) images/color-profile-mask-image-svg.html [ Failure ]
 Bug(none) images/color-profile-reflection.html [ Crash Failure ]
-Bug(none) images/color-profile-svg-fill-text.html [ Failure ]
 Bug(none) images/color-profile-svg-foreign-object.html [ Failure ]
 Bug(none) images/content-url-image-with-alt-text-dynamic-2.html [ Pass Failure ]
 Bug(none) images/mask-box-image-crash.html [ Failure ]
-Bug(none) images/pixel-crack-image-background-webkit-transform-scale.html [ Failure ]
-Bug(none) images/sprite-no-bleed.html [ Failure ]
 Bug(none) fast/inline/inline-borders-with-bidi-override.html [ Failure ]
 Bug(none) fast/inline/inline-continuation-borders.html [ Failure ]
-Bug(none) fast/invalid/014.html [ Failure ]
 Bug(none) fast/layers/normal-flow-hit-test.html [ Crash Failure ]
 Bug(none) fast/layers/opacity-outline.html [ Failure ]
 Bug(none) fast/layers/opacity-transforms.html [ Failure ]
-Bug(none) fast/layers/overflow-hidden-clip-path-occlusion.html [ Failure ]
 Bug(none) fast/layers/overflow-hidden-rounded-corners-occlusion.html [ Failure ]
 Bug(none) fast/layers/remove-layer-with-nested-stacking.html [ Skip ]
 Bug(none) fast/layers/scroll-rect-to-visible.html [ Failure ]
-Bug(none) fast/layers/scroll-with-transform-layer.html [ Failure ]
 Bug(none) fast/lists/008.html [ Failure ]
 Bug(none) fast/lists/ol-start-parsing.html [ Failure ]
 Bug(none) fast/lists/olstart.html [ Failure ]
@@ -961,7 +808,6 @@
 Bug(none) fast/multicol/positive-leading.html [ Failure ]
 Bug(none) fast/multicol/pushed-line-affected-by-float.html [ Failure ]
 Bug(none) fast/multicol/scrolling-overflow.html [ Failure ]
-Bug(none) fast/multicol/shrink-to-column-height-for-pagination.html [ Failure ]
 Bug(none) fast/multicol/single-line.html [ Failure ]
 Bug(none) fast/multicol/span/abspos-containing-block-outside-spanner.html [ Failure ]
 Bug(none) fast/multicol/span/adjacent-spanners.html [ Failure ]
@@ -974,7 +820,6 @@
 Bug(none) fast/multicol/span/block-with-top-border-and-margin-around-spanner-exact-fit.html [ Failure ]
 Bug(none) fast/multicol/span/block-with-top-border-and-margin-around-spanner-extra-space.html [ Failure ]
 Bug(none) fast/multicol/span/change-multicol-writing-mode.html [ Failure ]
-Bug(none) fast/multicol/span/change-spanner-margins.html [ Failure ]
 Bug(none) fast/multicol/span/fill-after-spanner-exact-fit.html [ Failure ]
 Bug(none) fast/multicol/span/fill-after-spanner-extra-height.html [ Failure ]
 Bug(none) fast/multicol/span/float.html [ Failure ]
@@ -1033,16 +878,11 @@
 Bug(none) fast/multicol/vertical-rl/float-edge.html [ Failure ]
 Bug(none) fast/multicol/vertical-rl/float-paginate.html [ Failure ]
 Bug(none) fast/multicol/vertical-rl/unsplittable-inline-block.html [ Failure ]
-Bug(none) fast/overflow/001.html [ Failure ]
 Bug(none) fast/overflow/002.html [ Failure ]
 Bug(none) fast/overflow/006.html [ Failure ]
 Bug(none) fast/overflow/007.html [ Failure ]
-Bug(none) fast/overflow/border-radius-clipping.html [ Failure ]
 Bug(none) fast/overflow/childFocusRingClip.html [ Failure ]
 Bug(none) fast/overflow/clip-rects-fixed-ancestor.html [ Failure ]
-Bug(none) fast/overflow/dynamic-hidden.html [ Failure ]
-Bug(none) fast/overflow/float-in-relpositioned.html [ Failure ]
-Bug(none) fast/overflow/hit-test-overflow-controls.html [ Failure ]
 Bug(none) fast/overflow/image-selection-highlight.html [ Failure ]
 Bug(none) fast/overflow/overflow-focus-ring.html [ Failure ]
 Bug(none) fast/overflow/overflow-rtl-vertical.html [ Failure ]
@@ -1052,11 +892,8 @@
 Bug(none) fast/overflow/overflow-with-local-background-attachment.html [ Failure ]
 Bug(none) fast/overflow/overflow-x-y.html [ Failure ]
 Bug(none) fast/overflow/position-fixed-transform-clipping.html [ Failure ]
-Bug(none) fast/overflow/scroll-nested-positioned-layer-in-overflow.html [ Failure ]
-Bug(none) fast/overflow/scrollbar-position-update.html [ Failure ]
 Bug(none) fast/overflow/scrollRevealButton.html [ Failure ]
 Bug(none) fast/overflow/table-overflow-float.html [ Crash Failure ]
-Bug(none) fast/parser/document-write-option.html [ Failure ]
 Bug(none) fast/reflections/abs-position-in-reflection.html [ Crash Failure ]
 Bug(none) fast/reflections/opacity-reflection-transform.html [ Crash Failure ]
 Bug(none) fast/reflections/reflection-direction.html [ Crash Failure ]
@@ -1070,38 +907,24 @@
 Bug(none) fast/reflections/transparent-reflected-sublayers.html [ Crash Failure ]
 Bug(none) fast/replaced/border-radius-clip-content-edge.html [ Failure ]
 Bug(none) fast/replaced/border-radius-clip.html [ Failure ]
-Bug(none) fast/replaced/outline-replaced-elements.html [ Failure ]
-Bug(none) fast/replaced/replaced-breaking-mixture.html [ Failure ]
-Bug(none) fast/replaced/replaced-breaking.html [ Failure ]
-Bug(none) fast/replaced/selection-rect-transform.html [ Failure ]
-Bug(none) fast/replaced/width100percent-button.html [ Failure ]
 Bug(none) fast/replaced/width100percent-textarea.html [ Failure ]
 Bug(none) fast/scroll-behavior/ [ Skip ]
 Bug(none) fast/scrolling/overflow-clip-with-page-scale.html [ Crash Timeout ]
 Bug(none) fast/scrolling/scrollbar-tickmarks-styled-after-onload.html [ Failure ]
 Bug(none) fast/scrolling/scrollbar-tickmarks-styled.html [ Failure ]
 Bug(none) fast/selectors/166.html [ Failure ]
-Bug(none) fast/selectors/input-with-selection-pseudo-element.html [ Failure ]
-Bug(none) fast/shapes/shape-outside-floats/shape-outside-boxes-001.html [ Failure ]
-Bug(none) fast/shapes/shape-outside-floats/shape-outside-boxes-002.html [ Failure ]
-Bug(none) fast/shapes/shape-outside-floats/shape-outside-boxes-003.html [ Failure ]
-Bug(none) fast/shapes/shape-outside-floats/shape-outside-dynamic-shape-margin.html [ Failure ]
-Bug(none) fast/shapes/shape-outside-floats/shape-outside-dynamic-shape-overhang.html [ Failure ]
-Bug(none) fast/spatial-navigation/snav-multiple-select-focusring.html [ Failure ]
 Bug(none) fast/sub-pixel/column-clipping.html [ Failure ]
 Bug(none) fast/sub-pixel/ellipsis-zoom.html [ Crash Failure ]
 Bug(none) fast/sub-pixel/repaint-subpixel-layer-in-subpixel-composited-layer.html [ Failure ]
 Bug(none) fast/sub-pixel/should-not-repaint-subpixel-composited-layer.html [ Failure ]
 Bug(none) fast/sub-pixel/sub-pixel-composited-layer-with-transform.html [ Failure ]
 Bug(none) fast/sub-pixel/transformed-iframe-copy-on-scroll.html [ Failure ]
-Bug(none) fast/table/007.html [ Failure ]
 Bug(none) fast/table/023.html [ Failure ]
 Bug(none) fast/table/027-vertical.html [ Failure ]
 Bug(none) fast/table/040-vertical.html [ Failure ]
 Bug(none) fast/table/040.html [ Failure ]
 Bug(none) fast/table/border-collapsing/004.html [ Failure ]
 Bug(none) fast/table/dynamic-caption-add-before-child.xhtml [ Failure ]
-Bug(none) fast/table/edge-offsets.html [ Failure ]
 Bug(none) fast/table/empty-cells.html [ Failure ]
 Bug(none) fast/table/frame-and-rules.html [ Failure ]
 Bug(none) fast/table/height-percent-test.html [ Failure ]
@@ -1109,16 +932,9 @@
 Bug(none) fast/table/overflowHidden.html [ Failure ]
 Bug(none) fast/table/prepend-in-anonymous-table.html [ Failure ]
 Bug(none) fast/table/table-display-types-vertical.html [ Failure ]
-Bug(none) fast/table/text-field-baseline.html [ Failure ]
 Bug(none) fast/text-autosizing/hackernews-comments.html [ Failure ]
 Bug(none) fast/text/capitalize-boundaries.html [ Failure ]
-Bug(none) fast/text/caps-lock-indicator-disabled.html [ Failure ]
-Bug(none) fast/text/caps-lock-indicator-enabled-rtl.html [ Failure ]
-Bug(none) fast/text/caps-lock-indicator-enabled.html [ Failure ]
-Bug(none) fast/text/color-emoji.html [ Failure ]
-Bug(none) fast/text/decorations-transformed.html [ Failure ]
 Bug(none) fast/text/descent-clip-in-scaled-page.html [ Crash Timeout ]
-Bug(none) fast/text/drawBidiText.html [ Failure ]
 Bug(none) fast/text/ellipsis-ltr-text-in-ltr-flow-underline-composition.html [ Failure ]
 Bug(none) fast/text/ellipsis-ltr-text-in-rtl-flow-underline-composition.html [ Failure ]
 Bug(none) fast/text/ellipsis-rtl-text-in-ltr-flow-underline-composition.html [ Failure ]
@@ -1128,29 +944,17 @@
 Bug(none) fast/text/ellipsis-rtl-text-in-rtl-flow-underline.html [ Failure ]
 Bug(none) fast/text/ellipsis-rtl-text-in-rtl-flow.html [ Failure ]
 Bug(none) fast/text/ellipsis-stroked.html [ Failure ]
-Bug(none) fast/text/emoticons.html [ Failure ]
 Bug(none) fast/text/emphasis.html [ Failure ]
 Bug(none) fast/text/font-stretch-variant.html [ Failure ]
 Bug(none) fast/text/font-weight-variant.html [ Failure ]
-Bug(none) fast/text/international/bidi-listbox-atsui.html [ Failure ]
-Bug(none) fast/text/international/bidi-listbox.html [ Failure ]
 Bug(none) fast/text/international/bidi-neutral-run.html [ Failure ]
-Bug(none) fast/text/international/hindi-spacing.html [ Failure ]
-Bug(none) fast/text/international/inline-block-with-mixed-direction-words.html [ Failure ]
-Bug(none) fast/text/international/mixed-directionality-selection.html [ Failure ]
-Bug(none) fast/text/international/text-overflow-ellipsis-bidi.html [ Failure ]
 Bug(none) fast/text/letter-spacing-negative-opacity.html [ Failure ]
-Bug(none) fast/text/selection-hard-linebreak.html [ Failure ]
 Bug(none) fast/text/softHyphen.html [ Failure ]
 Bug(none) fast/text/stroking-decorations.html [ Failure Pass ]
-Bug(none) fast/text/textIteratorNilRenderer.html [ Failure ]
 Bug(none) fast/text/unicode-fallback-font.html [ Failure ]
 Bug(none) fast/text/whitespace/024.html [ Failure ]
-Bug(none) fast/text/whitespace/normal-after-nowrap-breaking.html [ Failure ]
-Bug(none) fast/text/whitespace/pre-wrap-overflow-selection.html [ Failure ]
 Bug(none) fast/text/whitespace/pre-wrap-spaces-after-newline.html [ Failure ]
 Bug(none) fast/text/word-break.html [ Failure ]
-Bug(none) fast/text/word-spacing-nbsp.html [ Failure ]
 Bug(none) fast/writing-mode/border-radius-clipping-vertical-lr.html [ Failure ]
 Bug(none) fast/writing-mode/fieldsets.html [ Failure ]
 Bug(none) svg/animations/animateMotion-accumulate-1a.svg [ Failure ]
@@ -1158,9 +962,7 @@
 Bug(none) svg/animations/animateMotion-accumulate-1c.svg [ Failure ]
 Bug(none) svg/animations/animateMotion-accumulate-2a.svg [ Failure ]
 Bug(none) svg/animations/animateMotion-accumulate-2b.svg [ Failure ]
-Bug(none) svg/as-background-image/svg-transformed-background.html [ Failure ]
 Bug(none) svg/as-background-image/tiled-background-image.html [ Crash Timeout ]
-Bug(none) svg/as-image/image-preserveAspectRatio-all.svg [ Failure ]
 Bug(none) svg/as-image/image-respects-pageScaleFactor.html [ Crash Timeout ]
 Bug(none) svg/as-image/img-preserveAspectRatio-support-1.html [ Failure ]
 Bug(none) svg/as-image/img-preserveAspectRatio-support-2.html [ Crash Failure ]
@@ -1181,7 +983,6 @@
 Bug(none) svg/batik/text/textAnchor2.svg [ Failure ]
 Bug(none) svg/batik/text/textAnchor3.svg [ Failure ]
 Bug(none) svg/batik/text/textDecoration.svg [ Failure ]
-Bug(none) svg/batik/text/textDecoration2.svg [ Failure ]
 Bug(none) svg/batik/text/textEffect.svg [ Failure ]
 Bug(none) svg/batik/text/textEffect2.svg [ Failure ]
 Bug(none) svg/batik/text/textEffect3.svg [ Failure ]
@@ -1194,7 +995,6 @@
 Bug(none) svg/batik/text/textOnPath2.svg [ Failure ]
 Bug(none) svg/batik/text/textOnPath3.svg [ Failure ]
 Bug(none) svg/batik/text/textOnPathSpaces.svg [ Failure ]
-Bug(none) svg/batik/text/textPCDATA.svg [ Failure ]
 Bug(none) svg/batik/text/textPosition.svg [ Failure ]
 Bug(none) svg/batik/text/textPosition2.svg [ Failure ]
 Bug(none) svg/batik/text/textProperties.svg [ Failure ]
@@ -1209,27 +1009,18 @@
 Bug(none) svg/carto.net/selectionlist.svg [ Failure ]
 Bug(none) svg/carto.net/slider.svg [ Failure ]
 Bug(none) svg/carto.net/textbox.svg [ Failure ]
-Bug(none) svg/css/text-shadow-multiple.xhtml [ Failure ]
 Bug(none) svg/custom/absolute-root-position-masking.xhtml [ Failure ]
-Bug(none) svg/custom/alignment-baseline-modes.svg [ Failure ]
 Bug(none) svg/custom/bug45331.svg [ Failure ]
-Bug(none) svg/custom/circular-marker-reference-1.svg [ Failure ]
-Bug(none) svg/custom/circular-marker-reference-2.svg [ Failure ]
-Bug(none) svg/custom/circular-marker-reference-3.svg [ Failure ]
-Bug(none) svg/custom/circular-marker-reference-4.svg [ Failure ]
 Bug(none) svg/custom/clamped-masking-clipping.svg [ Failure ]
 Bug(none) svg/custom/clip-mask-negative-scale.svg [ Failure ]
 Bug(none) svg/custom/clip-path-referencing-use.svg [ Failure ]
 Bug(none) svg/custom/clip-path-with-css-transform-1.svg [ Failure ]
 Bug(none) svg/custom/clip-path-with-css-transform-2.svg [ Failure ]
 Bug(none) svg/custom/clip-path-with-transform.svg [ Failure ]
-Bug(none) svg/custom/clone-element-with-animated-svg-properties.html [ Failure ]
 Bug(none) svg/custom/container-opacity-clip-viewBox.svg [ Failure ]
 Bug(none) svg/custom/coords-relative-units-transforms.svg [ Failure ]
 Bug(none) svg/custom/cross-referenced-resources.html [ Failure ]
 Bug(none) svg/custom/dominant-baseline-hanging.svg [ Failure ]
-Bug(none) svg/custom/dominant-baseline-modes.svg [ Failure ]
-Bug(none) svg/custom/dynamic-empty-path.svg [ Failure ]
 Bug(none) svg/custom/embedding-external-svgs.xhtml [ Failure ]
 Bug(none) svg/custom/feComponentTransfer-Discrete.svg [ Failure ]
 Bug(none) svg/custom/feComponentTransfer-Gamma.svg [ Failure ]
@@ -1238,55 +1029,32 @@
 Bug(none) svg/custom/feDisplacementMap-01.svg [ Failure ]
 Bug(none) svg/custom/focus-ring.svg [ Failure ]
 Bug(none) svg/custom/foreign-object-skew.svg [ Failure ]
-Bug(none) svg/custom/fractional-rects.svg [ Failure ]
 Bug(none) svg/custom/getscreenctm-in-scrollable-div-area-nested.xhtml [ Failure ]
 Bug(none) svg/custom/getscreenctm-in-scrollable-div-area.xhtml [ Failure ]
 Bug(none) svg/custom/getscreenctm-in-scrollable-svg-area.xhtml [ Failure ]
-Bug(none) svg/custom/gradient-deep-referencing.svg [ Failure ]
-Bug(none) svg/custom/gradient-rotated-bbox.svg [ Failure ]
-Bug(none) svg/custom/gradient-stop-corner-cases.svg [ Failure ]
-Bug(none) svg/custom/gradient-with-1d-boundingbox.svg [ Failure ]
 Bug(none) svg/custom/grayscale-gradient-mask-2.svg [ Failure ]
 Bug(none) svg/custom/grayscale-gradient-mask.svg [ Failure ]
 Bug(none) svg/custom/group-opacity.svg [ Failure ]
 Bug(none) svg/custom/image-with-preserveAspectRatio-none.html [ Failure ]
 Bug(none) svg/custom/image-with-transform-clip-filter.svg [ Failure ]
 Bug(none) svg/custom/inline-svg-in-xhtml.xml [ Failure ]
-Bug(none) svg/custom/invalid-css.svg [ Failure ]
 Bug(none) svg/custom/invalid-stroke-hex.svg [ Failure ]
 Bug(none) svg/custom/junk-data.svg [ Failure ]
-Bug(none) svg/custom/linking-a-03-b-all.svg [ Failure ]
 Bug(none) svg/custom/linking-a-03-b-transform.svg [ Failure ]
 Bug(none) svg/custom/linking-a-03-b-viewBox-transform.svg [ Failure ]
 Bug(none) svg/custom/linking-a-03-b-viewBox.svg [ Failure ]
 Bug(none) svg/custom/linking-uri-01-b.svg [ Failure ]
 Bug(none) svg/custom/load-non-wellformed.svg [ Failure ]
 Bug(none) svg/custom/local-url-references.html [ Failure ]
-Bug(none) svg/custom/marker-default-width-height.svg [ Failure ]
-Bug(none) svg/custom/marker-orient-auto.html [ Failure ]
-Bug(none) svg/custom/marker-referencePoint.svg [ Failure ]
 Bug(none) svg/custom/mask-colorspace.svg [ Failure ]
 Bug(none) svg/custom/mask-inside-defs.svg [ Failure ]
 Bug(none) svg/custom/mask-with-all-units.svg [ Failure ]
 Bug(none) svg/custom/mask-with-default-value.svg [ Failure ]
 Bug(none) svg/custom/masking-clipping-hidpi.svg [ Failure ]
 Bug(none) svg/custom/missing-xlink.svg [ Failure ]
-Bug(none) svg/custom/mouse-move-on-svg-container-standalone.svg [ Failure ]
-Bug(none) svg/custom/mouse-move-on-svg-container.xhtml [ Failure ]
-Bug(none) svg/custom/no-inherited-dashed-stroke.xhtml [ Failure ]
-Bug(none) svg/custom/non-circular-marker-reference.svg [ Failure ]
 Bug(none) svg/custom/non-scaling-stroke.svg [ Failure ]
 Bug(none) svg/custom/object-sizing-no-width-height.xhtml [ Failure ]
-Bug(none) svg/custom/object-sizing.xhtml [ Failure ]
 Bug(none) svg/custom/path-bad-data.svg [ Failure ]
-Bug(none) svg/custom/path-moveto-only-rendering.svg [ Failure ]
-Bug(none) svg/custom/path-textPath-simulation.svg [ Failure ]
-Bug(none) svg/custom/path-update.svg [ Failure ]
-Bug(none) svg/custom/pattern-deep-referencing.svg [ Failure ]
-Bug(none) svg/custom/pattern-rotate-gaps.svg [ Failure ]
-Bug(none) svg/custom/pattern-rotate.svg [ Failure ]
-Bug(none) svg/custom/pattern-scaling.svg [ Failure ]
-Bug(none) svg/custom/pointer-events-image-css-transform.svg [ Failure ]
 Bug(none) svg/custom/pointer-events-text-css-transform.svg [ Crash Timeout Failure ]
 Bug(none) svg/custom/preserve-aspect-ratio-syntax.svg [ Failure ]
 Bug(none) svg/custom/recursive-clippath.svg [ Failure ]
@@ -1296,96 +1064,37 @@
 Bug(none) svg/custom/root-container-opacity-clip-viewBox.svg [ Failure ]
 Bug(none) svg/custom/shape-rendering.svg [ Failure ]
 Bug(none) svg/custom/shapes-supporting-markers.svg [ Failure ]
-Bug(none) svg/custom/stroke-width-large.svg [ Failure ]
-Bug(none) svg/custom/stroked-pattern.svg [ Failure ]
-Bug(none) svg/custom/subpaths-moveto-only-rendering.svg [ Failure ]
-Bug(none) svg/custom/svg-float-border-padding.xml [ Failure ]
-Bug(none) svg/custom/svg-image-par-none-no-intrinsic-size.html [ Failure ]
 Bug(none) svg/custom/svg-overflow-types.svg [ Failure ]
-Bug(none) svg/custom/svg-root-padding-border-margin.html [ Failure ]
 Bug(none) svg/custom/text-clip.svg [ Failure ]
-Bug(none) svg/custom/text-dom-01-f.svg [ Failure ]
-Bug(none) svg/custom/text-match-highlight.html [ Failure ]
-Bug(none) svg/custom/text-rotated-gradient.svg [ Failure ]
-Bug(none) svg/custom/text-whitespace-handling.svg [ Failure ]
-Bug(none) svg/custom/text-x-dy-lists.svg [ Failure ]
 Bug(none) svg/custom/transformed-outlines.svg [ Failure ]
 Bug(none) svg/custom/transformed-pattern-clamp-svg-root.svg [ Failure ]
 Bug(none) svg/custom/use-clipped-transform.svg [ Failure ]
 Bug(none) svg/custom/use-css-no-effect-on-shadow-tree.svg [ Failure ]
 Bug(none) svg/custom/use-font-face-crash.svg [ Failure ]
-Bug(none) svg/custom/use-forward-refs.svg [ Failure ]
 Bug(none) svg/custom/use-modify-container-in-target.svg [ Failure ]
 Bug(none) svg/custom/use-modify-target-container.svg [ Failure ]
 Bug(none) svg/custom/use-nested-transform.svg [ Failure ]
 Bug(none) svg/custom/use-on-clip-path-with-transformation.svg [ Failure ]
-Bug(none) svg/custom/use-on-disallowed-foreign-object-1.svg [ Failure ]
-Bug(none) svg/custom/use-on-disallowed-foreign-object-2.svg [ Failure ]
-Bug(none) svg/custom/use-on-disallowed-foreign-object-3.svg [ Failure ]
-Bug(none) svg/custom/use-on-disallowed-foreign-object-4.svg [ Failure ]
-Bug(none) svg/custom/use-on-disallowed-foreign-object-5.svg [ Failure ]
-Bug(none) svg/custom/use-on-disallowed-foreign-object-6.svg [ Failure ]
 Bug(none) svg/custom/use-on-g-containing-use.svg [ Failure ]
 Bug(none) svg/custom/use-on-g.svg [ Failure ]
-Bug(none) svg/custom/use-on-non-svg-namespaced-element.svg [ Failure ]
-Bug(none) svg/custom/use-on-rect.svg [ Failure ]
-Bug(none) svg/custom/use-on-symbol-inside-pattern.svg [ Failure ]
-Bug(none) svg/custom/use-on-symbol.svg [ Failure ]
-Bug(none) svg/custom/use-on-text.svg [ Failure ]
 Bug(none) svg/custom/use-on-use.svg [ Failure ]
-Bug(none) svg/custom/use-property-changes-through-dom.svg [ Failure ]
-Bug(none) svg/custom/use-property-changes-through-svg-dom.svg [ Failure ]
-Bug(none) svg/custom/use-referencing-nonexisting-symbol.svg [ Failure ]
 Bug(none) svg/custom/use-transform.svg [ Failure ]
-Bug(none) svg/custom/viewBox-hit.svg [ Failure ]
 Bug(none) svg/custom/viewbox-syntax.svg [ Failure ]
 Bug(none) svg/custom/viewport-clippath-invalidation.html [ Failure ]
 Bug(none) svg/custom/visibility-override-clip.svg [ Failure ]
 Bug(none) svg/custom/visibility-override-mask.svg [ Failure ]
 Bug(none) svg/custom/visited-link-color.svg [ Failure ]
 Bug(none) svg/custom/width-full-percentage.svg [ Failure ]
-Bug(none) svg/custom/zero-path-square-cap-rendering2.svg [ Failure ]
-Bug(none) svg/custom/zoomed-background-alignment.html [ Failure ]
-Bug(none) svg/dom/complex-svgView-specification.html [ Failure ]
 Bug(none) svg/dom/css-transforms.xhtml [ Failure ]
 Bug(none) svg/dom/SVGStringList-basics.xhtml [ Failure ]
 Bug(none) svg/dynamic-updates/SVG-dynamic-css-transform.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGCircleElement-dom-cx-attr.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGCircleElement-dom-cy-attr.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGCircleElement-dom-r-attr.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGCircleElement-svgdom-cx-prop.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGCircleElement-svgdom-cy-prop.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGCircleElement-svgdom-r-prop.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGEllipseElement-dom-cx-attr.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGEllipseElement-dom-cy-attr.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGEllipseElement-dom-rx-attr.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGEllipseElement-dom-ry-attr.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGEllipseElement-svgdom-cx-prop.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGEllipseElement-svgdom-cy-prop.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGEllipseElement-svgdom-rx-prop.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGEllipseElement-svgdom-ry-prop.html [ Failure ]
 Bug(none) svg/dynamic-updates/SVGFEColorMatrixElement-dom-in-attr.html [ Failure ]
 Bug(none) svg/dynamic-updates/SVGFEColorMatrixElement-dom-type-attr.html [ Failure ]
 Bug(none) svg/dynamic-updates/SVGFEColorMatrixElement-dom-values-attr.html [ Failure ]
 Bug(none) svg/dynamic-updates/SVGFEColorMatrixElement-svgdom-in-prop.html [ Failure ]
 Bug(none) svg/dynamic-updates/SVGFEColorMatrixElement-svgdom-type-prop.html [ Failure ]
 Bug(none) svg/dynamic-updates/SVGFEColorMatrixElement-svgdom-values-prop.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGFEImageElement-dom-preserveAspectRatio-attr.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGFEImageElement-svgdom-preserveAspectRatio-prop.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGFEMergeNodeElement-dom-in-attr.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGFEMergeNodeElement-svgdom-in-prop.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGLinearGradientElement-dom-gradientTransform-attr.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGLinearGradientElement-dom-gradientUnits-attr.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGLinearGradientElement-dom-x1-attr.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGLinearGradientElement-dom-x2-attr.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGLinearGradientElement-dom-y1-attr.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGLinearGradientElement-dom-y2-attr.html [ Failure ]
 Bug(none) svg/dynamic-updates/SVGLinearGradientElement-svgdom-gradientTransform-prop.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGLinearGradientElement-svgdom-gradientUnits-prop.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGLinearGradientElement-svgdom-x1-prop.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGLinearGradientElement-svgdom-x2-prop.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGLinearGradientElement-svgdom-y1-prop.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGLinearGradientElement-svgdom-y2-prop.html [ Failure ]
 Bug(none) svg/dynamic-updates/SVGMaskElement-dom-height-attr.html [ Failure ]
 Bug(none) svg/dynamic-updates/SVGMaskElement-dom-maskContentUnits-attr.html [ Failure ]
 Bug(none) svg/dynamic-updates/SVGMaskElement-dom-maskUnits-attr.html [ Failure ]
@@ -1398,23 +1107,7 @@
 Bug(none) svg/dynamic-updates/SVGMaskElement-svgdom-width-prop.html [ Failure ]
 Bug(none) svg/dynamic-updates/SVGMaskElement-svgdom-x-prop.html [ Failure ]
 Bug(none) svg/dynamic-updates/SVGMaskElement-svgdom-y-prop.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGRadialGradientElement-dom-cx-attr.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGRadialGradientElement-dom-cy-attr.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGRadialGradientElement-dom-fx-attr.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGRadialGradientElement-dom-fy-attr.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGRadialGradientElement-dom-gradientTransform-attr.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGRadialGradientElement-dom-gradientUnits-attr.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGRadialGradientElement-dom-r-attr.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGRadialGradientElement-svgdom-cx-prop.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGRadialGradientElement-svgdom-cy-prop.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGRadialGradientElement-svgdom-fx-prop.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGRadialGradientElement-svgdom-fy-prop.html [ Failure ]
 Bug(none) svg/dynamic-updates/SVGRadialGradientElement-svgdom-gradientTransform-prop.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGRadialGradientElement-svgdom-gradientUnits-prop.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGRadialGradientElement-svgdom-r-prop.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGTextElement-dom-lengthAdjust-attr.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGTextElement-dom-rotate-attr.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGTextElement-svgdom-lengthAdjust-prop.html [ Failure ]
 Bug(none) svg/filters/big-sized-filter.svg [ Failure ]
 Bug(none) svg/filters/feDropShadow.svg [ Failure ]
 Bug(none) svg/filters/feImage-filterUnits-objectBoundingBox-primitiveUnits-objectBoundingBox.svg [ Failure ]
@@ -1422,16 +1115,11 @@
 Bug(none) svg/filters/feImage-filterUnits-userSpaceOnUse-primitiveUnits-objectBoundingBox.svg [ Failure ]
 Bug(none) svg/filters/feImage-filterUnits-userSpaceOnUse-primitiveUnits-userSpaceOnUse.svg [ Failure ]
 Bug(none) svg/filters/feImage-late-indirect-update.svg [ Failure ]
-Bug(none) svg/filters/feImage-preserveAspectRatio-all.svg [ Failure ]
-Bug(none) svg/filters/feImage-reference-svg-primitive.svg [ Failure ]
 Bug(none) svg/filters/feImage-subregions-preseveAspectRatio-none-with-viewBox.svg [ Failure ]
 Bug(none) svg/filters/feImage-subregions-preseveAspectRatio-none.svg [ Failure ]
 Bug(none) svg/filters/feImage-subregions.svg [ Failure ]
-Bug(none) svg/filters/feLighting-crash.svg [ Failure ]
-Bug(none) svg/filters/feTile.svg [ Failure ]
 Bug(none) svg/filters/filter-clip.svg [ Failure ]
 Bug(none) svg/filters/filter-huge-clamping.svg [ Failure ]
-Bug(none) svg/filters/filter-on-tspan.svg [ Failure ]
 Bug(none) svg/filters/subRegion-one-effect.svg [ Failure ]
 Bug(none) svg/filters/subRegion-two-effects.svg [ Failure ]
 Bug(none) svg/filters/svg-element-invalid-filter.html [ Failure ]
@@ -1443,23 +1131,14 @@
 Bug(none) svg/hixie/error/012.xml [ Failure ]
 Bug(none) svg/hixie/error/017.xml [ Failure ]
 Bug(none) svg/hixie/intrinsic/003.html [ Crash Failure ]
-Bug(none) svg/hixie/links/001.xml [ Failure ]
-Bug(none) svg/hixie/mixed/004.xml [ Failure ]
-Bug(none) svg/hixie/mixed/005.xml [ Failure ]
 Bug(none) svg/hixie/mixed/006.xml [ Failure ]
-Bug(none) svg/hixie/mixed/008.xml [ Failure ]
 Bug(none) svg/hixie/mixed/009.xml [ Failure ]
 Bug(none) svg/hixie/mixed/011.xml [ Failure ]
-Bug(none) svg/hixie/perf/001.xml [ Failure ]
-Bug(none) svg/hixie/perf/002.xml [ Failure ]
-Bug(none) svg/hixie/perf/003.xml [ Failure ]
 Bug(none) svg/hixie/perf/004.xml [ Failure ]
 Bug(none) svg/hixie/perf/005.xml [ Failure ]
 Bug(none) svg/hixie/perf/006.xml [ Failure ]
 Bug(none) svg/hixie/perf/007.xml [ Failure ]
 Bug(none) svg/hixie/viewbox/preserveAspectRatio/001.xml [ Failure ]
-Bug(none) svg/in-html/circle.html [ Failure ]
-Bug(none) svg/markers/marker-orientation-minus-one.html [ Failure ]
 Bug(none) svg/overflow/overflow-on-foreignObject.svg [ Failure Pass ]
 Bug(none) svg/overflow/overflow-on-inner-svg-element-defaults.svg [ Failure ]
 Bug(none) svg/overflow/overflow-on-inner-svg-element.svg [ Failure ]
@@ -1467,83 +1146,27 @@
 Bug(none) svg/overflow/overflow-on-outermost-svg-element-ignore-attribute-2.svg [ Failure ]
 Bug(none) svg/overflow/overflow-on-outermost-svg-element-ignore-attribute-3.svg [ Failure ]
 Bug(none) svg/overflow/overflow-on-outermost-svg-element-in-xhtml-defaults.xhtml [ Failure ]
-Bug(none) svg/stroke/non-scaling-stroke-zero-length-subpath-linecaps.html [ Failure ]
 Bug(none) svg/stroke/zero-length-arc-linecaps-rendering.svg [ Failure ]
 Bug(none) svg/stroke/zero-length-path-linecap-rendering.svg [ Failure ]
 Bug(none) svg/stroke/zero-length-subpaths-linecap-rendering.svg [ Failure ]
-Bug(none) svg/text/bbox-with-glyph-overflow-on-path.html [ Failure ]
-Bug(none) svg/text/bbox-with-glyph-overflow-zoomed.html [ Failure ]
-Bug(none) svg/text/bbox-with-glyph-overflow.html [ Failure ]
-Bug(none) svg/text/bidi-embedded-direction.svg [ Failure ]
-Bug(none) svg/text/bidi-text-anchor-direction.svg [ Failure ]
-Bug(none) svg/text/bidi-text-query.svg [ Failure ]
-Bug(none) svg/text/bidi-tspans.svg [ Failure ]
 Bug(none) svg/text/combining-character-queries.html [ Failure ]
-Bug(none) svg/text/font-size-below-point-five-2.svg [ Failure ]
 Bug(none) svg/text/foreignObject-text-clipping-bug.xml [ Failure ]
-Bug(none) svg/text/ligature-queries.html [ Failure ]
-Bug(none) svg/text/non-invertible-matrix-text.svg [ Failure ]
-Bug(none) svg/text/scaled-font.svg [ Failure ]
-Bug(none) svg/text/scaling-font-with-geometric-precision.html [ Failure ]
-Bug(none) svg/text/select-textLength-spacing-squeeze-1.svg [ Failure ]
-Bug(none) svg/text/select-textLength-spacing-squeeze-2.svg [ Failure ]
-Bug(none) svg/text/select-textLength-spacing-squeeze-3.svg [ Failure ]
-Bug(none) svg/text/select-textLength-spacing-squeeze-4.svg [ Failure ]
-Bug(none) svg/text/select-textLength-spacing-stretch-1.svg [ Failure ]
-Bug(none) svg/text/select-textLength-spacing-stretch-2.svg [ Failure ]
-Bug(none) svg/text/select-textLength-spacing-stretch-3.svg [ Failure ]
-Bug(none) svg/text/select-textLength-spacing-stretch-4.svg [ Failure ]
-Bug(none) svg/text/select-textLength-spacingAndGlyphs-squeeze-1.svg [ Failure ]
-Bug(none) svg/text/select-textLength-spacingAndGlyphs-squeeze-2.svg [ Failure ]
-Bug(none) svg/text/select-textLength-spacingAndGlyphs-squeeze-3.svg [ Failure ]
 Bug(none) svg/text/select-textLength-spacingAndGlyphs-squeeze-4.svg [ Failure ]
-Bug(none) svg/text/select-textLength-spacingAndGlyphs-stretch-1.svg [ Failure ]
-Bug(none) svg/text/select-textLength-spacingAndGlyphs-stretch-2.svg [ Failure ]
-Bug(none) svg/text/select-textLength-spacingAndGlyphs-stretch-3.svg [ Failure ]
-Bug(none) svg/text/select-textLength-spacingAndGlyphs-stretch-4.svg [ Failure ]
-Bug(none) svg/text/select-x-list-1.svg [ Failure ]
-Bug(none) svg/text/select-x-list-2.svg [ Failure ]
-Bug(none) svg/text/select-x-list-3.svg [ Failure ]
-Bug(none) svg/text/select-x-list-4.svg [ Failure ]
-Bug(none) svg/text/select-x-list-with-tspans-1.svg [ Failure ]
-Bug(none) svg/text/select-x-list-with-tspans-2.svg [ Failure ]
-Bug(none) svg/text/select-x-list-with-tspans-3.svg [ Failure ]
-Bug(none) svg/text/select-x-list-with-tspans-4.svg [ Failure ]
-Bug(none) svg/text/selection-background-color.xhtml [ Failure ]
-Bug(none) svg/text/selection-doubleclick.svg [ Failure ]
 Bug(none) svg/text/selection-styles.xhtml [ Failure ]
-Bug(none) svg/text/selection-tripleclick.svg [ Failure ]
-Bug(none) svg/text/small-fonts-2.svg [ Failure ]
 Bug(none) svg/text/small-fonts-3.svg [ Failure ]
 Bug(none) svg/text/small-fonts.svg [ Crash Timeout Failure ]
-Bug(none) svg/text/surrogate-pair-queries.html [ Failure ]
 Bug(none) svg/text/text-fill-opacity.svg [ Failure ]
-Bug(none) svg/text/text-repaint-rects.xhtml [ Failure ]
 Bug(none) svg/text/text-selection-align-01-b.svg [ Failure ]
 Bug(none) svg/text/text-selection-align-02-b.svg [ Failure ]
 Bug(none) svg/text/text-selection-align-03-b.svg [ Failure ]
 Bug(none) svg/text/text-selection-align-04-b.svg [ Failure ]
 Bug(none) svg/text/text-selection-align-05-b.svg [ Failure ]
 Bug(none) svg/text/text-selection-align-06-b.svg [ Failure ]
-Bug(none) svg/text/text-selection-deco-01-b.svg [ Failure ]
-Bug(none) svg/text/text-selection-fonts-01-t.svg [ Failure ]
-Bug(none) svg/text/text-selection-fonts-02-t.svg [ Failure ]
-Bug(none) svg/text/text-selection-intro-05-t.svg [ Failure ]
 Bug(none) svg/text/text-selection-path-01-b.svg [ Failure ]
-Bug(none) svg/text/text-selection-spacing-01-b.svg [ Failure ]
-Bug(none) svg/text/text-selection-text-01-b.svg [ Failure ]
-Bug(none) svg/text/text-selection-text-03-b.svg [ Failure ]
 Bug(none) svg/text/text-selection-text-04-t.svg [ Failure ]
-Bug(none) svg/text/text-selection-text-06-t.svg [ Failure ]
-Bug(none) svg/text/text-selection-text-07-t.svg [ Failure ]
 Bug(none) svg/text/text-selection-text-08-b.svg [ Failure ]
-Bug(none) svg/text/text-selection-tselect-01-b.svg [ Failure ]
-Bug(none) svg/text/text-selection-tselect-02-f.svg [ Failure ]
-Bug(none) svg/text/text-selection-tspan-01-b.svg [ Failure ]
-Bug(none) svg/text/text-selection-ws-01-t.svg [ Failure ]
 Bug(none) svg/text/text-selection-ws-02-t.svg [ Failure ]
 Bug(none) svg/text/text-with-geometric-precision.svg [ Crash Failure ]
-Bug(none) svg/text/textPathBoundsBug.svg [ Failure ]
 Bug(none) svg/transforms/svg-css-transforms-clip-path.xhtml [ Failure ]
 Bug(none) svg/transforms/svg-css-transforms.xhtml [ Failure ]
 Bug(none) svg/transforms/text-with-mask-with-svg-transform.svg [ Failure ]
@@ -1596,24 +1219,16 @@
 Bug(none) svg/W3C-SVG-1.1-SE/coords-units-03-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1-SE/filters-image-03-f.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1-SE/filters-image-05-f.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1-SE/linking-uri-01-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1-SE/painting-marker-05-f.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1-SE/painting-marker-06-f.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1-SE/pservers-grad-17-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1-SE/pservers-grad-20-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1-SE/pservers-pattern-03-f.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1-SE/struct-use-11-f.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1-SE/struct-use-14-f.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1-SE/svgdom-over-01-f.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1-SE/text-tspan-02-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1-SE/types-dom-01-b.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1-SE/types-dom-02-f.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1-SE/types-dom-04-b.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1-SE/types-dom-06-f.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1-SE/types-dom-07-f.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/animate-elem-02-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/animate-elem-04-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/animate-elem-05-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/animate-elem-06-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/animate-elem-07-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/animate-elem-08-t.svg [ Failure ]
@@ -1628,10 +1243,7 @@
 Bug(none) svg/W3C-SVG-1.1/animate-elem-18-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/animate-elem-19-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/animate-elem-24-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/animate-elem-25-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/animate-elem-28-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/animate-elem-30-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/animate-elem-31-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/animate-elem-33-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/animate-elem-34-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/animate-elem-36-t.svg [ Failure ]
@@ -1639,9 +1251,7 @@
 Bug(none) svg/W3C-SVG-1.1/animate-elem-39-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/animate-elem-40-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/animate-elem-41-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/animate-elem-44-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/animate-elem-46-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/animate-elem-52-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/animate-elem-60-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/animate-elem-61-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/animate-elem-62-t.svg [ Failure ]
@@ -1659,49 +1269,33 @@
 Bug(none) svg/W3C-SVG-1.1/animate-elem-81-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/animate-elem-82-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/animate-elem-83-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/animate-elem-84-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/coords-coord-01-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/coords-coord-02-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/coords-trans-01-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/coords-trans-02-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/coords-trans-03-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/coords-trans-04-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/coords-trans-05-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/coords-trans-06-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/coords-units-01-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/coords-units-02-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/coords-viewattr-01-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/coords-viewattr-02-b.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/coords-viewattr-03-b.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/extend-namespace-01-f.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/filters-blend-01-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/filters-color-01-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/filters-composite-02-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/filters-comptran-01-b.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/filters-conv-01-f.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/filters-diffuse-01-f.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/filters-displace-01-f.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/filters-example-01-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/filters-gauss-01-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/filters-image-01-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/filters-light-01-f.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/filters-light-04-f.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/filters-morph-01-f.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/filters-offset-01-b.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/filters-specular-01-f.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/filters-turb-02-f.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/fonts-elem-03-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/fonts-elem-04-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/fonts-elem-07-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/interact-events-01-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/interact-zoom-01-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/linking-a-01-b.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/linking-a-02-b.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/linking-a-03-b.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/linking-a-04-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/linking-a-05-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/linking-a-07-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/linking-uri-02-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/masking-intro-01-f.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/masking-mask-01-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/masking-opacity-01-b.svg [ Failure ]
@@ -1713,27 +1307,14 @@
 Bug(none) svg/W3C-SVG-1.1/metadata-example-01-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/painting-fill-03-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/painting-fill-04-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/painting-marker-01-f.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/painting-marker-02-f.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/painting-marker-03-f.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/painting-render-01-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/painting-stroke-01-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/painting-stroke-02-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/painting-stroke-03-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/painting-stroke-04-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/painting-stroke-07-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/paths-data-02-t.svg [ Pass Failure ]
-Bug(none) svg/W3C-SVG-1.1/paths-data-04-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/paths-data-05-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/paths-data-06-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/paths-data-07-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/paths-data-08-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/paths-data-09-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/paths-data-10-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/paths-data-14-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/paths-data-15-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/pservers-grad-07-b.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/pservers-grad-08-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/pservers-grad-09-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/pservers-grad-12-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/pservers-grad-13-b.svg [ Failure ]
@@ -1748,14 +1329,10 @@
 Bug(none) svg/W3C-SVG-1.1/shapes-circle-02-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/shapes-ellipse-02-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/shapes-rect-02-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/struct-cond-03-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/struct-frag-02-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/struct-frag-03-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/struct-frag-06-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/struct-group-01-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/struct-group-02-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/struct-group-03-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/struct-image-02-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/struct-image-06-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/struct-image-08-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/struct-image-09-t.svg [ Failure ]
@@ -1763,9 +1340,6 @@
 Bug(none) svg/W3C-SVG-1.1/struct-symbol-01-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/struct-use-01-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/struct-use-03-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/styling-css-01-b.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/styling-css-02-b.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/styling-css-03-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/text-align-01-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/text-align-02-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/text-align-03-b.svg [ Failure ]
@@ -1775,18 +1349,11 @@
 Bug(none) svg/W3C-SVG-1.1/text-align-08-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/text-intro-03-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/text-path-01-b.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/text-spacing-01-b.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/text-text-01-b.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/text-text-04-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/text-text-05-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/text-text-06-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/text-text-08-b.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.1/text-tselect-02-f.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/text-ws-02-t.svg [ Failure ]
 Bug(none) svg/W3C-SVG-1.1/types-basicDOM-01-b.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.2-Tiny/struct-use-recursion-01-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.2-Tiny/struct-use-recursion-02-t.svg [ Failure ]
-Bug(none) svg/W3C-SVG-1.2-Tiny/struct-use-recursion-03-t.svg [ Failure ]
 Bug(none) svg/wicd/test-rightsizing-b.xhtml [ Crash ]
 Bug(none) svg/wicd/test-scalable-background-image1.xhtml [ Failure ]
 Bug(none) svg/zoom/page/absolute-sized-document-scrollbars.svg [ Failure ]
@@ -1798,29 +1365,18 @@
 Bug(none) svg/zoom/page/zoom-hixie-mixed-009.xml [ Failure ]
 Bug(none) svg/zoom/page/zoom-img-preserveAspectRatio-support-1.html [ Crash Failure Timeout ]
 Bug(none) svg/zoom/page/zoom-mask-with-percentages.svg [ Failure ]
-Bug(none) svg/zoom/page/zoom-replaced-intrinsic-ratio-001.htm [ Failure ]
-Bug(none) svg/zoom/page/zoom-svg-as-object.html [ Failure ]
 Bug(none) svg/zoom/page/zoom-svg-float-border-padding.xml [ Failure ]
-Bug(none) svg/zoom/page/zoom-svg-through-object-with-absolute-size-2.xhtml [ Failure ]
-Bug(none) svg/zoom/page/zoom-svg-through-object-with-absolute-size.xhtml [ Failure ]
-Bug(none) svg/zoom/page/zoom-svg-through-object-with-auto-size.html [ Failure ]
 Bug(none) svg/zoom/page/zoom-svg-through-object-with-huge-size.xhtml [ Failure ]
 Bug(none) svg/zoom/page/zoom-svg-through-object-with-override-size.html [ Failure ]
-Bug(none) svg/zoom/page/zoom-svg-through-object-with-percentage-size.xhtml [ Failure ]
 Bug(none) svg/zoom/text/zoom-hixie-mixed-008.xml [ Failure ]
 Bug(none) svg/zoom/text/zoom-hixie-mixed-009.xml [ Failure ]
 Bug(none) svg/zoom/text/zoom-svg-float-border-padding.xml [ Failure ]
-Bug(none) transforms/diamond.html [ Failure ]
-Bug(none) transforms/matrix-01.html [ Failure ]
-Bug(none) transforms/matrix-02.html [ Failure ]
 Bug(none) transforms/rotated-transform-affects-scrolling-1.html [ Failure ]
 Bug(none) transforms/rotated-transform-affects-scrolling-2.html [ Failure ]
 Bug(none) transforms/shadows.html [ Failure ]
-Bug(none) transforms/skew-with-unitless-zero.html [ Failure ]
 Bug(none) transforms/transform-on-inline.html [ Failure ]
 Bug(none) transforms/transform-table-row.html [ Failure ]
 Bug(none) transforms/transformed-caret.html [ Pass Failure ]
-Bug(none) transforms/transformed-document-element.html [ Failure ]
 Bug(none) transforms/transformed-focused-text-input.html [ Failure ]
 Bug(none) transforms/transforms-with-opacity.html [ Failure ]
 
@@ -1830,24 +1386,14 @@
 crbug.com/644358 compositing/iframes/enter-compositing-iframe.html [ Failure ]
 crbug.com/644358 compositing/squashing/squashed-layer-loses-graphicslayer.html [ Failure ]
 
-crbug.com/644358 compositing/overflow/overflow-positioning.html [ Failure ]
-crbug.com/644358 compositing/sibling-positioning.html [ Failure ]
 crbug.com/644358 fast/canvas/canvas-composite-video-shadow.html [ Failure ]
 
-Bug(none) compositing/force-compositing-mode/no-overflow-iframe-layer.html [ Failure ]
-Bug(none) compositing/force-compositing-mode/overflow-hidden-iframe-layer.html [ Failure ]
-Bug(none) compositing/iframes/visibility-hidden-transformed-content.html [ Failure ]
-Bug(none) compositing/layer-creation/fixed-position-nonscrollable-body.html [ Failure ]
 Bug(none) compositing/layer-creation/main-thread-scrolling-for-non-composited-fixed-position-if-overflow-hidden.html [ Failure ]
 Bug(none) compositing/layer-creation/main-thread-scrolling-for-non-composited-fixed-position.html [ Failure ]
-Bug(none) compositing/layer-creation/no-main-thread-scrolling-for-non-composited-fixed-position-without-scroll.html [ Failure ]
-Bug(none) compositing/overflow/overflow-auto-with-touch-no-overflow.html [ Failure ]
 Bug(none) compositing/overflow/overflow-auto-with-touch-toggle.html [ Failure ]
 Bug(none) compositing/overflow/overflow-auto-with-touch.html [ Failure ]
 Bug(none) compositing/overflow/overflow-hidden-with-touch.html [ Failure ]
-Bug(none) compositing/overflow/overflow-overlay-with-touch-no-overflow.html [ Failure ]
 Bug(none) compositing/overflow/overflow-overlay-with-touch.html [ Failure ]
-Bug(none) compositing/overflow/overflow-scroll-with-touch-no-overflow.html [ Failure ]
 Bug(none) compositing/squashing/invalidations-with-large-negative-margin-inline-content.html [ Failure ]
 Bug(none) fast/dom/vertical-scrollbar-in-rtl.html [ Failure ]
 Bug(none) fast/events/continuous-platform-wheelevent-in-scrolling-div.html [ Failure ]
@@ -1892,170 +1438,11 @@
 crbug.com/651292 svg/dynamic-updates/SVGImageElement-dom-y-attr.html [ Pass Failure ]
 
 # Invisible pixel diffs caused by different methods of clipping.
-crbug.com/637316 svg/W3C-SVG-1.1-SE/color-prop-05-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1-SE/coords-dom-03-f.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1-SE/filters-felem-01-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1-SE/interact-pointer-03-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1-SE/painting-control-04-f.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1-SE/painting-marker-07-f.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1-SE/pservers-pattern-04-f.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1-SE/struct-dom-11-f.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1-SE/styling-css-04-f.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1-SE/styling-pres-02-f.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1-SE/text-intro-02-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1-SE/text-intro-05-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1-SE/text-intro-09-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1-SE/types-dom-03-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1-SE/types-dom-05-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/animate-elem-03-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/animate-elem-13-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/animate-elem-20-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/animate-elem-21-t.svg [ Failure ]
 crbug.com/637316 svg/W3C-SVG-1.1/animate-elem-22-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/animate-elem-23-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/animate-elem-26-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/animate-elem-27-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/animate-elem-29-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/animate-elem-32-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/animate-elem-85-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/color-prof-01-f.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/color-prop-01-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/color-prop-02-f.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/color-prop-03-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/filters-tile-01-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/filters-turb-01-f.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/interact-cursor-01-f.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/interact-dom-01-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/interact-order-01-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/interact-order-02-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/interact-order-03-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/linking-uri-03-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/painting-fill-01-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/painting-fill-02-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/painting-fill-05-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/paths-data-01-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/paths-data-03-f.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/paths-data-12-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/paths-data-13-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/pservers-grad-01-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/pservers-grad-02-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/pservers-grad-03-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/pservers-grad-04-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/pservers-grad-05-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/pservers-grad-06-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/pservers-grad-10-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/pservers-grad-11-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/pservers-grad-14-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/pservers-grad-15-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/pservers-grad-16-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/pservers-grad-18-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/pservers-grad-19-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/pservers-pattern-01-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/render-elems-06-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/render-elems-07-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/render-elems-08-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/script-handle-01-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/shapes-circle-01-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/shapes-ellipse-01-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/shapes-intro-01-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/shapes-line-01-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/shapes-polygon-01-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/shapes-polyline-01-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/shapes-rect-01-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/struct-cond-01-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/struct-cond-02-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/struct-defs-01-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/struct-dom-01-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/struct-dom-02-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/struct-dom-03-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/struct-dom-04-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/struct-dom-05-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/struct-dom-06-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/struct-frag-04-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/struct-frag-05-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/struct-image-01-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/struct-image-03-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/struct-image-04-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/struct-image-05-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/struct-use-05-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/styling-css-05-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/styling-css-06-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/styling-inherit-01-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/styling-pres-01-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/text-deco-01-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/text-fonts-01-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/text-fonts-02-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/text-intro-01-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/text-intro-04-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/text-text-03-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/text-text-07-t.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/text-tselect-01-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/text-tspan-01-b.svg [ Failure ]
-crbug.com/637316 svg/W3C-SVG-1.1/text-ws-01-t.svg [ Failure ]
-crbug.com/637316 svg/css/path-gradient-stroke-shadow.svg [ Failure ]
-crbug.com/637316 svg/css/rect-gradient-stroke-shadow.svg [ Failure ]
-crbug.com/637316 svg/css/text-gradient-shadow.svg [ Failure ]
-crbug.com/637316 svg/custom/broken-internal-references.svg [ Failure ]
-crbug.com/637316 svg/custom/control-points-for-S-and-T.svg [ Failure ]
-crbug.com/637316 svg/custom/dasharrayOrigin.svg [ Failure ]
-crbug.com/637316 svg/custom/empty-clip-path.svg [ Failure ]
-crbug.com/637316 svg/custom/fill-fallback.svg [ Failure ]
-crbug.com/637316 svg/custom/focus-ring-2.svg [ Failure ]
-crbug.com/637316 svg/custom/focus-ring-text.svg [ Failure ]
-crbug.com/637316 svg/custom/gradient-stroke-width.svg [ Failure ]
-crbug.com/637316 svg/custom/gradient-userSpaceOnUse-with-percentage.svg [ Failure ]
-crbug.com/637316 svg/custom/invalid-fill-hex.svg [ Failure ]
-crbug.com/637316 svg/custom/linking-a-03-b-preserveAspectRatio.svg [ Failure ]
-crbug.com/637316 svg/custom/linking-a-03-b-viewTarget.svg [ Failure ]
-crbug.com/637316 svg/custom/linking-a-03-b-zoomAndPan.svg [ Failure ]
 crbug.com/637316 svg/custom/marker-opacity.svg [ Failure ]
-crbug.com/637316 svg/custom/nested-pattern-boundingBoxModeContent.svg [ Failure ]
-crbug.com/637316 svg/custom/pattern-incorrect-tiling.svg [ Failure ]
-crbug.com/637316 svg/custom/pattern-with-transformation.svg [ Failure ]
-crbug.com/637316 svg/custom/pattern-y-offset.svg [ Failure ]
-crbug.com/637316 svg/custom/pointer-events-image.svg [ Failure ]
-crbug.com/637316 svg/custom/pointer-events-path.svg [ Failure ]
-crbug.com/637316 svg/custom/pointer-events-text.svg [ Failure ]
-crbug.com/637316 svg/custom/radialGradient-focal-radius.svg [ Failure ]
-crbug.com/637316 svg/custom/recursive-pattern.svg [ Failure ]
-crbug.com/637316 svg/custom/rgba-color-outline.svg [ Failure ]
-crbug.com/637316 svg/custom/rounded-rects.svg [ Failure ]
-crbug.com/637316 svg/custom/stroke-fallback.svg [ Failure ]
 crbug.com/637316 svg/custom/text-image-opacity.svg [ Failure ]
-crbug.com/637316 svg/custom/text-linking.svg [ Failure ]
-crbug.com/637316 svg/custom/text-rotation.svg [ Failure ]
-crbug.com/637316 svg/filters/feImage-preserveAspectratio.svg [ Failure ]
-crbug.com/637316 svg/hixie/cascade/001-broken.xml [ Failure ]
-crbug.com/637316 svg/hixie/rendering-model/002.xml [ Failure ]
-crbug.com/637316 svg/hixie/shapes/path/001.xml [ Failure ]
-crbug.com/637316 svg/hixie/transform/001.xml [ Failure ]
-crbug.com/637316 svg/text/text-decorations-in-scaled-pattern.svg [ Failure ]
-crbug.com/637316 svg/text/text-gradient-positioning.svg [ Failure ]
-crbug.com/637316 svg/text/text-outline-rgba.html [ Failure ]
-crbug.com/637316 svg/text/text-path-middle-align.svg [ Failure ]
 
 Bug(none) fast/block/basic/quirk-percent-height-table-cell.html [ Failure ]
-Bug(none) fast/box-shadow/transform-fringing.html [ Failure ]
-Bug(none) svg/animations/animateMotion_changingPath.html [ Failure ]
-Bug(none) svg/as-object/svg-embedded-in-html-in-iframe.html [ Failure ]
-Bug(none) svg/custom/mouse-move-on-svg-root-standalone.svg [ Failure ]
-Bug(none) svg/custom/mouse-move-on-svg-root.xhtml [ Failure ]
-Bug(none) svg/custom/object-sizing-explicit-height.xhtml [ Failure ]
-Bug(none) svg/custom/object-sizing-explicit-width-height.xhtml [ Failure ]
-Bug(none) svg/custom/object-sizing-explicit-width.xhtml [ Failure ]
-Bug(none) svg/custom/path-zero-strokewidth.svg [ Failure ]
-Bug(none) svg/custom/svgpolyparser-extra-space.svg [ Failure ]
-Bug(none) svg/dynamic-updates/SVGLineElement-dom-x1-attr.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGLineElement-dom-x2-attr.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGLineElement-dom-y1-attr.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGLineElement-dom-y2-attr.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGLineElement-svgdom-x1-prop.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGLineElement-svgdom-x2-prop.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGLineElement-svgdom-y1-prop.html [ Failure ]
-Bug(none) svg/dynamic-updates/SVGLineElement-svgdom-y2-prop.html [ Failure ]
-Bug(none) svg/hixie/cascade/002.xml [ Failure ]
-Bug(none) svg/hixie/mixed/003.xml [ Failure ]
-Bug(none) svg/hixie/rendering-model/001.xml [ Failure ]
 Bug(none) svg/hixie/viewbox/preserveAspectRatio/002.xml [ Failure ]
 Bug(none) fast/scrolling/overflow-scrollability.html [ Failure ]
 Bug(none) fast/scrolling/scrollbar-prevent-default.html [ Failure ]
@@ -2124,8 +1511,6 @@
 
 crbug.com/667071 svg/foreignObject/vertical-foreignObject.html [ Failure ]
 
-Bug(none) fast/deprecated-flexbox/009-horizontal.html [ Failure ]
-Bug(none) fast/deprecated-flexbox/009.html [ Failure ]
 Bug(none) fast/overflow/003.xml [ Failure ]
 Bug(none) fast/overflow/overflow-float-stacking.html [ Failure ]
 Bug(none) fast/overflow/overflow-stacking.html [ Failure ]
@@ -2136,7 +1521,6 @@
 Bug(none) css3/blending/effect-background-blend-mode-stacking.html [ Failure ]
 Bug(none) css3/blending/mix-blend-mode-with-masking.html [ Failure ]
 Bug(none) css3/blending/svg-blend-layer-mask.html [ Failure ]
-Bug(none) css3/blending/svg-isolation-add-masking.html [ Failure ]
 Bug(none) css3/blending/svg-isolation-embed-isolate.html [ Failure ]
 Bug(none) css3/blending/svg-isolation-iframe-isolate.html [ Failure ]
 Bug(none) css3/blending/svg-isolation-object-isolate.html [ Failure ]
@@ -2222,8 +1606,6 @@
 # Subpixel adjustments due to differences in compositing
 Bug(none) fast/pagination/auto-height-with-break.html [ Failure ]
 Bug(none) svg/custom/non-scaling-stroke-update.svg [ Failure ]
-Bug(none) fast/css/transform-default-parameter.html [ Failure ]
 Bug(none) svg/custom/use-css-events.svg [ Failure ]
 Bug(none) svg/text/text-layout-crash.html [ Failure ]
-Bug(none) fast/multicol/span/invalid-spanner-in-transform.html [ Failure ]
 Bug(none) images/color-profile-iframe.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 438e095..037087e 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1708,6 +1708,22 @@
 crbug.com/490015 virtual/stable/http/tests/navigation/same-and-different-back.html [ Skip ]
 
 # ====== New tests from w3c-test-autoroller added here ======
+crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] imported/wpt/web-animations/animation-model/animation-types/spacing-keyframes-transform.html [ Failure ]
+crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] imported/wpt/web-animations/animation-model/animation-types/interpolation-per-property.html [ Timeout ]
+crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] imported/wpt/web-animations/interfaces/KeyframeEffectReadOnly/copy-contructor.html [ Failure ]
+crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] imported/wpt/web-animations/animation-model/animation-types/spacing-keyframes-shapes.html [ Failure ]
+crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] imported/wpt/web-animations/animation-model/animation-types/addition-per-property.html [ Timeout ]
+crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] imported/wpt/user-timing/test_user_timing_mark_and_measure_exception_when_invoke_with_timing_attributes.html [ Failure ]
+crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] imported/wpt/html/syntax/parsing/html5lib_innerHTML_webkit02.html [ Failure ]
+crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] imported/wpt/web-animations/interfaces/KeyframeEffect/composite.html [ Failure ]
+crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] imported/wpt/web-animations/animation-model/combining-effects/effect-composition.html [ Failure ]
+crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] imported/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken.html [ Failure ]
+crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] imported/wpt/html/syntax/parsing/html5lib_innerHTML_foreign-fragment.html [ Failure ]
+crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] imported/wpt/html/syntax/parsing/html5lib_innerHTML_adoption01.html [ Failure ]
+crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] imported/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-weird.html [ Failure ]
+crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] imported/wpt/web-animations/interfaces/KeyframeEffect/copy-contructor.html [ Failure ]
+crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] imported/wpt/web-animations/animation-model/animation-types/spacing-keyframes-filters.html [ Failure ]
+crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] imported/wpt/html/browsers/history/the-location-interface/location-pathname-setter-question-mark.html [ Failure ]
 crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] imported/wpt/html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/moving-documents.html [ Timeout ]
 crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] imported/wpt/html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/dynamic-append.html [ Timeout ]
 crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] imported/wpt/html/semantics/interfaces.html [ Failure ]
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 3462208..56913ce 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
@@ -21,6 +21,7 @@
     ["listStylePosition", "outside", "inside"],
     ["webkitBoxDirection", "normal", "reverse"],
     ["webkitPrintColorAdjust", "economy", "exact"],
+    ["textAlign", "start", "left"],
 ];
 
 independent_properties.forEach(function(test_data)
diff --git a/third_party/WebKit/LayoutTests/fast/mediacapturefromelement/HTMLMediaElementCapture-capture.html b/third_party/WebKit/LayoutTests/fast/mediacapturefromelement/HTMLMediaElementCapture-capture.html
index 6141bc1..420e395 100644
--- a/third_party/WebKit/LayoutTests/fast/mediacapturefromelement/HTMLMediaElementCapture-capture.html
+++ b/third_party/WebKit/LayoutTests/fast/mediacapturefromelement/HTMLMediaElementCapture-capture.html
@@ -27,9 +27,10 @@
   }), "<video>.captureStream() and assert data flows.";
 };
 
-generate_tests(makeAsyncTest,
-               [[ "video-only", "test-v-128k-320x240-24fps-8kfr.webm"],
-                [ "audio-only", "test-a-128k-44100Hz-1ch.webm"],
-                [ "video+audio", "test.webm"]]);
+generate_tests(makeAsyncTest, [
+  [ "video-only", "test-v-128k-320x240-24fps-8kfr.webm" ],
+  [ "audio-only", "test-a-128k-44100Hz-1ch.webm" ],
+  [ "video+audio", "test-av-384k-44100Hz-1ch-320x240-30fps-10kfr.webm" ]
+]);
 
 </script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-unit/filtered-item-selection-dialog-filtering.js b/third_party/WebKit/LayoutTests/http/tests/inspector-unit/filtered-item-selection-dialog-filtering.js
index a8dcea9..51279f2 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector-unit/filtered-item-selection-dialog-filtering.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector-unit/filtered-item-selection-dialog-filtering.js
@@ -1,4 +1,4 @@
-TestRunner.loadLazyModules(["ui_lazy"]).then(test);
+TestRunner.loadLazyModules(["quick_open"]).then(test);
 function test() {
     TestRunner.addResult("Check to see that FilteredItemSelectionDialog uses proper regex to filter results.");
 
@@ -6,7 +6,7 @@
     var overrideShowMatchingItems = true;
     var history = [];
 
-    var StubDelegate = class extends UI.FilteredListWidget.Delegate {
+    var StubDelegate = class extends QuickOpen.FilteredListWidget.Delegate {
         constructor()
         {
             super(history);
@@ -31,7 +31,7 @@
 
         TestRunner.addResult("Input:" + JSON.stringify(input));
 
-        var filteredSelectionDialog = new UI.FilteredListWidget(delegate);
+        var filteredSelectionDialog = new QuickOpen.FilteredListWidget(delegate);
         filteredSelectionDialog.showAsDialog();
         var promise = TestRunner.addSniffer(filteredSelectionDialog, "_itemsFilteredForTest").then(accept);
         filteredSelectionDialog.setQuery(query);
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/IndexedDB/support-promises.js b/third_party/WebKit/LayoutTests/imported/wpt/IndexedDB/support-promises.js
index cd23d94d..2db0512 100644
--- a/third_party/WebKit/LayoutTests/imported/wpt/IndexedDB/support-promises.js
+++ b/third_party/WebKit/LayoutTests/imported/wpt/IndexedDB/support-promises.js
@@ -1,42 +1,46 @@
-// Returns an IndexedDB database name likely to be unique to the test case.
-const databaseName = (testCase) => {
+'use strict';
+
+// Returns an IndexedDB database name that is unique to the test case.
+function databaseName(testCase) {
   return 'db' + self.location.pathname + '-' + testCase.name;
-};
+}
 
 // Creates an EventWatcher covering all the events that can be issued by
 // IndexedDB requests and transactions.
-const requestWatcher = (testCase, request) => {
+function requestWatcher(testCase, request) {
   return new EventWatcher(testCase, request,
-      ['error', 'success', 'upgradeneeded']);
-};
+      ['abort', 'blocked', 'complete', 'error', 'success', 'upgradeneeded']);
+}
 
 // Migrates an IndexedDB database whose name is unique for the test case.
 //
 // newVersion must be greater than the database's current version.
 //
 // migrationCallback will be called during a versionchange transaction and will
-// be given the created database and the versionchange transaction.
+// given the created database, the versionchange transaction, and the database
+// open request.
 //
 // Returns a promise. If the versionchange transaction goes through, the promise
 // resolves to an IndexedDB database that must be closed by the caller. If the
 // versionchange transaction is aborted, the promise resolves to an error.
-const migrateDatabase = (testCase, newVersion, migrationCallback) => {
+function migrateDatabase(testCase, newVersion, migrationCallback) {
   return migrateNamedDatabase(
       testCase, databaseName(testCase), newVersion, migrationCallback);
-};
+}
 
 // Migrates an IndexedDB database.
 //
 // newVersion must be greater than the database's current version.
 //
 // migrationCallback will be called during a versionchange transaction and will
-// be given the created database and the versionchange transaction.
+// given the created database, the versionchange transaction, and the database
+// open request.
 //
 // Returns a promise. If the versionchange transaction goes through, the promise
 // resolves to an IndexedDB database that must be closed by the caller. If the
 // versionchange transaction is aborted, the promise resolves to an error.
-const migrateNamedDatabase =
-    (testCase, databaseName, newVersion, migrationCallback) => {
+function migrateNamedDatabase(
+    testCase, databaseName, newVersion, migrationCallback) {
   // We cannot use eventWatcher.wait_for('upgradeneeded') here, because
   // the versionchange transaction auto-commits before the Promise's then
   // callback gets called.
@@ -45,62 +49,78 @@
     request.onupgradeneeded = testCase.step_func(event => {
       const database = event.target.result;
       const transaction = event.target.transaction;
-      let abortCalled = false;
+      let shouldBeAborted = false;
+      let requestEventPromise = null;
 
       // We wrap IDBTransaction.abort so we can set up the correct event
       // listeners and expectations if the test chooses to abort the
       // versionchange transaction.
       const transactionAbort = transaction.abort.bind(transaction);
       transaction.abort = () => {
-        request.onerror = event => {
-          event.preventDefault();
-          resolve(event);
-        };
-        request.onsuccess = () => reject(new Error(
-            'indexedDB.open should not succeed after the versionchange ' +
-            'transaction is aborted'));
+        transaction._willBeAborted();
         transactionAbort();
-        abortCalled = true;
+      }
+      transaction._willBeAborted = () => {
+        requestEventPromise = new Promise((resolve, reject) => {
+          request.onerror = event => {
+            event.preventDefault();
+            resolve(event);
+          };
+          request.onsuccess = () => reject(new Error(
+              'indexedDB.open should not succeed for an aborted ' +
+              'versionchange transaction'));
+        });
+        shouldBeAborted = true;
       }
 
-      migrationCallback(database, transaction);
-      if (!abortCalled) {
+      // If migration callback returns a promise, we'll wait for it to resolve.
+      // This simplifies some tests.
+      const callbackResult = migrationCallback(database, transaction, request);
+      if (!shouldBeAborted) {
+        request.onerror = null;
         request.onsuccess = null;
-        resolve(requestWatcher(testCase, request).wait_for('success'));
+        requestEventPromise =
+            requestWatcher(testCase, request).wait_for('success');
       }
+
+      // requestEventPromise needs to be the last promise in the chain, because
+      // we want the event that it resolves to.
+      resolve(Promise.resolve(callbackResult).then(() => requestEventPromise));
     });
     request.onerror = event => reject(event.target.error);
     request.onsuccess = () => reject(new Error(
         'indexedDB.open should not succeed without creating a ' +
         'versionchange transaction'));
   }).then(event => event.target.result || event.target.error);
-};
+}
 
 // Creates an IndexedDB database whose name is unique for the test case.
 //
 // setupCallback will be called during a versionchange transaction, and will be
-// given the created database and the versionchange transaction.
+// given the created database, the versionchange transaction, and the database
+// open request.
 //
 // Returns a promise that resolves to an IndexedDB database. The caller must
 // close the database.
-const createDatabase = (testCase, setupCallback) => {
+function createDatabase(testCase, setupCallback) {
   return createNamedDatabase(testCase, databaseName(testCase), setupCallback);
-};
+}
 
 // Creates an IndexedDB database.
 //
 // setupCallback will be called during a versionchange transaction, and will be
-// given the created database and the versionchange transaction.
+// given the created database, the versionchange transaction, and the database
+// open request.
 //
 // Returns a promise that resolves to an IndexedDB database. The caller must
 // close the database.
-const createNamedDatabase = (testCase, databaseName, setupCallback) => {
+function createNamedDatabase(testCase, databaseName, setupCallback) {
   const request = indexedDB.deleteDatabase(databaseName);
   const eventWatcher = requestWatcher(testCase, request);
 
   return eventWatcher.wait_for('success').then(event =>
       migrateNamedDatabase(testCase, databaseName, 1, setupCallback));
-};
+}
 
 // Opens an IndexedDB database without performing schema changes.
 //
@@ -108,7 +128,7 @@
 //
 // Returns a promise that resolves to an IndexedDB database. The caller must
 // close the database.
-const openDatabase = (testCase, version) => {
+function openDatabase(testCase, version) {
   return openNamedDatabase(testCase, databaseName(testCase), version);
 }
 
@@ -118,7 +138,7 @@
 //
 // Returns a promise that resolves to an IndexedDB database. The caller must
 // close the database.
-const openNamedDatabase = (testCase, databaseName, version) => {
+function openNamedDatabase(testCase, databaseName, version) {
   const request = indexedDB.open(databaseName, version);
   const eventWatcher = requestWatcher(testCase, request);
   return eventWatcher.wait_for('success').then(event => event.target.result);
@@ -142,16 +162,16 @@
   for (let record of BOOKS_RECORD_DATA)
       store.put(record);
   return store;
-};
+}
 
 // Creates a 'not_books' object store used to test renaming into existing or
 // deleted store names.
-const createNotBooksStore = (testCase, database) => {
-    const store = database.createObjectStore('not_books');
-    store.createIndex('not_by_author', 'author');
-    store.createIndex('not_by_title', 'title', { unique: true });
-    return store;
-};
+function createNotBooksStore(testCase, database) {
+  const store = database.createObjectStore('not_books');
+  store.createIndex('not_by_author', 'author');
+  store.createIndex('not_by_title', 'title', { unique: true });
+  return store;
+}
 
 // Verifies that an object store's indexes match the indexes used to create the
 // books store in the test database's version 1.
@@ -159,7 +179,7 @@
 // The errorMessage is used if the assertions fail. It can state that the
 // IndexedDB implementation being tested is incorrect, or that the testing code
 // is using it incorrectly.
-const checkStoreIndexes = (testCase, store, errorMessage) => {
+function checkStoreIndexes (testCase, store, errorMessage) {
   assert_array_equals(
       store.indexNames, ['by_author', 'by_title'], errorMessage);
   const authorIndex = store.index('by_author');
@@ -168,7 +188,7 @@
       checkAuthorIndexContents(testCase, authorIndex, errorMessage),
       checkTitleIndexContents(testCase, titleIndex, errorMessage),
   ]);
-};
+}
 
 // Verifies that an object store's key generator is in the same state as the
 // key generator created for the books store in the test database's version 1.
@@ -176,7 +196,7 @@
 // The errorMessage is used if the assertions fail. It can state that the
 // IndexedDB implementation being tested is incorrect, or that the testing code
 // is using it incorrectly.
-const checkStoreGenerator = (testCase, store, expectedKey, errorMessage) => {
+function checkStoreGenerator(testCase, store, expectedKey, errorMessage) {
   const request = store.put(
       { title: 'Bedrock Nights ' + expectedKey, author: 'Barney' });
   const eventWatcher = requestWatcher(testCase, request);
@@ -184,7 +204,7 @@
     const result = request.result;
     assert_equals(result, expectedKey, errorMessage);
   });
-};
+}
 
 // Verifies that an object store's contents matches the contents used to create
 // the books store in the test database's version 1.
@@ -192,7 +212,7 @@
 // The errorMessage is used if the assertions fail. It can state that the
 // IndexedDB implementation being tested is incorrect, or that the testing code
 // is using it incorrectly.
-const checkStoreContents = (testCase, store, errorMessage) => {
+function checkStoreContents(testCase, store, errorMessage) {
   const request = store.get(123456);
   const eventWatcher = requestWatcher(testCase, request);
   return eventWatcher.wait_for('success').then(() => {
@@ -201,7 +221,7 @@
     assert_equals(result.author, BOOKS_RECORD_DATA[0].author, errorMessage);
     assert_equals(result.title, BOOKS_RECORD_DATA[0].title, errorMessage);
   });
-};
+}
 
 // Verifies that index matches the 'by_author' index used to create the
 // by_author books store in the test database's version 1.
@@ -209,7 +229,7 @@
 // The errorMessage is used if the assertions fail. It can state that the
 // IndexedDB implementation being tested is incorrect, or that the testing code
 // is using it incorrectly.
-const checkAuthorIndexContents = (testCase, index, errorMessage) => {
+function checkAuthorIndexContents(testCase, index, errorMessage) {
   const request = index.get(BOOKS_RECORD_DATA[2].author);
   const eventWatcher = requestWatcher(testCase, request);
   return eventWatcher.wait_for('success').then(() => {
@@ -217,7 +237,7 @@
     assert_equals(result.isbn, BOOKS_RECORD_DATA[2].isbn, errorMessage);
     assert_equals(result.title, BOOKS_RECORD_DATA[2].title, errorMessage);
   });
-};
+}
 
 // Verifies that an index matches the 'by_title' index used to create the books
 // store in the test database's version 1.
@@ -225,7 +245,7 @@
 // The errorMessage is used if the assertions fail. It can state that the
 // IndexedDB implementation being tested is incorrect, or that the testing code
 // is using it incorrectly.
-const checkTitleIndexContents = (testCase, index, errorMessage) => {
+function checkTitleIndexContents(testCase, index, errorMessage) {
   const request = index.get(BOOKS_RECORD_DATA[2].title);
   const eventWatcher = requestWatcher(testCase, request);
   return eventWatcher.wait_for('success').then(() => {
@@ -233,4 +253,4 @@
     assert_equals(result.isbn, BOOKS_RECORD_DATA[2].isbn, errorMessage);
     assert_equals(result.author, BOOKS_RECORD_DATA[2].author, errorMessage);
   });
-};
+}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/IndexedDB/upgrade-transaction-lifecycle-backend-aborted.html b/third_party/WebKit/LayoutTests/imported/wpt/IndexedDB/upgrade-transaction-lifecycle-backend-aborted.html
new file mode 100644
index 0000000..9a7c4b42
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/IndexedDB/upgrade-transaction-lifecycle-backend-aborted.html
@@ -0,0 +1,84 @@
+<!doctype html>
+<meta charset="utf8">
+<title>IndexedDB: backend-aborted versionchange transaction lifecycle</title>
+<link rel="help"
+      href="https://w3c.github.io/IndexedDB/#upgrade-transaction-steps">
+<link rel="help"
+      href="https://w3c.github.io/IndexedDB/#dom-idbdatabase-createobjectstore">
+<link rel="help"
+      href="https://w3c.github.io/IndexedDB/#dom-idbdatabase-deleteobjectstore">
+<link rel="author" href="pwnall@chromium.org" title="Victor Costan">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support-promises.js"></script>
+<script>
+'use strict';
+
+promise_test(t => {
+  return createDatabase(t, database => {
+    createBooksStore(t, database);
+  }).then(database => {
+    database.close();
+  }).then(() => migrateDatabase(t, 2, (database, transaction, request) => {
+    return new Promise((resolve, reject) => {
+      transaction.addEventListener('abort', () => {
+        resolve(new Promise((resolve, reject) => {
+          assert_equals(
+              request.transaction, transaction,
+              "The open request's transaction should be reset after onabort");
+          assert_throws(
+              'InvalidStateError',
+              () => { database.createObjectStore('books2'); },
+              'createObjectStore exception should reflect that the ' +
+              'transaction is no longer running');
+          assert_throws(
+              'InvalidStateError',
+              () => { database.deleteObjectStore('books'); },
+              'deleteObjectStore exception should reflect that the ' +
+              'transaction is no longer running');
+          resolve();
+        }));
+      }, false);
+      transaction.objectStore('books').add(BOOKS_RECORD_DATA[0]);
+      transaction._willBeAborted();
+    });
+  }));
+}, 'in the abort event handler for a transaction aborted due to an unhandled ' +
+   'request error');
+
+promise_test(t => {
+  return createDatabase(t, database => {
+    createBooksStore(t, database);
+  }).then(database => {
+    database.close();
+  }).then(() => migrateDatabase(t, 2, (database, transaction, request) => {
+    return new Promise((resolve, reject) => {
+      transaction.addEventListener('abort', () => {
+        setTimeout(() => {
+          resolve(new Promise((resolve, reject) => {
+            assert_equals(
+                request.transaction, null,
+                "The open request's transaction should be reset after " +
+                'onabort microtasks');
+            assert_throws(
+                'InvalidStateError',
+                () => { database.createObjectStore('books2'); },
+                'createObjectStore exception should reflect that the ' +
+                'transaction is no longer running');
+            assert_throws(
+                'InvalidStateError',
+                () => { database.deleteObjectStore('books'); },
+                'deleteObjectStore exception should reflect that the ' +
+                'transaction is no longer running');
+            resolve();
+          }));
+        }, 0);
+      }, false);
+      transaction.objectStore('books').add(BOOKS_RECORD_DATA[0]);
+      transaction._willBeAborted();
+    });
+  }));
+}, 'in a setTimeout(0) callback after the abort event is fired for a ' +
+   'transaction aborted due to an unhandled request failure');
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/IndexedDB/upgrade-transaction-lifecycle-committed.html b/third_party/WebKit/LayoutTests/imported/wpt/IndexedDB/upgrade-transaction-lifecycle-committed.html
new file mode 100644
index 0000000..366ed38
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/IndexedDB/upgrade-transaction-lifecycle-committed.html
@@ -0,0 +1,80 @@
+<!doctype html>
+<meta charset="utf8">
+<title>IndexedDB: committed versionchange transaction lifecycle</title>
+<link rel="help"
+      href="https://w3c.github.io/IndexedDB/#upgrade-transaction-steps">
+<link rel="help"
+      href="https://w3c.github.io/IndexedDB/#dom-idbdatabase-createobjectstore">
+<link rel="help"
+      href="https://w3c.github.io/IndexedDB/#dom-idbdatabase-deleteobjectstore">
+<link rel="author" href="pwnall@chromium.org" title="Victor Costan">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support-promises.js"></script>
+<script>
+'use strict';
+
+promise_test(t => {
+  return createDatabase(t, database => {
+    createBooksStore(t, database);
+  }).then(database => {
+    database.close();
+  }).then(() => migrateDatabase(t, 2, (database, transaction, request) => {
+    return new Promise((resolve, reject) => {
+      transaction.addEventListener('complete', () => {
+        resolve(new Promise((resolve, reject) => {
+          assert_equals(
+              request.transaction, transaction,
+              "The open request's transaction should be reset after " +
+              'oncomplete');
+          assert_throws(
+              'InvalidStateError',
+              () => { database.createObjectStore('books2'); },
+              'createObjectStore exception should reflect that the ' +
+              'transaction is no longer running');
+          assert_throws(
+              'InvalidStateError',
+              () => { database.deleteObjectStore('books'); },
+              'deleteObjectStore exception should reflect that the ' +
+              'transaction is no longer running');
+          resolve();
+        }));
+      }, false);
+    });
+  })).then(database => { database.close(); });
+}, 'in the complete event handler for a committed transaction');
+
+promise_test(t => {
+  return createDatabase(t, database => {
+    createBooksStore(t, database);
+  }).then(database => {
+    database.close();
+  }).then(() => migrateDatabase(t, 2, (database, transaction, request) => {
+    return new Promise((resolve, reject) => {
+      transaction.addEventListener('complete', () => {
+        setTimeout(() => {
+          resolve(new Promise((resolve, reject) => {
+            assert_equals(
+                request.transaction, null,
+                "The open request's transaction should be reset after " +
+                'oncomplete microtasks');
+            assert_throws(
+                'InvalidStateError',
+                () => { database.createObjectStore('books2'); },
+                'createObjectStore exception should reflect that the ' +
+                'transaction is no longer running');
+            assert_throws(
+                'InvalidStateError',
+                () => { database.deleteObjectStore('books'); },
+                'deleteObjectStore exception should reflect that the ' +
+                'transaction is no longer running');
+            resolve();
+          }));
+        }, 0);
+      }, false);
+    });
+  })).then(database => { database.close(); });
+}, 'in a setTimeout(0) callback after the complete event is fired for a ' +
+   'committed transaction');
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/IndexedDB/upgrade-transaction-lifecycle-user-aborted.html b/third_party/WebKit/LayoutTests/imported/wpt/IndexedDB/upgrade-transaction-lifecycle-user-aborted.html
new file mode 100644
index 0000000..9db93db
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/IndexedDB/upgrade-transaction-lifecycle-user-aborted.html
@@ -0,0 +1,143 @@
+<!doctype html>
+<meta charset="utf8">
+<title>IndexedDB: user-abort()ed versionchange transaction lifecycle</title>
+<link rel="help"
+      href="https://w3c.github.io/IndexedDB/#upgrade-transaction-steps">
+<link rel="help"
+      href="https://w3c.github.io/IndexedDB/#dom-idbdatabase-createobjectstore">
+<link rel="help"
+      href="https://w3c.github.io/IndexedDB/#dom-idbdatabase-deleteobjectstore">
+<link rel="author" href="pwnall@chromium.org" title="Victor Costan">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support-promises.js"></script>
+<script>
+'use strict';
+
+promise_test(t => {
+  return createDatabase(t, database => {
+    createBooksStore(t, database);
+  }).then(database => {
+    database.close();
+  }).then(() => migrateDatabase(t, 2, (database, transaction, request) => {
+    transaction.abort();
+    assert_equals(
+        request.transaction, transaction,
+        "The open request's transaction should be reset after onabort");
+
+    assert_throws(
+        'TransactionInactiveError',
+        () => { database.createObjectStore('books2'); },
+        'createObjectStore exception should reflect that the transaction is ' +
+        'still running');
+    assert_throws(
+        'TransactionInactiveError',
+        () => { database.deleteObjectStore('books'); },
+        'deleteObjectStore exception should reflect that the transaction is' +
+        'still running');
+  }));
+}, 'synchronously after abort() is called');
+
+promise_test(t => {
+  return createDatabase(t, database => {
+    createBooksStore(t, database);
+  }).then(database => {
+    database.close();
+  }).then(() => migrateDatabase(t, 2, (database, transaction, request) => {
+    let abortFired = false;
+    const abortPromise = new Promise((resolve, reject) => {
+      transaction.addEventListener('abort', () => {
+        abortFired = true;
+        resolve();
+      }, false);
+      transaction.abort();
+    });
+
+    return Promise.resolve().then(() => {
+      assert_false(
+          abortFired,
+          'The abort event should fire after promises are resolved');
+      assert_equals(
+          request.transaction, transaction,
+          "The open request's transaction should be reset after onabort");
+      assert_throws(
+          'TransactionInactiveError',
+          () => { database.createObjectStore('books2'); },
+          'createObjectStore exception should reflect that the transaction ' +
+          'is still running');
+      assert_throws(
+          'TransactionInactiveError',
+          () => { database.deleteObjectStore('books'); },
+          'deleteObjectStore exception should reflect that the transaction ' +
+          'is still running');
+    }).then(() => abortPromise);
+  }));
+}, 'in a promise microtask after abort() is called, before the transaction ' +
+   'abort event is fired');
+
+promise_test(t => {
+  return createDatabase(t, database => {
+    createBooksStore(t, database);
+  }).then(database => {
+    database.close();
+  }).then(() => migrateDatabase(t, 2, (database, transaction, request) => {
+    return new Promise((resolve, reject) => {
+      transaction.addEventListener('abort', () => {
+        resolve(new Promise((resolve, reject) => {
+          assert_equals(
+              request.transaction, transaction,
+              "The open request's transaction should be reset after onabort");
+          assert_throws(
+              'InvalidStateError',
+              () => { database.createObjectStore('books2'); },
+              'createObjectStore exception should reflect that the ' +
+              'transaction is no longer running');
+          assert_throws(
+              'InvalidStateError',
+              () => { database.deleteObjectStore('books'); },
+              'deleteObjectStore exception should reflect that the ' +
+              'transaction is no longer running');
+          resolve();
+        }));
+      }, false);
+      transaction.abort();
+    });
+  }));
+}, 'in the abort event handler for a transaction aborted due to an abort() ' +
+   'call');
+
+promise_test(t => {
+  return createDatabase(t, database => {
+    createBooksStore(t, database);
+  }).then(database => {
+    database.close();
+  }).then(() => migrateDatabase(t, 2, (database, transaction, request) => {
+    return new Promise((resolve, reject) => {
+      transaction.addEventListener('abort', () => {
+        setTimeout(() => {
+          resolve(new Promise((resolve, reject) => {
+            assert_equals(
+                request.transaction, null,
+                "The open request's transaction should be reset after " +
+                'onabort microtasks');
+            assert_throws(
+                'InvalidStateError',
+                () => { database.createObjectStore('books2'); },
+                'createObjectStore exception should reflect that the ' +
+                'transaction is no longer running');
+            assert_throws(
+                'InvalidStateError',
+                () => { database.deleteObjectStore('books'); },
+                'deleteObjectStore exception should reflect that the ' +
+                'transaction is no longer running');
+            resolve();
+          }));
+        }, 0);
+      }, false);
+      transaction.abort();
+    });
+  }));
+}, 'in a setTimeout(0) callback after the abort event is fired for a ' +
+   'transaction aborted due to an abort() call');
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/MANIFEST.json b/third_party/WebKit/LayoutTests/imported/wpt/MANIFEST.json
index d098ca7..e27e487 100644
--- a/third_party/WebKit/LayoutTests/imported/wpt/MANIFEST.json
+++ b/third_party/WebKit/LayoutTests/imported/wpt/MANIFEST.json
@@ -3715,11 +3715,6 @@
      {}
     ]
    ],
-   "./MANIFEST.json": [
-    [
-     {}
-    ]
-   ],
    "./README.md": [
     [
      {}
@@ -4830,6 +4825,11 @@
      {}
     ]
    ],
+   "domxpath/xml_xpath_tests.xml": [
+    [
+     {}
+    ]
+   ],
    "encoding/idlharness-expected.txt": [
     [
      {}
@@ -18728,6 +18728,24 @@
      {}
     ]
    ],
+   "IndexedDB/upgrade-transaction-lifecycle-backend-aborted.html": [
+    [
+     "/IndexedDB/upgrade-transaction-lifecycle-backend-aborted.html",
+     {}
+    ]
+   ],
+   "IndexedDB/upgrade-transaction-lifecycle-committed.html": [
+    [
+     "/IndexedDB/upgrade-transaction-lifecycle-committed.html",
+     {}
+    ]
+   ],
+   "IndexedDB/upgrade-transaction-lifecycle-user-aborted.html": [
+    [
+     "/IndexedDB/upgrade-transaction-lifecycle-user-aborted.html",
+     {}
+    ]
+   ],
    "IndexedDB/value.htm": [
     [
      "/IndexedDB/value.htm",
@@ -32191,10 +32209,6 @@
    "89af73c41d456ee93bd40921e96414c1908fc48c",
    "support"
   ],
-  "./MANIFEST.json": [
-   "a45804cdc253f3d9735529c0bec828441e671aa0",
-   "support"
-  ],
   "./README.md": [
    "930f9755157d0a3da03b6a6f67c3ba12c05b22c4",
    "support"
@@ -33488,7 +33502,7 @@
    "testharness"
   ],
   "IndexedDB/support-promises.js": [
-   "c72263743e6983048484776cabc12f47c069bebf",
+   "174d4db1b6634baeca46c80be43552f9da81ce07",
    "support"
   ],
   "IndexedDB/support.js": [
@@ -33535,6 +33549,18 @@
    "4a75702a58021e337f884590508c1a0b84063edc",
    "testharness"
   ],
+  "IndexedDB/upgrade-transaction-lifecycle-backend-aborted.html": [
+   "c816400517298785753b39639b3cec925d57029e",
+   "testharness"
+  ],
+  "IndexedDB/upgrade-transaction-lifecycle-committed.html": [
+   "6ccbc2eaf0d8db8bbc787bb68dc7a843b6fa0af2",
+   "testharness"
+  ],
+  "IndexedDB/upgrade-transaction-lifecycle-user-aborted.html": [
+   "7a05b801be5b6ca7c651195abda0788c130a540f",
+   "testharness"
+  ],
   "IndexedDB/value.htm": [
    "bf8b42aba531bfbe5d4898c7e93eb5b00274d4b0",
    "testharness"
@@ -33704,7 +33730,7 @@
    "support"
   ],
   "common/vendor-prefix.js": [
-   "2807645fda3cb1decbb944627b038fc87ef019a0",
+   "b80ec842b65a3423dd789a2226f2ba3caf598049",
    "support"
   ],
   "css-values/unset-value-storage.html": [
@@ -35667,6 +35693,10 @@
    "4842d40e22e25ee72536946d785a3cd03bc6a11d",
    "testharness"
   ],
+  "domxpath/xml_xpath_tests.xml": [
+   "daef25b99b0e26c6bf726cb2efb8f903337746dd",
+   "support"
+  ],
   "encoding/api-basics.html": [
    "f941c016bd9f6117af2e28652c770613c475b064",
    "testharness"
diff --git a/third_party/WebKit/LayoutTests/inspector/components/file-path-scoring.html b/third_party/WebKit/LayoutTests/inspector/components/file-path-scoring.html
index dc073b5..022b8ec 100644
--- a/third_party/WebKit/LayoutTests/inspector/components/file-path-scoring.html
+++ b/third_party/WebKit/LayoutTests/inspector/components/file-path-scoring.html
@@ -45,7 +45,7 @@
         var scorer = new Sources.FilePathScoreFunction(query);
         var bestScore = -1;
         var bestIndex = -1;
-        var filter = UI.FilteredListWidget.filterRegex(query);
+        var filter = QuickOpen.FilteredListWidget.filterRegex(query);
         for(var i = 0; i < paths.length; ++i) {
             if (!filter.test(paths[i]))
                 continue;
diff --git a/third_party/WebKit/LayoutTests/inspector/initial-modules-load-expected.txt b/third_party/WebKit/LayoutTests/inspector/initial-modules-load-expected.txt
index b394b091..d522e79 100644
--- a/third_party/WebKit/LayoutTests/inspector/initial-modules-load-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/initial-modules-load-expected.txt
@@ -51,9 +51,11 @@
     host
     main
     network
+    perf_ui
     persistence
     platform
     protocol
+    quick_open
     sdk
     services
     snippets
@@ -79,9 +81,11 @@
     host
     main
     network
+    perf_ui
     persistence
     platform
     protocol
+    quick_open
     sdk
     services
     snippets
@@ -107,9 +111,11 @@
     host
     main
     network
+    perf_ui
     persistence
     platform
     protocol
+    quick_open
     sdk
     services
     snippets
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/source-frame.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/source-frame.html
index e128fb5..2b0d545 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/source-frame.html
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/source-frame.html
@@ -29,8 +29,8 @@
             {
                 InspectorTest.addResult("Script source was shown.");
                 shownSourceFrame = sourceFrame;
-                InspectorTest.addSniffer(Sources.UISourceCodeFrame.prototype, "_addMessageToSource", didAddMessage);
-                InspectorTest.addSniffer(Sources.UISourceCodeFrame.prototype, "_removeMessageFromSource", didRemoveMessage);
+                InspectorTest.addSniffer(SourceFrame.UISourceCodeFrame.prototype, "_addMessageToSource", didAddMessage);
+                InspectorTest.addSniffer(SourceFrame.UISourceCodeFrame.prototype, "_removeMessageFromSource", didRemoveMessage);
                 InspectorTest.evaluateInPage("addErrorToConsole()");
             }
 
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/source-code-diff.html b/third_party/WebKit/LayoutTests/inspector/sources/source-code-diff.html
index 45267525..51fb1e6b 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/source-code-diff.html
+++ b/third_party/WebKit/LayoutTests/inspector/sources/source-code-diff.html
@@ -22,7 +22,7 @@
 
     function onBefore(beforeFrame)
     {
-        InspectorTest.addSniffer(Sources.SourceCodeDiff.prototype, "_decorationsSetForTest", decorationsSet);
+        InspectorTest.addSniffer(SourceFrame.SourceCodeDiff.prototype, "_decorationsSetForTest", decorationsSet);
         beforeFrame.setContent(textAfter);
     }
 
@@ -35,11 +35,11 @@
         {
             var type = decoration[1].type;
             var name = "Unknown";
-            if (type === Sources.SourceCodeDiff.GutterDecorationType.Insert)
+            if (type === SourceFrame.SourceCodeDiff.GutterDecorationType.Insert)
                 name = "Insert";
-            else if (type === Sources.SourceCodeDiff.GutterDecorationType.Delete)
+            else if (type === SourceFrame.SourceCodeDiff.GutterDecorationType.Delete)
                 name = "Delete";
-            else if (type === Sources.SourceCodeDiff.GutterDecorationType.Modify)
+            else if (type === SourceFrame.SourceCodeDiff.GutterDecorationType.Modify)
                 name = "Modify";
 
             InspectorTest.addResult(decoration[0] + ":" + name)
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-line-level-profile.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-line-level-profile.html
index ef18a523..5f1d4bf8 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-line-level-profile.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-line-level-profile.html
@@ -65,7 +65,7 @@
         var url = frame.uiSourceCode().url();
         InspectorTest.addResult(InspectorTest.formatters.formatAsURL(url));
         cpuProfile.nodes.forEach(n => n.callFrame.url = url);
-        var lineProfile = Components.LineLevelProfile.instance();
+        var lineProfile = PerfUI.LineLevelProfile.instance();
         lineProfile.appendCPUProfile(new SDK.CPUProfileDataModel(cpuProfile));
         setTimeout(() => InspectorTest.completeTest(), 0);
     }
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8BindingForTesting.cpp b/third_party/WebKit/Source/bindings/core/v8/V8BindingForTesting.cpp
index 0a4c895..d6b8c797 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8BindingForTesting.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8BindingForTesting.cpp
@@ -79,9 +79,6 @@
   // the isolate.  Otherwise, the leak detector complains.  Really mysterious
   // hack.
   v8::Function::New(context(), nullptr);
-
-  if (m_holder->document().frame())
-    getScriptState()->disposePerContextData();
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp b/third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp
index 891b68f..61471d3 100644
--- a/third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp
@@ -83,12 +83,15 @@
 WindowProxy::WindowProxy(Frame* frame,
                          PassRefPtr<DOMWrapperWorld> world,
                          v8::Isolate* isolate)
-    : m_frame(frame), m_isolate(isolate), m_world(world) {}
+    : m_frame(frame),
+      m_isolate(isolate),
+      m_world(world),
+      m_lifecycle(Lifecycle::ContextUninitialized) {}
 
 WindowProxy::~WindowProxy() {
   // clearForClose() or clearForNavigation() must be invoked before destruction
   // starts.
-  ASSERT(!isContextInitialized());
+  DCHECK(m_lifecycle != Lifecycle::ContextInitialized);
 }
 
 DEFINE_TRACE(WindowProxy) {
@@ -96,7 +99,7 @@
 }
 
 void WindowProxy::disposeContext(GlobalDetachmentBehavior behavior) {
-  if (!isContextInitialized())
+  if (m_lifecycle != Lifecycle::ContextInitialized)
     return;
 
   ScriptState::Scope scope(m_scriptState.get());
@@ -133,6 +136,9 @@
   // it up when idle.
   V8GCForContextDispose::instance().notifyContextDisposed(
       m_frame->isMainFrame());
+
+  DCHECK(m_lifecycle == Lifecycle::ContextInitialized);
+  m_lifecycle = Lifecycle::ContextDetached;
 }
 
 void WindowProxy::clearForClose() {
@@ -144,20 +150,21 @@
 }
 
 v8::Local<v8::Object> WindowProxy::globalIfNotDetached() {
-  if (!isContextInitialized())
-    return v8::Local<v8::Object>();
-  DCHECK(m_scriptState->contextIsValid());
-  DCHECK(m_globalProxy == m_scriptState->context()->Global());
-  return m_globalProxy.newLocal(m_isolate);
+  if (m_lifecycle == Lifecycle::ContextInitialized) {
+    DCHECK(m_scriptState->contextIsValid());
+    DCHECK(m_globalProxy == m_scriptState->context()->Global());
+    return m_globalProxy.newLocal(m_isolate);
+  }
+  return v8::Local<v8::Object>();
 }
 
 v8::Local<v8::Object> WindowProxy::releaseGlobal() {
-  ASSERT(!isContextInitialized());
-  // If a ScriptState was created, the context was initialized at some point.
+  DCHECK(m_lifecycle != Lifecycle::ContextInitialized);
   // Make sure the global object was detached from the proxy by calling
   // clearForNavigation().
-  if (m_scriptState)
+  if (m_lifecycle == Lifecycle::ContextDetached)
     ASSERT(m_scriptState->isGlobalObjectDetached());
+
   v8::Local<v8::Object> global = m_globalProxy.newLocal(m_isolate);
   m_globalProxy.clear();
   return global;
@@ -211,12 +218,13 @@
 // If there are JS code holds a closure to the old inner window,
 // it won't be able to reach the outer window via its global object.
 void WindowProxy::initializeIfNeeded() {
-  if (isContextInitialized())
-    return;
-  initialize();
-
-  if (m_world->isMainWorld() && m_frame->isLocalFrame())
-    toLocalFrame(m_frame)->loader().dispatchDidClearWindowObjectInMainWorld();
+  // TODO(haraken): It is wrong to re-initialize an already detached window
+  // proxy. This must be 'if(m_lifecycle == Lifecycle::ContextUninitialized)'.
+  if (m_lifecycle != Lifecycle::ContextInitialized) {
+    initialize();
+    if (m_world->isMainWorld() && m_frame->isLocalFrame())
+      toLocalFrame(m_frame)->loader().dispatchDidClearWindowObjectInMainWorld();
+  }
 }
 
 void WindowProxy::initialize() {
@@ -231,7 +239,6 @@
   v8::HandleScope handleScope(m_isolate);
 
   createContext();
-  CHECK(isContextInitialized());
 
   ScriptState::Scope scope(m_scriptState.get());
   v8::Local<v8::Context> context = m_scriptState->context();
@@ -317,6 +324,12 @@
   CHECK(!context.IsEmpty());
 
   m_scriptState = ScriptState::create(context, m_world);
+
+  // TODO(haraken): Currently we cannot enable the following DCHECK because
+  // an already detached window proxy can be re-initialized. This is wrong.
+  // DCHECK(m_lifecycle == Lifecycle::ContextUninitialized);
+  m_lifecycle = Lifecycle::ContextInitialized;
+  DCHECK(m_scriptState->contextIsValid());
 }
 
 void WindowProxy::setupWindowPrototypeChain() {
@@ -465,7 +478,12 @@
   DCHECK(m_world->isMainWorld());
   // For an uninitialized main window proxy, there's nothing we need
   // to update. The update is done when the window proxy gets initialized later.
-  if (!isContextInitialized())
+  if (m_lifecycle == Lifecycle::ContextUninitialized)
+    return;
+  // TODO(yukishiino): Is it okay to not update document when the context
+  // is detached? It's not trivial to fix this because udpateDocumentProperty
+  // requires a not-yet-detached context to instantiate a document wrapper.
+  if (m_lifecycle == Lifecycle::ContextDetached)
     return;
 
   updateActivityLogger();
@@ -523,8 +541,12 @@
 void WindowProxy::namedItemAdded(HTMLDocument* document,
                                  const AtomicString& name) {
   DCHECK(m_world->isMainWorld());
-  DCHECK(m_scriptState);
-  if (!isContextInitialized())
+
+  // Context must be initialized before this point.
+  DCHECK(m_lifecycle >= Lifecycle::ContextInitialized);
+  // TODO(yukishiino): Is it okay to not update named properties
+  // after the context gets detached?
+  if (m_lifecycle == Lifecycle::ContextDetached)
     return;
 
   ScriptState::Scope scope(m_scriptState.get());
@@ -540,12 +562,16 @@
 void WindowProxy::namedItemRemoved(HTMLDocument* document,
                                    const AtomicString& name) {
   DCHECK(m_world->isMainWorld());
-  DCHECK(m_scriptState);
-  if (!isContextInitialized())
-    return;
-  if (document->hasNamedItem(name) || document->hasExtraNamedItem(name))
+
+  // Context must be initialized before this point.
+  DCHECK(m_lifecycle >= Lifecycle::ContextInitialized);
+  // TODO(yukishiino): Is it okay to not update named properties
+  // after the context gets detached?
+  if (m_lifecycle == Lifecycle::ContextDetached)
     return;
 
+  if (document->hasNamedItem(name) || document->hasExtraNamedItem(name))
+    return;
   ScriptState::Scope scope(m_scriptState.get());
   v8::Local<v8::Object> documentWrapper =
       m_world->domDataStore().get(document, m_isolate);
@@ -555,8 +581,15 @@
 }
 
 void WindowProxy::updateSecurityOrigin(SecurityOrigin* origin) {
-  if (!isContextInitialized())
+  // For an uninitialized main window proxy, there's nothing we need
+  // to update. The update is done when the window proxy gets initialized later.
+  if (m_lifecycle == Lifecycle::ContextUninitialized)
     return;
+  // TODO(yukishiino): Is it okay to not update security origin when the context
+  // is detached?
+  if (m_lifecycle == Lifecycle::ContextDetached)
+    return;
+
   setSecurityToken(origin);
 }
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/WindowProxy.h b/third_party/WebKit/Source/bindings/core/v8/WindowProxy.h
index 7373e0f..9f074f2b 100644
--- a/third_party/WebKit/Source/bindings/core/v8/WindowProxy.h
+++ b/third_party/WebKit/Source/bindings/core/v8/WindowProxy.h
@@ -72,9 +72,6 @@
   // (e.g., after setting docoument.domain).
   void updateSecurityOrigin(SecurityOrigin*);
 
-  bool isContextInitialized() {
-    return m_scriptState && !!m_scriptState->perContextData();
-  }
   void initializeIfNeeded();
 
   void clearForNavigation();
@@ -87,6 +84,14 @@
   DOMWrapperWorld& world() { return *m_world; }
 
  private:
+  // A valid transition is from ContextUninitialized to ContextInitialized,
+  // and then ContextDetached. Other transitions are forbidden.
+  enum class Lifecycle {
+    ContextUninitialized,
+    ContextInitialized,
+    ContextDetached,
+  };
+
   WindowProxy(Frame*, PassRefPtr<DOMWrapperWorld>, v8::Isolate*);
   void initialize();
 
@@ -118,6 +123,7 @@
   RefPtr<ScriptState> m_scriptState;
   RefPtr<DOMWrapperWorld> m_world;
   ScopedPersistent<v8::Object> m_globalProxy;
+  Lifecycle m_lifecycle;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/BUILD.gn b/third_party/WebKit/Source/core/css/BUILD.gn
index cf6c3e7..9ecf1aa 100644
--- a/third_party/WebKit/Source/core/css/BUILD.gn
+++ b/third_party/WebKit/Source/core/css/BUILD.gn
@@ -346,6 +346,7 @@
     "properties/CSSPropertyAPI.h",
     "properties/CSSPropertyAPISize.cpp",
     "properties/CSSPropertyAPITextDecorationColor.cpp",
+    "properties/CSSPropertyAPITextDecorationSkip.cpp",
     "properties/CSSPropertyAPITextUnderlinePosition.cpp",
     "properties/CSSPropertyAPITransformOrigin.cpp",
     "properties/CSSPropertyAPITranslate.cpp",
diff --git a/third_party/WebKit/Source/core/css/CSSProperties.in b/third_party/WebKit/Source/core/css/CSSProperties.in
index d0e5f98..24f359f 100644
--- a/third_party/WebKit/Source/core/css/CSSProperties.in
+++ b/third_party/WebKit/Source/core/css/CSSProperties.in
@@ -368,7 +368,7 @@
 stroke-width interpolable, inherited, svg, converter=convertUnzoomedLength
 table-layout
 tab-size inherited, converter=convertLengthOrTabSpaces, type_name=TabSize
-text-align inherited, custom_value, keyword_only, keywords=[left|right|center|justify|webkitLeft|webkitRight|webkitCenter|start|end], initial_keyword=start
+text-align inherited, independent, custom_value, keyword_only, keywords=[left|right|center|justify|webkitLeft|webkitRight|webkitCenter|start|end], initial_keyword=start
 text-align-last inherited, type_name=TextAlignLast
 text-anchor inherited, svg
 text-combine-upright inherited, type_name=TextCombine, name_for_methods=TextCombine
@@ -376,7 +376,7 @@
 text-decoration use_handlers_for=CSSPropertyTextDecorationLine, longhands=text-decoration-line;text-decoration-style;text-decoration-color
 text-decoration-color runtime_flag=CSS3TextDecorations, interpolable, custom_all, api_class
 text-decoration-line runtime_flag=CSS3TextDecorations, name_for_methods=TextDecoration, type_name=TextDecoration, converter=convertFlags<TextDecoration>
-text-decoration-skip runtime_flag=CSS3TextDecorations, inherited, type_name=TextDecorationSkip, converter=convertFlags<TextDecorationSkip>
+text-decoration-skip runtime_flag=CSS3TextDecorations, inherited, type_name=TextDecorationSkip, converter=convertFlags<TextDecorationSkip>, api_class
 text-decoration-style runtime_flag=CSS3TextDecorations, type_name=TextDecorationStyle
 text-indent interpolable, inherited, custom_all
 text-justify runtime_flag=CSS3Text, inherited, type_name=TextJustify
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
index a0dae57c..b897acdc 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
@@ -1401,24 +1401,6 @@
   return list;
 }
 
-static CSSValue* consumeTextDecorationSkip(CSSParserTokenRange& range) {
-  CSSValueList* list = CSSValueList::createSpaceSeparated();
-  while (true) {
-    CSSIdentifierValue* ident =
-        consumeIdent<CSSValueObjects, CSSValueInk>(range);
-    if (!ident)
-      break;
-    if (list->hasValue(*ident))
-      return nullptr;
-    list->append(*ident);
-  }
-
-  if (!list->length())
-    return nullptr;
-
-  return list;
-}
-
 // none | strict | content | [ layout || style || paint || size ]
 static CSSValue* consumeContain(CSSParserTokenRange& range) {
   CSSValueID id = range.peek().id();
@@ -3526,9 +3508,6 @@
     case CSSPropertyWebkitTextDecorationsInEffect:
     case CSSPropertyTextDecorationLine:
       return consumeTextDecorationLine(m_range);
-    case CSSPropertyTextDecorationSkip:
-      DCHECK(RuntimeEnabledFeatures::css3TextDecorationsEnabled());
-      return consumeTextDecorationSkip(m_range);
     case CSSPropertyOffsetAnchor:
       return consumeOffsetAnchor(m_range, m_context.mode());
     case CSSPropertyOffsetPosition:
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITextDecorationSkip.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITextDecorationSkip.cpp
new file mode 100644
index 0000000..946f7be7
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITextDecorationSkip.cpp
@@ -0,0 +1,36 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/css/properties/CSSPropertyAPITextDecorationSkip.h"
+
+#include "core/css/CSSIdentifierValue.h"
+#include "core/css/CSSValueList.h"
+#include "core/css/parser/CSSPropertyParserHelpers.h"
+#include "platform/RuntimeEnabledFeatures.h"
+
+namespace blink {
+
+const CSSValue* CSSPropertyAPITextDecorationSkip::parseSingleValue(
+    CSSParserTokenRange& range,
+    const CSSParserContext& context) {
+  DCHECK(RuntimeEnabledFeatures::css3TextDecorationsEnabled());
+  CSSValueList* list = CSSValueList::createSpaceSeparated();
+  while (true) {
+    CSSIdentifierValue* ident =
+        CSSPropertyParserHelpers::consumeIdent<CSSValueObjects, CSSValueInk>(
+            range);
+    if (!ident)
+      break;
+    if (list->hasValue(*ident))
+      return nullptr;
+    list->append(*ident);
+  }
+
+  if (!list->length())
+    return nullptr;
+
+  return list;
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
index 3173b5d..27681120 100644
--- a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
+++ b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
@@ -838,22 +838,21 @@
     WebLayerTreeView& layerTreeView) {
   if (Platform::current()->isThreadedAnimationEnabled() &&
       layerTreeView.compositorAnimationHost()) {
-    m_compositorAnimationHost = WTF::makeUnique<CompositorAnimationHost>(
+    m_animationHost = WTF::makeUnique<CompositorAnimationHost>(
         layerTreeView.compositorAnimationHost());
     m_programmaticScrollAnimatorTimeline =
         CompositorAnimationTimeline::create();
-    m_compositorAnimationHost->addTimeline(
-        *m_programmaticScrollAnimatorTimeline.get());
+    m_animationHost->addTimeline(*m_programmaticScrollAnimatorTimeline.get());
   }
 }
 
 void ScrollingCoordinator::willCloseLayerTreeView(
     WebLayerTreeView& layerTreeView) {
   if (m_programmaticScrollAnimatorTimeline) {
-    m_compositorAnimationHost->removeTimeline(
+    m_animationHost->removeTimeline(
         *m_programmaticScrollAnimatorTimeline.get());
     m_programmaticScrollAnimatorTimeline = nullptr;
-    m_compositorAnimationHost = nullptr;
+    m_animationHost = nullptr;
   }
 }
 
diff --git a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.h b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.h
index fa93940..7d97eb4 100644
--- a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.h
+++ b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.h
@@ -121,7 +121,7 @@
   void updateTouchEventTargetRectsIfNeeded();
 
   CompositorAnimationHost* compositorAnimationHost() {
-    return m_compositorAnimationHost.get();
+    return m_animationHost.get();
   }
   CompositorAnimationTimeline* compositorAnimationTimeline() {
     return m_programmaticScrollAnimatorTimeline.get();
@@ -167,7 +167,7 @@
 
   bool frameViewIsDirty() const;
 
-  std::unique_ptr<CompositorAnimationHost> m_compositorAnimationHost;
+  std::unique_ptr<CompositorAnimationHost> m_animationHost;
   std::unique_ptr<CompositorAnimationTimeline>
       m_programmaticScrollAnimatorTimeline;
 
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.cpp b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
index 23deafc..ca64c123 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.cpp
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
@@ -104,7 +104,7 @@
     EDisplay display) {
   RefPtr<ComputedStyle> newStyle = ComputedStyle::create();
   newStyle->inheritFrom(parentStyle);
-  newStyle->inheritUnicodeBidiFrom(parentStyle);
+  newStyle->setUnicodeBidi(parentStyle.unicodeBidi());
   newStyle->setDisplay(display);
   return newStyle;
 }
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.h b/third_party/WebKit/Source/core/style/ComputedStyle.h
index 1ad4dc9..c4eecd3 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.h
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.h
@@ -3726,10 +3726,6 @@
                         setVisitedLinkCaretColor, v);
   }
 
-  void inheritUnicodeBidiFrom(const ComputedStyle& parent) {
-    m_nonInheritedData.m_unicodeBidi = parent.m_nonInheritedData.m_unicodeBidi;
-  }
-
   static bool isDisplayFlexibleBox(EDisplay display) {
     return display == EDisplay::Flex || display == EDisplay::InlineFlex;
   }
diff --git a/third_party/WebKit/Source/core/timing/PerformanceBase.cpp b/third_party/WebKit/Source/core/timing/PerformanceBase.cpp
index 78da775..320aad6 100644
--- a/third_party/WebKit/Source/core/timing/PerformanceBase.cpp
+++ b/third_party/WebKit/Source/core/timing/PerformanceBase.cpp
@@ -556,16 +556,23 @@
 }
 
 DOMHighResTimeStamp PerformanceBase::monotonicTimeToDOMHighResTimeStamp(
-    double monotonicTime) const {
+    double timeOrigin,
+    double monotonicTime) {
   // Avoid exposing raw platform timestamps.
-  if (m_timeOrigin == 0.0)
+  if (!monotonicTime || !timeOrigin)
     return 0.0;
 
-  double timeInSeconds = monotonicTime - m_timeOrigin;
+  double timeInSeconds = monotonicTime - timeOrigin;
+  DCHECK_GE(timeInSeconds, 0);
   return convertSecondsToDOMHighResTimeStamp(
       clampTimeResolution(timeInSeconds));
 }
 
+DOMHighResTimeStamp PerformanceBase::monotonicTimeToDOMHighResTimeStamp(
+    double monotonicTime) const {
+  return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, monotonicTime);
+}
+
 DOMHighResTimeStamp PerformanceBase::now() const {
   return monotonicTimeToDOMHighResTimeStamp(monotonicallyIncreasingTime());
 }
diff --git a/third_party/WebKit/Source/core/timing/PerformanceBase.h b/third_party/WebKit/Source/core/timing/PerformanceBase.h
index ac699ab..d455a48 100644
--- a/third_party/WebKit/Source/core/timing/PerformanceBase.h
+++ b/third_party/WebKit/Source/core/timing/PerformanceBase.h
@@ -74,6 +74,10 @@
   // http://www.w3.org/TR/hr-time-2/#privacy-security
   static double clampTimeResolution(double timeSeconds);
 
+  static DOMHighResTimeStamp monotonicTimeToDOMHighResTimeStamp(
+      double timeOrigin,
+      double monotonicTime);
+
   // Translate given platform monotonic time in seconds into a high resolution
   // DOMHighResTimeStamp in milliseconds. The result timestamp is relative to
   // document's time origin and has a time resolution that is safe for
diff --git a/third_party/WebKit/Source/core/timing/PerformanceEntry.cpp b/third_party/WebKit/Source/core/timing/PerformanceEntry.cpp
index e5779fac..46791f12 100644
--- a/third_party/WebKit/Source/core/timing/PerformanceEntry.cpp
+++ b/third_party/WebKit/Source/core/timing/PerformanceEntry.cpp
@@ -55,11 +55,11 @@
   return m_entryType;
 }
 
-double PerformanceEntry::startTime() const {
+DOMHighResTimeStamp PerformanceEntry::startTime() const {
   return m_startTime;
 }
 
-double PerformanceEntry::duration() const {
+DOMHighResTimeStamp PerformanceEntry::duration() const {
   return m_duration;
 }
 
diff --git a/third_party/WebKit/Source/core/timing/PerformanceEntry.h b/third_party/WebKit/Source/core/timing/PerformanceEntry.h
index 3abb644..06e7a923 100644
--- a/third_party/WebKit/Source/core/timing/PerformanceEntry.h
+++ b/third_party/WebKit/Source/core/timing/PerformanceEntry.h
@@ -34,6 +34,7 @@
 
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "core/CoreExport.h"
+#include "core/dom/DOMHighResTimeStamp.h"
 #include "platform/heap/Handle.h"
 #include "wtf/text/WTFString.h"
 
@@ -68,8 +69,8 @@
 
   String name() const;
   String entryType() const;
-  double startTime() const;
-  double duration() const;
+  DOMHighResTimeStamp startTime() const;
+  DOMHighResTimeStamp duration() const;
 
   ScriptValue toJSONForBinding(ScriptState*) const;
 
diff --git a/third_party/WebKit/Source/core/timing/PerformanceNavigationTiming.cpp b/third_party/WebKit/Source/core/timing/PerformanceNavigationTiming.cpp
index 5580c3a3..8e75bcc 100644
--- a/third_party/WebKit/Source/core/timing/PerformanceNavigationTiming.cpp
+++ b/third_party/WebKit/Source/core/timing/PerformanceNavigationTiming.cpp
@@ -9,17 +9,6 @@
 
 namespace blink {
 
-// TODO(sunjian): Move this logic into PerformanceBase
-static double monotonicTimeToDOMHighResTimeStamp(double timeOrigin,
-                                                 double seconds) {
-  DCHECK(seconds >= 0.0);
-  if (!seconds || !timeOrigin)
-    return 0.0;
-  if (seconds < timeOrigin)
-    return 0.0;
-  return PerformanceBase::clampTimeResolution(seconds - timeOrigin) * 1000.0;
-}
-
 PerformanceNavigationTiming::PerformanceNavigationTiming(
     double timeOrigin,
     double unloadEventStart,
@@ -81,43 +70,51 @@
 
 PerformanceNavigationTiming::~PerformanceNavigationTiming() {}
 
-double PerformanceNavigationTiming::unloadEventStart() const {
+DOMHighResTimeStamp PerformanceNavigationTiming::unloadEventStart() const {
   if (!m_allowRedirectDetails || !m_hasSameOriginAsPreviousDocument)
     return 0;
-  return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_unloadEventStart);
+  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(
+      m_timeOrigin, m_unloadEventStart);
 }
 
-double PerformanceNavigationTiming::unloadEventEnd() const {
+DOMHighResTimeStamp PerformanceNavigationTiming::unloadEventEnd() const {
   if (!m_allowRedirectDetails || !m_hasSameOriginAsPreviousDocument)
     return 0;
 
-  return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_unloadEventEnd);
+  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(m_timeOrigin,
+                                                             m_unloadEventEnd);
 }
 
-double PerformanceNavigationTiming::domInteractive() const {
-  return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_domInteractive);
+DOMHighResTimeStamp PerformanceNavigationTiming::domInteractive() const {
+  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(m_timeOrigin,
+                                                             m_domInteractive);
 }
 
-double PerformanceNavigationTiming::domContentLoadedEventStart() const {
-  return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin,
-                                            m_domContentLoadedEventStart);
+DOMHighResTimeStamp PerformanceNavigationTiming::domContentLoadedEventStart()
+    const {
+  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(
+      m_timeOrigin, m_domContentLoadedEventStart);
 }
 
-double PerformanceNavigationTiming::domContentLoadedEventEnd() const {
-  return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin,
-                                            m_domContentLoadedEventEnd);
+DOMHighResTimeStamp PerformanceNavigationTiming::domContentLoadedEventEnd()
+    const {
+  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(
+      m_timeOrigin, m_domContentLoadedEventEnd);
 }
 
-double PerformanceNavigationTiming::domComplete() const {
-  return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_domComplete);
+DOMHighResTimeStamp PerformanceNavigationTiming::domComplete() const {
+  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(m_timeOrigin,
+                                                             m_domComplete);
 }
 
-double PerformanceNavigationTiming::loadEventStart() const {
-  return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_loadEventStart);
+DOMHighResTimeStamp PerformanceNavigationTiming::loadEventStart() const {
+  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(m_timeOrigin,
+                                                             m_loadEventStart);
 }
 
-double PerformanceNavigationTiming::loadEventEnd() const {
-  return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_loadEventEnd);
+DOMHighResTimeStamp PerformanceNavigationTiming::loadEventEnd() const {
+  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(m_timeOrigin,
+                                                             m_loadEventEnd);
 }
 
 AtomicString PerformanceNavigationTiming::type() const {
@@ -141,24 +138,28 @@
   return m_redirectCount;
 }
 
-double PerformanceNavigationTiming::fetchStart() const {
-  return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_fetchStart);
+DOMHighResTimeStamp PerformanceNavigationTiming::fetchStart() const {
+  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(m_timeOrigin,
+                                                             m_fetchStart);
 }
 
-double PerformanceNavigationTiming::redirectStart() const {
+DOMHighResTimeStamp PerformanceNavigationTiming::redirectStart() const {
   if (!m_allowRedirectDetails)
     return 0;
-  return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_redirectStart);
+  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(m_timeOrigin,
+                                                             m_redirectStart);
 }
 
-double PerformanceNavigationTiming::redirectEnd() const {
+DOMHighResTimeStamp PerformanceNavigationTiming::redirectEnd() const {
   if (!m_allowRedirectDetails)
     return 0;
-  return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_redirectEnd);
+  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(m_timeOrigin,
+                                                             m_redirectEnd);
 }
 
-double PerformanceNavigationTiming::responseEnd() const {
-  return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_responseEnd);
+DOMHighResTimeStamp PerformanceNavigationTiming::responseEnd() const {
+  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(m_timeOrigin,
+                                                             m_responseEnd);
 }
 
 void PerformanceNavigationTiming::buildJSONValue(
diff --git a/third_party/WebKit/Source/core/timing/PerformanceNavigationTiming.h b/third_party/WebKit/Source/core/timing/PerformanceNavigationTiming.h
index 64e54fa..2022807 100644
--- a/third_party/WebKit/Source/core/timing/PerformanceNavigationTiming.h
+++ b/third_party/WebKit/Source/core/timing/PerformanceNavigationTiming.h
@@ -6,6 +6,7 @@
 #define PerformanceNavigationTiming_h
 
 #include "core/CoreExport.h"
+#include "core/dom/DOMHighResTimeStamp.h"
 #include "core/timing/PerformanceResourceTiming.h"
 
 namespace blink {
@@ -42,22 +43,22 @@
                               unsigned long long decodedBodyLength,
                               bool didReuseConnection);
 
-  double unloadEventStart() const;
-  double unloadEventEnd() const;
-  double domInteractive() const;
-  double domContentLoadedEventStart() const;
-  double domContentLoadedEventEnd() const;
-  double domComplete() const;
-  double loadEventStart() const;
-  double loadEventEnd() const;
+  DOMHighResTimeStamp unloadEventStart() const;
+  DOMHighResTimeStamp unloadEventEnd() const;
+  DOMHighResTimeStamp domInteractive() const;
+  DOMHighResTimeStamp domContentLoadedEventStart() const;
+  DOMHighResTimeStamp domContentLoadedEventEnd() const;
+  DOMHighResTimeStamp domComplete() const;
+  DOMHighResTimeStamp loadEventStart() const;
+  DOMHighResTimeStamp loadEventEnd() const;
   AtomicString type() const;
   unsigned short redirectCount() const;
 
   // PerformanceResourceTiming overrides:
-  double fetchStart() const override;
-  double redirectStart() const override;
-  double redirectEnd() const override;
-  double responseEnd() const override;
+  DOMHighResTimeStamp fetchStart() const override;
+  DOMHighResTimeStamp redirectStart() const override;
+  DOMHighResTimeStamp redirectEnd() const override;
+  DOMHighResTimeStamp responseEnd() const override;
 
  protected:
   void buildJSONValue(V8ObjectBuilder&) const override;
diff --git a/third_party/WebKit/Source/core/timing/PerformanceResourceTiming.cpp b/third_party/WebKit/Source/core/timing/PerformanceResourceTiming.cpp
index e20534b..3353a97 100644
--- a/third_party/WebKit/Source/core/timing/PerformanceResourceTiming.cpp
+++ b/third_party/WebKit/Source/core/timing/PerformanceResourceTiming.cpp
@@ -39,15 +39,6 @@
 
 namespace blink {
 
-// TODO(majidvp): Should return DOMHighResTimeStamp type instead
-static double monotonicTimeToDOMHighResTimeStamp(double timeOrigin,
-                                                 double seconds) {
-  ASSERT(seconds >= 0.0);
-  if (!seconds || !timeOrigin)
-    return 0.0;
-  return PerformanceBase::clampTimeResolution(seconds - timeOrigin) * 1000.0;
-}
-
 PerformanceResourceTiming::PerformanceResourceTiming(
     const AtomicString& initiatorType,
     double timeOrigin,
@@ -66,8 +57,10 @@
     : PerformanceEntry(
           name,
           entryType,
-          monotonicTimeToDOMHighResTimeStamp(timeOrigin, startTime),
-          monotonicTimeToDOMHighResTimeStamp(timeOrigin, finishTime)),
+          PerformanceBase::monotonicTimeToDOMHighResTimeStamp(timeOrigin,
+                                                              startTime),
+          PerformanceBase::monotonicTimeToDOMHighResTimeStamp(timeOrigin,
+                                                              finishTime)),
       m_initiatorType(initiatorType),
       m_timeOrigin(timeOrigin),
       m_timing(timing),
@@ -108,76 +101,78 @@
   return m_initiatorType;
 }
 
-double PerformanceResourceTiming::workerStart() const {
+DOMHighResTimeStamp PerformanceResourceTiming::workerStart() const {
   if (!m_timing || m_timing->workerStart() == 0.0)
     return 0.0;
 
-  return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin,
-                                            m_timing->workerStart());
+  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(
+      m_timeOrigin, m_timing->workerStart());
 }
 
-double PerformanceResourceTiming::workerReady() const {
+DOMHighResTimeStamp PerformanceResourceTiming::workerReady() const {
   if (!m_timing || m_timing->workerReady() == 0.0)
     return 0.0;
 
-  return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin,
-                                            m_timing->workerReady());
+  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(
+      m_timeOrigin, m_timing->workerReady());
 }
 
-double PerformanceResourceTiming::redirectStart() const {
+DOMHighResTimeStamp PerformanceResourceTiming::redirectStart() const {
   if (!m_lastRedirectEndTime || !m_allowRedirectDetails)
     return 0.0;
 
-  if (double workerReadyTime = workerReady())
+  if (DOMHighResTimeStamp workerReadyTime = workerReady())
     return workerReadyTime;
 
   return PerformanceEntry::startTime();
 }
 
-double PerformanceResourceTiming::redirectEnd() const {
+DOMHighResTimeStamp PerformanceResourceTiming::redirectEnd() const {
   if (!m_lastRedirectEndTime || !m_allowRedirectDetails)
     return 0.0;
 
-  return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin,
-                                            m_lastRedirectEndTime);
+  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(
+      m_timeOrigin, m_lastRedirectEndTime);
 }
 
-double PerformanceResourceTiming::fetchStart() const {
+DOMHighResTimeStamp PerformanceResourceTiming::fetchStart() const {
   if (m_lastRedirectEndTime) {
     // FIXME: ASSERT(m_timing) should be in constructor once timeticks of
     // AppCache is exposed from chrome network stack, crbug/251100
     ASSERT(m_timing);
-    return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin,
-                                              m_timing->requestTime());
+    return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(
+        m_timeOrigin, m_timing->requestTime());
   }
 
-  if (double workerReadyTime = workerReady())
+  if (DOMHighResTimeStamp workerReadyTime = workerReady())
     return workerReadyTime;
 
   return PerformanceEntry::startTime();
 }
 
-double PerformanceResourceTiming::domainLookupStart() const {
+DOMHighResTimeStamp PerformanceResourceTiming::domainLookupStart() const {
   if (!m_allowTimingDetails)
     return 0.0;
 
   if (!m_timing || m_timing->dnsStart() == 0.0)
     return fetchStart();
 
-  return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_timing->dnsStart());
+  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(
+      m_timeOrigin, m_timing->dnsStart());
 }
 
-double PerformanceResourceTiming::domainLookupEnd() const {
+DOMHighResTimeStamp PerformanceResourceTiming::domainLookupEnd() const {
   if (!m_allowTimingDetails)
     return 0.0;
 
   if (!m_timing || m_timing->dnsEnd() == 0.0)
     return domainLookupStart();
 
-  return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_timing->dnsEnd());
+  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(
+      m_timeOrigin, m_timing->dnsEnd());
 }
 
-double PerformanceResourceTiming::connectStart() const {
+DOMHighResTimeStamp PerformanceResourceTiming::connectStart() const {
   if (!m_allowTimingDetails)
     return 0.0;
 
@@ -190,10 +185,11 @@
   if (m_timing->dnsEnd() > 0.0)
     connectStart = m_timing->dnsEnd();
 
-  return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, connectStart);
+  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(m_timeOrigin,
+                                                             connectStart);
 }
 
-double PerformanceResourceTiming::connectEnd() const {
+DOMHighResTimeStamp PerformanceResourceTiming::connectEnd() const {
   if (!m_allowTimingDetails)
     return 0.0;
 
@@ -201,11 +197,11 @@
   if (!m_timing || m_timing->connectEnd() == 0.0 || m_didReuseConnection)
     return connectStart();
 
-  return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin,
-                                            m_timing->connectEnd());
+  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(
+      m_timeOrigin, m_timing->connectEnd());
 }
 
-double PerformanceResourceTiming::secureConnectionStart() const {
+DOMHighResTimeStamp PerformanceResourceTiming::secureConnectionStart() const {
   if (!m_allowTimingDetails)
     return 0.0;
 
@@ -213,21 +209,22 @@
       m_timing->sslStart() == 0.0)  // Secure connection not negotiated.
     return 0.0;
 
-  return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_timing->sslStart());
+  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(
+      m_timeOrigin, m_timing->sslStart());
 }
 
-double PerformanceResourceTiming::requestStart() const {
+DOMHighResTimeStamp PerformanceResourceTiming::requestStart() const {
   if (!m_allowTimingDetails)
     return 0.0;
 
   if (!m_timing)
     return connectEnd();
 
-  return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin,
-                                            m_timing->sendStart());
+  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(
+      m_timeOrigin, m_timing->sendStart());
 }
 
-double PerformanceResourceTiming::responseStart() const {
+DOMHighResTimeStamp PerformanceResourceTiming::responseStart() const {
   if (!m_allowTimingDetails)
     return 0.0;
 
@@ -236,15 +233,16 @@
 
   // FIXME: This number isn't exactly correct. See the notes in
   // PerformanceTiming::responseStart().
-  return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin,
-                                            m_timing->receiveHeadersEnd());
+  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(
+      m_timeOrigin, m_timing->receiveHeadersEnd());
 }
 
-double PerformanceResourceTiming::responseEnd() const {
+DOMHighResTimeStamp PerformanceResourceTiming::responseEnd() const {
   if (!m_finishTime)
     return responseStart();
 
-  return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_finishTime);
+  return PerformanceBase::monotonicTimeToDOMHighResTimeStamp(m_timeOrigin,
+                                                             m_finishTime);
 }
 
 unsigned long long PerformanceResourceTiming::transferSize() const {
diff --git a/third_party/WebKit/Source/core/timing/PerformanceResourceTiming.h b/third_party/WebKit/Source/core/timing/PerformanceResourceTiming.h
index c6e6bfc..222b1e2 100644
--- a/third_party/WebKit/Source/core/timing/PerformanceResourceTiming.h
+++ b/third_party/WebKit/Source/core/timing/PerformanceResourceTiming.h
@@ -32,6 +32,7 @@
 #ifndef PerformanceResourceTiming_h
 #define PerformanceResourceTiming_h
 
+#include "core/dom/DOMHighResTimeStamp.h"
 #include "core/timing/PerformanceEntry.h"
 #include "platform/heap/Handle.h"
 #include "wtf/Forward.h"
@@ -67,18 +68,18 @@
 
   AtomicString initiatorType() const;
 
-  double workerStart() const;
-  virtual double redirectStart() const;
-  virtual double redirectEnd() const;
-  virtual double fetchStart() const;
-  double domainLookupStart() const;
-  double domainLookupEnd() const;
-  double connectStart() const;
-  double connectEnd() const;
-  double secureConnectionStart() const;
-  double requestStart() const;
-  double responseStart() const;
-  virtual double responseEnd() const;
+  DOMHighResTimeStamp workerStart() const;
+  virtual DOMHighResTimeStamp redirectStart() const;
+  virtual DOMHighResTimeStamp redirectEnd() const;
+  virtual DOMHighResTimeStamp fetchStart() const;
+  DOMHighResTimeStamp domainLookupStart() const;
+  DOMHighResTimeStamp domainLookupEnd() const;
+  DOMHighResTimeStamp connectStart() const;
+  DOMHighResTimeStamp connectEnd() const;
+  DOMHighResTimeStamp secureConnectionStart() const;
+  DOMHighResTimeStamp requestStart() const;
+  DOMHighResTimeStamp responseStart() const;
+  virtual DOMHighResTimeStamp responseEnd() const;
   unsigned long long transferSize() const;
   unsigned long long encodedBodySize() const;
   unsigned long long decodedBodySize() const;
diff --git a/third_party/WebKit/Source/devtools/BUILD.gn b/third_party/WebKit/Source/devtools/BUILD.gn
index a97ca989..f98ba46 100644
--- a/third_party/WebKit/Source/devtools/BUILD.gn
+++ b/third_party/WebKit/Source/devtools/BUILD.gn
@@ -118,8 +118,6 @@
   "front_end/components_lazy/FilmStripModel.js",
   "front_end/components_lazy/filmStripView.css",
   "front_end/components_lazy/FilmStripView.js",
-  "front_end/components_lazy/GCActionDelegate.js",
-  "front_end/components_lazy/LineLevelProfile.js",
   "front_end/components_lazy/module.json",
   "front_end/components/breakpointsList.css",
   "front_end/components/BreakpointsSidebarPaneBase.js",
@@ -145,7 +143,6 @@
   "front_end/components/objectValue.css",
   "front_end/components/Reload.js",
   "front_end/components/RemoteObjectPreviewFormatter.js",
-  "front_end/components/RequestAppBannerActionDelegate.js",
   "front_end/components/ShortcutsScreen.js",
   "front_end/components/spectrum.css",
   "front_end/components/Spectrum.js",
@@ -269,12 +266,14 @@
   "front_end/layers/LayerTreeModel.js",
   "front_end/layers/module.json",
   "front_end/main/errorWarningCounter.css",
+  "front_end/main/GCActionDelegate.js",
   "front_end/main/Main.js",
   "front_end/main/module.json",
   "front_end/main/OverlayController.js",
   "front_end/main/remoteDebuggingTerminatedScreen.css",
   "front_end/main/renderingOptions.css",
   "front_end/main/RenderingOptions.js",
+  "front_end/main/RequestAppBannerActionDelegate.js",
   "front_end/main/SimpleApp.js",
   "front_end/main/targetCrashedScreen.css",
   "front_end/network/blockedURLsPane.css",
@@ -314,6 +313,7 @@
   "front_end/network/xmlTree.css",
   "front_end/network/xmlView.css",
   "front_end/network/XMLView.js",
+  "front_end/perf_ui/LineLevelProfile.js",
   "front_end/persistence/Automapping.js",
   "front_end/persistence/DefaultMapping.js",
   "front_end/persistence/FileSystemWorkspaceBinding.js",
@@ -342,6 +342,9 @@
   "front_end/profiler/TargetsComboBoxController.js",
   "front_end/profiler/TopDownProfileDataGrid.js",
   "front_end/protocol/InspectorBackend.js",
+  "front_end/quick_open/CommandMenu.js",
+  "front_end/quick_open/filteredListWidget.css",
+  "front_end/quick_open/FilteredListWidget.js",
   "front_end/resources/ApplicationCacheItemsView.js",
   "front_end/resources/appManifestView.css",
   "front_end/resources/AppManifestView.js",
@@ -441,8 +444,10 @@
   "front_end/source_frame/ImageView.js",
   "front_end/source_frame/module.json",
   "front_end/source_frame/ResourceSourceFrame.js",
+  "front_end/source_frame/SourceCodeDiff.js",
   "front_end/source_frame/SourceFrame.js",
   "front_end/source_frame/SourcesTextEditor.js",
+  "front_end/source_frame/UISourceCodeFrame.js",
   "front_end/sources/AddSourceMapURLDialog.js",
   "front_end/sources/AdvancedSearchView.js",
   "front_end/sources/CallStackSidebarPane.js",
@@ -472,7 +477,6 @@
   "front_end/sources/ScriptFormatterEditorAction.js",
   "front_end/sources/serviceWorkersSidebar.css",
   "front_end/sources/SimpleHistoryManager.js",
-  "front_end/sources/SourceCodeDiff.js",
   "front_end/sources/SourceMapNamesResolver.js",
   "front_end/sources/SourcesNavigator.js",
   "front_end/sources/sourcesPanel.css",
@@ -486,7 +490,6 @@
   "front_end/sources/ThreadsSidebarPane.js",
   "front_end/sources/uiList.css",
   "front_end/sources/UIList.js",
-  "front_end/sources/UISourceCodeFrame.js",
   "front_end/sources/WatchExpressionsSidebarPane.js",
   "front_end/sources/WorkspaceMappingTip.js",
   "front_end/sources/XHRBreakpointsSidebarPane.js",
@@ -535,12 +538,9 @@
   "front_end/toolbox.js",
   "front_end/toolbox.json",
   "front_end/ui_lazy/ChartViewport.js",
-  "front_end/ui_lazy/CommandMenu.js",
   "front_end/ui_lazy/dataGrid.css",
   "front_end/ui_lazy/DataGrid.js",
   "front_end/ui_lazy/dialog.css",
-  "front_end/ui_lazy/filteredListWidget.css",
-  "front_end/ui_lazy/FilteredListWidget.js",
   "front_end/ui_lazy/flameChart.css",
   "front_end/ui_lazy/FlameChart.js",
   "front_end/ui_lazy/module.json",
@@ -803,7 +803,9 @@
   "$resources_out_dir/layer_viewer/layer_viewer_module.js",
   "$resources_out_dir/layers/layers_module.js",
   "$resources_out_dir/network/network_module.js",
+  "$resources_out_dir/perf_ui/perf_ui_module.js",
   "$resources_out_dir/profiler/profiler_module.js",
+  "$resources_out_dir/quick_open/quick_open_module.js",
   "$resources_out_dir/resources/resources_module.js",
   "$resources_out_dir/sass/sass_module.js",
   "$resources_out_dir/security/security_module.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/Runtime.js b/third_party/WebKit/Source/devtools/front_end/Runtime.js
index 2a9732f..0d500cb 100644
--- a/third_party/WebKit/Source/devtools/front_end/Runtime.js
+++ b/third_party/WebKit/Source/devtools/front_end/Runtime.js
@@ -772,18 +772,20 @@
     if (!this._descriptor.scripts || !this._descriptor.scripts.length)
       return Promise.resolve();
 
-    // Module namespaces.
-    var namespace = this._name.replace('_lazy', '');
     // the namespace keyword confuses clang-format
     // clang-format off
-    if (namespace === 'sdk' || namespace === 'ui')
-      namespace = namespace.toUpperCase();
-    if (namespace === 'css_tracker')
-      namespace = 'CSSTracker';
-    // clang-format on
-    namespace = namespace.split('_').map(a => a.substring(0, 1).toUpperCase() + a.substring(1)).join('');
+    // Module namespaces.
+    const specialCases = {
+      'sdk': 'SDK',
+      'ui': 'UI',
+      'perf_ui': 'PerfUI',
+      'css_tracker': 'CSSTracker',
+      'ui_lazy': 'UI',
+      'components_lazy': 'Components'
+    };
+    var namespace = specialCases[this._name] || this._name.split('_').map(a => a.substring(0, 1).toUpperCase() + a.substring(1)).join('');
     self[namespace] = self[namespace] || {};
-
+    // clang-format on
     return Runtime._loadScriptsPromise(this._descriptor.scripts.map(this._modularizeURL, this), this._remoteBase());
   }
 
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 6f5d793c8..a696fcb2 100644
--- a/third_party/WebKit/Source/devtools/front_end/common/Object.js
+++ b/third_party/WebKit/Source/devtools/front_end/common/Object.js
@@ -27,6 +27,10 @@
  * @unrestricted
  */
 Common.Object = class {
+  constructor() {
+    /** @type {(!Map<(symbol|!Common.Emittable), !Array<!Common.Object._listenerCallbackTuple>>|undefined)} */
+    this._listeners;
+  }
   /**
    * @override
    * @param {symbol} eventType
@@ -40,6 +44,7 @@
 
     if (!this._listeners)
       this._listeners = new Map();
+
     if (!this._listeners.has(eventType))
       this._listeners.set(eventType, []);
     this._listeners.get(eventType).push({thisObject: thisObject, listener: listener});
@@ -73,7 +78,7 @@
    * @return {boolean}
    */
   hasEventListeners(eventType) {
-    return this._listeners && this._listeners.has(eventType);
+    return !!(this._listeners && this._listeners.has(eventType));
   }
 
   /**
@@ -92,12 +97,12 @@
   }
 
   /**
-   * @template T
    * @override
-   * @param {function(new:T, ...)} eventType
+   * @param {function(new:Common.Emittable, ...)} eventType
    * @param {function(!T)} listener
    * @param {!Object=} thisObject
    * @return {!Common.EventTarget.TypedEventDescriptor}
+   * @template T
    */
   on(eventType, listener, thisObject) {
     if (!this._listeners)
@@ -109,10 +114,9 @@
   }
 
   /**
-   * @template T
    * @override
-   * @param {function(new:T, ...)} eventType
-   * @param {function(!T)} listener
+   * @param {function(new:Common.Emittable, ...)} eventType
+   * @param {function(!Common.Emittable)} listener
    * @param {!Object=} thisObject
    */
   off(eventType, listener, thisObject) {
@@ -128,9 +132,8 @@
   }
 
   /**
-   * @template T
    * @override
-   * @param {!T} event
+   * @param {!Common.Emittable} event
    */
   emit(event) {
     var eventType = event.constructor;
@@ -143,6 +146,17 @@
 };
 
 /**
+ * @interface
+ */
+Common.Emittable = function() {};
+
+/**
+ * @typedef {!{thisObject: (!Object|undefined), listener: function(!Common.Emittable)}}
+ */
+Common.Object._listenerCallbackTuple;
+
+/**
+ * @implements {Common.Emittable}
  * @unrestricted
  */
 Common.Event = class {
@@ -160,15 +174,72 @@
 Common.EventTarget = function() {};
 
 /**
- * @param {!Array<!Common.EventTarget.EventDescriptor|!Common.EventTarget.TypedEventDescriptor>} eventList
+ * @record
+ * @template T
+ */
+Common.EventTarget.EventDescriptorStruct = class {
+  constructor() {
+    /** @type {!Common.EventTarget} */
+    this.eventTarget;
+    /** @type {!T} */
+    this.eventType;
+    /** @type {(!Object|undefined)} */
+    this.receiver;
+    /** @type {function(!Common.Emittable)} */
+    this.method;
+  }
+};
+
+/**
+ * @implements {Common.EventTarget.EventDescriptorStruct<symbol>}
+ * @unrestricted
+ */
+Common.EventTarget.EventDescriptor = class {
+  /**
+   * @param {!Common.EventTarget} eventTarget
+   * @param {symbol} eventType
+   * @param {(!Object|undefined)} receiver
+   * @param {function(!Common.Event)} method
+   */
+  constructor(eventTarget, eventType, receiver, method) {
+    this.eventTarget = eventTarget;
+    this.eventType = eventType;
+    this.receiver = receiver;
+    this.method = method;
+  }
+};
+
+/**
+ * @implements {Common.EventTarget.EventDescriptorStruct<function(new:Common.Emittable)>}
+ * @unrestricted
+ */
+Common.EventTarget.TypedEventDescriptor = class {
+  /**
+   * @param {!Common.EventTarget} eventTarget
+   * @param {function(new:Common.Emittable, ...)} eventType
+   * @param {(!Object|undefined)} receiver
+   * @param {function(!Common.Emittable)} method
+   */
+  constructor(eventTarget, eventType, receiver, method) {
+    this.eventTarget = eventTarget;
+    this.eventType = eventType;
+    this.receiver = receiver;
+    this.method = method;
+  }
+};
+
+/**
+ * @param {!Array<!Common.EventTarget.EventDescriptorStruct>} eventList
  */
 Common.EventTarget.removeEventListeners = function(eventList) {
   for (var i = 0; i < eventList.length; ++i) {
-    var eventInfo = eventList[i];
-    if (eventInfo instanceof Common.EventTarget.EventDescriptor)
+    if (eventList[i] instanceof Common.EventTarget.EventDescriptor) {
+      var eventInfo = /** @type {!Common.EventTarget.EventDescriptor} */ (eventList[i]);
       eventInfo.eventTarget.removeEventListener(eventInfo.eventType, eventInfo.method, eventInfo.receiver);
-    else
+    } else {
+      var eventInfo = /** @type {!Common.EventTarget.TypedEventDescriptor} */ (eventList[i]);
       eventInfo.eventTarget.off(eventInfo.eventType, eventInfo.method, eventInfo.receiver);
+    }
   }
   // Do not hold references on unused event descriptors.
   eventList.splice(0, eventList.length);
@@ -203,62 +274,23 @@
   dispatchEventToListeners(eventType, eventData) {},
 
   /**
-   * @template T
-   * @param {function(new:T, ...)} eventType
+   * @param {function(new:Common.Emittable, ...)} eventType
    * @param {function(!T)} listener
    * @param {!Object=} thisObject
    * @return {!Common.EventTarget.TypedEventDescriptor}
+   * @template T
    */
   on(eventType, listener, thisObject) {},
 
   /**
-   * @template T
-   * @param {function(new:T, ...)} eventType
-   * @param {function(!T)} listener
+   * @param {function(new:Common.Emittable, ...)} eventType
+   * @param {function(!Common.Emittable)} listener
    * @param {!Object=} thisObject
    */
   off(eventType, listener, thisObject) {},
 
   /**
-   * @template T
-   * @param {!T} event
+   * @param {!Common.Emittable} event
    */
   emit(event) {},
 };
-
-/**
- * @unrestricted
- */
-Common.EventTarget.EventDescriptor = class {
-  /**
-   * @param {!Common.EventTarget} eventTarget
-   * @param {symbol} eventType
-   * @param {(!Object|undefined)} receiver
-   * @param {function(?):?} method
-   */
-  constructor(eventTarget, eventType, receiver, method) {
-    this.eventTarget = eventTarget;
-    this.eventType = eventType;
-    this.receiver = receiver;
-    this.method = method;
-  }
-};
-
-/**
- * @template T
- * @unrestricted
- */
-Common.EventTarget.TypedEventDescriptor = class {
-  /**
-   * @param {!Common.EventTarget} eventTarget
-   * @param {function(new:T, ...)} eventType
-   * @param {(!Object|undefined)} receiver
-   * @param {function(!T)} method
-   */
-  constructor(eventTarget, eventType, receiver, method) {
-    this.eventTarget = eventTarget;
-    this.eventType = eventType;
-    this.receiver = receiver;
-    this.method = method;
-  }
-};
diff --git a/third_party/WebKit/Source/devtools/front_end/components/module.json b/third_party/WebKit/Source/devtools/front_end/components/module.json
index dbbf800..82de149 100644
--- a/third_party/WebKit/Source/devtools/front_end/components/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/components/module.json
@@ -47,13 +47,6 @@
             "settings": [
                 "customNetworkConditions"
             ]
-        },
-        {
-            "type": "@UI.ActionDelegate",
-            "category": "Mobile",
-            "actionId": "components.request-app-banner",
-            "className": "Components.RequestAppBannerActionDelegate",
-            "title": "Add to homescreen"
         }
     ],
     "dependencies": [
@@ -75,7 +68,6 @@
         "ObjectPopoverHelper.js",
         "ObjectPropertiesSection.js",
         "RemoteObjectPreviewFormatter.js",
-        "RequestAppBannerActionDelegate.js",
         "ShortcutsScreen.js",
         "Spectrum.js",
         "EventListenersUtils.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/components_lazy/module.json b/third_party/WebKit/Source/devtools/front_end/components_lazy/module.json
index dceef3e..0777916 100644
--- a/third_party/WebKit/Source/devtools/front_end/components_lazy/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/components_lazy/module.json
@@ -6,26 +6,11 @@
         "ui",
         "ui_lazy"
     ],
-    "extensions": [
-        {
-            "type": "@Sources.UISourceCodeFrame.LineDecorator",
-            "className": "Components.LineLevelProfile.LineDecorator",
-            "decoratorType": "performance"
-        },
-        {
-            "type": "@UI.ActionDelegate",
-            "actionId": "components.collect-garbage",
-            "title": "Collect garbage",
-            "iconClass": "largeicon-trash-bin",
-            "className": "Components.GCActionDelegate"
-        }
-    ],
+    "extensions": [],
     "scripts": [
         "CookiesTable.js",
         "FilmStripModel.js",
-        "FilmStripView.js",
-        "GCActionDelegate.js",
-        "LineLevelProfile.js"
+        "FilmStripView.js"
     ],
     "resources": [
         "filmStripDialog.css",
diff --git a/third_party/WebKit/Source/devtools/front_end/css_tracker/CSSTrackerView.js b/third_party/WebKit/Source/devtools/front_end/css_tracker/CSSTrackerView.js
index 45effdd..87ce396 100644
--- a/third_party/WebKit/Source/devtools/front_end/css_tracker/CSSTrackerView.js
+++ b/third_party/WebKit/Source/devtools/front_end/css_tracker/CSSTrackerView.js
@@ -382,7 +382,7 @@
 };
 
 /**
- * @implements {Sources.UISourceCodeFrame.LineDecorator}
+ * @implements {SourceFrame.UISourceCodeFrame.LineDecorator}
  */
 CSSTracker.CSSTrackerView.LineDecorator = class {
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/css_tracker/module.json b/third_party/WebKit/Source/devtools/front_end/css_tracker/module.json
index f3e930a..3951ef21 100644
--- a/third_party/WebKit/Source/devtools/front_end/css_tracker/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/css_tracker/module.json
@@ -11,15 +11,15 @@
             "experiment": "cssTrackerPanel"
         },
         {
-           "type": "@Sources.UISourceCodeFrame.LineDecorator",
-           "className": "CSSTracker.CSSTrackerView.LineDecorator",
-           "decoratorType": "coverage"
+            "type": "@SourceFrame.UISourceCodeFrame.LineDecorator",
+            "className": "CSSTracker.CSSTrackerView.LineDecorator",
+            "decoratorType": "coverage"
         }
     ],
     "dependencies": [
         "sdk",
-        "sources",
-        "ui"
+        "ui",
+        "source_frame"
     ],
     "scripts": [
         "CSSTrackerView.js"
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/AdvancedApp.js b/third_party/WebKit/Source/devtools/front_end/emulation/AdvancedApp.js
index 24117b8a..3f107358 100644
--- a/third_party/WebKit/Source/devtools/front_end/emulation/AdvancedApp.js
+++ b/third_party/WebKit/Source/devtools/front_end/emulation/AdvancedApp.js
@@ -28,6 +28,7 @@
     var rootView = new UI.RootView();
 
     this._rootSplitWidget = new UI.SplitWidget(false, true, 'InspectorView.splitViewState', 555, 300, true);
+    this._rootSplitWidget.element.classList.add('root-split-widget');
     this._rootSplitWidget.show(rootView.element);
     this._rootSplitWidget.setSidebarWidget(UI.inspectorView);
     this._rootSplitWidget.setDefaultFocusedChild(UI.inspectorView);
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeWrapper.js b/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeWrapper.js
index faaa35b..0c98630 100644
--- a/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeWrapper.js
+++ b/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeWrapper.js
@@ -49,12 +49,12 @@
       if (!this._deviceModeView)
         this._deviceModeView = new Emulation.DeviceModeView();
       this._deviceModeView.show(this.element);
-      this._inspectedPagePlaceholder.clearMinimumSizeAndMargins();
+      this._inspectedPagePlaceholder.clearMinimumSize();
       this._inspectedPagePlaceholder.show(this._deviceModeView.element);
     } else {
       if (this._deviceModeView)
         this._deviceModeView.detach();
-      this._inspectedPagePlaceholder.restoreMinimumSizeAndMargins();
+      this._inspectedPagePlaceholder.restoreMinimumSize();
       this._inspectedPagePlaceholder.show(this.element);
     }
   }
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/InspectedPagePlaceholder.js b/third_party/WebKit/Source/devtools/front_end/emulation/InspectedPagePlaceholder.js
index dd46640f..a3f74fc 100644
--- a/third_party/WebKit/Source/devtools/front_end/emulation/InspectedPagePlaceholder.js
+++ b/third_party/WebKit/Source/devtools/front_end/emulation/InspectedPagePlaceholder.js
@@ -8,62 +8,25 @@
   constructor() {
     super(true);
     this.registerRequiredCSS('emulation/inspectedPagePlaceholder.css');
-    UI.zoomManager.addEventListener(UI.ZoomManager.Events.ZoomChanged, this._scheduleUpdate, this);
-    this._margins = {top: 0, right: 0, bottom: 0, left: 0};
-    this.restoreMinimumSizeAndMargins();
-  }
-
-  _findMargins() {
-    var margins = {top: 0, right: 0, bottom: 0, left: 0};
-
-    if (this._useMargins) {
-      var adjacent = {top: true, right: true, bottom: true, left: true};
-      var widget = this;
-      while (widget.parentWidget()) {
-        var parent = widget.parentWidget();
-        // This view assumes it's always inside the main split widget element, not a sidebar.
-        // Every parent which is not a split widget, must be of the same size as this widget.
-        if (parent instanceof UI.SplitWidget) {
-          var side = parent.sidebarSide();
-          if (adjacent[side] && !parent.hasCustomResizer() && parent.isResizable())
-            margins[side] = Emulation.InspectedPagePlaceholder.MarginValue;
-          adjacent[side] = false;
-        }
-        widget = parent;
-      }
-    }
-
-    if (this._margins.top !== margins.top || this._margins.left !== margins.left ||
-        this._margins.right !== margins.right || this._margins.bottom !== margins.bottom) {
-      this._margins = margins;
-      this._scheduleUpdate();
-    }
+    UI.zoomManager.addEventListener(UI.ZoomManager.Events.ZoomChanged, this.onResize, this);
+    this.restoreMinimumSize();
   }
 
   /**
    * @override
    */
   onResize() {
-    this._findMargins();
-    this._scheduleUpdate();
-  }
-
-  _scheduleUpdate() {
     if (this._updateId)
       this.element.window().cancelAnimationFrame(this._updateId);
     this._updateId = this.element.window().requestAnimationFrame(this.update.bind(this));
   }
 
-  restoreMinimumSizeAndMargins() {
-    this._useMargins = true;
+  restoreMinimumSize() {
     this.setMinimumSize(150, 150);
-    this._findMargins();
   }
 
-  clearMinimumSizeAndMargins() {
-    this._useMargins = false;
+  clearMinimumSize() {
     this.setMinimumSize(1, 1);
-    this._findMargins();
   }
 
   _dipPageRect() {
@@ -71,10 +34,10 @@
     var rect = this.element.getBoundingClientRect();
     var bodyRect = this.element.ownerDocument.body.getBoundingClientRect();
 
-    var left = Math.max(rect.left * zoomFactor + this._margins.left, bodyRect.left * zoomFactor);
-    var top = Math.max(rect.top * zoomFactor + this._margins.top, bodyRect.top * zoomFactor);
-    var bottom = Math.min(rect.bottom * zoomFactor - this._margins.bottom, bodyRect.bottom * zoomFactor);
-    var right = Math.min(rect.right * zoomFactor - this._margins.right, bodyRect.right * zoomFactor);
+    var left = Math.max(rect.left * zoomFactor, bodyRect.left * zoomFactor);
+    var top = Math.max(rect.top * zoomFactor, bodyRect.top * zoomFactor);
+    var bottom = Math.min(rect.bottom * zoomFactor, bodyRect.bottom * zoomFactor);
+    var right = Math.min(rect.right * zoomFactor, bodyRect.right * zoomFactor);
 
     return {x: left, y: top, width: right - left, height: bottom - top};
   }
@@ -96,5 +59,3 @@
 Emulation.InspectedPagePlaceholder.Events = {
   Update: Symbol('Update')
 };
-
-Emulation.InspectedPagePlaceholder.MarginValue = 3;
diff --git a/third_party/WebKit/Source/devtools/front_end/externs.js b/third_party/WebKit/Source/devtools/front_end/externs.js
index 8d3f180..798da89 100644
--- a/third_party/WebKit/Source/devtools/front_end/externs.js
+++ b/third_party/WebKit/Source/devtools/front_end/externs.js
@@ -861,6 +861,8 @@
 /** @type {!Object} */
 var Network = {};
 /** @type {!Object} */
+var PerfUI = {};
+/** @type {!Object} */
 var Persistence = {};
 /** @type {!Object} */
 var Platform = {};
@@ -869,6 +871,8 @@
 /** @type {!Object} */
 var Protocol = {};
 /** @type {!Object} */
+var QuickOpen = {};
+/** @type {!Object} */
 var Resources = {};
 /** @type {!Object} */
 var Sass = {};
diff --git a/third_party/WebKit/Source/devtools/front_end/inspector.json b/third_party/WebKit/Source/devtools/front_end/inspector.json
index f19defff..46d6544 100644
--- a/third_party/WebKit/Source/devtools/front_end/inspector.json
+++ b/third_party/WebKit/Source/devtools/front_end/inspector.json
@@ -43,7 +43,9 @@
         { "name": "animation", "condition": "!v8only" },
         { "name": "css_tracker", "condition": "!v8only" },
         { "name": "screencast", "condition": "remoteFrontend", "type": "remote" },
-        { "name": "emulated_devices", "condition": "!v8only" , "type": "remote" }
+        { "name": "emulated_devices", "condition": "!v8only" , "type": "remote" },
+        { "name": "perf_ui" },
+        { "name": "quick_open" }
     ],
 
     "has_html": true
diff --git a/third_party/WebKit/Source/devtools/front_end/layer_viewer/module.json b/third_party/WebKit/Source/devtools/front_end/layer_viewer/module.json
index 48a25df5..4d2c944 100644
--- a/third_party/WebKit/Source/devtools/front_end/layer_viewer/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/layer_viewer/module.json
@@ -4,7 +4,8 @@
         "sdk",
         "timeline_model",
         "ui",
-        "ui_lazy"
+        "ui_lazy",
+        "perf_ui"
     ],
     "scripts": [
         "LayerDetailsView.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/components_lazy/GCActionDelegate.js b/third_party/WebKit/Source/devtools/front_end/main/GCActionDelegate.js
similarity index 92%
rename from third_party/WebKit/Source/devtools/front_end/components_lazy/GCActionDelegate.js
rename to third_party/WebKit/Source/devtools/front_end/main/GCActionDelegate.js
index 966002d..110bf10 100644
--- a/third_party/WebKit/Source/devtools/front_end/components_lazy/GCActionDelegate.js
+++ b/third_party/WebKit/Source/devtools/front_end/main/GCActionDelegate.js
@@ -5,7 +5,7 @@
 /**
  * @implements {UI.ActionDelegate}
  */
-Components.GCActionDelegate = class {
+Main.GCActionDelegate = class {
   /**
    * @override
    * @param {!UI.Context} context
diff --git a/third_party/WebKit/Source/devtools/front_end/components/RequestAppBannerActionDelegate.js b/third_party/WebKit/Source/devtools/front_end/main/RequestAppBannerActionDelegate.js
similarity index 91%
rename from third_party/WebKit/Source/devtools/front_end/components/RequestAppBannerActionDelegate.js
rename to third_party/WebKit/Source/devtools/front_end/main/RequestAppBannerActionDelegate.js
index 1221e09..5b2779f5 100644
--- a/third_party/WebKit/Source/devtools/front_end/components/RequestAppBannerActionDelegate.js
+++ b/third_party/WebKit/Source/devtools/front_end/main/RequestAppBannerActionDelegate.js
@@ -5,7 +5,7 @@
  * @implements {UI.ActionDelegate}
  * @unrestricted
  */
-Components.RequestAppBannerActionDelegate = class {
+Main.RequestAppBannerActionDelegate = class {
   /**
    * @override
    * @param {!UI.Context} context
diff --git a/third_party/WebKit/Source/devtools/front_end/main/module.json b/third_party/WebKit/Source/devtools/front_end/main/module.json
index 60020383..85e83f67 100644
--- a/third_party/WebKit/Source/devtools/front_end/main/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/main/module.json
@@ -7,17 +7,25 @@
         },
         {
             "type": "@UI.ContextMenu.Provider",
-            "contextTypes": ["Workspace.UISourceCode", "SDK.Resource", "SDK.NetworkRequest"],
+            "contextTypes": [
+                "Workspace.UISourceCode",
+                "SDK.Resource",
+                "SDK.NetworkRequest"
+            ],
             "className": "Components.Linkifier.ContentProviderContextMenuProvider"
         },
         {
             "type": "@UI.ContextMenu.Provider",
-            "contextTypes": ["Node"],
+            "contextTypes": [
+                "Node"
+            ],
             "className": "UI.ExternaLinkContextMenuProvider"
         },
         {
             "type": "@UI.ContextMenu.Provider",
-            "contextTypes": ["Node"],
+            "contextTypes": [
+                "Node"
+            ],
             "className": "Components.Linkifier.LinkContextMenuProvider"
         },
         {
@@ -227,8 +235,14 @@
             "order": 0,
             "defaultValue": false,
             "options": [
-                { "value": true, "title": "Disable cache (while DevTools is open)" },
-                { "value": false, "title": "Enable cache" }
+                {
+                    "value": true,
+                    "title": "Disable cache (while DevTools is open)"
+                },
+                {
+                    "value": false,
+                    "title": "Enable cache"
+                }
             ]
         },
         {
@@ -240,8 +254,14 @@
             "order": 1,
             "defaultValue": false,
             "options": [
-                { "value": true, "title": "Disable JavaScript" },
-                { "value": false, "title": "Enable JavaScript" }
+                {
+                    "value": true,
+                    "title": "Disable JavaScript"
+                },
+                {
+                    "value": false,
+                    "title": "Enable JavaScript"
+                }
             ]
         },
         {
@@ -253,8 +273,14 @@
             "order": 2,
             "defaultValue": false,
             "options": [
-                { "value": true, "title": "Auto-open DevTools for popups" },
-                { "value": false, "title": "Do not auto-open DevTools for popups" }
+                {
+                    "value": true,
+                    "title": "Auto-open DevTools for popups"
+                },
+                {
+                    "value": false,
+                    "title": "Do not auto-open DevTools for popups"
+                }
             ]
         },
         {
@@ -265,8 +291,16 @@
             "settingType": "enum",
             "defaultValue": "default",
             "options": [
-                { "title": "Switch to light theme", "text": "Light", "value": "default" },
-                { "title": "Switch to dark theme", "text": "Dark", "value": "dark" }
+                {
+                    "title": "Switch to light theme",
+                    "text": "Light",
+                    "value": "default"
+                },
+                {
+                    "title": "Switch to dark theme",
+                    "text": "Dark",
+                    "value": "dark"
+                }
             ],
             "tags": "dark, light"
         },
@@ -278,9 +312,21 @@
             "settingType": "enum",
             "defaultValue": "auto",
             "options": [
-                { "title": "Use horizontal panel layout", "text": "horizontal", "value": "bottom" },
-                { "title": "Use vertical panel layout", "text": "vertical", "value": "right" },
-                { "title": "Use automatic panel layout", "text": "auto", "value": "auto" }
+                {
+                    "title": "Use horizontal panel layout",
+                    "text": "horizontal",
+                    "value": "bottom"
+                },
+                {
+                    "title": "Use vertical panel layout",
+                    "text": "vertical",
+                    "value": "right"
+                },
+                {
+                    "title": "Use automatic panel layout",
+                    "text": "auto",
+                    "value": "auto"
+                }
             ]
         },
         {
@@ -342,15 +388,38 @@
             "settingType": "enum",
             "defaultValue": "right",
             "options": [
-                { "value": "right", "title": "Dock to right" },
-                { "value": "bottom", "title": "Dock to bottom" },
-                { "value": "undocked", "title": "Undock into separate window" }
+                {
+                    "value": "right",
+                    "title": "Dock to right"
+                },
+                {
+                    "value": "bottom",
+                    "title": "Dock to bottom"
+                },
+                {
+                    "value": "undocked",
+                    "title": "Undock into separate window"
+                }
             ]
         },
         {
             "type": "@UI.ViewLocationResolver",
             "name": "drawer-view",
             "className": "UI.InspectorView"
+        },
+        {
+            "type": "@UI.ActionDelegate",
+            "actionId": "components.collect-garbage",
+            "title": "Collect garbage",
+            "iconClass": "largeicon-trash-bin",
+            "className": "Main.GCActionDelegate"
+        },
+        {
+            "type": "@UI.ActionDelegate",
+            "category": "Mobile",
+            "actionId": "components.request-app-banner",
+            "className": "Main.RequestAppBannerActionDelegate",
+            "title": "Add to homescreen"
         }
     ],
     "dependencies": [
@@ -364,7 +433,9 @@
         "RenderingOptions.js",
         "SimpleApp.js",
         "OverlayController.js",
-        "Main.js"
+        "Main.js",
+        "GCActionDelegate.js",
+        "RequestAppBannerActionDelegate.js"
     ],
     "resources": [
         "errorWarningCounter.css",
diff --git a/third_party/WebKit/Source/devtools/front_end/network/module.json b/third_party/WebKit/Source/devtools/front_end/network/module.json
index 1209c399..1478116 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/network/module.json
@@ -10,12 +10,18 @@
         },
         {
             "type": "@UI.ContextMenu.Provider",
-            "contextTypes": ["SDK.NetworkRequest", "SDK.Resource", "Workspace.UISourceCode"],
+            "contextTypes": [
+                "SDK.NetworkRequest",
+                "SDK.Resource",
+                "Workspace.UISourceCode"
+            ],
             "className": "Network.NetworkPanel.ContextMenuProvider"
         },
         {
             "type": "@Common.Revealer",
-            "contextTypes": ["SDK.NetworkRequest"],
+            "contextTypes": [
+                "SDK.NetworkRequest"
+            ],
             "className": "Network.NetworkPanel.RequestRevealer"
         },
         {
@@ -27,8 +33,14 @@
             "defaultValue": false,
             "tags": "color code, resource type",
             "options": [
-                { "value": true, "title": "Color code by resource type" },
-                { "value": false, "title": "Use default colors" }
+                {
+                    "value": true,
+                    "title": "Color code by resource type"
+                },
+                {
+                    "value": false,
+                    "title": "Use default colors"
+                }
             ]
         },
         {
@@ -44,11 +56,19 @@
             "iconClass": "largeicon-start-recording",
             "toggledIconClass": "largeicon-stop-recording",
             "toggleWithRedColor": true,
-            "contextTypes": ["Network.NetworkPanel"],
+            "contextTypes": [
+                "Network.NetworkPanel"
+            ],
             "className": "Network.NetworkPanel.RecordActionDelegate",
             "options": [
-                { "value": true, "title": "Record network log" },
-                { "value": false, "title": "Stop recording network log" }
+                {
+                    "value": true,
+                    "title": "Record network log"
+                },
+                {
+                    "value": false,
+                    "title": "Stop recording network log"
+                }
             ],
             "bindings": [
                 {
@@ -86,7 +106,8 @@
         "source_frame",
         "components",
         "components_lazy",
-        "ui_lazy"
+        "ui_lazy",
+        "perf_ui"
     ],
     "scripts": [
         "BlockedURLsPane.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/components_lazy/LineLevelProfile.js b/third_party/WebKit/Source/devtools/front_end/perf_ui/LineLevelProfile.js
similarity index 78%
rename from third_party/WebKit/Source/devtools/front_end/components_lazy/LineLevelProfile.js
rename to third_party/WebKit/Source/devtools/front_end/perf_ui/LineLevelProfile.js
index b0351bb..0f1ed19 100644
--- a/third_party/WebKit/Source/devtools/front_end/components_lazy/LineLevelProfile.js
+++ b/third_party/WebKit/Source/devtools/front_end/perf_ui/LineLevelProfile.js
@@ -4,19 +4,19 @@
 /**
  * @unrestricted
  */
-Components.LineLevelProfile = class {
+PerfUI.LineLevelProfile = class {
   constructor() {
     this._locationPool = new Bindings.LiveLocationPool();
     this.reset();
   }
 
   /**
-   * @return {!Components.LineLevelProfile}
+   * @return {!PerfUI.LineLevelProfile}
    */
   static instance() {
-    if (!Components.LineLevelProfile._instance)
-      Components.LineLevelProfile._instance = new Components.LineLevelProfile();
-    return Components.LineLevelProfile._instance;
+    if (!PerfUI.LineLevelProfile._instance)
+      PerfUI.LineLevelProfile._instance = new PerfUI.LineLevelProfile();
+    return PerfUI.LineLevelProfile._instance;
   }
 
   /**
@@ -67,7 +67,7 @@
     // TODO(alph): use scriptId instead of urls for the target.
     this._locationPool.disposeAll();
     Workspace.workspace.uiSourceCodes().forEach(
-        uiSourceCode => uiSourceCode.removeDecorationsForType(Components.LineLevelProfile.LineDecorator.type));
+        uiSourceCode => uiSourceCode.removeDecorationsForType(PerfUI.LineLevelProfile.LineDecorator.type));
     for (var fileInfo of this._files) {
       var url = /** @type {string} */ (fileInfo[0]);
       var uiSourceCode = Workspace.workspace.uiSourceCodeForURL(url);
@@ -82,9 +82,9 @@
         var time = lineInfo[1];
         var rawLocation = debuggerModel.createRawLocationByURL(url, line, 0);
         if (rawLocation)
-          new Components.LineLevelProfile.Presentation(rawLocation, time, this._locationPool);
+          new PerfUI.LineLevelProfile.Presentation(rawLocation, time, this._locationPool);
         else if (uiSourceCode)
-          uiSourceCode.addLineDecoration(line, Components.LineLevelProfile.LineDecorator.type, time);
+          uiSourceCode.addLineDecoration(line, PerfUI.LineLevelProfile.LineDecorator.type, time);
       }
     }
   }
@@ -94,7 +94,7 @@
 /**
  * @unrestricted
  */
-Components.LineLevelProfile.Presentation = class {
+PerfUI.LineLevelProfile.Presentation = class {
   /**
    * @param {!SDK.DebuggerModel.Location} rawLocation
    * @param {number} time
@@ -110,20 +110,20 @@
    */
   updateLocation(liveLocation) {
     if (this._uiLocation)
-      this._uiLocation.uiSourceCode.removeDecorationsForType(Components.LineLevelProfile.LineDecorator.type);
+      this._uiLocation.uiSourceCode.removeDecorationsForType(PerfUI.LineLevelProfile.LineDecorator.type);
     this._uiLocation = liveLocation.uiLocation();
     if (this._uiLocation) {
       this._uiLocation.uiSourceCode.addLineDecoration(
-          this._uiLocation.lineNumber, Components.LineLevelProfile.LineDecorator.type, this._time);
+          this._uiLocation.lineNumber, PerfUI.LineLevelProfile.LineDecorator.type, this._time);
     }
   }
 };
 
 /**
- * @implements {Sources.UISourceCodeFrame.LineDecorator}
+ * @implements {SourceFrame.UISourceCodeFrame.LineDecorator}
  * @unrestricted
  */
-Components.LineLevelProfile.LineDecorator = class {
+PerfUI.LineLevelProfile.LineDecorator = class {
   /**
    * @override
    * @param {!Workspace.UISourceCode} uiSourceCode
@@ -131,7 +131,7 @@
    */
   decorate(uiSourceCode, textEditor) {
     var gutterType = 'CodeMirror-gutter-performance';
-    var decorations = uiSourceCode.decorationsForType(Components.LineLevelProfile.LineDecorator.type);
+    var decorations = uiSourceCode.decorationsForType(PerfUI.LineLevelProfile.LineDecorator.type);
     textEditor.uninstallGutter(gutterType);
     if (!decorations || !decorations.size)
       return;
@@ -148,4 +148,4 @@
   }
 };
 
-Components.LineLevelProfile.LineDecorator.type = 'performance';
+PerfUI.LineLevelProfile.LineDecorator.type = 'performance';
diff --git a/third_party/WebKit/Source/devtools/front_end/perf_ui/module.json b/third_party/WebKit/Source/devtools/front_end/perf_ui/module.json
new file mode 100644
index 0000000..f4e1027
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/perf_ui/module.json
@@ -0,0 +1,19 @@
+{
+    "extensions": [
+        {
+            "type": "@SourceFrame.UISourceCodeFrame.LineDecorator",
+            "className": "PerfUI.LineLevelProfile.LineDecorator",
+            "decoratorType": "performance"
+        }
+    ],
+    "dependencies": [
+        "ui",
+        "sdk",
+        "bindings",
+        "source_frame",
+        "text_editor"
+    ],
+    "scripts": [
+        "LineLevelProfile.js"
+    ]
+}
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 3fb466a..002180a 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/CPUProfileView.js
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/CPUProfileView.js
@@ -44,7 +44,7 @@
    */
   wasShown() {
     super.wasShown();
-    var lineLevelProfile = Components.LineLevelProfile.instance();
+    var lineLevelProfile = PerfUI.LineLevelProfile.instance();
     lineLevelProfile.reset();
     lineLevelProfile.appendCPUProfile(this.profile);
   }
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/module.json b/third_party/WebKit/Source/devtools/front_end/profiler/module.json
index 81a4bee..14032b01 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/module.json
@@ -20,7 +20,9 @@
         },
         {
             "type": "@UI.ContextMenu.Provider",
-            "contextTypes": ["SDK.RemoteObject"],
+            "contextTypes": [
+                "SDK.RemoteObject"
+            ],
             "className": "Profiler.ProfilesPanel.ContextMenuProvider"
         },
         {
@@ -53,7 +55,9 @@
             "iconClass": "largeicon-start-recording",
             "toggledIconClass": "largeicon-stop-recording",
             "toggleWithRedColor": true,
-            "contextTypes": ["Profiler.ProfilesPanel"],
+            "contextTypes": [
+                "Profiler.ProfilesPanel"
+            ],
             "className": "Profiler.ProfilesPanel.RecordActionDelegate",
             "bindings": [
                 {
@@ -70,7 +74,8 @@
     "dependencies": [
         "components",
         "components_lazy",
-        "ui_lazy"
+        "ui_lazy",
+        "perf_ui"
     ],
     "scripts": [
         "ProfilesPanel.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/ui_lazy/CommandMenu.js b/third_party/WebKit/Source/devtools/front_end/quick_open/CommandMenu.js
similarity index 79%
rename from third_party/WebKit/Source/devtools/front_end/ui_lazy/CommandMenu.js
rename to third_party/WebKit/Source/devtools/front_end/quick_open/CommandMenu.js
index 93d494d..7a48ee5 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui_lazy/CommandMenu.js
+++ b/third_party/WebKit/Source/devtools/front_end/quick_open/CommandMenu.js
@@ -4,7 +4,7 @@
 /**
  * @unrestricted
  */
-UI.CommandMenu = class {
+QuickOpen.CommandMenu = class {
   constructor() {
     this._commands = [];
     this._loadCommands();
@@ -17,26 +17,27 @@
    * @param {string} shortcut
    * @param {function()} executeHandler
    * @param {function()=} availableHandler
-   * @return {!UI.CommandMenu.Command}
+   * @return {!QuickOpen.CommandMenu.Command}
    */
   static createCommand(category, keys, title, shortcut, executeHandler, availableHandler) {
     // Separate keys by null character, to prevent fuzzy matching from matching across them.
     var key = keys.replace(/,/g, '\0');
-    return new UI.CommandMenu.Command(category, title, key, shortcut, executeHandler, availableHandler);
+    return new QuickOpen.CommandMenu.Command(category, title, key, shortcut, executeHandler, availableHandler);
   }
 
   /**
    * @param {!Runtime.Extension} extension
    * @param {string} title
    * @param {V} value
-   * @return {!UI.CommandMenu.Command}
+   * @return {!QuickOpen.CommandMenu.Command}
    * @template V
    */
   static createSettingCommand(extension, title, value) {
     var category = extension.descriptor()['category'] || '';
     var tags = extension.descriptor()['tags'] || '';
     var setting = Common.settings.moduleSetting(extension.descriptor()['settingName']);
-    return UI.CommandMenu.createCommand(category, tags, title, '', setting.set.bind(setting, value), availableHandler);
+    return QuickOpen.CommandMenu.createCommand(
+        category, tags, title, '', setting.set.bind(setting, value), availableHandler);
 
     /**
      * @return {boolean}
@@ -48,22 +49,22 @@
 
   /**
    * @param {!UI.Action} action
-   * @return {!UI.CommandMenu.Command}
+   * @return {!QuickOpen.CommandMenu.Command}
    */
   static createActionCommand(action) {
     var shortcut = UI.shortcutRegistry.shortcutTitleForAction(action.id()) || '';
-    return UI.CommandMenu.createCommand(
+    return QuickOpen.CommandMenu.createCommand(
         action.category(), action.tags(), action.title(), shortcut, action.execute.bind(action));
   }
 
   /**
    * @param {!Runtime.Extension} extension
-   * @return {!UI.CommandMenu.Command}
+   * @return {!QuickOpen.CommandMenu.Command}
    */
   static createRevealPanelCommand(extension) {
     var panelName = extension.descriptor()['name'];
     var tags = extension.descriptor()['tags'] || '';
-    return UI.CommandMenu.createCommand(
+    return QuickOpen.CommandMenu.createCommand(
         Common.UIString('Panel'), tags, Common.UIString('Show %s', extension.title()), '', executeHandler,
         availableHandler);
 
@@ -81,13 +82,13 @@
 
   /**
    * @param {!Runtime.Extension} extension
-   * @return {!UI.CommandMenu.Command}
+   * @return {!QuickOpen.CommandMenu.Command}
    */
   static createRevealDrawerCommand(extension) {
     var drawerId = extension.descriptor()['id'];
     var executeHandler = UI.viewManager.showView.bind(UI.viewManager, drawerId);
     var tags = extension.descriptor()['tags'] || '';
-    return UI.CommandMenu.createCommand(
+    return QuickOpen.CommandMenu.createCommand(
         Common.UIString('Drawer'), tags, Common.UIString('Show %s', extension.title()), '', executeHandler);
   }
 
@@ -95,14 +96,14 @@
     // Populate panels.
     var panelExtensions = self.runtime.extensions(UI.Panel);
     for (var extension of panelExtensions)
-      this._commands.push(UI.CommandMenu.createRevealPanelCommand(extension));
+      this._commands.push(QuickOpen.CommandMenu.createRevealPanelCommand(extension));
 
     // Populate drawers.
     var drawerExtensions = self.runtime.extensions('view');
     for (var extension of drawerExtensions) {
       if (extension.descriptor()['location'] !== 'drawer-view')
         continue;
-      this._commands.push(UI.CommandMenu.createRevealDrawerCommand(extension));
+      this._commands.push(QuickOpen.CommandMenu.createRevealDrawerCommand(extension));
     }
 
     // Populate whitelisted settings.
@@ -112,12 +113,12 @@
       if (!options || !extension.descriptor()['category'])
         continue;
       for (var pair of options)
-        this._commands.push(UI.CommandMenu.createSettingCommand(extension, pair['title'], pair['value']));
+        this._commands.push(QuickOpen.CommandMenu.createSettingCommand(extension, pair['title'], pair['value']));
     }
   }
 
   /**
-   * @return {!Array.<!UI.CommandMenu.Command>}
+   * @return {!Array.<!QuickOpen.CommandMenu.Command>}
    */
   commands() {
     return this._commands;
@@ -127,7 +128,7 @@
 /**
  * @unrestricted
  */
-UI.CommandMenuDelegate = class extends UI.FilteredListWidget.Delegate {
+QuickOpen.CommandMenuDelegate = class extends QuickOpen.FilteredListWidget.Delegate {
   constructor() {
     super([]);
     this._commands = [];
@@ -135,13 +136,13 @@
   }
 
   _appendAvailableCommands() {
-    var allCommands = UI.commandMenu.commands();
+    var allCommands = QuickOpen.commandMenu.commands();
 
     // Populate whitelisted actions.
     var actions = UI.actionRegistry.availableActions();
     for (var action of actions) {
       if (action.category())
-        this._commands.push(UI.CommandMenu.createActionCommand(action));
+        this._commands.push(QuickOpen.CommandMenu.createActionCommand(action));
     }
 
     for (var command of allCommands) {
@@ -152,8 +153,8 @@
     this._commands = this._commands.sort(commandComparator);
 
     /**
-     * @param {!UI.CommandMenu.Command} left
-     * @param {!UI.CommandMenu.Command} right
+     * @param {!QuickOpen.CommandMenu.Command} left
+     * @param {!QuickOpen.CommandMenu.Command} right
      * @return {number}
      */
     function commandComparator(left, right) {
@@ -215,8 +216,8 @@
     var command = this._commands[itemIndex];
     titleElement.removeChildren();
     var tagElement = titleElement.createChild('span', 'tag');
-    var index = String.hashCode(command.category()) % UI.CommandMenuDelegate.MaterialPaletteColors.length;
-    tagElement.style.backgroundColor = UI.CommandMenuDelegate.MaterialPaletteColors[index];
+    var index = String.hashCode(command.category()) % QuickOpen.CommandMenuDelegate.MaterialPaletteColors.length;
+    tagElement.style.backgroundColor = QuickOpen.CommandMenuDelegate.MaterialPaletteColors[index];
     tagElement.textContent = command.category();
     titleElement.createTextChild(command.title());
     this.highlightRanges(titleElement, query);
@@ -251,7 +252,7 @@
   }
 };
 
-UI.CommandMenuDelegate.MaterialPaletteColors = [
+QuickOpen.CommandMenuDelegate.MaterialPaletteColors = [
   '#F44336', '#E91E63', '#9C27B0', '#673AB7', '#3F51B5', '#03A9F4', '#00BCD4', '#009688', '#4CAF50', '#8BC34A',
   '#CDDC39', '#FFC107', '#FF9800', '#FF5722', '#795548', '#9E9E9E', '#607D8B'
 ];
@@ -259,7 +260,7 @@
 /**
  * @unrestricted
  */
-UI.CommandMenu.Command = class {
+QuickOpen.CommandMenu.Command = class {
   /**
    * @param {string} category
    * @param {string} title
@@ -318,14 +319,14 @@
 };
 
 
-/** @type {!UI.CommandMenu} */
-UI.commandMenu = new UI.CommandMenu();
+/** @type {!QuickOpen.CommandMenu} */
+QuickOpen.commandMenu = new QuickOpen.CommandMenu();
 
 /**
  * @implements {UI.ActionDelegate}
  * @unrestricted
  */
-UI.CommandMenu.ShowActionDelegate = class {
+QuickOpen.CommandMenu.ShowActionDelegate = class {
   /**
    * @override
    * @param {!UI.Context} context
@@ -333,7 +334,7 @@
    * @return {boolean}
    */
   handleAction(context, actionId) {
-    new UI.FilteredListWidget(new UI.CommandMenuDelegate()).showAsDialog();
+    new QuickOpen.FilteredListWidget(new QuickOpen.CommandMenuDelegate()).showAsDialog();
     InspectorFrontendHost.bringToFront();
     return true;
   }
diff --git a/third_party/WebKit/Source/devtools/front_end/ui_lazy/FilteredListWidget.js b/third_party/WebKit/Source/devtools/front_end/quick_open/FilteredListWidget.js
similarity index 97%
rename from third_party/WebKit/Source/devtools/front_end/ui_lazy/FilteredListWidget.js
rename to third_party/WebKit/Source/devtools/front_end/quick_open/FilteredListWidget.js
index e55d2d8..44bb6449 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui_lazy/FilteredListWidget.js
+++ b/third_party/WebKit/Source/devtools/front_end/quick_open/FilteredListWidget.js
@@ -7,9 +7,9 @@
  * @unrestricted
  * @implements {UI.ListDelegate}
  */
-UI.FilteredListWidget = class extends UI.VBox {
+QuickOpen.FilteredListWidget = class extends UI.VBox {
   /**
-   * @param {!UI.FilteredListWidget.Delegate} delegate
+   * @param {!QuickOpen.FilteredListWidget.Delegate} delegate
    */
   constructor(delegate) {
     super(true);
@@ -20,7 +20,7 @@
     this.contentElement.addEventListener('keydown', this._onKeyDown.bind(this), true);
     if (delegate.renderMonospace())
       this.contentElement.classList.add('monospace');
-    this.registerRequiredCSS('ui_lazy/filteredListWidget.css');
+    this.registerRequiredCSS('quick_open/filteredListWidget.css');
 
     this._promptElement = this.contentElement.createChild('div', 'filtered-list-widget-input');
     this._promptElement.setAttribute('spellcheck', 'false');
@@ -209,7 +209,7 @@
     var query = this._delegate.rewriteQuery(this._value());
     this._query = query;
 
-    var filterRegex = query ? UI.FilteredListWidget.filterRegex(query) : null;
+    var filterRegex = query ? QuickOpen.FilteredListWidget.filterRegex(query) : null;
 
     var filteredItems = [];
 
@@ -234,7 +234,7 @@
 
     /**
      * @param {number} fromIndex
-     * @this {UI.FilteredListWidget}
+     * @this {QuickOpen.FilteredListWidget}
      */
     function scoreItems(fromIndex) {
       delete this._scoringTimer;
@@ -357,7 +357,7 @@
 /**
  * @unrestricted
  */
-UI.FilteredListWidget.Delegate = class {
+QuickOpen.FilteredListWidget.Delegate = class {
   /**
    * @param {!Array<string>} promptHistory
    */
diff --git a/third_party/WebKit/Source/devtools/front_end/ui_lazy/filteredListWidget.css b/third_party/WebKit/Source/devtools/front_end/quick_open/filteredListWidget.css
similarity index 100%
rename from third_party/WebKit/Source/devtools/front_end/ui_lazy/filteredListWidget.css
rename to third_party/WebKit/Source/devtools/front_end/quick_open/filteredListWidget.css
diff --git a/third_party/WebKit/Source/devtools/front_end/quick_open/module.json b/third_party/WebKit/Source/devtools/front_end/quick_open/module.json
new file mode 100644
index 0000000..60f97fd
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/quick_open/module.json
@@ -0,0 +1,30 @@
+{
+    "extensions": [
+        {
+            "type": "@UI.ActionDelegate",
+            "actionId": "commandMenu.show",
+            "className": "QuickOpen.CommandMenu.ShowActionDelegate",
+            "bindings": [
+                {
+                    "platform": "windows,linux",
+                    "shortcut": "Ctrl+Shift+P"
+                },
+                {
+                    "platform": "mac",
+                    "shortcut": "Meta+Shift+P"
+                }
+            ]
+        }
+    ],
+    "dependencies": [
+        "ui",
+        "diff"
+    ],
+    "scripts": [
+        "FilteredListWidget.js",
+        "CommandMenu.js"
+    ],
+    "resources": [
+        "filteredListWidget.css"
+    ]
+}
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/DatabaseModel.js b/third_party/WebKit/Source/devtools/front_end/resources/DatabaseModel.js
index 361e01ec..6490293 100644
--- a/third_party/WebKit/Source/devtools/front_end/resources/DatabaseModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/resources/DatabaseModel.js
@@ -186,6 +186,7 @@
   }
 };
 
+/** @implements {Common.Emittable} */
 Resources.DatabaseModel.DatabaseAddedEvent = class {
   /**
    * @param {!Resources.Database} database
@@ -195,6 +196,7 @@
   }
 };
 
+/** @implements {Common.Emittable} */
 Resources.DatabaseModel.DatabasesRemovedEvent = class {};
 
 /**
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js
index b76ab642..9d304fc 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js
@@ -1037,7 +1037,6 @@
     this._init(this, false, payload);
     this.documentURL = payload.documentURL || '';
     this.baseURL = payload.baseURL || '';
-    this._listeners = {};
   }
 };
 
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/SourceCodeDiff.js b/third_party/WebKit/Source/devtools/front_end/source_frame/SourceCodeDiff.js
similarity index 77%
rename from third_party/WebKit/Source/devtools/front_end/sources/SourceCodeDiff.js
rename to third_party/WebKit/Source/devtools/front_end/source_frame/SourceCodeDiff.js
index 0a4aca4..78843689 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/SourceCodeDiff.js
+++ b/third_party/WebKit/Source/devtools/front_end/source_frame/SourceCodeDiff.js
@@ -4,7 +4,7 @@
 /**
  * @unrestricted
  */
-Sources.SourceCodeDiff = class {
+SourceFrame.SourceCodeDiff = class {
   /**
    * @param {!Promise<?string>} diffBaseline
    * @param {!TextEditor.CodeMirrorTextEditor} textEditor
@@ -12,7 +12,7 @@
   constructor(diffBaseline, textEditor) {
     this._textEditor = textEditor;
     this._decorations = [];
-    this._textEditor.installGutter(Sources.SourceCodeDiff.DiffGutterType, true);
+    this._textEditor.installGutter(SourceFrame.SourceCodeDiff.DiffGutterType, true);
     this._diffBaseline = diffBaseline;
     /** @type {!Array<!TextEditor.TextEditorPositionHandle>}*/
     this._animatedLines = [];
@@ -22,7 +22,7 @@
     if (this._updateTimeout)
       clearTimeout(this._updateTimeout);
     this._updateTimeout =
-        setTimeout(this.updateDiffMarkersImmediately.bind(this), Sources.SourceCodeDiff.UpdateTimeout);
+        setTimeout(this.updateDiffMarkersImmediately.bind(this), SourceFrame.SourceCodeDiff.UpdateTimeout);
   }
 
   updateDiffMarkersImmediately() {
@@ -44,7 +44,7 @@
     var changedLines = [];
     for (var i = 0; i < diff.length; ++i) {
       var diffEntry = diff[i];
-      if (diffEntry.type === Sources.SourceCodeDiff.GutterDecorationType.Delete)
+      if (diffEntry.type === SourceFrame.SourceCodeDiff.GutterDecorationType.Delete)
         continue;
       for (var lineNumber = diffEntry.from; lineNumber < diffEntry.to; ++lineNumber) {
         var position = this._textEditor.textEditorPositionHandle(lineNumber, 0);
@@ -67,7 +67,7 @@
     this._textEditor.operation(operation.bind(this));
 
     /**
-     * @this {Sources.SourceCodeDiff}
+     * @this {SourceFrame.SourceCodeDiff}
      */
     function operation() {
       toggleLines.call(this, false);
@@ -77,7 +77,7 @@
 
     /**
      * @param {boolean} value
-     * @this {Sources.SourceCodeDiff}
+     * @this {SourceFrame.SourceCodeDiff}
      */
     function toggleLines(value) {
       for (var i = 0; i < this._animatedLines.length; ++i) {
@@ -89,8 +89,8 @@
   }
 
   /**
-   * @param {!Array<!Sources.SourceCodeDiff.GutterDecoration>} removed
-   * @param {!Array<!Sources.SourceCodeDiff.GutterDecoration>} added
+   * @param {!Array<!SourceFrame.SourceCodeDiff.GutterDecoration>} removed
+   * @param {!Array<!SourceFrame.SourceCodeDiff.GutterDecoration>} added
    */
   _updateDecorations(removed, added) {
     this._textEditor.operation(operation);
@@ -106,7 +106,7 @@
   /**
    * @param {string} baseline
    * @param {string} current
-   * @return {!Array<!{type: !Sources.SourceCodeDiff.GutterDecorationType, from: number, to: number}>}
+   * @return {!Array<!{type: !SourceFrame.SourceCodeDiff.GutterDecorationType, from: number, to: number}>}
    */
   _computeDiff(baseline, current) {
     var diff = Diff.Diff.lineDiff(baseline.split('\n'), current.split('\n'));
@@ -140,22 +140,22 @@
     if (isInsideBlock)
       flush();
     if (result.length > 1 && result[0].from === 0 && result[1].from === 0) {
-      var merged = {type: Sources.SourceCodeDiff.GutterDecorationType.Modify, from: 0, to: result[1].to};
+      var merged = {type: SourceFrame.SourceCodeDiff.GutterDecorationType.Modify, from: 0, to: result[1].to};
       result.splice(0, 2, merged);
     }
     return result;
 
     function flush() {
-      var type = Sources.SourceCodeDiff.GutterDecorationType.Insert;
+      var type = SourceFrame.SourceCodeDiff.GutterDecorationType.Insert;
       var from = blockStartLineNumber;
       var to = currentLineNumber;
       if (hasAdded && hasRemoved) {
-        type = Sources.SourceCodeDiff.GutterDecorationType.Modify;
+        type = SourceFrame.SourceCodeDiff.GutterDecorationType.Modify;
       } else if (!hasAdded && hasRemoved && from === 0 && to === 0) {
-        type = Sources.SourceCodeDiff.GutterDecorationType.Modify;
+        type = SourceFrame.SourceCodeDiff.GutterDecorationType.Modify;
         to = 1;
       } else if (!hasAdded && hasRemoved) {
-        type = Sources.SourceCodeDiff.GutterDecorationType.Delete;
+        type = SourceFrame.SourceCodeDiff.GutterDecorationType.Delete;
         from -= 1;
       }
       result.push({type: type, from: from, to: to});
@@ -178,7 +178,7 @@
 
     var diff = this._computeDiff(baseline, current);
 
-    /** @type {!Map<number, !Sources.SourceCodeDiff.GutterDecoration>} */
+    /** @type {!Map<number, !SourceFrame.SourceCodeDiff.GutterDecoration>} */
     var oldDecorations = new Map();
     for (var i = 0; i < this._decorations.length; ++i) {
       var decoration = this._decorations[i];
@@ -188,7 +188,7 @@
       oldDecorations.set(lineNumber, decoration);
     }
 
-    /** @type {!Map<number, !{lineNumber: number, type: !Sources.SourceCodeDiff.GutterDecorationType}>} */
+    /** @type {!Map<number, !{lineNumber: number, type: !SourceFrame.SourceCodeDiff.GutterDecorationType}>} */
     var newDecorations = new Map();
     for (var i = 0; i < diff.length; ++i) {
       var diffEntry = diff[i];
@@ -198,7 +198,7 @@
 
     var decorationDiff = oldDecorations.diff(newDecorations, (e1, e2) => e1.type === e2.type);
     var addedDecorations = decorationDiff.added.map(
-        entry => new Sources.SourceCodeDiff.GutterDecoration(this._textEditor, entry.lineNumber, entry.type));
+        entry => new SourceFrame.SourceCodeDiff.GutterDecoration(this._textEditor, entry.lineNumber, entry.type));
 
     this._decorations = decorationDiff.equal.concat(addedDecorations);
     this._updateDecorations(decorationDiff.removed, addedDecorations);
@@ -206,20 +206,20 @@
   }
 
   /**
-   * @param {!Map<number, !{lineNumber: number, type: !Sources.SourceCodeDiff.GutterDecorationType}>} decorations
+   * @param {!Map<number, !{lineNumber: number, type: !SourceFrame.SourceCodeDiff.GutterDecorationType}>} decorations
    */
   _decorationsSetForTest(decorations) {
   }
 };
 
 /** @type {number} */
-Sources.SourceCodeDiff.UpdateTimeout = 200;
+SourceFrame.SourceCodeDiff.UpdateTimeout = 200;
 
 /** @type {string} */
-Sources.SourceCodeDiff.DiffGutterType = 'CodeMirror-gutter-diff';
+SourceFrame.SourceCodeDiff.DiffGutterType = 'CodeMirror-gutter-diff';
 
 /** @enum {symbol} */
-Sources.SourceCodeDiff.GutterDecorationType = {
+SourceFrame.SourceCodeDiff.GutterDecorationType = {
   Insert: Symbol('Insert'),
   Delete: Symbol('Delete'),
   Modify: Symbol('Modify'),
@@ -228,21 +228,21 @@
 /**
  * @unrestricted
  */
-Sources.SourceCodeDiff.GutterDecoration = class {
+SourceFrame.SourceCodeDiff.GutterDecoration = class {
   /**
    * @param {!TextEditor.CodeMirrorTextEditor} textEditor
    * @param {number} lineNumber
-   * @param {!Sources.SourceCodeDiff.GutterDecorationType} type
+   * @param {!SourceFrame.SourceCodeDiff.GutterDecorationType} type
    */
   constructor(textEditor, lineNumber, type) {
     this._textEditor = textEditor;
     this._position = this._textEditor.textEditorPositionHandle(lineNumber, 0);
     this._className = '';
-    if (type === Sources.SourceCodeDiff.GutterDecorationType.Insert)
+    if (type === SourceFrame.SourceCodeDiff.GutterDecorationType.Insert)
       this._className = 'diff-entry-insert';
-    else if (type === Sources.SourceCodeDiff.GutterDecorationType.Delete)
+    else if (type === SourceFrame.SourceCodeDiff.GutterDecorationType.Delete)
       this._className = 'diff-entry-delete';
-    else if (type === Sources.SourceCodeDiff.GutterDecorationType.Modify)
+    else if (type === SourceFrame.SourceCodeDiff.GutterDecorationType.Modify)
       this._className = 'diff-entry-modify';
     this.type = type;
   }
@@ -263,7 +263,7 @@
       return;
     var element = createElementWithClass('div', 'diff-marker');
     element.textContent = '\u00A0';
-    this._textEditor.setGutterDecoration(location.lineNumber, Sources.SourceCodeDiff.DiffGutterType, element);
+    this._textEditor.setGutterDecoration(location.lineNumber, SourceFrame.SourceCodeDiff.DiffGutterType, element);
     this._textEditor.toggleLineClass(location.lineNumber, this._className, true);
   }
 
@@ -271,7 +271,7 @@
     var location = this._position.resolve();
     if (!location)
       return;
-    this._textEditor.setGutterDecoration(location.lineNumber, Sources.SourceCodeDiff.DiffGutterType, null);
+    this._textEditor.setGutterDecoration(location.lineNumber, SourceFrame.SourceCodeDiff.DiffGutterType, null);
     this._textEditor.toggleLineClass(location.lineNumber, this._className, false);
   }
 };
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/UISourceCodeFrame.js b/third_party/WebKit/Source/devtools/front_end/source_frame/UISourceCodeFrame.js
similarity index 88%
rename from third_party/WebKit/Source/devtools/front_end/sources/UISourceCodeFrame.js
rename to third_party/WebKit/Source/devtools/front_end/source_frame/UISourceCodeFrame.js
index 7604cf9f..1046c64 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/UISourceCodeFrame.js
+++ b/third_party/WebKit/Source/devtools/front_end/source_frame/UISourceCodeFrame.js
@@ -29,7 +29,7 @@
 /**
  * @unrestricted
  */
-Sources.UISourceCodeFrame = class extends SourceFrame.SourceFrame {
+SourceFrame.UISourceCodeFrame = class extends SourceFrame.SourceFrame {
   /**
    * @param {!Workspace.UISourceCode} uiSourceCode
    */
@@ -39,7 +39,7 @@
     this.setEditable(this._canEditSource());
 
     if (Runtime.experiments.isEnabled('sourceDiff'))
-      this._diff = new Sources.SourceCodeDiff(uiSourceCode.requestOriginalContent(), this.textEditor);
+      this._diff = new SourceFrame.SourceCodeDiff(uiSourceCode.requestOriginalContent(), this.textEditor);
 
     /** @type {?UI.AutocompleteConfig} */
     this._autocompleteConfig = {isWordChar: Common.TextUtils.isWordChar};
@@ -49,7 +49,7 @@
     /** @type {?Persistence.PersistenceBinding} */
     this._persistenceBinding = Persistence.persistence.binding(uiSourceCode);
 
-    /** @type {!Map<number, !Sources.UISourceCodeFrame.RowMessageBucket>} */
+    /** @type {!Map<number, !SourceFrame.UISourceCodeFrame.RowMessageBucket>} */
     this._rowMessageBuckets = new Map();
     /** @type {!Set<string>} */
     this._typeDecorationsPending = new Set();
@@ -65,10 +65,10 @@
 
     this.textEditor.addEventListener(
         SourceFrame.SourcesTextEditor.Events.EditorBlurred,
-        () => UI.context.setFlavor(Sources.UISourceCodeFrame, null));
+        () => UI.context.setFlavor(SourceFrame.UISourceCodeFrame, null));
     this.textEditor.addEventListener(
         SourceFrame.SourcesTextEditor.Events.EditorFocused,
-        () => UI.context.setFlavor(Sources.UISourceCodeFrame, this));
+        () => UI.context.setFlavor(SourceFrame.UISourceCodeFrame, this));
 
     this._updateStyle();
 
@@ -136,7 +136,7 @@
    */
   willHide() {
     super.willHide();
-    UI.context.setFlavor(Sources.UISourceCodeFrame, null);
+    UI.context.setFlavor(SourceFrame.UISourceCodeFrame, null);
     this._uiSourceCode.removeWorkingCopyGetter();
   }
 
@@ -294,7 +294,7 @@
    */
   populateTextAreaContextMenu(contextMenu, lineNumber, columnNumber) {
     /**
-     * @this {Sources.UISourceCodeFrame}
+     * @this {SourceFrame.UISourceCodeFrame}
      */
     function appendItems() {
       contextMenu.appendApplicableItems(this._uiSourceCode);
@@ -347,7 +347,7 @@
 
     var messageBucket = this._rowMessageBuckets.get(lineNumber);
     if (!messageBucket) {
-      messageBucket = new Sources.UISourceCodeFrame.RowMessageBucket(this, this.textEditor, lineNumber);
+      messageBucket = new SourceFrame.UISourceCodeFrame.RowMessageBucket(this, this.textEditor, lineNumber);
       this._rowMessageBuckets.set(lineNumber, messageBucket);
     }
     messageBucket.addMessage(message);
@@ -438,7 +438,7 @@
     if (this._typeDecorationsPending.has(type))
       return;
     this._typeDecorationsPending.add(type);
-    self.runtime.extensions(Sources.UISourceCodeFrame.LineDecorator)
+    self.runtime.extensions(SourceFrame.UISourceCodeFrame.LineDecorator)
         .find(extension => extension.descriptor()['decoratorType'] === type)
         .instance()
         .then(decorator => {
@@ -449,31 +449,31 @@
   }
 
   _decorateAllTypes() {
-    var extensions = self.runtime.extensions(Sources.UISourceCodeFrame.LineDecorator);
+    var extensions = self.runtime.extensions(SourceFrame.UISourceCodeFrame.LineDecorator);
     extensions.forEach(extension => this._decorateTypeThrottled(extension.descriptor()['decoratorType']));
   }
 };
 
-Sources.UISourceCodeFrame._iconClassPerLevel = {};
-Sources.UISourceCodeFrame._iconClassPerLevel[Workspace.UISourceCode.Message.Level.Error] = 'smallicon-error';
-Sources.UISourceCodeFrame._iconClassPerLevel[Workspace.UISourceCode.Message.Level.Warning] = 'smallicon-warning';
+SourceFrame.UISourceCodeFrame._iconClassPerLevel = {};
+SourceFrame.UISourceCodeFrame._iconClassPerLevel[Workspace.UISourceCode.Message.Level.Error] = 'smallicon-error';
+SourceFrame.UISourceCodeFrame._iconClassPerLevel[Workspace.UISourceCode.Message.Level.Warning] = 'smallicon-warning';
 
-Sources.UISourceCodeFrame._bubbleTypePerLevel = {};
-Sources.UISourceCodeFrame._bubbleTypePerLevel[Workspace.UISourceCode.Message.Level.Error] = 'error';
-Sources.UISourceCodeFrame._bubbleTypePerLevel[Workspace.UISourceCode.Message.Level.Warning] = 'warning';
+SourceFrame.UISourceCodeFrame._bubbleTypePerLevel = {};
+SourceFrame.UISourceCodeFrame._bubbleTypePerLevel[Workspace.UISourceCode.Message.Level.Error] = 'error';
+SourceFrame.UISourceCodeFrame._bubbleTypePerLevel[Workspace.UISourceCode.Message.Level.Warning] = 'warning';
 
-Sources.UISourceCodeFrame._lineClassPerLevel = {};
-Sources.UISourceCodeFrame._lineClassPerLevel[Workspace.UISourceCode.Message.Level.Error] =
+SourceFrame.UISourceCodeFrame._lineClassPerLevel = {};
+SourceFrame.UISourceCodeFrame._lineClassPerLevel[Workspace.UISourceCode.Message.Level.Error] =
     'text-editor-line-with-error';
-Sources.UISourceCodeFrame._lineClassPerLevel[Workspace.UISourceCode.Message.Level.Warning] =
+SourceFrame.UISourceCodeFrame._lineClassPerLevel[Workspace.UISourceCode.Message.Level.Warning] =
     'text-editor-line-with-warning';
 
 /**
  * @interface
  */
-Sources.UISourceCodeFrame.LineDecorator = function() {};
+SourceFrame.UISourceCodeFrame.LineDecorator = function() {};
 
-Sources.UISourceCodeFrame.LineDecorator.prototype = {
+SourceFrame.UISourceCodeFrame.LineDecorator.prototype = {
   /**
    * @param {!Workspace.UISourceCode} uiSourceCode
    * @param {!TextEditor.CodeMirrorTextEditor} textEditor
@@ -484,7 +484,7 @@
 /**
  * @unrestricted
  */
-Sources.UISourceCodeFrame.RowMessage = class {
+SourceFrame.UISourceCodeFrame.RowMessage = class {
   /**
    * @param {!Workspace.UISourceCode.Message} message
    */
@@ -493,9 +493,9 @@
     this._repeatCount = 1;
     this.element = createElementWithClass('div', 'text-editor-row-message');
     this._icon = this.element.createChild('label', '', 'dt-icon-label');
-    this._icon.type = Sources.UISourceCodeFrame._iconClassPerLevel[message.level()];
+    this._icon.type = SourceFrame.UISourceCodeFrame._iconClassPerLevel[message.level()];
     this._repeatCountElement = this.element.createChild('label', 'message-repeat-count hidden', 'dt-small-bubble');
-    this._repeatCountElement.type = Sources.UISourceCodeFrame._bubbleTypePerLevel[message.level()];
+    this._repeatCountElement.type = SourceFrame.UISourceCodeFrame._bubbleTypePerLevel[message.level()];
     var linesContainer = this.element.createChild('div', 'text-editor-row-message-lines');
     var lines = this._message.text().split('\n');
     for (var i = 0; i < lines.length; ++i) {
@@ -536,9 +536,9 @@
 /**
  * @unrestricted
  */
-Sources.UISourceCodeFrame.RowMessageBucket = class {
+SourceFrame.UISourceCodeFrame.RowMessageBucket = class {
   /**
-   * @param {!Sources.UISourceCodeFrame} sourceFrame
+   * @param {!SourceFrame.UISourceCodeFrame} sourceFrame
    * @param {!TextEditor.CodeMirrorTextEditor} textEditor
    * @param {number} lineNumber
    */
@@ -553,7 +553,7 @@
     this._hasDecoration = false;
 
     this._messagesDescriptionElement = createElementWithClass('div', 'text-editor-messages-description-container');
-    /** @type {!Array.<!Sources.UISourceCodeFrame.RowMessage>} */
+    /** @type {!Array.<!SourceFrame.UISourceCodeFrame.RowMessage>} */
     this._messages = [];
 
     this._level = null;
@@ -591,7 +591,7 @@
       return;
     var lineNumber = position.lineNumber;
     if (this._level)
-      this.textEditor.toggleLineClass(lineNumber, Sources.UISourceCodeFrame._lineClassPerLevel[this._level], false);
+      this.textEditor.toggleLineClass(lineNumber, SourceFrame.UISourceCodeFrame._lineClassPerLevel[this._level], false);
     if (this._hasDecoration)
       this.textEditor.removeDecoration(this._decoration, lineNumber);
     this._hasDecoration = false;
@@ -616,7 +616,7 @@
       }
     }
 
-    var rowMessage = new Sources.UISourceCodeFrame.RowMessage(message);
+    var rowMessage = new SourceFrame.UISourceCodeFrame.RowMessage(message);
     this._messages.push(rowMessage);
     this._updateDecoration();
   }
@@ -658,14 +658,14 @@
     this._updateWavePosition(lineNumber, columnNumber);
 
     if (this._level) {
-      this.textEditor.toggleLineClass(lineNumber, Sources.UISourceCodeFrame._lineClassPerLevel[this._level], false);
+      this.textEditor.toggleLineClass(lineNumber, SourceFrame.UISourceCodeFrame._lineClassPerLevel[this._level], false);
       this._icon.type = '';
     }
     this._level = maxMessage.level();
     if (!this._level)
       return;
-    this.textEditor.toggleLineClass(lineNumber, Sources.UISourceCodeFrame._lineClassPerLevel[this._level], true);
-    this._icon.type = Sources.UISourceCodeFrame._iconClassPerLevel[this._level];
+    this.textEditor.toggleLineClass(lineNumber, SourceFrame.UISourceCodeFrame._lineClassPerLevel[this._level], true);
+    this._icon.type = SourceFrame.UISourceCodeFrame._iconClassPerLevel[this._level];
   }
 };
 
diff --git a/third_party/WebKit/Source/devtools/front_end/source_frame/module.json b/third_party/WebKit/Source/devtools/front_end/source_frame/module.json
index e32c25c..ca4f0e5 100644
--- a/third_party/WebKit/Source/devtools/front_end/source_frame/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/source_frame/module.json
@@ -8,24 +8,44 @@
             "settingType": "enum",
             "defaultValue": "    ",
             "options": [
-                { "title": "Set indentation to 2 spaces", "text": "2 spaces", "value": "  " },
-                { "title": "Set indentation to 4 spaces", "text": "4 spaces", "value": "    " },
-                { "title": "Set indentation to 8 spaces", "text": "8 spaces", "value": "        " },
-                { "title": "Set indentation to tab character", "text": "Tab character", "value": "\t" }
+                {
+                    "title": "Set indentation to 2 spaces",
+                    "text": "2 spaces",
+                    "value": "  "
+                },
+                {
+                    "title": "Set indentation to 4 spaces",
+                    "text": "4 spaces",
+                    "value": "    "
+                },
+                {
+                    "title": "Set indentation to 8 spaces",
+                    "text": "8 spaces",
+                    "value": "        "
+                },
+                {
+                    "title": "Set indentation to tab character",
+                    "text": "Tab character",
+                    "value": "\t"
+                }
             ]
         }
     ],
     "dependencies": [
         "text_editor",
         "ui",
-        "platform"
+        "platform",
+        "persistence",
+        "diff"
     ],
     "scripts": [
         "SourcesTextEditor.js",
         "FontView.js",
         "ImageView.js",
         "SourceFrame.js",
-        "ResourceSourceFrame.js"
+        "ResourceSourceFrame.js",
+        "UISourceCodeFrame.js",
+        "SourceCodeDiff.js"
     ],
     "resources": [
         "fontView.css",
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/CSSSourceFrame.js b/third_party/WebKit/Source/devtools/front_end/sources/CSSSourceFrame.js
index b85199e..10dfa89 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/CSSSourceFrame.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/CSSSourceFrame.js
@@ -31,7 +31,7 @@
 /**
  * @unrestricted
  */
-Sources.CSSSourceFrame = class extends Sources.UISourceCodeFrame {
+Sources.CSSSourceFrame = class extends SourceFrame.UISourceCodeFrame {
   /**
    * @param {!Workspace.UISourceCode} uiSourceCode
    */
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/EditingLocationHistoryManager.js b/third_party/WebKit/Source/devtools/front_end/sources/EditingLocationHistoryManager.js
index 1d00c4e..afd3d4d 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/EditingLocationHistoryManager.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/EditingLocationHistoryManager.js
@@ -43,7 +43,7 @@
   }
 
   /**
-   * @param {!Sources.UISourceCodeFrame} sourceFrame
+   * @param {!SourceFrame.UISourceCodeFrame} sourceFrame
    */
   trackSourceFrameCursorJumps(sourceFrame) {
     sourceFrame.textEditor.addEventListener(
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/FilteredUISourceCodeListDelegate.js b/third_party/WebKit/Source/devtools/front_end/sources/FilteredUISourceCodeListDelegate.js
index b15e0cd7..a374fd4 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/FilteredUISourceCodeListDelegate.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/FilteredUISourceCodeListDelegate.js
@@ -7,7 +7,7 @@
 /**
  * @unrestricted
  */
-Sources.FilteredUISourceCodeListDelegate = class extends UI.FilteredListWidget.Delegate {
+Sources.FilteredUISourceCodeListDelegate = class extends QuickOpen.FilteredListWidget.Delegate {
   /**
    * @param {!Map.<!Workspace.UISourceCode, number>=} defaultScores
    * @param {!Array<string>=} history
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptOutlineDialog.js b/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptOutlineDialog.js
index 2c49751..f9283d21 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptOutlineDialog.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptOutlineDialog.js
@@ -7,7 +7,7 @@
 /**
  * @unrestricted
  */
-Sources.JavaScriptOutlineDialog = class extends UI.FilteredListWidget.Delegate {
+Sources.JavaScriptOutlineDialog = class extends QuickOpen.FilteredListWidget.Delegate {
   /**
    * @param {!Workspace.UISourceCode} uiSourceCode
    * @param {function(number, number)} selectItemCallback
@@ -27,7 +27,7 @@
   static show(uiSourceCode, selectItemCallback) {
     Sources.JavaScriptOutlineDialog._instanceForTests =
         new Sources.JavaScriptOutlineDialog(uiSourceCode, selectItemCallback);
-    new UI.FilteredListWidget(Sources.JavaScriptOutlineDialog._instanceForTests).showAsDialog();
+    new QuickOpen.FilteredListWidget(Sources.JavaScriptOutlineDialog._instanceForTests).showAsDialog();
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js b/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js
index 817a396..e5c0653b 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js
@@ -31,7 +31,7 @@
 /**
  * @unrestricted
  */
-Sources.JavaScriptSourceFrame = class extends Sources.UISourceCodeFrame {
+Sources.JavaScriptSourceFrame = class extends SourceFrame.UISourceCodeFrame {
   /**
    * @param {!Workspace.UISourceCode} uiSourceCode
    */
@@ -81,7 +81,7 @@
     this._valueWidgets = new Map();
     this.onBindingChanged();
     Bindings.debuggerWorkspaceBinding.addEventListener(
-          Bindings.DebuggerWorkspaceBinding.Events.SourceMappingChanged, this._onSourceMappingChanged, this);
+        Bindings.DebuggerWorkspaceBinding.Events.SourceMappingChanged, this._onSourceMappingChanged, this);
   }
 
   /**
@@ -1294,7 +1294,7 @@
    */
   dispose() {
     Bindings.debuggerWorkspaceBinding.removeEventListener(
-          Bindings.DebuggerWorkspaceBinding.Events.SourceMappingChanged, this._onSourceMappingChanged, this);
+        Bindings.DebuggerWorkspaceBinding.Events.SourceMappingChanged, this._onSourceMappingChanged, this);
     this._breakpointManager.removeEventListener(
         Bindings.BreakpointManager.Events.BreakpointAdded, this._breakpointAdded, this);
     this._breakpointManager.removeEventListener(
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/OpenResourceDialog.js b/third_party/WebKit/Source/devtools/front_end/sources/OpenResourceDialog.js
index 1a228a51..357014a 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/OpenResourceDialog.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/OpenResourceDialog.js
@@ -29,7 +29,7 @@
     var dialog = new Sources.OpenResourceDialog(sourcesView, defaultScores, history);
     if (InspectorFrontendHost.isUnderTest())
       Sources.OpenResourceDialog._instanceForTest = dialog;
-    var filteredItemSelectionDialog = new UI.FilteredListWidget(dialog);
+    var filteredItemSelectionDialog = new QuickOpen.FilteredListWidget(dialog);
     filteredItemSelectionDialog.showAsDialog();
     filteredItemSelectionDialog.setQuery(query);
   }
@@ -98,7 +98,7 @@
    */
   static show(name, types, callback) {
     var filteredItemSelectionDialog =
-        new UI.FilteredListWidget(new Sources.SelectUISourceCodeForProjectTypesDialog(types, callback));
+        new QuickOpen.FilteredListWidget(new Sources.SelectUISourceCodeForProjectTypesDialog(types, callback));
     filteredItemSelectionDialog.showAsDialog();
     filteredItemSelectionDialog.setQuery(name);
   }
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 9bd0b4e0..214762e 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js
@@ -843,7 +843,7 @@
    * @param {!Object} target
    */
   _appendUISourceCodeFrameItems(event, contextMenu, target) {
-    if (!(target instanceof Sources.UISourceCodeFrame))
+    if (!(target instanceof SourceFrame.UISourceCodeFrame))
       return;
     contextMenu.appendAction('debugger.evaluate-selection');
   }
@@ -1262,7 +1262,7 @@
         panel._toggleBreakpointsActive();
         return true;
       case 'debugger.evaluate-selection':
-        var frame = UI.context.flavor(Sources.UISourceCodeFrame);
+        var frame = UI.context.flavor(SourceFrame.UISourceCodeFrame);
         if (frame) {
           var text = frame.textEditor.text(frame.textEditor.selection());
           var executionContext = UI.context.flavor(SDK.ExecutionContext);
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/SourcesView.js b/third_party/WebKit/Source/devtools/front_end/sources/SourcesView.js
index e815b65..88eafe3 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/SourcesView.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/SourcesView.js
@@ -199,13 +199,13 @@
   }
 
   /**
-   * @return {?Sources.UISourceCodeFrame}
+   * @return {?SourceFrame.UISourceCodeFrame}
    */
   currentSourceFrame() {
     var view = this.visibleView();
-    if (!(view instanceof Sources.UISourceCodeFrame))
+    if (!(view instanceof SourceFrame.UISourceCodeFrame))
       return null;
-    return /** @type {!Sources.UISourceCodeFrame} */ (view);
+    return /** @type {!SourceFrame.UISourceCodeFrame} */ (view);
   }
 
   /**
@@ -326,7 +326,7 @@
     else if (contentType === Common.resourceTypes.Font)
       sourceView = new SourceFrame.FontView(Bindings.NetworkProject.uiSourceCodeMimeType(uiSourceCode), uiSourceCode);
     else
-      sourceFrame = new Sources.UISourceCodeFrame(uiSourceCode);
+      sourceFrame = new SourceFrame.UISourceCodeFrame(uiSourceCode);
 
     if (sourceFrame) {
       sourceFrame.setHighlighterType(Bindings.NetworkProject.uiSourceCodeMimeType(uiSourceCode));
@@ -347,7 +347,7 @@
   }
 
   /**
-   * @param {!Sources.UISourceCodeFrame} sourceFrame
+   * @param {!SourceFrame.UISourceCodeFrame} sourceFrame
    * @param {!Workspace.UISourceCode} uiSourceCode
    * @return {boolean}
    */
@@ -364,9 +364,9 @@
    */
   _recreateSourceFrameIfNeeded(uiSourceCode) {
     var oldSourceView = this._sourceViewByUISourceCode.get(uiSourceCode);
-    if (!oldSourceView || !(oldSourceView instanceof Sources.UISourceCodeFrame))
+    if (!oldSourceView || !(oldSourceView instanceof SourceFrame.UISourceCodeFrame))
       return;
-    var oldSourceFrame = /** @type {!Sources.UISourceCodeFrame} */ (oldSourceView);
+    var oldSourceFrame = /** @type {!SourceFrame.UISourceCodeFrame} */ (oldSourceView);
     if (this._sourceFrameMatchesUISourceCode(oldSourceFrame, uiSourceCode)) {
       oldSourceFrame.setHighlighterType(Bindings.NetworkProject.uiSourceCodeMimeType(uiSourceCode));
     } else {
@@ -391,8 +391,8 @@
     var sourceView = this._sourceViewByUISourceCode.get(uiSourceCode);
     this._sourceViewByUISourceCode.remove(uiSourceCode);
     uiSourceCode.removeEventListener(Workspace.UISourceCode.Events.TitleChanged, this._uiSourceCodeTitleChanged, this);
-    if (sourceView && sourceView instanceof Sources.UISourceCodeFrame)
-      /** @type {!Sources.UISourceCodeFrame} */ (sourceView).dispose();
+    if (sourceView && sourceView instanceof SourceFrame.UISourceCodeFrame)
+      /** @type {!SourceFrame.UISourceCodeFrame} */ (sourceView).dispose();
   }
 
   _onBindingChanged() {
@@ -418,10 +418,10 @@
     var binding = Persistence.persistence.binding(uiLocation.uiSourceCode);
     var uiSourceCode = binding ? binding.fileSystem : uiLocation.uiSourceCode;
     var sourceView = this._getOrCreateSourceView(uiSourceCode);
-    if (!(sourceView instanceof Sources.UISourceCodeFrame))
+    if (!(sourceView instanceof SourceFrame.UISourceCodeFrame))
       return;
     Persistence.persistence.subscribeForBindingEvent(uiLocation.uiSourceCode, this._bindingChangeBound);
-    var sourceFrame = /** @type {!Sources.UISourceCodeFrame} */ (sourceView);
+    var sourceFrame = /** @type {!SourceFrame.UISourceCodeFrame} */ (sourceView);
     sourceFrame.setExecutionLocation(
         new Workspace.UILocation(uiSourceCode, uiLocation.lineNumber, uiLocation.columnNumber));
     this._executionSourceFrame = sourceFrame;
@@ -454,11 +454,11 @@
    */
   _editorSelected(event) {
     var previousSourceFrame =
-        event.data.previousView instanceof Sources.UISourceCodeFrame ? event.data.previousView : null;
+        event.data.previousView instanceof SourceFrame.UISourceCodeFrame ? event.data.previousView : null;
     if (previousSourceFrame)
       previousSourceFrame.setSearchableView(null);
     var currentSourceFrame =
-        event.data.currentView instanceof Sources.UISourceCodeFrame ? event.data.currentView : null;
+        event.data.currentView instanceof SourceFrame.UISourceCodeFrame ? event.data.currentView : null;
     if (currentSourceFrame)
       currentSourceFrame.setSearchableView(this._searchableView);
 
@@ -648,9 +648,9 @@
    * @param {?UI.Widget} sourceFrame
    */
   _saveSourceFrame(sourceFrame) {
-    if (!(sourceFrame instanceof Sources.UISourceCodeFrame))
+    if (!(sourceFrame instanceof SourceFrame.UISourceCodeFrame))
       return;
-    var uiSourceCodeFrame = /** @type {!Sources.UISourceCodeFrame} */ (sourceFrame);
+    var uiSourceCodeFrame = /** @type {!SourceFrame.UISourceCodeFrame} */ (sourceFrame);
     uiSourceCodeFrame.commitEditing();
   }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/StyleSheetOutlineDialog.js b/third_party/WebKit/Source/devtools/front_end/sources/StyleSheetOutlineDialog.js
index 803b687..bdee992 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/StyleSheetOutlineDialog.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/StyleSheetOutlineDialog.js
@@ -29,7 +29,7 @@
 /**
  * @unrestricted
  */
-Sources.StyleSheetOutlineDialog = class extends UI.FilteredListWidget.Delegate {
+Sources.StyleSheetOutlineDialog = class extends QuickOpen.FilteredListWidget.Delegate {
   /**
    * @param {!Workspace.UISourceCode} uiSourceCode
    * @param {function(number, number)} selectItemCallback
@@ -52,7 +52,7 @@
   static show(uiSourceCode, selectItemCallback) {
     Sources.StyleSheetOutlineDialog._instanceForTests =
         new Sources.StyleSheetOutlineDialog(uiSourceCode, selectItemCallback);
-    new UI.FilteredListWidget(Sources.StyleSheetOutlineDialog._instanceForTests).showAsDialog();
+    new QuickOpen.FilteredListWidget(Sources.StyleSheetOutlineDialog._instanceForTests).showAsDialog();
   }
 
   /**
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 0ef1d30..fe488fbc 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/WatchExpressionsSidebarPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/WatchExpressionsSidebarPane.js
@@ -184,7 +184,7 @@
    * @return {boolean}
    */
   handleAction(context, actionId) {
-    var frame = UI.context.flavor(Sources.UISourceCodeFrame);
+    var frame = UI.context.flavor(SourceFrame.UISourceCodeFrame);
     if (!frame)
       return false;
     var text = frame.textEditor.text(frame.textEditor.selection());
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/module.json b/third_party/WebKit/Source/devtools/front_end/sources/module.json
index 35b1128..a4587fd 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/sources/module.json
@@ -10,7 +10,13 @@
         },
         {
             "type": "@UI.ContextMenu.Provider",
-            "contextTypes": ["Workspace.UISourceCode", "Workspace.UILocation", "SDK.RemoteObject", "SDK.NetworkRequest", "Sources.UISourceCodeFrame"],
+            "contextTypes": [
+                "Workspace.UISourceCode",
+                "Workspace.UILocation",
+                "SDK.RemoteObject",
+                "SDK.NetworkRequest",
+                "SourceFrame.UISourceCodeFrame"
+            ],
             "className": "Sources.SourcesPanel"
         },
         {
@@ -20,10 +26,19 @@
             "iconClass": "largeicon-pause",
             "toggledIconClass": "largeicon-resume",
             "className": "Sources.SourcesPanel.RevealingActionDelegate",
-            "contextTypes": ["Sources.SourcesPanel", "UI.ShortcutRegistry.ForwardedShortcut"],
+            "contextTypes": [
+                "Sources.SourcesPanel",
+                "UI.ShortcutRegistry.ForwardedShortcut"
+            ],
             "options": [
-                { "value": true, "title": "Pause script execution" },
-                { "value": false, "title": "Resume script execution" }
+                {
+                    "value": true,
+                    "title": "Pause script execution"
+                },
+                {
+                    "value": false,
+                    "title": "Resume script execution"
+                }
             ],
             "bindings": [
                 {
@@ -42,7 +57,9 @@
             "className": "Sources.SourcesPanel.DebuggingActionDelegate",
             "title": "Step over next function call",
             "iconClass": "largeicon-step-over",
-            "contextTypes": ["Sources.SourcesPanel"],
+            "contextTypes": [
+                "Sources.SourcesPanel"
+            ],
             "bindings": [
                 {
                     "platform": "windows,linux",
@@ -60,7 +77,9 @@
             "className": "Sources.SourcesPanel.DebuggingActionDelegate",
             "title": "Step into next function call",
             "iconClass": "largeicon-step-in",
-            "contextTypes": ["Sources.SourcesPanel"],
+            "contextTypes": [
+                "Sources.SourcesPanel"
+            ],
             "bindings": [
                 {
                     "platform": "windows,linux",
@@ -78,7 +97,9 @@
             "className": "Sources.SourcesPanel.DebuggingActionDelegate",
             "title": "Step out of current function",
             "iconClass": "largeicon-step-out",
-            "contextTypes": ["Sources.SourcesPanel"],
+            "contextTypes": [
+                "Sources.SourcesPanel"
+            ],
             "bindings": [
                 {
                     "platform": "windows,linux",
@@ -96,7 +117,9 @@
             "className": "Sources.SourcesPanel.DebuggingActionDelegate",
             "title": "Run snippet",
             "iconClass": "largeicon-play",
-            "contextTypes": ["Sources.SourcesPanel"],
+            "contextTypes": [
+                "Sources.SourcesPanel"
+            ],
             "bindings": [
                 {
                     "platform": "windows,linux",
@@ -132,10 +155,18 @@
             "iconClass": "largeicon-deactivate-breakpoints",
             "toggledIconClass": "largeicon-activate-breakpoints",
             "className": "Sources.SourcesPanel.DebuggingActionDelegate",
-            "contextTypes": ["Sources.SourcesPanel"],
+            "contextTypes": [
+                "Sources.SourcesPanel"
+            ],
             "options": [
-                { "value": true, "title": "Deactivate breakpoints" },
-                { "value": false, "title": "Activate breakpoints" }
+                {
+                    "value": true,
+                    "title": "Deactivate breakpoints"
+                },
+                {
+                    "value": false,
+                    "title": "Activate breakpoints"
+                }
             ],
             "bindings": [
                 {
@@ -153,7 +184,9 @@
             "actionId": "sources.add-to-watch",
             "className": "Sources.WatchExpressionsSidebarPane",
             "title": "Add selected text to watches",
-            "contextTypes": ["Sources.UISourceCodeFrame"],
+            "contextTypes": [
+                "SourceFrame.UISourceCodeFrame"
+            ],
             "bindings": [
                 {
                     "shortcut": "Ctrl+Shift+A"
@@ -162,7 +195,9 @@
         },
         {
             "type": "@UI.ContextMenu.Provider",
-            "contextTypes": ["TextEditor.CodeMirrorTextEditor"],
+            "contextTypes": [
+                "TextEditor.CodeMirrorTextEditor"
+            ],
             "className": "Sources.WatchExpressionsSidebarPane"
         },
         {
@@ -170,7 +205,9 @@
             "actionId": "debugger.evaluate-selection",
             "className": "Sources.SourcesPanel.DebuggingActionDelegate",
             "title": "Evaluate in console",
-            "contextTypes": ["Sources.UISourceCodeFrame"],
+            "contextTypes": [
+                "SourceFrame.UISourceCodeFrame"
+            ],
             "bindings": [
                 {
                     "shortcut": "Ctrl+Shift+E"
@@ -189,22 +226,30 @@
         },
         {
             "type": "@Common.Revealer",
-            "contextTypes": ["Workspace.UILocation"],
+            "contextTypes": [
+                "Workspace.UILocation"
+            ],
             "className": "Sources.SourcesPanel.UILocationRevealer"
         },
         {
             "type": "@Common.Revealer",
-            "contextTypes": ["SDK.DebuggerModel.Location"],
+            "contextTypes": [
+                "SDK.DebuggerModel.Location"
+            ],
             "className": "Sources.SourcesPanel.DebuggerLocationRevealer"
         },
         {
             "type": "@Common.Revealer",
-            "contextTypes": ["Workspace.UISourceCode"],
+            "contextTypes": [
+                "Workspace.UISourceCode"
+            ],
             "className": "Sources.SourcesPanel.UISourceCodeRevealer"
         },
         {
             "type": "@Common.Revealer",
-            "contextTypes": ["SDK.DebuggerPausedDetails"],
+            "contextTypes": [
+                "SDK.DebuggerPausedDetails"
+            ],
             "className": "Sources.SourcesPanel.DebuggerPausedDetailsRevealer"
         },
         {
@@ -312,7 +357,9 @@
             "type": "@UI.ActionDelegate",
             "actionId": "sources.switch-file",
             "className": "Sources.SourcesView.SwitchFileActionDelegate",
-            "contextTypes": ["Sources.SourcesView"],
+            "contextTypes": [
+                "Sources.SourcesView"
+            ],
             "bindings": [
                 {
                     "shortcut": "Alt+O"
@@ -381,9 +428,21 @@
             "settingType": "enum",
             "defaultValue": "original",
             "options": [
-                { "title": "Do not show whitespace characters", "text": "None", "value": "none" },
-                { "title": "Show all whitespace characters", "text": "All", "value": "all" },
-                { "title": "Show trailing whitespace characters", "text": "Trailing", "value": "trailing" }
+                {
+                    "title": "Do not show whitespace characters",
+                    "text": "None",
+                    "value": "none"
+                },
+                {
+                    "title": "Show all whitespace characters",
+                    "text": "All",
+                    "value": "all"
+                },
+                {
+                    "title": "Show trailing whitespace characters",
+                    "text": "Trailing",
+                    "value": "trailing"
+                }
             ]
         },
         {
@@ -514,27 +573,37 @@
         },
         {
             "type": "@UI.ContextFlavorListener",
-            "contextTypes": ["SDK.DebuggerPausedDetails"],
+            "contextTypes": [
+                "SDK.DebuggerPausedDetails"
+            ],
             "className": "Sources.JavaScriptBreakpointsSidebarPane"
         },
         {
             "type": "@UI.ContextFlavorListener",
-            "contextTypes": ["SDK.DebuggerPausedDetails"],
+            "contextTypes": [
+                "SDK.DebuggerPausedDetails"
+            ],
             "className": "Sources.XHRBreakpointsSidebarPane"
         },
         {
             "type": "@UI.ContextFlavorListener",
-            "contextTypes": ["SDK.DebuggerPausedDetails"],
+            "contextTypes": [
+                "SDK.DebuggerPausedDetails"
+            ],
             "className": "Components.DOMBreakpointsSidebarPane"
         },
         {
             "type": "@UI.ContextFlavorListener",
-            "contextTypes": ["SDK.DebuggerPausedDetails"],
+            "contextTypes": [
+                "SDK.DebuggerPausedDetails"
+            ],
             "className": "Sources.CallStackSidebarPane"
         },
         {
             "type": "@UI.ContextFlavorListener",
-            "contextTypes": ["SDK.DebuggerModel.CallFrame"],
+            "contextTypes": [
+                "SDK.DebuggerModel.CallFrame"
+            ],
             "className": "Sources.ScopeChainSidebarPane"
         }
     ],
@@ -544,7 +613,8 @@
         "snippets",
         "ui_lazy",
         "extensions",
-        "persistence"
+        "persistence",
+        "quick_open"
     ],
     "scripts": [
         "UIList.js",
@@ -556,11 +626,9 @@
         "EventListenerBreakpointsSidebarPane.js",
         "FilePathScoreFunction.js",
         "FilteredUISourceCodeListDelegate.js",
-        "UISourceCodeFrame.js",
         "SourceMapNamesResolver.js",
         "JavaScriptBreakpointsSidebarPane.js",
         "JavaScriptOutlineDialog.js",
-        "SourceCodeDiff.js",
         "JavaScriptSourceFrame.js",
         "CSSSourceFrame.js",
         "NavigatorView.js",
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 03f117c..eaba99b 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js
@@ -553,7 +553,8 @@
     for (var i = 0; i < this._overviewControls.length; ++i)
       this._overviewControls[i].timelineStarted();
 
-    Host.userMetrics.actionTaken(userInitiated ? Host.UserMetrics.Action.TimelineStarted : Host.UserMetrics.Action.TimelinePageReloadStarted);
+    Host.userMetrics.actionTaken(
+        userInitiated ? Host.UserMetrics.Action.TimelineStarted : Host.UserMetrics.Action.TimelinePageReloadStarted);
     this._setUIControlsEnabled(false);
     this._hideLandingPage();
   }
@@ -600,7 +601,7 @@
   }
 
   _reset() {
-    Components.LineLevelProfile.instance().reset();
+    PerfUI.LineLevelProfile.instance().reset();
     this._tracingModel.reset();
     this._model.reset();
     for (let extensionEntry of this._extensionTracingModels)
@@ -723,7 +724,7 @@
     var groups = TimelineModel.TimelineModel.AsyncEventGroup;
     var asyncEventsByGroup = this._model.mainThreadAsyncEvents();
     this._irModel.populate(asyncEventsByGroup.get(groups.input), asyncEventsByGroup.get(groups.animation));
-    this._model.cpuProfiles().forEach(profile => Components.LineLevelProfile.instance().appendCPUProfile(profile));
+    this._model.cpuProfiles().forEach(profile => PerfUI.LineLevelProfile.instance().appendCPUProfile(profile));
     if (this._statusPane)
       this._statusPane.hide();
     delete this._statusPane;
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 1f16c0d4..7670eeba 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/module.json
@@ -37,11 +37,19 @@
             "iconClass": "largeicon-start-recording",
             "toggledIconClass": "largeicon-stop-recording",
             "toggleWithRedColor": true,
-            "contextTypes": ["Timeline.TimelinePanel"],
+            "contextTypes": [
+                "Timeline.TimelinePanel"
+            ],
             "className": "Timeline.TimelinePanel.ActionDelegate",
             "options": [
-                { "value": true, "title": "Record" },
-                { "value": false, "title": "Stop" }
+                {
+                    "value": true,
+                    "title": "Record"
+                },
+                {
+                    "value": false,
+                    "title": "Stop"
+                }
             ],
             "bindings": [
                 {
@@ -58,7 +66,9 @@
             "type": "@UI.ActionDelegate",
             "category": "Timeline",
             "actionId": "timeline.save-to-file",
-            "contextTypes": ["Timeline.TimelinePanel"],
+            "contextTypes": [
+                "Timeline.TimelinePanel"
+            ],
             "className": "Timeline.TimelinePanel.ActionDelegate",
             "title": "Save profile\u2026",
             "bindings": [
@@ -76,7 +86,9 @@
             "type": "@UI.ActionDelegate",
             "category": "Timeline",
             "actionId": "timeline.load-from-file",
-            "contextTypes": ["Timeline.TimelinePanel"],
+            "contextTypes": [
+                "Timeline.TimelinePanel"
+            ],
             "order": "10",
             "className": "Timeline.TimelinePanel.ActionDelegate",
             "title": "Load profile\u2026",
@@ -94,7 +106,9 @@
         {
             "type": "@UI.ActionDelegate",
             "actionId": "timeline.jump-to-previous-frame",
-            "contextTypes": ["Timeline.TimelinePanel"],
+            "contextTypes": [
+                "Timeline.TimelinePanel"
+            ],
             "className": "Timeline.TimelinePanel.ActionDelegate",
             "bindings": [
                 {
@@ -105,7 +119,9 @@
         {
             "type": "@UI.ActionDelegate",
             "actionId": "timeline.jump-to-next-frame",
-            "contextTypes": ["Timeline.TimelinePanel"],
+            "contextTypes": [
+                "Timeline.TimelinePanel"
+            ],
             "className": "Timeline.TimelinePanel.ActionDelegate",
             "bindings": [
                 {
@@ -119,7 +135,9 @@
         "components_lazy",
         "layer_viewer",
         "timeline_model",
-        "ui_lazy"
+        "ui_lazy",
+        "perf_ui",
+        "extensions"
     ],
     "scripts": [
         "CountersGraph.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/SuggestBox.js b/third_party/WebKit/Source/devtools/front_end/ui/SuggestBox.js
index 4340f0c..113f32ff 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/SuggestBox.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/SuggestBox.js
@@ -197,10 +197,6 @@
     delete this._lastAnchorBox;
   }
 
-  removeFromElement() {
-    this.hide();
-  }
-
   /**
    * @param {boolean=} isIntermediateSuggestion
    * @return {boolean}
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/TextPrompt.js b/third_party/WebKit/Source/devtools/front_end/ui/TextPrompt.js
index 5afcdec..2579859e 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/TextPrompt.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/TextPrompt.js
@@ -214,7 +214,7 @@
     if (this._isEditing)
       this._stopEditing();
     if (this._suggestBox)
-      this._suggestBox.removeFromElement();
+      this._suggestBox.hide();
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/splitWidget.css b/third_party/WebKit/Source/devtools/front_end/ui/splitWidget.css
index e95ae683..b1754b4 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/splitWidget.css
+++ b/third_party/WebKit/Source/devtools/front_end/ui/splitWidget.css
@@ -97,3 +97,8 @@
     border: 0;
     border-right: 1px solid rgb(64%, 64%, 64%);
 }
+
+
+:host(.root-split-widget) .shadow-split-widget.hbox > .shadow-split-widget-resizer {
+    margin-right: -5px !important;
+}
diff --git a/third_party/WebKit/Source/devtools/front_end/ui_lazy/module.json b/third_party/WebKit/Source/devtools/front_end/ui_lazy/module.json
index ccd610b..518b013 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui_lazy/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/ui_lazy/module.json
@@ -1,21 +1,5 @@
 {
-    "extensions": [
-        {
-            "type": "@UI.ActionDelegate",
-            "actionId": "commandMenu.show",
-            "className": "UI.CommandMenu.ShowActionDelegate",
-            "bindings": [
-                {
-                    "platform": "windows,linux",
-                    "shortcut": "Ctrl+Shift+P"
-                },
-                {
-                    "platform": "mac",
-                    "shortcut": "Meta+Shift+P"
-                }
-            ]
-        }
-    ],
+    "extensions": [],
     "dependencies": [
         "platform",
         "common",
@@ -29,8 +13,6 @@
         "ViewportDataGrid.js",
         "SortableDataGrid.js",
         "ShowMoreDataGridNode.js",
-        "FilteredListWidget.js",
-        "CommandMenu.js",
         "FlameChart.js",
         "OverviewGrid.js",
         "PieChart.js",
@@ -40,7 +22,6 @@
     "resources": [
         "dataGrid.css",
         "dialog.css",
-        "filteredListWidget.css",
         "flameChart.css",
         "overviewGrid.css",
         "pieChart.css",
diff --git a/third_party/WebKit/Source/devtools/front_end/unit_test_runner.json b/third_party/WebKit/Source/devtools/front_end/unit_test_runner.json
index 63512ef0..50cd288 100644
--- a/third_party/WebKit/Source/devtools/front_end/unit_test_runner.json
+++ b/third_party/WebKit/Source/devtools/front_end/unit_test_runner.json
@@ -1,19 +1,18 @@
 {
-  "modules" : [
-    { "name": "platform", "type": "autostart" },
-    { "name": "ui", "type": "autostart" },
-    { "name": "host", "type": "autostart" },
-    { "name": "common", "type": "autostart" },
-    { "name": "workspace", "type": "autostart" },
-    { "name": "source_frame", "type": "autostart" },
-    { "name": "text_editor", "type": "autostart" },
-    { "name": "cm", "type": "autostart" },
-    { "name": "cm_modes", "type": "autostart" },
-    { "name": "diff", "type": "autostart" },
-    { "name": "shell", "type": "autostart" },
-    { "name": "test_runner", "type": "autostart" },
-    { "name": "ui_lazy" }
-  ],
-
-  "has_html": true
+    "modules" : [
+        { "name": "platform", "type": "autostart" },
+        { "name": "ui", "type": "autostart" },
+        { "name": "host", "type": "autostart" },
+        { "name": "common", "type": "autostart" },
+        { "name": "workspace", "type": "autostart" },
+        { "name": "text_editor", "type": "autostart" },
+        { "name": "cm", "type": "autostart" },
+        { "name": "cm_modes", "type": "autostart" },
+        { "name": "diff", "type": "autostart" },
+        { "name": "shell", "type": "autostart" },
+        { "name": "test_runner", "type": "autostart" },
+        { "name": "ui_lazy" },
+        { "name": "quick_open" }
+    ],
+    "has_html": true
 }
\ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/scripts/build/build_release_applications.py b/third_party/WebKit/Source/devtools/scripts/build/build_release_applications.py
index e095c38..a60bdd5 100755
--- a/third_party/WebKit/Source/devtools/scripts/build/build_release_applications.py
+++ b/third_party/WebKit/Source/devtools/scripts/build/build_release_applications.py
@@ -30,6 +30,8 @@
 except ImportError:
     import json
 
+special_case_namespaces_path = path.join(path.dirname(path.dirname(path.abspath(__file__))), 'special_case_namespaces.json')
+
 
 def main(argv):
     try:
@@ -93,6 +95,8 @@
         self.descriptors = descriptors
         self.application_dir = application_dir
         self.output_dir = output_dir
+        with open(special_case_namespaces_path) as json_file:
+            self._special_case_namespaces = json.load(json_file)
 
     def app_file(self, extension):
         return self.application_name + '.' + extension
@@ -189,17 +193,17 @@
                 non_autostart_deps = deps & non_autostart
                 if len(non_autostart_deps):
                     bail_error('Non-autostart dependencies specified for the autostarted module "%s": %s' % (name, non_autostart_deps))
-
-                namespace = name.replace('_lazy', '')
-                if namespace == 'sdk' or namespace == 'ui':
-                    namespace = namespace.upper();
-                namespace = "".join(map(lambda x: x[0].upper() + x[1:], namespace.split('_')))
+                namespace = self._map_module_to_namespace(name)
                 output.write('\n/* Module %s */\n' % name)
                 output.write('\nself[\'%s\'] = self[\'%s\'] || {};\n' % (namespace, namespace))
                 modular_build.concatenate_scripts(desc.get('scripts'), join(self.application_dir, name), self.output_dir, output)
             else:
                 non_autostart.add(name)
 
+    def _map_module_to_namespace(self, module):
+        camel_case_namespace = "".join(map(lambda x: x[0].upper() + x[1:], module.split('_')))
+        return self._special_case_namespaces.get(module, camel_case_namespace)
+
     def _concatenate_application_script(self, output):
         runtime_contents = read_file(join(self.application_dir, 'Runtime.js'))
         runtime_contents = re.sub('var allDescriptors = \[\];', 'var allDescriptors = %s;' % self._release_module_descriptors().replace('\\', '\\\\'), runtime_contents, 1)
diff --git a/third_party/WebKit/Source/devtools/scripts/extract_module/extract_module.js b/third_party/WebKit/Source/devtools/scripts/extract_module/extract_module.js
new file mode 100644
index 0000000..888edbcb
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/scripts/extract_module/extract_module.js
@@ -0,0 +1,749 @@
+// 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.
+'use strict';
+const fs = require('fs');
+const path = require('path');
+
+const utils = require('../utils');
+
+const FRONTEND_PATH = path.resolve(__dirname, '..', '..', 'front_end');
+const BUILD_GN_PATH = path.resolve(__dirname, '..', '..', 'BUILD.gn');
+const SPECIAL_CASE_NAMESPACES_PATH = path.resolve(__dirname, '..', 'special_case_namespaces.json');
+
+const APPLICATION_DESCRIPTORS = [
+  'inspector.json',
+  'unit_test_runner.json',
+];
+
+// Replace based on specified transformation
+
+const MODULES_TO_REMOVE = []; // ['components_lazy', 'ui_lazy'];
+
+// NOTE: Extensions-only change
+const FILES_AFFECTING_EXTENSIONS = [
+  'components_lazy/LineLevelProfile.js',
+  'components_lazy/GCActionDelegate.js',
+  'components/RequestAppBannerActionDelegate.js',
+  'ui_lazy/CommandMenu.js',
+];
+
+const JS_FILES_MAPPING = [
+  // {file: 'components_lazy/CookiesTable.js', new: 'cookie_table'},
+  // {file: 'ui/BezierEditor.js', new: 'inline_editor'},
+  // {file: 'ui/BezierUI.js', new: 'inline_editor'},
+  // {file: 'ui/ColorSwatch.js', new: 'inline_editor'},
+  // {file: 'ui/CSSShadowEditor.js', new: 'inline_editor'},
+  // {file: 'ui/SwatchPopoverHelper.js', new: 'inline_editor'},
+  // {file: 'components/Spectrum.js', new: 'color_picker'},
+  //
+  // // Cannot extract dom_ui because of cyclic dependency with components
+  // // {file: 'components/DOMPresentationUtils.js', new: 'dom_ui'},
+  // {file: 'components/ExecutionContextSelector.js', existing: 'main'},
+  // {file: 'components_lazy/FilmStripModel.js', existing: 'sdk'},
+  //
+  // {file: 'components_lazy/FilmStripView.js', new: 'perf_ui'},
+  {file: 'components_lazy/GCActionDelegate.js', existing: 'main'},
+  {file: 'components_lazy/LineLevelProfile.js', new: 'perf_ui'},
+  {file: 'components/RequestAppBannerActionDelegate.js', existing: 'main'},
+  // {file: 'components/ShortcutsScreen.js', existing: 'ui'},
+  {file: 'ui_lazy/FilteredListWidget.js', new: 'quick_open'},
+  {file: 'ui_lazy/CommandMenu.js', new: 'quick_open'},
+  // {file: 'ui_lazy/DataGrid.js', new: 'data_grid'},
+  // {file: 'ui_lazy/ViewportDataGrid.js', new: 'data_grid'},
+  // {file: 'ui_lazy/SortableDataGrid.js', new: 'data_grid'},
+  // {file: 'ui_lazy/ShowMoreDataGridNode.js', new: 'data_grid'},
+  // {file: 'ui_lazy/ChartViewport.js', new: 'perf_ui'},
+  // {file: 'ui_lazy/FlameChart.js', new: 'perf_ui'},
+  // {file: 'ui_lazy/OverviewGrid.js', new: 'perf_ui'},
+  // {file: 'ui_lazy/PieChart.js', new: 'perf_ui'},
+  // {file: 'ui_lazy/TimelineGrid.js', new: 'perf_ui'},
+  // {file: 'ui_lazy/TimelineOverviewPane.js', new: 'perf_ui'},
+  {file: 'sources/UISourceCodeFrame.js', existing: 'source_frame'},
+  {file: 'sources/SourceCodeDiff.js', existing: 'source_frame'},
+];
+
+const MODULE_MAPPING = {
+  // cookie_table: {
+  //   dependencies: ['ui', 'sdk', 'data_grid'],
+  //   dependents: ['resources', 'network'],
+  //   applications: ['inspector.json'],
+  //   autostart: false,
+  // },
+  // inline_editor: {
+  //   dependencies: ['ui'],
+  //   dependents: ['sources', 'elements', 'resources'],
+  //   applications: ['inspector.json', 'unit_test_runner.json'],
+  //   autostart: false,
+  // },
+  // color_picker: {
+  //   dependencies: ['ui', 'sdk'],
+  //   dependents: ['sources', 'elements'],
+  //   applications: ['inspector.json'],
+  //   autostart: false,
+  // },
+  perf_ui: {
+    dependencies: ['ui', 'sdk', 'bindings', 'source_frame', 'text_editor'],
+    dependents: ['network', 'timeline', 'profiler', 'layer_viewer'],
+    applications: ['inspector.json'],
+    autostart: false,
+  },
+  quick_open: {
+    dependencies: ['ui', 'diff'],
+    dependents: ['sources'],
+    applications: ['inspector.json', 'unit_test_runner.json'],
+    autostart: false,
+  },
+  // data_grid: {
+  //   dependencies: ['ui'],
+  //   dependents: ['network', 'profiler', 'resources', 'console', 'timeline'],
+  //   applications: ['inspector.json', 'unit_test_runner.json'],
+  //   autostart: false,
+  // },
+};
+
+const NEW_DEPENDENCIES_BY_EXISTING_MODULES = {
+  // resources: ['components'],
+  source_frame: ['persistence', 'diff'],
+  timeline: ['extensions'],
+  css_tracker: ['source_frame'],
+};
+
+const REMOVE_DEPENDENCIES_BY_EXISTING_MODULES = {
+  css_tracker: ['sources'],
+};
+
+const DEPENDENCIES_BY_MODULE = Object.keys(MODULE_MAPPING).reduce((acc, module) => {
+  acc[module] = MODULE_MAPPING[module].dependencies;
+  return acc;
+}, {});
+
+const APPLICATIONS_BY_MODULE = Object.keys(MODULE_MAPPING).reduce((acc, module) => {
+  acc[module] = MODULE_MAPPING[module].applications;
+  return acc;
+}, {});
+
+const DEPENDENTS_BY_MODULE = Object.keys(MODULE_MAPPING).reduce((acc, module) => {
+  acc[module] = MODULE_MAPPING[module].dependents;
+  return acc;
+}, {});
+
+function extractModule() {
+  const modules = new Set();
+  for (let fileObj of JS_FILES_MAPPING) {
+    let moduleName = fileObj.file.split('/')[0];
+    modules.add(moduleName);
+  }
+  const newModuleSet = JS_FILES_MAPPING.reduce((acc, file) => file.new ? acc.add(file.new) : acc, new Set());
+  const targetToOriginalFilesMap = JS_FILES_MAPPING.reduce((acc, f) => {
+    let components = f.file.split('/');
+    components[0] = f.new || f.existing;
+    acc.set(components.join('/'), f.file);
+    return acc;
+  }, new Map());
+
+  const cssFilesMapping = findCSSFiles();
+  const identifiersByFile = calculateIdentifiers();
+  const identifierMap = mapIdentifiers(identifiersByFile, cssFilesMapping);
+  const extensionMap = removeFromExistingModuleDescriptors(modules, identifierMap, cssFilesMapping);
+
+  // Find out which files are moving extensions
+  for (let e of extensionMap.keys()) {
+    for (let [f, identifiers] of identifiersByFile) {
+      if (identifiers.includes(e))
+        console.log(`extension: ${e} in file: ${f}`);
+    }
+  }
+
+  moveFiles(cssFilesMapping);
+  createNewModuleDescriptors(extensionMap, cssFilesMapping, identifiersByFile, targetToOriginalFilesMap);
+  updateExistingModuleDescriptors(extensionMap, cssFilesMapping, identifiersByFile, targetToOriginalFilesMap);
+  addDependenciesToDescriptors();
+  renameIdentifiers(identifierMap);
+  updateBuildGNFile(cssFilesMapping, newModuleSet);
+  for (let descriptor of APPLICATION_DESCRIPTORS)
+    updateApplicationDescriptor(descriptor, newModuleSet);
+
+  for (let m of MODULES_TO_REMOVE) {
+    utils.removeRecursive(path.resolve(FRONTEND_PATH, m));
+  }
+}
+
+String.prototype.replaceAll = function(search, replacement) {
+  let target = this;
+  return target.replace(new RegExp('\\b' + search + '\\b', 'g'), replacement);
+};
+
+Set.prototype.union = function(setB) {
+  let union = new Set(this);
+  for (let elem of setB)
+    union.add(elem);
+
+  return union;
+};
+
+function mapModuleToNamespace(module) {
+  const specialCases = require(SPECIAL_CASE_NAMESPACES_PATH);
+  return specialCases[module] || toCamelCase(module);
+
+  function toCamelCase(module) {
+    return module.split('_').map(a => a.substring(0, 1).toUpperCase() + a.substring(1)).join('');
+  }
+}
+
+function findCSSFiles() {
+  let cssFilesMapping = new Map();
+  for (let fileObj of JS_FILES_MAPPING)
+    cssFilesMapping.set(fileObj.file, scrapeCSSFile(fileObj.file));
+
+
+  function scrapeCSSFile(filePath) {
+    let cssFiles = new Set();
+    const fullPath = path.resolve(FRONTEND_PATH, filePath);
+    let content = fs.readFileSync(fullPath).toString();
+    let lines = content.split('\n');
+    for (let line of lines) {
+      let match = line.match(/'(.+\.css)'/);
+      if (!match)
+        continue;
+      let matchPath = match[1];
+      cssFiles.add(path.basename(path.resolve(FRONTEND_PATH, matchPath)));
+    }
+    return cssFiles;
+  }
+
+  return cssFilesMapping;
+}
+
+function calculateIdentifiers() {
+  const identifiersByFile = new Map();
+  for (let fileObj of JS_FILES_MAPPING) {
+    const fullPath = path.resolve(FRONTEND_PATH, fileObj.file);
+    let content = fs.readFileSync(fullPath).toString();
+    identifiersByFile.set(fileObj.file, scrapeIdentifiers(content, fileObj));
+  }
+  return identifiersByFile;
+
+  function scrapeIdentifiers(content, fileObj) {
+    let identifiers = [];
+    let lines = content.split('\n');
+    for (let line of lines) {
+      let match = line.match(new RegExp(`^([a-z_A-Z0-9\.]+)\\s=`)) || line.match(new RegExp(`^([a-z_A-Z0-9\.]+);`));
+      if (!match)
+        continue;
+      let name = match[1];
+
+      var currentModule = fileObj.file.split('/')[0];
+      if (name.split('.')[0] !== mapModuleToNamespace(currentModule))
+        console.log(`POSSIBLE ISSUE: identifier: ${name} found in ${currentModule}`);
+      else
+        identifiers.push(name);
+    }
+    return identifiers;
+  }
+}
+
+function moveFiles(cssFilesMapping) {
+  for (let fileObj of JS_FILES_MAPPING) {
+    let sourceFilePath = path.resolve(FRONTEND_PATH, fileObj.file);
+    let targetFilePath = getMappedFilePath(fileObj);
+    let moduleDir = path.resolve(targetFilePath, '..');
+    if (!fs.existsSync(moduleDir))
+      fs.mkdirSync(moduleDir);
+
+    move(sourceFilePath, targetFilePath);
+    if (cssFilesMapping.has(fileObj.file)) {
+      cssFilesMapping.get(fileObj.file).forEach((file) => {
+        let module = fileObj.new || fileObj.existing;
+        move(path.resolve(FRONTEND_PATH, fileObj.file.split('/')[0], file), path.resolve(FRONTEND_PATH, module, file));
+      });
+    }
+  }
+
+  function move(sourceFilePath, targetFilePath) {
+    try {
+      fs.writeFileSync(targetFilePath, fs.readFileSync(sourceFilePath));
+      fs.unlinkSync(sourceFilePath);
+    } catch (err) {
+      console.log(`error moving ${sourceFilePath} -> ${targetFilePath}`);
+    }
+  }
+
+  function getMappedFilePath(fileObj) {
+    let components = fileObj.file.split('/');
+    components[0] = fileObj.existing || fileObj.new;
+    return path.resolve(FRONTEND_PATH, components.join('/'));
+  }
+}
+
+function updateBuildGNFile(cssFilesMapping, newModuleSet) {
+  let content = fs.readFileSync(BUILD_GN_PATH).toString();
+  let newSourcesToAdd = [];
+  let partialPathMapping = calculatePartialPathMapping();
+  for (let module of MODULES_TO_REMOVE) {
+    partialPathMapping.set(`"front_end/${module}/module.json",\n`, '');
+    partialPathMapping.set(`"$resources_out_dir/${module}/${module}_module.js",\n`, '');
+  }
+  const newNonAutostartModules = [...newModuleSet]
+                                     .filter(module => !MODULE_MAPPING[module].autostart)
+                                     .map(module => `"$resources_out_dir/${module}/${module}_module.js",`);
+
+  let newContent = addContentToLinesInSortedOrder({
+    content,
+    startLine: '# this contains non-autostart non-remote modules only.',
+    endLine: ']',
+    linesToInsert: newNonAutostartModules,
+  });
+
+  for (let pair of partialPathMapping.entries())
+    newContent = newContent.replace(pair[0], pair[1]);
+
+  newContent = addContentToLinesInSortedOrder({
+    content: newContent,
+    startLine: 'all_devtools_files = [',
+    endLine: ']',
+    linesToInsert: newSourcesToAdd,
+  });
+
+  fs.writeFileSync(BUILD_GN_PATH, newContent);
+
+  function calculatePartialPathMapping() {
+    let partialPathMapping = new Map();
+    for (let fileObj of JS_FILES_MAPPING) {
+      let components = fileObj.file.split('/');
+      let sourceModule = components[0];
+      let targetModule = fileObj.existing || fileObj.new;
+      components[0] = targetModule;
+      partialPathMapping.set(`"front_end/${fileObj.file}",\n`, '');
+      newSourcesToAdd.push(`"front_end/${components.join('/')}",`);
+      if (cssFilesMapping.has(fileObj.file)) {
+        for (let cssFile of cssFilesMapping.get(fileObj.file)) {
+          partialPathMapping.set(`"front_end/${sourceModule}/${cssFile}",\n`, '');
+          newSourcesToAdd.push(`"front_end/${targetModule}/${cssFile}",`);
+        }
+      }
+    }
+    return partialPathMapping;
+  }
+
+  function top(array) {
+    return array[array.length - 1];
+  }
+
+  function addContentToLinesInSortedOrder({content, startLine, endLine, linesToInsert}) {
+    let lines = content.split('\n');
+    let seenStartLine = false;
+    let contentStack = linesToInsert.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())).reverse();
+    for (var i = 0; i < lines.length; i++) {
+      let line = lines[i].trim();
+      let nextLine = lines[i + 1].trim();
+      if (line === startLine)
+        seenStartLine = true;
+
+      if (line === endLine && seenStartLine)
+        break;
+
+      if (!seenStartLine)
+        continue;
+
+      const nextContent = top(contentStack) ? top(contentStack).toLowerCase() : '';
+      if ((line === startLine || nextContent > line.toLowerCase()) &&
+          (nextLine === endLine || nextContent < nextLine.toLowerCase()))
+        lines.splice(i + 1, 0, contentStack.pop());
+    }
+    if (contentStack.length)
+      lines.splice(i, 0, ...contentStack);
+    return lines.join('\n');
+  }
+}
+
+function mapIdentifiers(identifiersByFile, cssFilesMapping) {
+  const filesToTargetModule = new Map();
+  for (let fileObj of JS_FILES_MAPPING)
+    filesToTargetModule.set(fileObj.file, fileObj.existing || fileObj.new);
+
+
+  const map = new Map();
+  for (let [file, identifiers] of identifiersByFile) {
+    let targetModule = filesToTargetModule.get(file);
+    for (let identifier of identifiers) {
+      let components = identifier.split('.');
+      components[0] = mapModuleToNamespace(targetModule);
+      let newIdentifier = components.join('.');
+      map.set(identifier, newIdentifier);
+    }
+  }
+  for (let [jsFile, cssFiles] of cssFilesMapping) {
+    let fileObj = JS_FILES_MAPPING.filter(f => f.file === jsFile)[0];
+    let sourceModule = fileObj.file.split('/')[0];
+    let targetModule = fileObj.existing || fileObj.new;
+    for (let cssFile of cssFiles) {
+      let key = `${sourceModule}/${cssFile}`;
+      let value = `${targetModule}/${cssFile}`;
+      map.set(key, value);
+    }
+  }
+  return map;
+}
+
+function renameIdentifiers(identifierMap) {
+  walkSync('front_end', write, true);
+
+  walkSync('../../LayoutTests/http/tests/inspector', write, false);
+  walkSync('../../LayoutTests/http/tests/inspector-enabled', write, false);
+  walkSync('../../LayoutTests/http/tests/inspector-protocol', write, false);
+  walkSync('../../LayoutTests/http/tests/inspector-unit', write, false);
+  walkSync('../../LayoutTests/inspector', write, false);
+  walkSync('../../LayoutTests/inspector-enabled', write, false);
+  walkSync('../../LayoutTests/inspector-protocol', write, false);
+
+  function walkSync(currentDirPath, process, json) {
+    fs.readdirSync(currentDirPath).forEach(function(name) {
+      let filePath = path.join(currentDirPath, name);
+      let stat = fs.statSync(filePath);
+      if (stat.isFile() && (filePath.endsWith('.js') || filePath.endsWith('.html') || filePath.endsWith('.xhtml') ||
+                            filePath.endsWith('-expected.txt') || (json && filePath.endsWith('.json')))) {
+        if (filePath.includes('ExtensionAPI.js'))
+          return;
+        if (filePath.includes('externs.js'))
+          return;
+        if (filePath.includes('eslint') || filePath.includes('lighthouse-background.js') || filePath.includes('/cm/') ||
+            filePath.includes('/xterm.js/') || filePath.includes('/acorn/') || filePath.includes('/gonzales-scss'))
+          return;
+        if (filePath.includes('/cm_modes/') && !filePath.includes('DefaultCodeMirror') &&
+            !filePath.includes('module.json'))
+          return;
+        process(filePath);
+      } else if (stat.isDirectory()) {
+        walkSync(filePath, process, json);
+      }
+    });
+  }
+
+  function write(filePath) {
+    let content = fs.readFileSync(filePath).toString();
+    let newContent = content;
+    for (let key of identifierMap.keys()) {
+      let originalIdentifier = key;
+      let newIdentifier = identifierMap.get(key);
+      newContent = newContent.replaceAll(originalIdentifier, newIdentifier);
+    }
+    // one-off
+    if (filePath.includes('LayoutTests/http/tests/inspector-unit/filtered-item-selection-dialog-filtering.js'))
+      newContent = newContent.replaceAll('ui_lazy', 'quick_open');
+    // if (filePath.includes('LayoutTests/inspector/components/cookies-table.html'))
+    //   newContent = newContent.replaceAll('components_lazy', 'cookie_table');
+    // if (filePath.includes('LayoutTests/inspector/components/datagrid-autosize.html'))
+    //   newContent = newContent.replaceAll('ui_lazy', 'data_grid');
+    // if (filePath.includes('LayoutTests/inspector/components/datagrid-test.js'))
+    //   newContent = newContent.replaceAll('ui_lazy', 'data_grid');
+
+    if (content !== newContent)
+      fs.writeFileSync(filePath, newContent);
+  }
+}
+
+function removeFromExistingModuleDescriptors(modules, identifierMap, cssFilesMapping) {
+  let extensionMap = new Map();
+  let moduleFileMap = new Map();
+
+  for (let fileObj of JS_FILES_MAPPING) {
+    let components = fileObj.file.split('/');
+    let module = components[0];
+    let fileName = components[1];
+
+    if (!moduleFileMap.get(module))
+      moduleFileMap.set(module, []);
+
+    moduleFileMap.set(module, moduleFileMap.get(module).concat(fileName));
+  }
+
+  for (let module of modules) {
+    let moduleJSONPath = path.resolve(FRONTEND_PATH, module, 'module.json');
+    let content = fs.readFileSync(moduleJSONPath).toString();
+    let moduleObj = parseJSON(content);
+    let removedScripts = removeScripts(moduleObj, module);
+    removeResources(moduleObj, removedScripts);
+    removeExtensions(moduleObj);
+    fs.writeFileSync(moduleJSONPath, stringifyJSON(moduleObj));
+  }
+
+  return extensionMap;
+
+  function removeScripts(moduleObj, module) {
+    let remainingScripts = [];
+    let removedScripts = [];
+    let moduleFiles = moduleFileMap.get(module);
+    for (let script of moduleObj.scripts) {
+      if (!moduleFiles.includes(script))
+        remainingScripts.push(script);
+      else
+        removedScripts.push(module + '/' + script);
+    }
+    moduleObj.scripts = remainingScripts;
+    return removedScripts;
+  }
+
+  function removeResources(moduleObj, removedScripts) {
+    if (!moduleObj.resources)
+      return;
+    let remainingResources = [];
+    let removedResources = new Set();
+    for (let script of removedScripts)
+      removedResources = removedResources.union(cssFilesMapping.get(script));
+
+
+    for (let resource of moduleObj.resources) {
+      if (!removedResources.has(resource))
+        remainingResources.push(resource);
+    }
+    moduleObj.resources = remainingResources;
+  }
+
+  function removeExtensions(moduleObj) {
+    if (!moduleObj.extensions)
+      return;
+    let remainingExtensions = [];
+    for (let extension of moduleObj.extensions) {
+      if (!objectIncludesIdentifier(extension))
+        remainingExtensions.push(extension);
+      else
+        extensionMap.set(objectIncludesIdentifier(extension), extension);
+    }
+    moduleObj.extensions = remainingExtensions;
+  }
+
+  function objectIncludesIdentifier(object) {
+    for (let key in object) {
+      let value = object[key];
+      if (identifierMap.has(value))
+        return value;
+    }
+    return false;
+  }
+}
+
+function createNewModuleDescriptors(extensionMap, cssFilesMapping, identifiersByFile, targetToOriginalFilesMap) {
+  let filesByNewModule = getFilesByNewModule();
+
+  for (let module of filesByNewModule.keys()) {
+    let moduleObj = {};
+
+    let scripts = getModuleScripts(module);
+    let extensions = getModuleExtensions(scripts, module);
+    if (extensions.length)
+      moduleObj.extensions = extensions;
+
+    moduleObj.dependencies = DEPENDENCIES_BY_MODULE[module];
+
+    moduleObj.scripts = scripts;
+
+    let resources = getModuleResources(moduleObj.scripts, module);
+    if (resources.length)
+      moduleObj.resources = resources;
+
+    let moduleJSONPath = path.resolve(FRONTEND_PATH, module, 'module.json');
+    fs.writeFileSync(moduleJSONPath, stringifyJSON(moduleObj));
+  }
+
+  function getFilesByNewModule() {
+    let filesByNewModule = new Map();
+    for (let fileObj of JS_FILES_MAPPING) {
+      if (!fileObj.new)
+        continue;
+      if (!filesByNewModule.has(fileObj.new))
+        filesByNewModule.set(fileObj.new, []);
+
+      filesByNewModule.set(fileObj.new, filesByNewModule.get(fileObj.new).concat([fileObj.file]));
+    }
+    return filesByNewModule;
+  }
+
+  function getModuleScripts(module) {
+    return filesByNewModule.get(module).map((file) => file.split('/')[1]);
+  }
+
+  function getModuleResources(scripts, module) {
+    let resources = [];
+    scripts.map(script => module + '/' + script).forEach((script) => {
+      script = targetToOriginalFilesMap.get(script);
+      if (!cssFilesMapping.has(script))
+        return;
+
+      resources = resources.concat([...cssFilesMapping.get(script)]);
+    });
+    return resources;
+  }
+
+  function getModuleExtensions(scripts, module) {
+    let extensions = [];
+    let identifiers =
+        scripts.map(script => module + '/' + script)
+            .reduce((acc, file) => acc.concat(identifiersByFile.get(targetToOriginalFilesMap.get(file))), []);
+    for (let identifier of identifiers) {
+      if (extensionMap.has(identifier))
+        extensions.push(extensionMap.get(identifier));
+    }
+    return extensions;
+  }
+}
+
+function calculateFilesByModuleType(type) {
+  let filesByNewModule = new Map();
+  for (let fileObj of JS_FILES_MAPPING) {
+    if (!fileObj[type])
+      continue;
+    if (!filesByNewModule.has(fileObj[type]))
+      filesByNewModule.set(fileObj[type], []);
+
+    filesByNewModule.set(fileObj[type], filesByNewModule.get(fileObj[type]).concat([fileObj.file]));
+  }
+  return filesByNewModule;
+}
+
+function updateExistingModuleDescriptors(extensionMap, cssFilesMapping, identifiersByFile, targetToOriginalFilesMap) {
+  let filesByExistingModule = calculateFilesByModuleType('existing');
+  for (let module of filesByExistingModule.keys()) {
+    let moduleJSONPath = path.resolve(FRONTEND_PATH, module, 'module.json');
+    let content = fs.readFileSync(moduleJSONPath).toString();
+    let moduleObj = parseJSON(content);
+
+    let scripts = getModuleScripts(module);
+    let existingExtensions = moduleObj.extensions || [];
+    let extensions = existingExtensions.concat(getModuleExtensions(scripts, module));
+    if (extensions.length)
+      moduleObj.extensions = extensions;
+
+    moduleObj.scripts = moduleObj.scripts.concat(scripts);
+
+    let existingResources = moduleObj.resources || [];
+    let resources = existingResources.concat(getModuleResources(scripts, module));
+    if (resources.length)
+      moduleObj.resources = resources;
+
+    fs.writeFileSync(moduleJSONPath, stringifyJSON(moduleObj));
+  }
+
+
+  function getModuleScripts(module) {
+    return filesByExistingModule.get(module).map((file) => file.split('/')[1]);
+  }
+
+  function getModuleResources(scripts, module) {
+    let resources = [];
+    scripts.map(script => module + '/' + script).forEach((script) => {
+      script = targetToOriginalFilesMap.get(script);
+      if (!cssFilesMapping.has(script))
+        return;
+
+      resources = resources.concat([...cssFilesMapping.get(script)]);
+    });
+    return resources;
+  }
+
+  function getModuleExtensions(scripts, module) {
+    let extensions = [];
+    let identifiers =
+        scripts.map(script => module + '/' + script)
+            .reduce((acc, file) => acc.concat(identifiersByFile.get(targetToOriginalFilesMap.get(file))), []);
+    for (let identifier of identifiers) {
+      if (extensionMap.has(identifier))
+        extensions.push(extensionMap.get(identifier));
+    }
+    return extensions;
+  }
+}
+
+function addDependenciesToDescriptors() {
+  for (let module of getModules()) {
+    let moduleJSONPath = path.resolve(FRONTEND_PATH, module, 'module.json');
+    let content = fs.readFileSync(moduleJSONPath).toString();
+    let moduleObj = parseJSON(content);
+
+    let existingDependencies = moduleObj.dependencies || [];
+    let dependencies = existingDependencies.concat(getModuleDependencies(module))
+                           .filter((depModule) => !MODULES_TO_REMOVE.includes(depModule))
+                           .filter((depModule) => !(REMOVE_DEPENDENCIES_BY_EXISTING_MODULES[module] || []).includes(depModule));
+    let newDependenciesForExistingModule = NEW_DEPENDENCIES_BY_EXISTING_MODULES[module];
+    if (newDependenciesForExistingModule)
+      dependencies = dependencies.concat(newDependenciesForExistingModule);
+    if (dependencies.length)
+      moduleObj.dependencies = dependencies;
+    let newStringified = stringifyJSON(moduleObj);
+    if (stringifyJSON(moduleObj) !== stringifyJSON(parseJSON(content)))
+      fs.writeFileSync(moduleJSONPath, newStringified);
+  }
+
+  function getModuleDependencies(existingModule) {
+    let newDeps = [];
+    for (let newModule in DEPENDENTS_BY_MODULE) {
+      let dependents = DEPENDENTS_BY_MODULE[newModule];
+      if (dependents.includes(existingModule))
+        newDeps.push(newModule);
+    }
+    return newDeps;
+  }
+}
+
+function updateApplicationDescriptor(descriptorFileName, newModuleSet) {
+  let descriptorPath = path.join(FRONTEND_PATH, descriptorFileName);
+  let newModules = [...newModuleSet].filter(m => APPLICATIONS_BY_MODULE[m].includes(descriptorFileName));
+  let includeNewModules = (acc, line) => {
+    if (line.includes('{') && line.endsWith('}')) {
+      line += ',';
+      acc.push(line);
+      return acc.concat(newModules.map((m, i) => {
+        // Need spacing to preserve indentation
+        let string;
+        if (MODULE_MAPPING[m].autostart)
+          string = `        { "name": "${m}", "type": "autostart"}`;
+        else
+          string = `        { "name": "${m}" }`;
+        if (i !== newModules.length - 1)
+          string += ',';
+        return string;
+      }));
+    }
+    return acc.concat([line]);
+  };
+  let removeModules = (acc, line) => MODULES_TO_REMOVE.every(m => !line.includes(m)) ? acc.concat([line]) : acc;
+  let lines =
+      fs.readFileSync(descriptorPath).toString().split('\n').reduce(includeNewModules, []).reduce(removeModules, []);
+  fs.writeFileSync(descriptorPath, lines.join('\n'));
+}
+
+function getModules() {
+  return fs.readdirSync(FRONTEND_PATH).filter(function(file) {
+    return fs.statSync(path.join(FRONTEND_PATH, file)).isDirectory() &&
+        utils.isFile(path.join(FRONTEND_PATH, file, 'module.json'));
+  });
+}
+
+function parseJSON(string) {
+  return JSON.parse(string);
+}
+
+function stringifyJSON(obj) {
+  return unicodeEscape(JSON.stringify(obj, null, 4) + '\n');
+}
+
+// http://stackoverflow.com/questions/7499473/need-to-escape-non-ascii-characters-in-javascript
+function unicodeEscape(string) {
+  function padWithLeadingZeros(string) {
+    return new Array(5 - string.length).join("0") + string;
+  }
+
+  function unicodeCharEscape(charCode) {
+    return "\\u" + padWithLeadingZeros(charCode.toString(16));
+  }
+
+  return string.split("")
+    .map(function (char) {
+      var charCode = char.charCodeAt(0);
+      return charCode > 127 ? unicodeCharEscape(charCode) : char;
+    })
+    .join("");
+}
+
+if (require.main === module)
+  extractModule();
diff --git a/third_party/WebKit/Source/devtools/scripts/special_case_namespaces.json b/third_party/WebKit/Source/devtools/scripts/special_case_namespaces.json
new file mode 100644
index 0000000..8e0e1e3
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/scripts/special_case_namespaces.json
@@ -0,0 +1,8 @@
+{
+  "sdk": "SDK",
+  "ui": "UI",
+  "perf_ui": "PerfUI",
+  "css_tracker": "CSSTracker",
+  "ui_lazy": "UI",
+  "components_lazy": "Components"
+}
\ No newline at end of file
diff --git a/third_party/WebKit/Source/modules/nfc/NFC.cpp b/third_party/WebKit/Source/modules/nfc/NFC.cpp
index dc55d6e..c42f893 100644
--- a/third_party/WebKit/Source/modules/nfc/NFC.cpp
+++ b/third_party/WebKit/Source/modules/nfc/NFC.cpp
@@ -120,21 +120,21 @@
 }
 
 template <>
-struct TypeConverter<mojo::WTFArray<uint8_t>, WTF::String> {
-  static mojo::WTFArray<uint8_t> Convert(const WTF::String& string) {
+struct TypeConverter<WTF::Vector<uint8_t>, WTF::String> {
+  static WTF::Vector<uint8_t> Convert(const WTF::String& string) {
     WTF::CString utf8String = string.utf8();
     WTF::Vector<uint8_t> array;
     array.append(utf8String.data(), utf8String.length());
-    return mojo::WTFArray<uint8_t>(std::move(array));
+    return array;
   }
 };
 
 template <>
-struct TypeConverter<mojo::WTFArray<uint8_t>, blink::DOMArrayBuffer*> {
-  static mojo::WTFArray<uint8_t> Convert(blink::DOMArrayBuffer* buffer) {
+struct TypeConverter<WTF::Vector<uint8_t>, blink::DOMArrayBuffer*> {
+  static WTF::Vector<uint8_t> Convert(blink::DOMArrayBuffer* buffer) {
     WTF::Vector<uint8_t> array;
     array.append(static_cast<uint8_t*>(buffer->data()), buffer->byteLength());
-    return mojo::WTFArray<uint8_t>(std::move(array));
+    return array;
   }
 };
 
@@ -145,7 +145,7 @@
     record->record_type = NFCRecordType::TEXT;
     record->media_type = kPlainTextMimeType;
     record->media_type.append(kCharSetUTF8);
-    record->data = mojo::WTFArray<uint8_t>::From(string).PassStorage();
+    record->data = mojo::ConvertTo<WTF::Vector<uint8_t>>(string);
     return record;
   }
 };
@@ -156,7 +156,7 @@
     NFCRecordPtr record = NFCRecord::New();
     record->record_type = NFCRecordType::OPAQUE_RECORD;
     record->media_type = kOpaqueMimeType;
-    record->data = mojo::WTFArray<uint8_t>::From(buffer).PassStorage();
+    record->data = mojo::ConvertTo<WTF::Vector<uint8_t>>(buffer);
     return record;
   }
 };
@@ -171,19 +171,21 @@
 };
 
 template <>
-struct TypeConverter<mojo::WTFArray<uint8_t>, blink::ScriptValue> {
-  static mojo::WTFArray<uint8_t> Convert(
+struct TypeConverter<WTF::Optional<WTF::Vector<uint8_t>>, blink::ScriptValue> {
+  static WTF::Optional<WTF::Vector<uint8_t>> Convert(
       const blink::ScriptValue& scriptValue) {
     v8::Local<v8::Value> value = scriptValue.v8Value();
 
     if (value->IsNumber())
-      return mojo::WTFArray<uint8_t>::From(
+      return mojo::ConvertTo<WTF::Vector<uint8_t>>(
           WTF::String::number(value.As<v8::Number>()->Value()));
 
     if (value->IsString()) {
       blink::V8StringResource<> stringResource = value;
-      if (stringResource.prepare())
-        return mojo::WTFArray<uint8_t>::From<WTF::String>(stringResource);
+      if (stringResource.prepare()) {
+        return mojo::ConvertTo<WTF::Vector<uint8_t>>(
+            WTF::String(stringResource));
+      }
     }
 
     if (value->IsObject() && !value->IsArray() && !value->IsArrayBuffer()) {
@@ -192,15 +194,15 @@
               .ToLocal(&jsonString)) {
         WTF::String wtfString = blink::v8StringToWebCoreString<WTF::String>(
             jsonString, blink::DoNotExternalize);
-        return mojo::WTFArray<uint8_t>::From(wtfString);
+        return mojo::ConvertTo<WTF::Vector<uint8_t>>(wtfString);
       }
     }
 
     if (value->IsArrayBuffer())
-      return mojo::WTFArray<uint8_t>::From(
+      return mojo::ConvertTo<WTF::Vector<uint8_t>>(
           blink::V8ArrayBuffer::toImpl(value.As<v8::Object>()));
 
-    return nullptr;
+    return WTF::nullopt;
   }
 };
 
@@ -236,14 +238,15 @@
         break;
     }
 
-    auto recordData = mojo::WTFArray<uint8_t>::From(record.data());
+    auto recordData =
+        mojo::ConvertTo<WTF::Optional<WTF::Vector<uint8_t>>>(record.data());
     // If JS object cannot be converted to uint8_t array, return null,
     // interrupt NFCMessage conversion algorithm and reject promise with
     // SyntaxError exception.
-    if (recordData.is_null())
+    if (!recordData)
       return nullptr;
 
-    recordPtr->data = recordData.PassStorage();
+    recordPtr->data = recordData.value();
     return recordPtr;
   }
 };
diff --git a/third_party/WebKit/Source/modules/payments/DEPS b/third_party/WebKit/Source/modules/payments/DEPS
index 724aeef7..1c8bd343 100644
--- a/third_party/WebKit/Source/modules/payments/DEPS
+++ b/third_party/WebKit/Source/modules/payments/DEPS
@@ -2,5 +2,4 @@
     "+components/payments",
     "+mojo/public/cpp/bindings/binding.h",
     "+mojo/public/cpp/bindings/interface_request.h",
-    "+mojo/public/cpp/bindings/wtf_array.h",
 ]
diff --git a/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp b/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp
index 403a187..373146c 100644
--- a/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp
+++ b/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp
@@ -30,7 +30,6 @@
 #include "modules/payments/PaymentShippingOption.h"
 #include "modules/payments/PaymentsValidators.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
-#include "mojo/public/cpp/bindings/wtf_array.h"
 #include "platform/RuntimeEnabledFeatures.h"
 #include "platform/mojo/MojoHelper.h"
 #include "public/platform/InterfaceProvider.h"
diff --git a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.cpp b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.cpp
index 190cd2d5..be6e146 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.cpp
@@ -14,10 +14,6 @@
     const PropertyTreeState& sourceState,
     const PropertyTreeState& destinationState,
     bool& success) {
-  if (sourceState == destinationState) {
-    success = true;
-    return rect;
-  }
   FloatRect result = localToVisualRectInAncestorSpace(
       rect, sourceState, destinationState, success);
   if (success)
@@ -31,10 +27,6 @@
     const PropertyTreeState& sourceState,
     const PropertyTreeState& destinationState,
     bool& success) {
-  if (sourceState == destinationState) {
-    success = true;
-    return rect;
-  }
   FloatRect result =
       localToAncestorRect(rect, sourceState, destinationState, success);
   if (success)
@@ -66,15 +58,7 @@
   DCHECK(success);
   result.intersect(clipRect);
 
-  const TransformationMatrix& destinationToLca =
-      localToAncestorMatrix(destinationState.transform(), lcaState, success);
-  DCHECK(success);
-  if (destinationToLca.isInvertible()) {
-    success = true;
-    return destinationToLca.inverse().mapRect(result);
-  }
-  success = false;
-  return rect;
+  return ancestorToLocalRect(result, destinationState, lcaState, success);
 }
 
 FloatRect GeometryMapper::slowMapRectToDestinationSpace(
@@ -91,15 +75,7 @@
   FloatRect result = localToAncestorRect(rect, sourceState, lcaState, success);
   DCHECK(success);
 
-  const TransformationMatrix& destinationToLca =
-      localToAncestorMatrix(destinationState.transform(), lcaState, success);
-  DCHECK(success);
-  if (destinationToLca.isInvertible()) {
-    success = true;
-    return destinationToLca.inverse().mapRect(result);
-  }
-  success = false;
-  return rect;
+  return ancestorToLocalRect(result, destinationState, lcaState, success);
 }
 
 FloatRect GeometryMapper::localToVisualRectInAncestorSpace(
@@ -107,6 +83,11 @@
     const PropertyTreeState& localState,
     const PropertyTreeState& ancestorState,
     bool& success) {
+  if (localState == ancestorState) {
+    success = true;
+    return rect;
+  }
+
   const auto& transformMatrix =
       localToAncestorMatrix(localState.transform(), ancestorState, success);
   if (!success)
@@ -139,6 +120,11 @@
     const PropertyTreeState& localState,
     const PropertyTreeState& ancestorState,
     bool& success) {
+  if (localState.transform() == ancestorState.transform()) {
+    success = true;
+    return rect;
+  }
+
   const auto& transformMatrix =
       localToAncestorMatrix(localState.transform(), ancestorState, success);
   if (!success)
@@ -151,6 +137,11 @@
     const PropertyTreeState& localState,
     const PropertyTreeState& ancestorState,
     bool& success) {
+  if (localState.transform() == ancestorState.transform()) {
+    success = true;
+    return rect;
+  }
+
   const auto& transformMatrix =
       localToAncestorMatrix(localState.transform(), ancestorState, success);
   if (!success)
@@ -178,11 +169,16 @@
     const PropertyTreeState& localState,
     const PropertyTreeState& ancestorState,
     bool& success) {
+  FloatRect clip(LayoutRect::infiniteIntRect());
+  if (localState.clip() == ancestorState.clip()) {
+    success = true;
+    return clip;
+  }
+
   PrecomputedDataForAncestor& precomputedData =
       getPrecomputedDataForAncestor(ancestorState);
   const ClipPaintPropertyNode* clipNode = localState.clip();
   Vector<const ClipPaintPropertyNode*> intermediateNodes;
-  FloatRect clip(LayoutRect::infiniteIntRect());
 
   bool found = false;
   // Iterate over the path from localState.clip to ancestorState.clip. Stop if
@@ -231,6 +227,11 @@
     const TransformPaintPropertyNode* localTransformNode,
     const PropertyTreeState& ancestorState,
     bool& success) {
+  if (localTransformNode == ancestorState.transform()) {
+    success = true;
+    return m_identity;
+  }
+
   PrecomputedDataForAncestor& precomputedData =
       getPrecomputedDataForAncestor(ancestorState);
 
@@ -238,7 +239,6 @@
   Vector<const TransformPaintPropertyNode*> intermediateNodes;
   TransformationMatrix transformMatrix;
 
-  bool found = false;
   // Iterate over the path from localTransformNode to ancestorState.transform.
   // Stop if we've found a memoized (precomputed) transform for any particular
   // node.
@@ -246,18 +246,16 @@
     auto it = precomputedData.toAncestorTransforms.find(transformNode);
     if (it != precomputedData.toAncestorTransforms.end()) {
       transformMatrix = it->value;
-      found = true;
       break;
     }
 
-    intermediateNodes.push_back(transformNode);
-
     if (transformNode == ancestorState.transform())
       break;
 
+    intermediateNodes.push_back(transformNode);
     transformNode = transformNode->parent();
   }
-  if (!found && transformNode != ancestorState.transform()) {
+  if (!transformNode) {
     success = false;
     return m_identity;
   }
@@ -266,12 +264,9 @@
   // computing and memoizing transforms as we go.
   for (auto it = intermediateNodes.rbegin(); it != intermediateNodes.rend();
        it++) {
-    if ((*it) != ancestorState.transform()) {
-      TransformationMatrix localTransformMatrix = (*it)->matrix();
-      localTransformMatrix.applyTransformOrigin((*it)->origin());
-      transformMatrix = transformMatrix * localTransformMatrix;
-    }
-
+    TransformationMatrix localTransformMatrix = (*it)->matrix();
+    localTransformMatrix.applyTransformOrigin((*it)->origin());
+    transformMatrix = transformMatrix * localTransformMatrix;
     precomputedData.toAncestorTransforms.set(*it, transformMatrix);
   }
   success = true;
diff --git a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTest.cpp
index 3b15334..cca8246 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTest.cpp
@@ -95,13 +95,18 @@
                        inputRect, localPropertyTreeState,                      \
                        ancestorPropertyTreeState, success));                   \
     EXPECT_TRUE(success);                                                      \
-    EXPECT_EQ(                                                                 \
-        expectedTransformToAncestor,                                           \
-        getPrecomputedDataForAncestor(ancestorPropertyTreeState)               \
-            .toAncestorTransforms.get(localPropertyTreeState.transform()));    \
-    EXPECT_EQ(expectedClipInAncestorSpace,                                     \
-              getPrecomputedDataForAncestor(ancestorPropertyTreeState)         \
-                  .toAncestorClipRects.get(localPropertyTreeState.clip()));    \
+    if (ancestorPropertyTreeState.transform() !=                               \
+        localPropertyTreeState.transform()) {                                  \
+      EXPECT_EQ(                                                               \
+          expectedTransformToAncestor,                                         \
+          getPrecomputedDataForAncestor(ancestorPropertyTreeState)             \
+              .toAncestorTransforms.get(localPropertyTreeState.transform()));  \
+    }                                                                          \
+    if (ancestorPropertyTreeState.clip() != localPropertyTreeState.clip()) {   \
+      EXPECT_EQ(expectedClipInAncestorSpace,                                   \
+                getPrecomputedDataForAncestor(ancestorPropertyTreeState)       \
+                    .toAncestorClipRects.get(localPropertyTreeState.clip()));  \
+    }                                                                          \
   } while (false)
 
 TEST_F(GeometryMapperTest, Root) {
diff --git a/third_party/WebKit/Source/platform/heap/HeapCompact.cpp b/third_party/WebKit/Source/platform/heap/HeapCompact.cpp
index 4a04981..b31a31b 100644
--- a/third_party/WebKit/Source/platform/heap/HeapCompact.cpp
+++ b/third_party/WebKit/Source/platform/heap/HeapCompact.cpp
@@ -4,6 +4,7 @@
 
 #include "platform/heap/HeapCompact.h"
 
+#include "platform/Histogram.h"
 #include "platform/RuntimeEnabledFeatures.h"
 #include "platform/heap/Heap.h"
 #include "platform/heap/SparseHeapBitmap.h"
@@ -256,12 +257,8 @@
       m_freeListSize(0),
       m_compactableArenas(0u),
       m_freedPages(0),
-      m_freedSize(0)
-#if DEBUG_LOG_HEAP_COMPACTION_RUNNING_TIME
-      ,
-      m_startCompactionTimeMS(0)
-#endif
-{
+      m_freedSize(0),
+      m_startCompactionTimeMS(0) {
   // The heap compaction implementation assumes the contiguous range,
   //
   //   [Vector1ArenaIndex, HashTableArenaIndex]
@@ -420,11 +417,10 @@
 void HeapCompact::startThreadCompaction() {
   if (!m_doCompact)
     return;
-#if DEBUG_LOG_HEAP_COMPACTION_RUNNING_TIME
+
   MutexLocker locker(m_mutex);
   if (!m_startCompactionTimeMS)
     m_startCompactionTimeMS = WTF::currentTimeMS();
-#endif
 }
 
 void HeapCompact::finishThreadCompaction() {
@@ -440,16 +436,28 @@
 #endif
     m_fixups.reset();
     m_doCompact = false;
+
+    double timeForHeapCompaction =
+        WTF::currentTimeMS() - m_startCompactionTimeMS;
+    DEFINE_STATIC_LOCAL(CustomCountHistogram, timeForHeapCompactionHistogram,
+                        ("BlinkGC.TimeForHeapCompaction", 1, 10 * 1000, 50));
+    timeForHeapCompactionHistogram.count(timeForHeapCompaction);
+    m_startCompactionTimeMS = 0;
+
+    DEFINE_STATIC_LOCAL(
+        CustomCountHistogram, objectSizeFreedByHeapCompaction,
+        ("BlinkGC.ObjectSizeFreedByHeapCompaction", 1, 4 * 1024 * 1024, 50));
+    objectSizeFreedByHeapCompaction.count(m_freedSize / 1024);
+
 #if DEBUG_LOG_HEAP_COMPACTION_RUNNING_TIME
-    double end = WTF::currentTimeMS();
     LOG_HEAP_COMPACTION_INTERNAL(
         "Compaction stats: time=%gms, pages freed=%zu, size=%zu\n",
-        end - m_startCompactionTimeMS, m_freedPages, m_freedSize);
-    m_startCompactionTimeMS = 0;
+        timeForHeapCompaction, m_freedPages, m_freedSize);
 #else
     LOG_HEAP_COMPACTION("Compaction stats: freed pages=%zu size=%zu\n",
                         m_freedPages, m_freedSize);
 #endif
+
     // Compaction has been completed by all participating threads, unblock
     // them all.
     m_finished.broadcast();
diff --git a/third_party/WebKit/Source/platform/heap/HeapCompact.h b/third_party/WebKit/Source/platform/heap/HeapCompact.h
index 23afccda..e7e13334 100644
--- a/third_party/WebKit/Source/platform/heap/HeapCompact.h
+++ b/third_party/WebKit/Source/platform/heap/HeapCompact.h
@@ -164,9 +164,7 @@
   size_t m_freedPages;
   size_t m_freedSize;
 
-#if DEBUG_LOG_HEAP_COMPACTION_RUNNING_TIME
   double m_startCompactionTimeMS;
-#endif
 
   static bool s_forceCompactionGC;
 };
diff --git a/third_party/WebKit/Source/platform/mojo/DEPS b/third_party/WebKit/Source/platform/mojo/DEPS
index ef35a2c..aee38e5 100644
--- a/third_party/WebKit/Source/platform/mojo/DEPS
+++ b/third_party/WebKit/Source/platform/mojo/DEPS
@@ -5,7 +5,6 @@
     "+base/message_loop/message_loop.h",
     "+base/strings/string16.h",
     "+mojo/public/cpp/bindings/binding.h",
-    "+mojo/public/cpp/bindings/wtf_array.h",
     "+mojo/common/string16.mojom-blink.h",
     "+mojo/common/test_common_custom_types.mojom-blink.h",
 ]
diff --git a/third_party/WebKit/Source/web/ChromeClientImpl.cpp b/third_party/WebKit/Source/web/ChromeClientImpl.cpp
index 47ddf85..c2bd6129 100644
--- a/third_party/WebKit/Source/web/ChromeClientImpl.cpp
+++ b/third_party/WebKit/Source/web/ChromeClientImpl.cpp
@@ -67,6 +67,7 @@
 #include "platform/KeyboardCodes.h"
 #include "platform/RuntimeEnabledFeatures.h"
 #include "platform/WebFrameScheduler.h"
+#include "platform/animation/CompositorAnimationHost.h"
 #include "platform/exported/WrappedResourceRequest.h"
 #include "platform/geometry/IntRect.h"
 #include "platform/graphics/GraphicsLayer.h"
@@ -827,8 +828,9 @@
     LocalFrame* localFrame) {
   WebLocalFrameImpl* webFrame =
       WebLocalFrameImpl::fromFrame(localFrame)->localRoot();
-  webFrame->frameWidget()->attachCompositorAnimationTimeline(
-      compositorTimeline);
+  if (CompositorAnimationHost* animationHost =
+          webFrame->frameWidget()->animationHost())
+    animationHost->addTimeline(*compositorTimeline);
 }
 
 void ChromeClientImpl::detachCompositorAnimationTimeline(
@@ -839,9 +841,11 @@
 
   // This method can be called when the frame is being detached, after the
   // widget is destroyed.
-  if (webFrame->frameWidget())
-    webFrame->frameWidget()->detachCompositorAnimationTimeline(
-        compositorTimeline);
+  if (webFrame->frameWidget()) {
+    if (CompositorAnimationHost* animationHost =
+            webFrame->frameWidget()->animationHost())
+      animationHost->removeTimeline(*compositorTimeline);
+  }
 }
 
 void ChromeClientImpl::enterFullscreen(LocalFrame& frame) {
@@ -859,13 +863,13 @@
 
 void ChromeClientImpl::clearCompositedSelection(LocalFrame* frame) {
   LocalFrame* localRoot = frame->localFrameRoot();
-  auto client =
-      WebLocalFrameImpl::fromFrame(localRoot)->frameWidget()->client();
+  WebFrameWidgetBase* widget =
+      WebLocalFrameImpl::fromFrame(localRoot)->frameWidget();
+  WebWidgetClient* client = widget->client();
   if (!client)
     return;
 
-  auto layerTreeView = client->layerTreeView();
-  if (layerTreeView)
+  if (WebLayerTreeView* layerTreeView = widget->getLayerTreeView())
     layerTreeView->clearSelection();
 }
 
@@ -873,13 +877,13 @@
     LocalFrame* frame,
     const CompositedSelection& selection) {
   LocalFrame* localRoot = frame->localFrameRoot();
-  WebWidgetClient* client =
-      WebLocalFrameImpl::fromFrame(localRoot)->frameWidget()->client();
+  WebFrameWidgetBase* widget =
+      WebLocalFrameImpl::fromFrame(localRoot)->frameWidget();
+  WebWidgetClient* client = widget->client();
   if (!client)
     return;
 
-  WebLayerTreeView* layerTreeView = client->layerTreeView();
-  if (layerTreeView)
+  if (WebLayerTreeView* layerTreeView = widget->getLayerTreeView())
     layerTreeView->registerSelection(WebSelection(selection));
 }
 
diff --git a/third_party/WebKit/Source/web/WebFrameWidgetBase.h b/third_party/WebKit/Source/web/WebFrameWidgetBase.h
index f424460..4d0e84d7 100644
--- a/third_party/WebKit/Source/web/WebFrameWidgetBase.h
+++ b/third_party/WebKit/Source/web/WebFrameWidgetBase.h
@@ -12,11 +12,12 @@
 
 namespace blink {
 
-class CompositorAnimationTimeline;
+class CompositorAnimationHost;
 class CompositorProxyClient;
 class GraphicsLayer;
 class WebImage;
 class WebLayer;
+class WebLayerTreeView;
 class WebViewImpl;
 class HitTestResult;
 struct WebPoint;
@@ -35,11 +36,8 @@
   // Sets the root layer. |WebLayer| can be null when detaching the root layer.
   virtual void setRootLayer(WebLayer*) = 0;
 
-  // Attaches/detaches a CompositorAnimationTimeline to the layer tree.
-  virtual void attachCompositorAnimationTimeline(
-      CompositorAnimationTimeline*) = 0;
-  virtual void detachCompositorAnimationTimeline(
-      CompositorAnimationTimeline*) = 0;
+  virtual WebLayerTreeView* getLayerTreeView() const = 0;
+  virtual CompositorAnimationHost* animationHost() const = 0;
 
   virtual HitTestResult coreHitTestResultAt(const WebPoint&) = 0;
 
diff --git a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
index dd38e0c..a565b87b 100644
--- a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
+++ b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
@@ -141,7 +141,7 @@
   m_layerTreeView = nullptr;
   m_rootLayer = nullptr;
   m_rootGraphicsLayer = nullptr;
-  m_compositorAnimationHost = nullptr;
+  m_animationHost = nullptr;
 
   m_selfKeepAlive.clear();
 }
@@ -656,7 +656,7 @@
   setIsAcceleratedCompositingActive(false);
   m_mutator = nullptr;
   m_layerTreeView = nullptr;
-  m_compositorAnimationHost = nullptr;
+  m_animationHost = nullptr;
   m_layerTreeViewClosed = true;
 }
 
@@ -976,7 +976,7 @@
     m_client->initializeLayerTreeView();
     m_layerTreeView = m_client->layerTreeView();
     if (m_layerTreeView && m_layerTreeView->compositorAnimationHost()) {
-      m_compositorAnimationHost = WTF::makeUnique<CompositorAnimationHost>(
+      m_animationHost = WTF::makeUnique<CompositorAnimationHost>(
           m_layerTreeView->compositorAnimationHost());
     }
   }
@@ -1062,16 +1062,12 @@
     m_layerTreeView->clearRootLayer();
 }
 
-void WebFrameWidgetImpl::attachCompositorAnimationTimeline(
-    CompositorAnimationTimeline* compositorTimeline) {
-  if (m_compositorAnimationHost)
-    m_compositorAnimationHost->addTimeline(*compositorTimeline);
+WebLayerTreeView* WebFrameWidgetImpl::getLayerTreeView() const {
+  return m_layerTreeView;
 }
 
-void WebFrameWidgetImpl::detachCompositorAnimationTimeline(
-    CompositorAnimationTimeline* compositorTimeline) {
-  if (m_compositorAnimationHost)
-    m_compositorAnimationHost->removeTimeline(*compositorTimeline);
+CompositorAnimationHost* WebFrameWidgetImpl::animationHost() const {
+  return m_animationHost.get();
 }
 
 HitTestResult WebFrameWidgetImpl::coreHitTestResultAt(
diff --git a/third_party/WebKit/Source/web/WebFrameWidgetImpl.h b/third_party/WebKit/Source/web/WebFrameWidgetImpl.h
index 229e8a0e..c99f3a6 100644
--- a/third_party/WebKit/Source/web/WebFrameWidgetImpl.h
+++ b/third_party/WebKit/Source/web/WebFrameWidgetImpl.h
@@ -55,7 +55,6 @@
 class LocalFrame;
 class PaintLayerCompositor;
 class UserGestureToken;
-class CompositorAnimationTimeline;
 class WebLayer;
 class WebLayerTreeView;
 class WebMouseEvent;
@@ -138,8 +137,8 @@
   WebWidgetClient* client() const override { return m_client; }
   void setRootGraphicsLayer(GraphicsLayer*) override;
   void setRootLayer(WebLayer*) override;
-  void attachCompositorAnimationTimeline(CompositorAnimationTimeline*) override;
-  void detachCompositorAnimationTimeline(CompositorAnimationTimeline*) override;
+  WebLayerTreeView* getLayerTreeView() const override;
+  CompositorAnimationHost* animationHost() const override;
   HitTestResult coreHitTestResultAt(const WebPoint&) override;
 
   // Exposed for the purpose of overriding device metrics.
@@ -215,7 +214,7 @@
   WebLayerTreeView* m_layerTreeView;
   WebLayer* m_rootLayer;
   GraphicsLayer* m_rootGraphicsLayer;
-  std::unique_ptr<CompositorAnimationHost> m_compositorAnimationHost;
+  std::unique_ptr<CompositorAnimationHost> m_animationHost;
   bool m_isAcceleratedCompositingActive;
   bool m_layerTreeViewClosed;
 
diff --git a/third_party/WebKit/Source/web/WebPagePopupImpl.cpp b/third_party/WebKit/Source/web/WebPagePopupImpl.cpp
index 0240718e..a0bffa4 100644
--- a/third_party/WebKit/Source/web/WebPagePopupImpl.cpp
+++ b/third_party/WebKit/Source/web/WebPagePopupImpl.cpp
@@ -138,14 +138,14 @@
 
   void attachCompositorAnimationTimeline(CompositorAnimationTimeline* timeline,
                                          LocalFrame*) override {
-    if (m_popup->m_compositorAnimationHost)
-      m_popup->m_compositorAnimationHost->addTimeline(*timeline);
+    if (m_popup->m_animationHost)
+      m_popup->m_animationHost->addTimeline(*timeline);
   }
 
   void detachCompositorAnimationTimeline(CompositorAnimationTimeline* timeline,
                                          LocalFrame*) override {
-    if (m_popup->m_compositorAnimationHost)
-      m_popup->m_compositorAnimationHost->removeTimeline(*timeline);
+    if (m_popup->m_animationHost)
+      m_popup->m_animationHost->removeTimeline(*timeline);
   }
 
   WebScreenInfo screenInfo() const override {
@@ -388,12 +388,12 @@
     if (m_layerTreeView) {
       m_layerTreeView->setVisible(true);
       m_isAcceleratedCompositingActive = true;
-      m_compositorAnimationHost = WTF::makeUnique<CompositorAnimationHost>(
+      m_animationHost = WTF::makeUnique<CompositorAnimationHost>(
           m_layerTreeView->compositorAnimationHost());
       m_page->layerTreeViewInitialized(*m_layerTreeView);
     } else {
       m_isAcceleratedCompositingActive = false;
-      m_compositorAnimationHost = nullptr;
+      m_animationHost = nullptr;
     }
   }
 }
@@ -412,7 +412,7 @@
 
   setIsAcceleratedCompositingActive(false);
   m_layerTreeView = nullptr;
-  m_compositorAnimationHost = nullptr;
+  m_animationHost = nullptr;
 }
 
 void WebPagePopupImpl::updateAllLifecyclePhases() {
diff --git a/third_party/WebKit/Source/web/WebPagePopupImpl.h b/third_party/WebKit/Source/web/WebPagePopupImpl.h
index 6908075..c168f67 100644
--- a/third_party/WebKit/Source/web/WebPagePopupImpl.h
+++ b/third_party/WebKit/Source/web/WebPagePopupImpl.h
@@ -120,7 +120,7 @@
   WebLayerTreeView* m_layerTreeView;
   WebLayer* m_rootLayer;
   GraphicsLayer* m_rootGraphicsLayer;
-  std::unique_ptr<CompositorAnimationHost> m_compositorAnimationHost;
+  std::unique_ptr<CompositorAnimationHost> m_animationHost;
   bool m_isAcceleratedCompositingActive;
 
   friend class WebPagePopup;
diff --git a/third_party/WebKit/Source/web/WebViewFrameWidget.cpp b/third_party/WebKit/Source/web/WebViewFrameWidget.cpp
index 5fe9a361..ed47459 100644
--- a/third_party/WebKit/Source/web/WebViewFrameWidget.cpp
+++ b/third_party/WebKit/Source/web/WebViewFrameWidget.cpp
@@ -227,14 +227,12 @@
   m_webView->setRootLayer(layer);
 }
 
-void WebViewFrameWidget::attachCompositorAnimationTimeline(
-    CompositorAnimationTimeline* compositorTimeline) {
-  m_webView->attachCompositorAnimationTimeline(compositorTimeline);
+WebLayerTreeView* WebViewFrameWidget::getLayerTreeView() const {
+  return m_webView->layerTreeView();
 }
 
-void WebViewFrameWidget::detachCompositorAnimationTimeline(
-    CompositorAnimationTimeline* compositorTimeline) {
-  m_webView->detachCompositorAnimationTimeline(compositorTimeline);
+CompositorAnimationHost* WebViewFrameWidget::animationHost() const {
+  return m_webView->animationHost();
 }
 
 HitTestResult WebViewFrameWidget::coreHitTestResultAt(const WebPoint& point) {
diff --git a/third_party/WebKit/Source/web/WebViewFrameWidget.h b/third_party/WebKit/Source/web/WebViewFrameWidget.h
index 89faa3bb..ab40015 100644
--- a/third_party/WebKit/Source/web/WebViewFrameWidget.h
+++ b/third_party/WebKit/Source/web/WebViewFrameWidget.h
@@ -100,8 +100,8 @@
   CompositorProxyClient* createCompositorProxyClient() override;
   void setRootGraphicsLayer(GraphicsLayer*) override;
   void setRootLayer(WebLayer*) override;
-  void attachCompositorAnimationTimeline(CompositorAnimationTimeline*) override;
-  void detachCompositorAnimationTimeline(CompositorAnimationTimeline*) override;
+  WebLayerTreeView* getLayerTreeView() const override;
+  CompositorAnimationHost* animationHost() const override;
   WebWidgetClient* client() const override { return m_client; }
   HitTestResult coreHitTestResultAt(const WebPoint&) override;
 
diff --git a/third_party/WebKit/Source/web/WebViewImpl.cpp b/third_party/WebKit/Source/web/WebViewImpl.cpp
index 9062b69..3259fdb2 100644
--- a/third_party/WebKit/Source/web/WebViewImpl.cpp
+++ b/third_party/WebKit/Source/web/WebViewImpl.cpp
@@ -2522,7 +2522,7 @@
     page()->willCloseLayerTreeView(*m_layerTreeView);
 
   setRootLayer(nullptr);
-  m_compositorAnimationHost = nullptr;
+  m_animationHost = nullptr;
 
   m_mutator = nullptr;
   m_layerTreeView = nullptr;
@@ -3936,14 +3936,14 @@
 
 void WebViewImpl::attachCompositorAnimationTimeline(
     CompositorAnimationTimeline* timeline) {
-  if (m_compositorAnimationHost)
-    m_compositorAnimationHost->addTimeline(*timeline);
+  if (m_animationHost)
+    m_animationHost->addTimeline(*timeline);
 }
 
 void WebViewImpl::detachCompositorAnimationTimeline(
     CompositorAnimationTimeline* timeline) {
-  if (m_compositorAnimationHost)
-    m_compositorAnimationHost->removeTimeline(*timeline);
+  if (m_animationHost)
+    m_animationHost->removeTimeline(*timeline);
 }
 
 void WebViewImpl::initializeLayerTreeView() {
@@ -3951,7 +3951,7 @@
     m_client->initializeLayerTreeView();
     m_layerTreeView = m_client->widgetClient()->layerTreeView();
     if (m_layerTreeView && m_layerTreeView->compositorAnimationHost()) {
-      m_compositorAnimationHost = WTF::makeUnique<CompositorAnimationHost>(
+      m_animationHost = WTF::makeUnique<CompositorAnimationHost>(
           m_layerTreeView->compositorAnimationHost());
     }
   }
diff --git a/third_party/WebKit/Source/web/WebViewImpl.h b/third_party/WebKit/Source/web/WebViewImpl.h
index bcf5884..e4ad02f 100644
--- a/third_party/WebKit/Source/web/WebViewImpl.h
+++ b/third_party/WebKit/Source/web/WebViewImpl.h
@@ -466,6 +466,9 @@
   WebRect computeBlockBound(const WebPoint&, bool ignoreClipping);
 
   WebLayerTreeView* layerTreeView() const { return m_layerTreeView; }
+  CompositorAnimationHost* animationHost() const {
+    return m_animationHost.get();
+  }
 
   bool matchesHeuristicsForGpuRasterizationForTesting() const {
     return m_matchesHeuristicsForGpuRasterization;
@@ -686,7 +689,7 @@
   RefPtr<UserGestureToken> m_pointerLockGestureToken;
 
   WebLayerTreeView* m_layerTreeView;
-  std::unique_ptr<CompositorAnimationHost> m_compositorAnimationHost;
+  std::unique_ptr<CompositorAnimationHost> m_animationHost;
 
   WebLayer* m_rootLayer;
   GraphicsLayer* m_rootGraphicsLayer;
diff --git a/third_party/analytics/compiled_resources2.gyp b/third_party/analytics/compiled_resources2.gyp
new file mode 100644
index 0000000..6fcc347a0
--- /dev/null
+++ b/third_party/analytics/compiled_resources2.gyp
@@ -0,0 +1,12 @@
+# 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.
+{
+  'targets': [
+    {
+      'target_name': 'externs',
+      'includes': ['../closure_compiler/include_js.gypi'],
+    },
+  ],
+}
+
diff --git a/third_party/closure_compiler/externs/web_animations.js b/third_party/closure_compiler/externs/web_animations.js
index e369b602b..39ffc37 100644
--- a/third_party/closure_compiler/externs/web_animations.js
+++ b/third_party/closure_compiler/externs/web_animations.js
@@ -174,6 +174,9 @@
 /** @type {number} */
 Animation.prototype.playbackRate;
 
+/** @type {!Promise<!Animation>} */
+Animation.prototype.finished;
+
 Animation.prototype.finish = function() {};
 
 Animation.prototype.play = function() {};
diff --git a/third_party/gestures/BUILD.gn b/third_party/gestures/BUILD.gn
new file mode 100644
index 0000000..1b80c0b
--- /dev/null
+++ b/third_party/gestures/BUILD.gn
@@ -0,0 +1,97 @@
+# 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/linux/pkg_config.gni")
+
+assert(is_linux)
+
+declare_args() {
+  # Controls whether the build should use the version of gestures
+  # library shipped with the system. In release builds of Chrome OS we
+  # use the system version, but when building on dev workstations we
+  # bundle it because Ubuntu doesn't ship a usable version.
+  use_system_gestures = true
+}
+
+if (!use_system_gestures) {
+  config("gestures_config") {
+    include_dirs = [
+      ".",
+      "include",
+      "//testing/gtest/include",
+    ]
+  }
+
+  pkg_config("jsoncpp") {
+    packages = [ "jsoncpp" ]
+  }
+
+  static_library("gestures") {
+    sources = [
+      "gestures/src/accel_filter_interpreter.cc",
+      "gestures/src/activity_log.cc",
+      "gestures/src/box_filter_interpreter.cc",
+      "gestures/src/click_wiggle_filter_interpreter.cc",
+      "gestures/src/cr48_profile_sensor_filter_interpreter.cc",
+      "gestures/src/file_util.cc",
+      "gestures/src/filter_interpreter.cc",
+      "gestures/src/finger_merge_filter_interpreter.cc",
+      "gestures/src/finger_metrics.cc",
+      "gestures/src/fling_stop_filter_interpreter.cc",
+      "gestures/src/gestures.cc",
+      "gestures/src/iir_filter_interpreter.cc",
+      "gestures/src/immediate_interpreter.cc",
+      "gestures/src/integral_gesture_filter_interpreter.cc",
+      "gestures/src/interpreter.cc",
+      "gestures/src/logging_filter_interpreter.cc",
+      "gestures/src/lookahead_filter_interpreter.cc",
+      "gestures/src/metrics_filter_interpreter.cc",
+      "gestures/src/mouse_interpreter.cc",
+      "gestures/src/multitouch_mouse_interpreter.cc",
+      "gestures/src/non_linearity_filter_interpreter.cc",
+      "gestures/src/palm_classifying_filter_interpreter.cc",
+      "gestures/src/prop_registry.cc",
+      "gestures/src/scaling_filter_interpreter.cc",
+      "gestures/src/sensor_jump_filter_interpreter.cc",
+      "gestures/src/split_correcting_filter_interpreter.cc",
+      "gestures/src/stationary_wiggle_filter_interpreter.cc",
+      "gestures/src/string_util.cc",
+      "gestures/src/stuck_button_inhibitor_filter_interpreter.cc",
+      "gestures/src/t5r2_correcting_filter_interpreter.cc",
+      "gestures/src/trace_marker.cc",
+      "gestures/src/tracer.cc",
+      "gestures/src/trend_classifying_filter_interpreter.cc",
+      "gestures/src/util.cc",
+    ]
+
+    defines = [ "GESTURES_INTERNAL=1" ]
+
+    configs -= [ "//build/config/compiler:chromium_code" ]
+    configs += [
+      "//build/config/compiler:no_chromium_code",
+      ":jsoncpp",
+    ]
+
+    # gestures uses typeid.
+    configs -= [ "//build/config/compiler:no_rtti" ]
+    configs += [ "//build/config/compiler:rtti" ]
+
+    if (is_clang) {
+      # Suppress warnings from the Chromium Clang plugin.
+      configs -= [ "//build/config/clang:find_bad_constructs" ]
+    }
+
+    public_configs = [ ":gestures_config" ]
+  }
+}
+
+if (use_system_gestures) {
+  pkg_config("libgestures") {
+    packages = [ "libgestures" ]
+  }
+
+  group("gestures") {
+    public_configs = [ ":libgestures" ]
+  }
+}
diff --git a/third_party/gestures/LICENSE b/third_party/gestures/LICENSE
new file mode 100644
index 0000000..02cb0fb
--- /dev/null
+++ b/third_party/gestures/LICENSE
@@ -0,0 +1,29 @@
+gestures/LICENSE
+
+// Copyright (c) 2011 The Chromium OS Authors. 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.
diff --git a/third_party/gestures/OWNERS b/third_party/gestures/OWNERS
new file mode 100644
index 0000000..08777b4
--- /dev/null
+++ b/third_party/gestures/OWNERS
@@ -0,0 +1,2 @@
+adlr@chromium.org
+djkurtz@chromium.org
diff --git a/third_party/gestures/README.chromium b/third_party/gestures/README.chromium
new file mode 100644
index 0000000..4e9d0a23
--- /dev/null
+++ b/third_party/gestures/README.chromium
@@ -0,0 +1,19 @@
+Name: gestures
+URL: https://chromium.googlesource.com/chromiumos/platform/gestures
+Version: 5a656849c7d2b0d0ddbe0ac6d300c1e2fada0bb4
+License: MIT
+License File: src/LICENSE
+Security Critical: yes
+
+Description:
+ChromeOS touchpad gestures library.
+
+Modifications:
+- None
+
+To import a new snapshot of gestures:
+- Checkout the latest version: git checkout 5a656849c7d2b0d0ddbe0ac6d300c1e2fada0bb4
+- Change the DEPS entry to the newly checked out commit.
+- Update header file:
+    cp gestures/include/gestures.h include/gestures/gestures.h
+- Update this README to reflect the new version number.
diff --git a/third_party/gestures/include/gestures/gestures.h b/third_party/gestures/include/gestures/gestures.h
new file mode 100644
index 0000000..96d4340
--- /dev/null
+++ b/third_party/gestures/include/gestures/gestures.h
@@ -0,0 +1,608 @@
+// Copyright (c) 2012 The Chromium OS 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 GESTURES_GESTURES_H__
+#define GESTURES_GESTURES_H__
+
+#include <stdint.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#ifdef __cplusplus
+#include <string>
+
+#include <memory>
+
+extern "C" {
+#endif
+
+// C API:
+
+// external logging interface
+#define GESTURES_LOG_ERROR 0
+#define GESTURES_LOG_INFO 1
+
+// this function has to be provided by the user of the library.
+void gestures_log(int verb, const char* format, ...)
+    __attribute__((format(printf, 2, 3)));
+
+typedef double stime_t;  // seconds
+
+enum GestureInterpreterDeviceClass {
+  GESTURES_DEVCLASS_UNKNOWN,
+  GESTURES_DEVCLASS_MOUSE,
+  GESTURES_DEVCLASS_MULTITOUCH_MOUSE,
+  GESTURES_DEVCLASS_TOUCHPAD,
+  GESTURES_DEVCLASS_TOUCHSCREEN,
+};
+
+stime_t StimeFromTimeval(const struct timeval*);
+stime_t StimeFromTimespec(const struct timespec*);
+
+struct HardwareProperties {
+  float left, top, right, bottom;
+  float res_x;  // pixels/mm
+  float res_y;  // pixels/mm
+  float screen_x_dpi;  // read from X server and passed to library
+  float screen_y_dpi;  // read from X server and passed to library
+  float orientation_minimum;
+  float orientation_maximum;
+  unsigned short max_finger_cnt; // Max finger slots in one report
+  unsigned short max_touch_cnt;  // Max fingers that can be detected at once
+  unsigned supports_t5r2:1;
+  unsigned support_semi_mt:1;
+  unsigned is_button_pad:1;
+  unsigned has_wheel:1;
+#ifdef __cplusplus
+  std::string String() const;
+#endif  // __cplusplus
+};
+
+// position is the (x,y) cartesian coord of the finger on the trackpad.
+// touch_major/minor are the large/small radii of the ellipse of the touching
+// finger. width_major/minor are also radii, but of the finger itself,
+// including a little bit that isn't touching. So, width* is generally a tad
+// larger than touch*.
+// tracking_id: If a finger is the same physical finger across two
+// consecutive frames, it must have the same tracking id; if it's a different
+// finger, it may (should) have a different tracking id.
+
+// Warp: If a finger has the 'warp' flag set for an axis, it means that while
+// the finger may have moved, it should not cause any motion in that direction.
+// This may occur is some situations where we thought a finger was in one place,
+// but then we realized later it was actually in another place.
+// The *_WARP_X/Y_MOVE version is an indication for suppressing unwanted
+// cursor movement, while the *_WARP_X/Y_NON_MOVE version is for unwanted
+// non-cursor movement (e.g. scrolling)
+#define GESTURES_FINGER_WARP_X_NON_MOVE        (1 << 0)
+#define GESTURES_FINGER_WARP_Y_NON_MOVE        (1 << 1)
+// If a finger has notap set, it shouldn't begin a tap gesture.
+#define GESTURES_FINGER_NO_TAP        (1 << 2)
+#define GESTURES_FINGER_POSSIBLE_PALM (1 << 3)
+#define GESTURES_FINGER_PALM          (1 << 4)
+#define GESTURES_FINGER_WARP_X_MOVE   (1 << 5)
+#define GESTURES_FINGER_WARP_Y_MOVE   (1 << 6)
+// If tap to click movement detection should warp:
+#define GESTURES_FINGER_WARP_X_TAP_MOVE   (1 << 7)
+#define GESTURES_FINGER_WARP_Y_TAP_MOVE   (1 << 8)
+// If a finger is a merged finger or one of close fingers
+#define GESTURES_FINGER_MERGE   (1 << 9)
+// If a finger is showing a trend of moving (see the TrendClassifyingFilter).
+#define GESTURES_FINGER_TREND_INC_X (1 << 10)
+#define GESTURES_FINGER_TREND_DEC_X (1 << 11)
+#define GESTURES_FINGER_TREND_INC_Y (1 << 12)
+#define GESTURES_FINGER_TREND_DEC_Y (1 << 13)
+#define GESTURES_FINGER_TREND_INC_PRESSURE (1 << 14)
+#define GESTURES_FINGER_TREND_DEC_PRESSURE (1 << 15)
+#define GESTURES_FINGER_TREND_INC_TOUCH_MAJOR (1 << 16)
+#define GESTURES_FINGER_TREND_DEC_TOUCH_MAJOR (1 << 17)
+// If a finger is non-stationary recently (see the StationaryWiggleFilter).
+// Compared to the trend flags, this one takes the magnitude of movements
+// into account so it might be more useful in some cases. However, it is also
+// more prone to abrupt noisy jumps than the trend flags. It also looks at
+// a shorter period of time than the trend ones so it may provide faster
+// response and lower latency.
+#define GESTURES_FINGER_INSTANTANEOUS_MOVING (1 << 18)
+// We sometimes use the warp flags only because we want to suppress unwanted
+// movements and not that we really have no good idea of the finger position.
+// This poses additional difficulty for some classifying logics that relies
+// much on the finger position. To maximize the use of any available data,
+// we further mark a finger as GESTURES_FINGER_WARP_TELEPORTATION only if we
+// indeed have no idea of its position (e.g. due to sensor jumps). For all
+// other cases (e.g. click wiggle, plams suppression, stationary wiggle), we
+// skip the flag so that we can have the option to use the not-that-accurate
+// positions.
+#define GESTURES_FINGER_WARP_TELEPORTATION (1 << 19)
+
+#define GESTURES_FINGER_WARP_X    (GESTURES_FINGER_WARP_X_NON_MOVE | \
+                                   GESTURES_FINGER_WARP_X_MOVE)
+#define GESTURES_FINGER_WARP_Y    (GESTURES_FINGER_WARP_Y_NON_MOVE | \
+                                   GESTURES_FINGER_WARP_Y_MOVE)
+
+struct FingerState {
+  float touch_major, touch_minor;
+  float width_major, width_minor;
+  float pressure;
+  float orientation;
+  float position_x;
+  float position_y;
+  short tracking_id;
+  unsigned flags;
+#ifdef __cplusplus
+  bool NonFlagsEquals(const FingerState& that) const {
+    return touch_major == that.touch_major &&
+        touch_minor == that.touch_minor &&
+        width_major == that.width_major &&
+        width_minor == that.width_minor &&
+        pressure == that.pressure &&
+        orientation == that.orientation &&
+        position_x == that.position_x &&
+        position_y == that.position_y &&
+        tracking_id == that.tracking_id;
+  }
+  bool operator==(const FingerState& that) const {
+    return NonFlagsEquals(that) && flags == that.flags;
+  }
+  bool operator!=(const FingerState& that) const { return !(*this == that); }
+  static std::string FlagsString(unsigned flags);
+  std::string String() const;
+#endif
+};
+
+#define GESTURES_BUTTON_NONE 0
+#define GESTURES_BUTTON_LEFT 1
+#define GESTURES_BUTTON_MIDDLE 2
+#define GESTURES_BUTTON_RIGHT 4
+#define GESTURES_BUTTON_BACK 8
+#define GESTURES_BUTTON_FORWARD 16
+
+// One frame of trackpad data
+struct HardwareState {
+#ifdef __cplusplus
+  FingerState* GetFingerState(short tracking_id);
+  const FingerState* GetFingerState(short tracking_id) const;
+  bool SameFingersAs(const HardwareState& that) const;
+  std::string String() const;
+  void DeepCopy(const HardwareState& that, unsigned short max_finger_cnt);
+#endif  // __cplusplus
+  stime_t timestamp;  // 64-bit Wall clock time in microseconds (10^-6 s)
+  int buttons_down;  // bit field, use GESTURES_BUTTON_*
+  unsigned short finger_cnt;  // Number of valid finger slots
+  unsigned short touch_cnt;  // Number of fingers touching pad
+  struct FingerState* fingers;
+  // For EV_REL events
+  float rel_x;
+  float rel_y;
+  float rel_wheel;
+  float rel_hwheel;
+};
+
+#define GESTURES_FLING_START 0  // Scroll end/fling begin
+#define GESTURES_FLING_TAP_DOWN 1  // Finger touched down/fling end
+
+#define GESTURES_ZOOM_START 0  // Pinch zoom begin
+#define GESTURES_ZOOM_UPDATE 1  // Zoom-in/Zoom-out update
+#define GESTURES_ZOOM_END 2  // Pinch zoom end
+
+// Gesture sub-structs
+
+// Note about ordinal_* values: Sometimes, UI will want to use unaccelerated
+// values for various gestures, so we expose the non-accelerated values in
+// the ordinal_* fields.
+
+typedef struct {
+  float dx, dy;
+  float ordinal_dx, ordinal_dy;
+} GestureMove;
+
+typedef struct{
+  float dx, dy;
+  float ordinal_dx, ordinal_dy;
+  // If set, stop_fling means that this scroll should stop flinging, thus
+  // if an interpreter suppresses it for any reason (e.g., rounds the size
+  // down to 0, thus making it a noop), it will replace it with a Fling
+  // TAP_DOWN gesture
+  unsigned stop_fling:1;
+} GestureScroll;
+
+typedef struct {
+  // If a bit is set in both down and up, client should process down first
+  unsigned down;  // bit field, use GESTURES_BUTTON_*
+  unsigned up;  // bit field, use GESTURES_BUTTON_*
+} GestureButtonsChange;
+
+typedef struct {
+  // fling velocity (valid when fling_state is GESTURES_FLING_START):
+  float vx, vy;
+  float ordinal_vx, ordinal_vy;
+  unsigned fling_state:1;  // GESTURES_FLING_START or GESTURES_FLING_TAP_DOWN
+} GestureFling;
+
+typedef struct {
+  float dx, dy;
+  float ordinal_dx, ordinal_dy;
+} GestureSwipe;
+
+typedef struct {
+  float dx, dy;
+  float ordinal_dx, ordinal_dy;
+} GestureFourFingerSwipe;
+
+typedef struct {
+  char __dummy;
+  // Remove this when there is a member in this struct. http://crbug.com/341155
+  // Currently no members
+} GestureFourFingerSwipeLift;
+
+typedef struct {
+  char __dummy;
+  // Remove this when there is a member in this struct. http://crbug.com/341155
+  // Currently no members
+} GestureSwipeLift;
+
+typedef struct {
+  // Relative pinch factor starting with 1.0 = no pinch
+  // <1.0 for outwards pinch
+  // >1.0 for inwards pinch
+  float dz;
+  float ordinal_dz;
+  // GESTURES_ZOOM_START, GESTURES_ZOOM_UPDATE, or GESTURES_ZOOM_END
+  unsigned zoom_state;
+} GesturePinch;
+
+// Metrics types that we care about
+enum GestureMetricsType {
+  kGestureMetricsTypeNoisyGround = 0,
+  kGestureMetricsTypeMouseMovement,
+  kGestureMetricsTypeUnknown,
+};
+
+typedef struct {
+  enum GestureMetricsType type;
+  // Optional values for the metrics. 2 are more than enough for now.
+  float data[2];
+} GestureMetrics;
+
+enum GestureType {
+#ifdef GESTURES_INTERNAL
+  kGestureTypeNull = -1,  // internal to Gestures library only
+#endif  // GESTURES_INTERNAL
+  kGestureTypeContactInitiated = 0,
+  kGestureTypeMove,
+  kGestureTypeScroll,
+  kGestureTypeButtonsChange,
+  kGestureTypeFling,
+  kGestureTypeSwipe,
+  kGestureTypePinch,
+  kGestureTypeSwipeLift,
+  kGestureTypeMetrics,
+  kGestureTypeFourFingerSwipe,
+  kGestureTypeFourFingerSwipeLift,
+};
+
+#ifdef __cplusplus
+// Pass these into Gesture() ctor as first arg
+extern const GestureMove kGestureMove;
+extern const GestureScroll kGestureScroll;
+extern const GestureButtonsChange kGestureButtonsChange;
+extern const GestureFling kGestureFling;
+extern const GestureSwipe kGestureSwipe;
+extern const GestureFourFingerSwipe kGestureFourFingerSwipe;
+extern const GesturePinch kGesturePinch;
+extern const GestureSwipeLift kGestureSwipeLift;
+extern const GestureFourFingerSwipeLift kGestureFourFingerSwipeLift;
+extern const GestureMetrics kGestureMetrics;
+#endif  // __cplusplus
+
+struct Gesture {
+#ifdef __cplusplus
+  // Create Move/Scroll gesture
+#ifdef GESTURES_INTERNAL
+  Gesture() : start_time(0), end_time(0), type(kGestureTypeNull) {}
+  std::string String() const;
+  bool operator==(const Gesture& that) const;
+  bool operator!=(const Gesture& that) const { return !(*this == that); };
+#endif  // GESTURES_INTERNAL
+  Gesture(const GestureMove&, stime_t start, stime_t end, float dx, float dy)
+      : start_time(start), end_time(end), type(kGestureTypeMove) {
+    details.move.ordinal_dx = details.move.dx = dx;
+    details.move.ordinal_dy = details.move.dy = dy;
+  }
+  Gesture(const GestureScroll&,
+          stime_t start, stime_t end, float dx, float dy)
+      : start_time(start), end_time(end), type(kGestureTypeScroll) {
+    details.scroll.ordinal_dx = details.scroll.dx = dx;
+    details.scroll.ordinal_dy = details.scroll.dy = dy;
+    details.scroll.stop_fling = 0;
+  }
+  Gesture(const GestureButtonsChange&,
+          stime_t start, stime_t end, unsigned down, unsigned up)
+      : start_time(start),
+        end_time(end),
+        type(kGestureTypeButtonsChange) {
+    details.buttons.down = down;
+    details.buttons.up = up;
+  }
+  Gesture(const GestureFling&,
+          stime_t start, stime_t end, float vx, float vy, unsigned state)
+      : start_time(start), end_time(end), type(kGestureTypeFling) {
+    details.fling.ordinal_vx = details.fling.vx = vx;
+    details.fling.ordinal_vy = details.fling.vy = vy;
+    details.fling.fling_state = state;
+  }
+  Gesture(const GestureSwipe&,
+          stime_t start, stime_t end, float dx, float dy)
+      : start_time(start),
+        end_time(end),
+        type(kGestureTypeSwipe) {
+    details.swipe.ordinal_dx = details.swipe.dx = dx;
+    details.swipe.ordinal_dy = details.swipe.dy = dy;
+  }
+  Gesture(const GestureFourFingerSwipe&,
+          stime_t start, stime_t end, float dx, float dy)
+      : start_time(start),
+        end_time(end),
+        type(kGestureTypeFourFingerSwipe) {
+    details.four_finger_swipe.ordinal_dx = details.four_finger_swipe.dx = dx;
+    details.four_finger_swipe.ordinal_dy = details.four_finger_swipe.dy = dy;
+  }
+  Gesture(const GesturePinch&,
+          stime_t start, stime_t end, float dz, unsigned state)
+      : start_time(start),
+        end_time(end),
+        type(kGestureTypePinch) {
+    details.pinch.ordinal_dz = details.pinch.dz = dz;
+    details.pinch.zoom_state = state;
+  }
+  Gesture(const GestureSwipeLift&, stime_t start, stime_t end)
+      : start_time(start),
+        end_time(end),
+        type(kGestureTypeSwipeLift) {}
+  Gesture(const GestureFourFingerSwipeLift&, stime_t start, stime_t end)
+      : start_time(start),
+        end_time(end),
+        type(kGestureTypeFourFingerSwipeLift) {}
+  Gesture(const GestureMetrics&,
+          stime_t start, stime_t end, GestureMetricsType m_type,
+          float d1, float d2)
+      : start_time(start),
+        end_time(end),
+        type(kGestureTypeMetrics) {
+    details.metrics.type = m_type;
+    details.metrics.data[0] = d1;
+    details.metrics.data[1] = d2;
+  }
+#endif  // __cplusplus
+
+  stime_t start_time, end_time;
+  enum GestureType type;
+  union {
+    GestureMove move;
+    GestureScroll scroll;
+    GestureButtonsChange buttons;
+    GestureFling fling;
+    GestureSwipe swipe;
+    GesturePinch pinch;
+    GestureSwipeLift swipe_lift;
+    GestureMetrics metrics;
+    GestureFourFingerSwipe four_finger_swipe;
+    GestureFourFingerSwipeLift four_finger_swipe_lift;
+  } details;
+};
+
+typedef void (*GestureReadyFunction)(void* client_data,
+                                     const struct Gesture* gesture);
+
+// Gestures Timer Provider Interface
+struct GesturesTimer;
+typedef struct GesturesTimer GesturesTimer;
+
+// If this returns < 0, the timer should be freed. If it returns >= 0.0, it
+// should be called again after that amount of delay.
+typedef stime_t (*GesturesTimerCallback)(stime_t now,
+                                         void* callback_data);
+// Allocate and return a new timer, or NULL if error.
+typedef GesturesTimer* (*GesturesTimerCreate)(void* data);
+// Set a timer:
+typedef void (*GesturesTimerSet)(void* data,
+                                 GesturesTimer* timer,
+                                 stime_t delay,
+                                 GesturesTimerCallback callback,
+                                 void* callback_data);
+// Cancel a set timer:
+typedef void (*GesturesTimerCancel)(void* data, GesturesTimer* timer);
+// Free the timer. Will not be called from within a timer callback.
+typedef void (*GesturesTimerFree)(void* data, GesturesTimer* timer);
+
+typedef struct {
+  GesturesTimerCreate create_fn;
+  GesturesTimerSet set_fn;
+  GesturesTimerCancel cancel_fn;
+  GesturesTimerFree free_fn;
+} GesturesTimerProvider;
+
+// Gestures Property Provider Interface
+struct GesturesProp;
+typedef struct GesturesProp GesturesProp;
+
+typedef unsigned char GesturesPropBool;
+
+// These functions create a named property of given type.
+//   data - data used by PropProvider
+//   loc - location of a variable to be updated by PropProvider.
+//         Set to NULL to create a ReadOnly property
+//   init - initial value for the property.
+//          If the PropProvider has an alternate configuration source, it may
+//          override this initial value, in which case *loc returns the
+//          value from the configuration source.
+typedef GesturesProp* (*GesturesPropCreateInt)(void* data, const char* name,
+                                               int* loc, size_t count,
+                                               const int* init);
+
+typedef GesturesProp* (*GesturesPropCreateShort)(void* data, const char* name,
+                                                 short* loc, size_t count,
+                                                 const short* init);
+
+typedef GesturesProp* (*GesturesPropCreateBool)(void* data, const char* name,
+                                                GesturesPropBool* loc,
+                                                size_t count,
+                                                const GesturesPropBool* init);
+
+typedef GesturesProp* (*GesturesPropCreateString)(void* data, const char* name,
+                                                  const char** loc,
+                                                  const char* const init);
+
+typedef GesturesProp* (*GesturesPropCreateReal)(void* data, const char* name,
+                                                double* loc, size_t count,
+                                                const double* init);
+
+// A function to call just before a property is to be read.
+// |handler_data| is a local context pointer that can be used by the handler.
+// Handler should return non-zero if it modifies the property's value.
+typedef GesturesPropBool (*GesturesPropGetHandler)(void* handler_data);
+
+// A function to call just after a property's value is updated.
+// |handler_data| is a local context pointer that can be used by the handler.
+typedef void (*GesturesPropSetHandler)(void* handler_data);
+
+// Register handlers to be called when a GesturesProp is accessed.
+// The get handler, if not NULL, is called immediately before the property's
+// value is to be read.  This gives the library a chance to update its value.
+// The set handler, if not NULL, is called immediately after the property's
+// value is updated.  This can be used to create a property that is used to
+// trigger an action, or to force an update to multiple properties atomically.
+// Note: the handlers are called from non-signal/interrupt context
+typedef void (*GesturesPropRegisterHandlers)(void* data, GesturesProp* prop,
+                                             void* handler_data,
+                                             GesturesPropGetHandler getter,
+                                             GesturesPropSetHandler setter);
+
+// Free a property.
+typedef void (*GesturesPropFree)(void* data, GesturesProp* prop);
+
+typedef struct GesturesPropProvider {
+  GesturesPropCreateInt create_int_fn;
+  GesturesPropCreateShort create_short_fn;
+  GesturesPropCreateBool create_bool_fn;
+  GesturesPropCreateString create_string_fn;
+  GesturesPropCreateReal create_real_fn;
+  GesturesPropRegisterHandlers register_handlers_fn;
+  GesturesPropFree free_fn;
+} GesturesPropProvider;
+
+#ifdef __cplusplus
+// C++ API:
+
+namespace gestures {
+
+class Interpreter;
+class PropRegistry;
+class LoggingFilterInterpreter;
+class Tracer;
+class GestureInterpreterConsumer;
+class MetricsProperties;
+
+#if __cplusplus >= 201103L
+
+struct GestureInterpreter {
+ public:
+  explicit GestureInterpreter(int version);
+  ~GestureInterpreter();
+  void PushHardwareState(HardwareState* hwstate);
+
+  void SetHardwareProperties(const HardwareProperties& hwprops);
+
+  void TimerCallback(stime_t now, stime_t* timeout);
+
+  void set_callback(GestureReadyFunction callback,
+                    void* client_data);
+  void SetTimerProvider(GesturesTimerProvider* tp, void* data);
+  void SetPropProvider(GesturesPropProvider* pp, void* data);
+
+  // Initialize GestureInterpreter based on device configuration.  This must be
+  // called after GesturesPropProvider is set and before it accepts any inputs.
+  void Initialize(
+      GestureInterpreterDeviceClass type=GESTURES_DEVCLASS_TOUCHPAD);
+
+  Interpreter* interpreter() const { return interpreter_.get(); }
+  PropRegistry* prop_reg() const { return prop_reg_.get(); }
+
+  std::string EncodeActivityLog();
+ private:
+  void InitializeTouchpad(void);
+  void InitializeTouchpad2(void);
+  void InitializeMouse(void);
+  void InitializeMultitouchMouse(void);
+
+  GestureReadyFunction callback_;
+  void* callback_data_;
+
+  std::unique_ptr<PropRegistry> prop_reg_;
+  std::unique_ptr<Tracer> tracer_;
+  std::unique_ptr<Interpreter> interpreter_;
+  std::unique_ptr<MetricsProperties> mprops_;
+
+  GesturesTimerProvider* timer_provider_;
+  void* timer_provider_data_;
+  GesturesTimer* interpret_timer_;
+
+  LoggingFilterInterpreter* loggingFilter_;
+  std::unique_ptr<GestureInterpreterConsumer> consumer_;
+  HardwareProperties hwprops_;
+
+  // Disallow copy & assign;
+  GestureInterpreter(const GestureInterpreter&);
+  void operator=(const GestureInterpreter&);
+};
+
+#else  // __cplusplus >= 201103L
+
+// Must be opaque under C++03 builds, since it has unique_ptr members.
+struct GestureInterpreter;
+
+#endif  // __cplusplus >= 201103L
+
+
+}  // namespace gestures
+
+typedef gestures::GestureInterpreter GestureInterpreter;
+#else
+struct GestureInterpreter;
+typedef struct GestureInterpreter GestureInterpreter;
+#endif  // __cplusplus
+
+#define GESTURES_VERSION 1
+GestureInterpreter* NewGestureInterpreterImpl(int);
+#define NewGestureInterpreter() NewGestureInterpreterImpl(GESTURES_VERSION)
+
+void DeleteGestureInterpreter(GestureInterpreter*);
+
+void GestureInterpreterSetHardwareProperties(GestureInterpreter*,
+                                             const struct HardwareProperties*);
+
+void GestureInterpreterPushHardwareState(GestureInterpreter*,
+                                         struct HardwareState*);
+
+void GestureInterpreterSetCallback(GestureInterpreter*,
+                                   GestureReadyFunction,
+                                   void*);
+
+// Gestures will hold a reference to passed provider. Pass NULL to tell
+// Gestures to stop holding a reference.
+void GestureInterpreterSetTimerProvider(GestureInterpreter*,
+                                        GesturesTimerProvider*,
+                                        void*);
+
+void GestureInterpreterSetPropProvider(GestureInterpreter*,
+                                       GesturesPropProvider*,
+                                       void*);
+
+void GestureInterpreterInitialize(GestureInterpreter*,
+                                  enum GestureInterpreterDeviceClass);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // GESTURES_GESTURES_H__
diff --git a/third_party/libevdev/BUILD.gn b/third_party/libevdev/BUILD.gn
new file mode 100644
index 0000000..16d3128a
--- /dev/null
+++ b/third_party/libevdev/BUILD.gn
@@ -0,0 +1,44 @@
+# 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/linux/pkg_config.gni")
+
+assert(is_linux)
+
+declare_args() {
+  # Controls whether the build should use the version of libevdev
+  # library shipped with the system. In release builds of Chrome OS we
+  # use the system version, but when building on dev workstations we
+  # bundle it because Ubuntu doesn't ship a usable version.
+  use_system_libevdev = true
+}
+
+if (!use_system_libevdev) {
+  config("libevdev_config") {
+    include_dirs = [ "src/include" ]
+  }
+
+  static_library("libevdev") {
+    sources = [
+      "src/src/libevdev.c",
+      "src/src/libevdev_event.c",
+      "src/src/libevdev_mt.c",
+    ]
+
+    configs -= [ "//build/config/compiler:chromium_code" ]
+    configs += [ "//build/config/compiler:no_chromium_code" ]
+
+    public_configs = [ ":libevdev_config" ]
+  }
+}
+
+if (use_system_libevdev) {
+  pkg_config("libevdev-cros") {
+    packages = [ "libevdev-cros" ]
+  }
+
+  group("libevdev") {
+    public_configs = [ ":libevdev-cros" ]
+  }
+}
diff --git a/third_party/libevdev/LICENSE b/third_party/libevdev/LICENSE
new file mode 100644
index 0000000..fcb713a
--- /dev/null
+++ b/third_party/libevdev/LICENSE
@@ -0,0 +1,3 @@
+Copyright (c) 2011 The Chromium OS 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/third_party/libevdev/OWNERS b/third_party/libevdev/OWNERS
new file mode 100644
index 0000000..08777b4
--- /dev/null
+++ b/third_party/libevdev/OWNERS
@@ -0,0 +1,2 @@
+adlr@chromium.org
+djkurtz@chromium.org
diff --git a/third_party/libevdev/README.chromium b/third_party/libevdev/README.chromium
new file mode 100644
index 0000000..4c09ae3
--- /dev/null
+++ b/third_party/libevdev/README.chromium
@@ -0,0 +1,16 @@
+Name: libevdev
+URL: https://chromium.googlesource.com/chromiumos/platform/libevdev
+Version: 9f7a1961eb4726211e18abd147d5a11a4ea86744
+License: MIT
+Security Critical: yes
+
+Description:
+The libevdev library (ChromeOS version).
+
+Modifications:
+- None
+
+To import a new snapshot of libevdev:
+- Checkout the latest version: git checkout 9f7a1961eb4726211e18abd147d5a11a4ea86744
+- Change the DEPS entry to the newly checked out commit.
+- Update this README to reflect the new version number.
diff --git a/third_party/libxml/README.chromium b/third_party/libxml/README.chromium
index cdd41e5..e7ad373 100644
--- a/third_party/libxml/README.chromium
+++ b/third_party/libxml/README.chromium
@@ -17,6 +17,7 @@
 - Apply patch contributed here: https://crbug.com/623378#c7
 - Apply patch contributed here: https://crbug.com/624011
 - Apply patch contributed here: https://crbug.com/628581#c18
+- Apply patch contributed here: https://crbug.com/620679#c34
 
 This import was generated by this script: https://goo.gl/72CTWf
 
diff --git a/third_party/libxml/src/parser.c b/third_party/libxml/src/parser.c
index e313612..33786f08 100644
--- a/third_party/libxml/src/parser.c
+++ b/third_party/libxml/src/parser.c
@@ -3426,8 +3426,15 @@
         xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
         return(NULL);
     }
-    if ((*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r'))
+    if ((*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r')) {
+        if (ctxt->input->base > ctxt->input->cur - (len + 1)) {
+            return(NULL);
+        }
         return(xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1), len));
+    }
+    if (ctxt->input->base > ctxt->input->cur - len) {
+        return(NULL);
+    }
     return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
 }
 
diff --git a/tools/clang-format-js b/tools/clang-format-js
index 4b04d8dc..b8a92b5 100755
--- a/tools/clang-format-js
+++ b/tools/clang-format-js
@@ -4,30 +4,37 @@
 # found in the LICENSE file.
 
 if [[ -z "${@}" ]]; then
-  echo >&2 "Usage: `basename $0` <paths_to_clang_format...>";
-  exit 1;
+  echo >&2 "Usage: `basename $0` <paths_to_clang_format...>"
+  exit 1
 fi
 
-which clang-format >/dev/null 2>&1;
+which clang-format >/dev/null 2>&1
 if [[ $? -ne 0 ]]; then
-  echo >&2 "Sorry, but you need \`clang-format\` on your \$PATH to run this script";
-  exit 1;
+  echo >&2 "Sorry, but you need \`clang-format\` on your \$PATH to run this script"
+  exit 1
 fi
 
-for arg in "${@}"; do
+for arg in ${@}; do
+  echo "Processing ${arg}"
+
   dir=`readlink -f "${arg}"`
   if [[ -d "${dir}" ]]; then
     dir="${dir}/stripped-by-dirname-on-next-line"
   fi
   while dir=`dirname ${dir}`; do
     if [[ -f "${dir}/.clang-format" ]]; then
-      echo "Using style from: ${dir}/.clang-format";
-      break;
+      echo "Using style from: ${dir}/.clang-format"
+      break
     elif [[ "${dir}" == "/" ]]; then
-      echo >&2 "No .clang-format file found. Make one at or above ${arg}";
-      exit 1;
+      echo >&2 "No .clang-format file found. Make one at or above ${arg}"
+      exit 1
     fi
   done
-done
 
-find "${@}" -type f -iname '*.js' | xargs clang-format -i -style=file;
+  js_files=$(git ls-tree -r --name-only HEAD -- "${arg}" | grep '\.js$')
+
+  for js_file in ${js_files}; do
+    echo "Formatting ${js_file}"
+    clang-format -i -style=file "$js_file"
+  done
+done
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index c0b7cf8..2fccd535 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -4661,6 +4661,14 @@
   </summary>
 </histogram>
 
+<histogram name="BlinkGC.ObjectSizeFreedByHeapCompaction" units="KB">
+  <owner>haraken@chromium.org</owner>
+  <summary>
+    The total size of objects freed by BlinkGC's heap compaction.   This is
+    recorded once following each compaction.
+  </summary>
+</histogram>
+
 <histogram name="BlinkGC.PerformPendingSweep" units="ms">
   <obsolete>
     Removed at 2014 Jan.
@@ -4678,6 +4686,13 @@
   </summary>
 </histogram>
 
+<histogram name="BlinkGC.TimeForHeapCompaction" units="ms">
+  <owner>haraken@chromium.org</owner>
+  <summary>
+    Duration of wall time taken to run BlinkGC's heap compaction.
+  </summary>
+</histogram>
+
 <histogram name="BlinkGC.TimeForInvokingPreFinalizers" units="ms">
   <owner>haraken@chromium.org</owner>
   <summary>
diff --git a/tools/perf/benchmarks/blink_perf.py b/tools/perf/benchmarks/blink_perf.py
index deb1f7d..943f3f7c 100644
--- a/tools/perf/benchmarks/blink_perf.py
+++ b/tools/perf/benchmarks/blink_perf.py
@@ -119,17 +119,6 @@
     print log
 
 
-class _BlinkPerfMeasurementSlimmingPaintInvalidation(_BlinkPerfMeasurement):
-  """Measures blink perf with the new paint invalidation system (see:
-  https://goo.gl/eQczQW). The benchmarks using this measurement should be
-  removed when slimming paint invalidation ships."""
-  def CustomizeBrowserOptions(self, options):
-    _BlinkPerfMeasurement.CustomizeBrowserOptions(self, options)
-    options.AppendExtraBrowserArgs([
-        '--enable-blink-features=SlimmingPaintInvalidation'
-    ])
-
-
 class _BlinkPerfBenchmark(perf_benchmark.PerfBenchmark):
   test = _BlinkPerfMeasurement
 
@@ -229,11 +218,6 @@
     return cls.IsSvelte(possible_browser)  # http://crbug.com/574483
 
 
-class BlinkPerfPaintSlimmingPaintInvalidation(BlinkPerfPaint):
-  tag = 'paint_slimmingpaintinvalidation'
-  test = _BlinkPerfMeasurementSlimmingPaintInvalidation
-
-
 @benchmark.Disabled('win')  # crbug.com/488493
 class BlinkPerfParser(_BlinkPerfBenchmark):
   tag = 'parser'
@@ -245,11 +229,6 @@
   subdir = 'SVG'
 
 
-class BlinkPerfSVGSlimmingPaintInvalidation(BlinkPerfSVG):
-  tag = 'svg_slimmingpaintinvalidation'
-  test = _BlinkPerfMeasurementSlimmingPaintInvalidation
-
-
 class BlinkPerfShadowDOM(_BlinkPerfBenchmark):
   tag = 'shadow_dom'
   subdir = 'ShadowDOM'
diff --git a/ui/base/ime/DEPS b/ui/base/ime/DEPS
index de08167..666a6eb 100644
--- a/ui/base/ime/DEPS
+++ b/ui/base/ime/DEPS
@@ -1,3 +1,4 @@
 include_rules = [
+  "+chromeos/system",
   "+ui/ozone/public",
 ]
diff --git a/ui/base/ime/input_method_chromeos.cc b/ui/base/ime/input_method_chromeos.cc
index 27d0a559..d867fb9 100644
--- a/ui/base/ime/input_method_chromeos.cc
+++ b/ui/base/ime/input_method_chromeos.cc
@@ -16,8 +16,8 @@
 #include "base/logging.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/sys_info.h"
 #include "base/third_party/icu/icu_utf.h"
+#include "chromeos/system/devicemode.h"
 #include "ui/base/ime/chromeos/ime_keyboard.h"
 #include "ui/base/ime/chromeos/input_method_manager.h"
 #include "ui/base/ime/composition_text.h"
@@ -66,7 +66,7 @@
   // For linux_chromeos, the ime keyboard cannot track the caps lock state by
   // itself, so need to call SetCapsLockEnabled() method to reflect the caps
   // lock state by the key event.
-  if (!base::SysInfo::IsRunningOnChromeOS()) {
+  if (!chromeos::IsRunningAsSystemCompositor()) {
     chromeos::input_method::InputMethodManager* manager =
         chromeos::input_method::InputMethodManager::Get();
     if (manager) {
diff --git a/ui/display/manager/BUILD.gn b/ui/display/manager/BUILD.gn
index 47b30ba..6f11374 100644
--- a/ui/display/manager/BUILD.gn
+++ b/ui/display/manager/BUILD.gn
@@ -50,6 +50,10 @@
 
   defines = [ "DISPLAY_MANAGER_IMPLEMENTATION" ]
 
+  if (is_chromeos) {
+    deps += [ "//chromeos" ]
+  }
+
   if (use_x11) {
     deps += [ "//ui/gfx/x" ]
   }
diff --git a/ui/display/manager/DEPS b/ui/display/manager/DEPS
index 3c96d4d..758e0c84 100644
--- a/ui/display/manager/DEPS
+++ b/ui/display/manager/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
+  "+chromeos/system",
   "+ui/base",
   "+ui/events/devices",
   "+ui/strings",
diff --git a/ui/display/manager/chromeos/display_configurator.cc b/ui/display/manager/chromeos/display_configurator.cc
index ea5857e..d718eb8 100644
--- a/ui/display/manager/chromeos/display_configurator.cc
+++ b/ui/display/manager/chromeos/display_configurator.cc
@@ -11,8 +11,8 @@
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/sys_info.h"
 #include "base/time/time.h"
+#include "chromeos/system/devicemode.h"
 #include "ui/display/display.h"
 #include "ui/display/display_switches.h"
 #include "ui/display/manager/chromeos/apply_content_protection_task.h"
@@ -466,7 +466,7 @@
     : state_controller_(NULL),
       mirroring_controller_(NULL),
       is_panel_fitting_enabled_(false),
-      configure_display_(base::SysInfo::IsRunningOnChromeOS()),
+      configure_display_(chromeos::IsRunningAsSystemCompositor()),
       current_display_state_(MULTIPLE_DISPLAY_STATE_INVALID),
       current_power_state_(chromeos::DISPLAY_POWER_ALL_ON),
       requested_display_state_(MULTIPLE_DISPLAY_STATE_INVALID),
diff --git a/ui/display/manager/display_manager.cc b/ui/display/manager/display_manager.cc
index 1ce11bc0..24c74f0c 100644
--- a/ui/display/manager/display_manager.cc
+++ b/ui/display/manager/display_manager.cc
@@ -40,6 +40,7 @@
 
 #if defined(OS_CHROMEOS)
 #include "base/sys_info.h"
+#include "chromeos/system/devicemode.h"
 #endif
 
 #if defined(OS_WIN)
@@ -136,7 +137,7 @@
       layout_store_(new DisplayLayoutStore),
       weak_ptr_factory_(this) {
 #if defined(OS_CHROMEOS)
-  configure_displays_ = base::SysInfo::IsRunningOnChromeOS();
+  configure_displays_ = chromeos::IsRunningAsSystemCompositor();
   change_display_upon_host_resize_ = !configure_displays_;
   unified_desktop_enabled_ = base::CommandLine::ForCurrentProcess()->HasSwitch(
       ::switches::kEnableUnifiedDesktop);
diff --git a/ui/events/ozone/BUILD.gn b/ui/events/ozone/BUILD.gn
index 314068c0..73d0195b 100644
--- a/ui/events/ozone/BUILD.gn
+++ b/ui/events/ozone/BUILD.gn
@@ -66,16 +66,6 @@
     defines = [ "USE_EVDEV_GESTURES" ]
   }
 
-  if (use_evdev_gestures) {
-    pkg_config("libevdev-cros") {
-      packages = [ "libevdev-cros" ]
-    }
-
-    pkg_config("libgestures") {
-      packages = [ "libgestures" ]
-    }
-  }
-
   component("events_ozone_evdev") {
     sources = [
       "evdev/device_event_dispatcher_evdev.cc",
@@ -162,12 +152,12 @@
         "evdev/libgestures_glue/gesture_timer_provider.h",
       ]
 
-      public_configs += [ ":evdev_gestures" ]
-
-      configs += [
-        ":libevdev-cros",
-        ":libgestures",
+      deps += [
+        "//third_party/gestures",
+        "//third_party/libevdev",
       ]
+
+      public_configs += [ ":evdev_gestures" ]
     }
   }
 }
diff --git a/ui/file_manager/audio_player/elements/compiled_resources2.gyp b/ui/file_manager/audio_player/elements/compiled_resources2.gyp
index b608c36..b102397 100644
--- a/ui/file_manager/audio_player/elements/compiled_resources2.gyp
+++ b/ui/file_manager/audio_player/elements/compiled_resources2.gyp
@@ -3,25 +3,39 @@
 # found in the LICENSE file.
 {
   'targets': [
-#    {
-#      'target_name': 'audio_player',
-#      'includes': ['../../compile_js2.gypi'],
-#    },
-#    {
-#      'target_name': 'control_panel',
-#      'includes': ['../../compile_js2.gypi'],
-#    },
-#    {
-#      'target_name': 'repeat_button',
-#      'includes': ['../../compile_js2.gypi'],
-#    },
-#    {
-#      'target_name': 'track_info_panel',
-#      'includes': ['../../compile_js2.gypi'],
-#    },
-#    {
-#      'target_name': 'track_list',
-#      'includes': ['../../compile_js2.gypi'],
-#    },
+    {
+      'target_name': 'audio_player',
+      'dependencies': [
+        'control_panel',
+        'track_info_panel',
+        'track_list',
+      ],
+      'includes': ['../../compile_js2.gypi'],
+    },
+    {
+      'target_name': 'control_panel',
+      'dependencies': [
+        '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-slider/compiled_resources2.gyp:paper-slider-extracted',
+        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
+        'repeat_button',
+      ],
+      'includes': ['../../compile_js2.gypi'],
+    },
+    {
+      'target_name': 'repeat_button',
+      'dependencies': [
+        '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-behaviors/compiled_resources2.gyp:iron-button-state-extracted',
+        '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-behaviors/compiled_resources2.gyp:iron-control-state-extracted',
+      ],
+      'includes': ['../../compile_js2.gypi'],
+    },
+    {
+      'target_name': 'track_info_panel',
+      'includes': ['../../compile_js2.gypi'],
+    },
+    {
+      'target_name': 'track_list',
+      'includes': ['../../compile_js2.gypi'],
+    },
   ],
 }
diff --git a/ui/file_manager/audio_player/elements/control_panel.js b/ui/file_manager/audio_player/elements/control_panel.js
index ad142fd17..2de3266c 100644
--- a/ui/file_manager/audio_player/elements/control_panel.js
+++ b/ui/file_manager/audio_player/elements/control_panel.js
@@ -2,6 +2,24 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+/**
+ * @typedef {?{
+ *   mute: string,
+ *   next: string,
+ *   pause: string,
+ *   play: string,
+ *   playList: string,
+ *   previous: string,
+ *   repeat: string,
+ *   seekSlider: string,
+ *   shuffle: string,
+ *   unmute: string,
+ *   volume: string,
+ *   volumeSlider: string,
+ * }}
+ */
+var AriaLabels;
+
 (function() {
   'use strict';
 
@@ -117,6 +135,7 @@
 
       /**
        * Dictionary which contains aria-labels for each controls.
+       * @type {AriaLabels}
        */
       ariaLabels: {
         type: Object,
diff --git a/ui/file_manager/compiled_resources2.gyp b/ui/file_manager/compiled_resources2.gyp
index bbb8a9c..1418caf 100644
--- a/ui/file_manager/compiled_resources2.gyp
+++ b/ui/file_manager/compiled_resources2.gyp
@@ -7,9 +7,11 @@
       'target_name': 'file_manager_resources',
       'type': 'none',
       'dependencies': [
+        'audio_player/elements/compiled_resources2.gyp:*',
         'audio_player/js/compiled_resources2.gyp:*',
         'file_manager/background/js/compiled_resources2.gyp:*',
         'file_manager/common/js/compiled_resources2.gyp:*',
+        'file_manager/foreground/elements/compiled_resources2.gyp:*',
         'file_manager/foreground/js/compiled_resources2.gyp:*',
         'gallery/js/compiled_resources2.gyp:*',
         'video_player/js/compiled_resources2.gyp:*',
diff --git a/ui/file_manager/file_manager/background/js/device_handler.js b/ui/file_manager/file_manager/background/js/device_handler.js
index 1c6f39fc..bbdb598 100644
--- a/ui/file_manager/file_manager/background/js/device_handler.js
+++ b/ui/file_manager/file_manager/background/js/device_handler.js
@@ -92,6 +92,17 @@
  * @type {DeviceHandler.Notification}
  * @const
  */
+DeviceHandler.Notification.DEVICE_NAVIGATION_READONLY_POLICY =
+    new DeviceHandler.Notification(
+        'deviceNavigation',
+        'REMOVABLE_DEVICE_DETECTION_TITLE',
+        'REMOVABLE_DEVICE_NAVIGATION_MESSAGE_READONLY_POLICY',
+        'REMOVABLE_DEVICE_NAVIGATION_BUTTON_LABEL');
+
+/**
+ * @type {DeviceHandler.Notification}
+ * @const
+ */
 DeviceHandler.Notification.DEVICE_IMPORT = new DeviceHandler.Notification(
     'deviceImport',
     'REMOVABLE_DEVICE_DETECTION_TITLE',
@@ -486,8 +497,14 @@
       .catch(
         function(error) {
           if (metadata.deviceType && metadata.devicePath) {
+            if (metadata.isReadOnly &&
+                !metadata.isReadOnlyRemovableDevice) {
+              DeviceHandler.Notification.DEVICE_NAVIGATION_READONLY_POLICY.show(
+                  /** @type {string} */ (metadata.devicePath));
+            } else {
               DeviceHandler.Notification.DEVICE_NAVIGATION.show(
                   /** @type {string} */ (metadata.devicePath));
+            }
           }
         });
 };
diff --git a/ui/file_manager/file_manager/common/js/compiled_resources2.gyp b/ui/file_manager/file_manager/common/js/compiled_resources2.gyp
index 02011536..c08690f9 100644
--- a/ui/file_manager/file_manager/common/js/compiled_resources2.gyp
+++ b/ui/file_manager/file_manager/common/js/compiled_resources2.gyp
@@ -23,18 +23,32 @@
       'target_name': 'lru_cache',
       'includes': ['../../../compile_js2.gypi'],
     },
-#    {
-#      'target_name': 'metrics',
-#      'includes': ['../../../compile_js2.gypi'],
-#    },
-#    {
-#      'target_name': 'metrics_base',
-#      'includes': ['../../../compile_js2.gypi'],
-#    },
-#    {
-#      'target_name': 'metrics_events',
-#      'includes': ['../../../compile_js2.gypi'],
-#    },
+    {
+      'target_name': 'metrics',
+      'dependencies': [
+        '<(DEPTH)/third_party/analytics/compiled_resources2.gyp:externs',
+        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
+        '<(EXTERNS_GYP):file_manager_private',
+        '<(EXTERNS_GYP):chrome_extensions',
+        'metrics_base',
+      ],
+      'includes': ['../../../compile_js2.gypi'],
+    },
+    {
+      'target_name': 'metrics_base',
+      'dependencies': [
+        '<(EXTERNS_GYP):metrics_private',
+      ],
+      'includes': ['../../../compile_js2.gypi'],
+    },
+    {
+      'target_name': 'metrics_events',
+      'dependencies': [
+        '<(DEPTH)/third_party/analytics/compiled_resources2.gyp:externs',
+        'metrics_base',
+      ],
+      'includes': ['../../../compile_js2.gypi'],
+    },
     {
       'target_name': 'progress_center_common',
       'includes': ['../../../compile_js2.gypi'],
diff --git a/ui/file_manager/file_manager/common/js/metrics_base.js b/ui/file_manager/file_manager/common/js/metrics_base.js
index 7d6974f..ac920df 100644
--- a/ui/file_manager/file_manager/common/js/metrics_base.js
+++ b/ui/file_manager/file_manager/common/js/metrics_base.js
@@ -8,6 +8,7 @@
  * To be included as a first script in main.html
  */
 
+var metrics;  // Needs to be defined in each window which uses metrics.
 var metricsBase = {};
 
 /**
diff --git a/ui/file_manager/file_manager/foreground/elements/compiled_resources2.gyp b/ui/file_manager/file_manager/foreground/elements/compiled_resources2.gyp
index 1b5af6d..85e2919 100644
--- a/ui/file_manager/file_manager/foreground/elements/compiled_resources2.gyp
+++ b/ui/file_manager/file_manager/foreground/elements/compiled_resources2.gyp
@@ -3,49 +3,62 @@
 # found in the LICENSE file.
 {
   'targets': [
-#    {
-#      'target_name': 'files_icon_button',
-#      'includes': ['../../../compile_js2.gypi'],
-#    },
-#    {
-#      'target_name': 'files_metadata_box',
-#      'includes': ['../../../compile_js2.gypi'],
-#    },
-#    {
-#      'target_name': 'files_metadata_entry',
-#      'includes': ['../../../compile_js2.gypi'],
-#    },
-#    {
-#      'target_name': 'files_quick_view',
-#      'includes': ['../../../compile_js2.gypi'],
-#    },
-#    {
-#      'target_name': 'files_ripple',
-#      'includes': ['../../../compile_js2.gypi'],
-#    },
-#    {
-#      'target_name': 'files_safe_img',
-#      'includes': ['../../../compile_js2.gypi'],
-#    },
-#    {
-#      'target_name': 'files_safe_img_webview_content',
-#      'includes': ['../../../compile_js2.gypi'],
-#    },
-#    {
-#      'target_name': 'files_toast',
-#      'includes': ['../../../compile_js2.gypi'],
-#    },
-#    {
-#      'target_name': 'files_toggle_ripple',
-#      'includes': ['../../../compile_js2.gypi'],
-#    },
-#    {
-#      'target_name': 'files_tooltip',
-#      'includes': ['../../../compile_js2.gypi'],
-#    },
-#    {
-#      'target_name': 'files_tooltip_unittest',
-#      'includes': ['../../../compile_js2.gypi'],
-#    },
+    {
+      'target_name': 'files_icon_button',
+      'dependencies': [
+        '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-behaviors/compiled_resources2.gyp:iron-button-state-extracted',
+        '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-behaviors/compiled_resources2.gyp:iron-control-state-extracted',
+      ],
+      'includes': ['../../../compile_js2.gypi'],
+    },
+    {
+      'target_name': 'files_metadata_box',
+      'includes': ['../../../compile_js2.gypi'],
+    },
+    {
+      'target_name': 'files_metadata_entry',
+      'includes': ['../../../compile_js2.gypi'],
+    },
+    {
+      'target_name': 'files_quick_view',
+      'dependencies': [
+        'files_metadata_box',
+      ],
+      'includes': ['../../../compile_js2.gypi'],
+    },
+    {
+      'target_name': 'files_ripple',
+      'dependencies': [
+        '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-ripple/compiled_resources2.gyp:paper-ripple-extracted',
+        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
+      ],
+      'includes': ['../../../compile_js2.gypi'],
+    },
+    {
+      'target_name': 'files_safe_media',
+      'includes': ['../../../compile_js2.gypi'],
+    },
+    {
+      'target_name': 'files_safe_media_webview_content',
+      'includes': ['../../../compile_js2.gypi'],
+    },
+    {
+      'target_name': 'files_toast',
+      'dependencies': [
+        '<(EXTERNS_GYP):web_animations',
+      ],
+      'includes': ['../../../compile_js2.gypi'],
+    },
+    {
+      'target_name': 'files_toggle_ripple',
+      'dependencies': [
+        '<(EXTERNS_GYP):web_animations',
+      ],
+      'includes': ['../../../compile_js2.gypi'],
+    },
+    {
+      'target_name': 'files_tooltip',
+      'includes': ['../../../compile_js2.gypi'],
+    },
   ],
 }
diff --git a/ui/file_manager/file_manager/foreground/elements/files_safe_media.js b/ui/file_manager/file_manager/foreground/elements/files_safe_media.js
index beaf05f..4537141 100644
--- a/ui/file_manager/file_manager/foreground/elements/files_safe_media.js
+++ b/ui/file_manager/file_manager/foreground/elements/files_safe_media.js
@@ -52,7 +52,8 @@
       this.webview_ = null;
     } else if (this.src && !this.webview_) {
       // Create webview node only if src exists to save resouces.
-      var webview = document.createElement('webview');
+      var webview =
+          /** @type {!HTMLElement} */ (document.createElement('webview'));
       this.webview_ = webview;
       webview.partition = 'trusted';
       webview.allowtransparency = 'true';
diff --git a/ui/file_manager/file_manager/foreground/elements/files_toast.js b/ui/file_manager/file_manager/foreground/elements/files_toast.js
index 63a35e77..e7a7a34 100644
--- a/ui/file_manager/file_manager/foreground/elements/files_toast.js
+++ b/ui/file_manager/file_manager/foreground/elements/files_toast.js
@@ -42,12 +42,12 @@
     this.generationId_ = 0;
 
     /**
-     * @private {AnimationPlayer}
+     * @private {Animation}
      */
     this.enterAnimationPlayer_ = null;
 
     /**
-     * @private {AnimationPlayer}
+     * @private {Animation}
      */
     this.hideAnimationPlayer_ = null;
   },
diff --git a/ui/file_manager/video_player/js/compiled_resources2.gyp b/ui/file_manager/video_player/js/compiled_resources2.gyp
index e2221379..e665539 100644
--- a/ui/file_manager/video_player/js/compiled_resources2.gyp
+++ b/ui/file_manager/video_player/js/compiled_resources2.gyp
@@ -19,10 +19,13 @@
 #      'target_name': 'video_player',
 #      'includes': ['../../compile_js2.gypi'],
 #    },
-#    {
-#      'target_name': 'video_player_metrics',
-#      'includes': ['../../compile_js2.gypi'],
-#    },
+    {
+      'target_name': 'video_player_metrics',
+      'dependencies': [
+        '../../file_manager/common/js/compiled_resources2.gyp:metrics_base',
+      ],
+      'includes': ['../../compile_js2.gypi'],
+    },
 #    {
 #      'target_name': 'video_player_scripts',
 #      'includes': ['../../compile_js2.gypi'],
diff --git a/ui/gfx/vector_icons/BUILD.gn b/ui/gfx/vector_icons/BUILD.gn
index b54103b..9751ed4 100644
--- a/ui/gfx/vector_icons/BUILD.gn
+++ b/ui/gfx/vector_icons/BUILD.gn
@@ -59,7 +59,6 @@
     "incognito.1x.icon",
     "incognito.icon",
     "info_outline.icon",
-    "laptop.icon",
     "location_bar_http.1x.icon",
     "location_bar_http.icon",
     "location_bar_https_invalid.1x.icon",
@@ -111,56 +110,18 @@
     "remove_circle.icon",
     "sad_tab.icon",
     "settings.icon",
-    "shelf_keyboard.1x.icon",
-    "shelf_keyboard.icon",
-    "shelf_logout.1x.icon",
-    "shelf_logout.icon",
-    "shelf_overflow.1x.icon",
-    "shelf_overflow.icon",
-    "shelf_overview.1x.icon",
-    "shelf_overview.icon",
-    "smartphone.icon",
     "submenu_arrow.1x.icon",
     "submenu_arrow.icon",
     "subresource_filter_active.icon",
     "supervisor_account.icon",
     "supervisor_account_circle.icon",
     "sync_problem.icon",
-    "tab.icon",
-    "tab_audio.1x.icon",
-    "tab_audio.icon",
-    "tab_audio_muting.1x.icon",
-    "tab_audio_muting.icon",
-    "tab_bluetooth_connected.icon",
-    "tab_close_hovered_pressed.1x.icon",
-    "tab_close_hovered_pressed.icon",
-    "tab_close_normal.1x.icon",
-    "tab_close_normal.icon",
-    "tab_media_capturing.icon",
-    "tab_media_recording.icon",
-    "tab_usb_connected.1x.icon",
-    "tab_usb_connected.icon",
-    "tablet.icon",
     "translate.icon",
     "user_account_avatar.icon",
     "videocam.icon",
     "warning.icon",
     "warning_badge.icon",
     "web.icon",
-    "window_control_back.1x.icon",
-    "window_control_back.icon",
-    "window_control_close.1x.icon",
-    "window_control_close.icon",
-    "window_control_left_snapped.1x.icon",
-    "window_control_left_snapped.icon",
-    "window_control_maximize.1x.icon",
-    "window_control_maximize.icon",
-    "window_control_minimize.1x.icon",
-    "window_control_minimize.icon",
-    "window_control_restore.1x.icon",
-    "window_control_restore.icon",
-    "window_control_right_snapped.1x.icon",
-    "window_control_right_snapped.icon",
     "zoom_minus.icon",
     "zoom_plus.icon",
     "${branding_path_component}/product.icon",
diff --git a/ui/message_center/views/message_center_button_bar.cc b/ui/message_center/views/message_center_button_bar.cc
index fb86d93..5f89a6a 100644
--- a/ui/message_center/views/message_center_button_bar.cc
+++ b/ui/message_center/views/message_center_button_bar.cc
@@ -68,9 +68,9 @@
     int text_id)
     : views::ToggleImageButton(listener), size_(kButtonSize, kButtonSize) {
   ui::ResourceBundle& resource_bundle = ui::ResourceBundle::GetSharedInstance();
-  SetImage(STATE_NORMAL, resource_bundle.GetImageSkiaNamed(normal_id));
-  SetImage(STATE_HOVERED, resource_bundle.GetImageSkiaNamed(hover_id));
-  SetImage(STATE_PRESSED, resource_bundle.GetImageSkiaNamed(pressed_id));
+  SetImage(STATE_NORMAL, *resource_bundle.GetImageSkiaNamed(normal_id));
+  SetImage(STATE_HOVERED, *resource_bundle.GetImageSkiaNamed(hover_id));
+  SetImage(STATE_PRESSED, *resource_bundle.GetImageSkiaNamed(pressed_id));
   SetImageAlignment(views::ImageButton::ALIGN_CENTER,
                     views::ImageButton::ALIGN_MIDDLE);
   if (text_id)
@@ -159,7 +159,7 @@
                                    IDS_MESSAGE_CENTER_CLEAR_ALL);
   close_all_button_->SetImage(
       views::Button::STATE_DISABLED,
-      resource_bundle.GetImageSkiaNamed(IDR_NOTIFICATION_CLEAR_ALL_DISABLED));
+      *resource_bundle.GetImageSkiaNamed(IDR_NOTIFICATION_CLEAR_ALL_DISABLED));
   button_container_->AddChildView(close_all_button_);
 
   settings_button_ =
diff --git a/ui/ozone/platform/drm/common/drm_util.cc b/ui/ozone/platform/drm/common/drm_util.cc
index 3c1eb88..0baf95e 100644
--- a/ui/ozone/platform/drm/common/drm_util.cc
+++ b/ui/ozone/platform/drm/common/drm_util.cc
@@ -10,8 +10,10 @@
 #include <sys/mman.h>
 #include <xf86drm.h>
 #include <xf86drmMode.h>
+#include <algorithm>
 #include <utility>
 
+#include "base/containers/small_map.h"
 #include "ui/display/util/edid_parser.h"
 
 #if !defined(DRM_FORMAT_YV12)
@@ -36,16 +38,21 @@
   return false;
 }
 
+// Return a CRTC compatible with |connector| and not already used in |displays|.
+// If there are multiple compatible CRTCs, the one that supports the majority of
+// planes will be returned.
 uint32_t GetCrtc(int fd,
                  drmModeConnector* connector,
                  drmModeRes* resources,
                  const ScopedVector<HardwareDisplayControllerInfo>& displays) {
-  // If the connector already has an encoder try to re-use.
-  if (connector->encoder_id) {
-    ScopedDrmEncoderPtr encoder(drmModeGetEncoder(fd, connector->encoder_id));
-    if (encoder && encoder->crtc_id && !IsCrtcInUse(encoder->crtc_id, displays))
-      return encoder->crtc_id;
-  }
+  ScopedDrmPlaneResPtr plane_resources(drmModeGetPlaneResources(fd));
+  std::vector<ScopedDrmPlanePtr> planes;
+  for (uint32_t i = 0; i < plane_resources->count_planes; i++)
+    planes.emplace_back(drmModeGetPlane(fd, plane_resources->planes[i]));
+
+  DCHECK_GE(32, resources->count_crtcs);
+  uint32_t best_crtc = 0;
+  int best_crtc_planes = 0;
 
   // Try to find an encoder for the connector.
   for (int i = 0; i < connector->count_encoders; ++i) {
@@ -55,15 +62,29 @@
 
     for (int j = 0; j < resources->count_crtcs; ++j) {
       // Check if the encoder is compatible with this CRTC
-      if (!(encoder->possible_crtcs & (1 << j)) ||
+      int crtc_bit = 1 << j;
+      if (!(encoder->possible_crtcs & crtc_bit) ||
           IsCrtcInUse(resources->crtcs[j], displays))
         continue;
 
-      return resources->crtcs[j];
+      int supported_planes = std::count_if(
+          planes.begin(), planes.end(), [crtc_bit](const ScopedDrmPlanePtr& p) {
+            return p->possible_crtcs & crtc_bit;
+          });
+
+      uint32_t assigned_crtc = 0;
+      if (connector->encoder_id == encoder->encoder_id)
+        assigned_crtc = encoder->crtc_id;
+      if (supported_planes > best_crtc_planes ||
+          (supported_planes == best_crtc_planes &&
+           assigned_crtc == resources->crtcs[j])) {
+        best_crtc_planes = supported_planes;
+        best_crtc = resources->crtcs[j];
+      }
     }
   }
 
-  return 0;
+  return best_crtc;
 }
 
 // Computes the refresh rate for the specific mode. If we have enough
@@ -206,21 +227,54 @@
   DCHECK(resources) << "Failed to get DRM resources";
   ScopedVector<HardwareDisplayControllerInfo> displays;
 
+  std::vector<ScopedDrmConnectorPtr> available_connectors;
+  std::vector<ScopedDrmConnectorPtr::element_type*> connectors;
   for (int i = 0; i < resources->count_connectors; ++i) {
     ScopedDrmConnectorPtr connector(
         drmModeGetConnector(fd, resources->connectors[i]));
+    connectors.push_back(connector.get());
 
-    if (!connector || connector->connection != DRM_MODE_CONNECTED ||
-        connector->count_modes == 0)
-      continue;
+    if (connector && connector->connection == DRM_MODE_CONNECTED &&
+        connector->count_modes != 0)
+      available_connectors.push_back(std::move(connector));
+  }
 
-    uint32_t crtc_id = GetCrtc(fd, connector.get(), resources.get(), displays);
+  base::SmallMap<std::map<ScopedDrmConnectorPtr::element_type*, int>>
+      connector_crtcs;
+  for (auto& c : available_connectors) {
+    uint32_t possible_crtcs = 0;
+    for (int i = 0; i < c->count_encoders; ++i) {
+      ScopedDrmEncoderPtr encoder(drmModeGetEncoder(fd, c->encoders[i]));
+      if (!encoder)
+        continue;
+      possible_crtcs |= encoder->possible_crtcs;
+    }
+    connector_crtcs[c.get()] = possible_crtcs;
+  }
+  // Make sure to start assigning a crtc to the connector that supports the
+  // fewest crtcs first.
+  std::stable_sort(available_connectors.begin(), available_connectors.end(),
+                   [&connector_crtcs](const ScopedDrmConnectorPtr& c1,
+                                      const ScopedDrmConnectorPtr& c2) {
+                     // When c1 supports a proper subset of the crtcs of c2, we
+                     // should process c1 first (return true).
+                     int c1_crtcs = connector_crtcs[c1.get()];
+                     int c2_crtcs = connector_crtcs[c2.get()];
+                     return (c1_crtcs & c2_crtcs) == c1_crtcs &&
+                            c1_crtcs != c2_crtcs;
+                   });
+
+  for (auto& c : available_connectors) {
+    uint32_t crtc_id = GetCrtc(fd, c.get(), resources.get(), displays);
     if (!crtc_id)
       continue;
 
     ScopedDrmCrtcPtr crtc(drmModeGetCrtc(fd, crtc_id));
-    displays.push_back(new HardwareDisplayControllerInfo(std::move(connector),
-                                                         std::move(crtc), i));
+    size_t index = std::find(connectors.begin(), connectors.end(), c.get()) -
+                   connectors.begin();
+    DCHECK_LT(index, connectors.size());
+    displays.push_back(new HardwareDisplayControllerInfo(
+        std::move(c), std::move(crtc), index));
   }
 
   return displays;
diff --git a/ui/views/controls/button/image_button.cc b/ui/views/controls/button/image_button.cc
index e875612c..fd2151e2a 100644
--- a/ui/views/controls/button/image_button.cc
+++ b/ui/views/controls/button/image_button.cc
@@ -48,10 +48,14 @@
 }
 
 void ImageButton::SetImage(ButtonState for_state, const gfx::ImageSkia* image) {
+  SetImage(for_state, image ? *image : gfx::ImageSkia());
+}
+
+void ImageButton::SetImage(ButtonState for_state, const gfx::ImageSkia& image) {
   if (for_state == STATE_HOVERED)
-    set_animate_on_state_change(image != nullptr);
+    set_animate_on_state_change(!image.isNull());
   const gfx::Size old_preferred_size = GetPreferredSize();
-  images_[for_state] = image ? *image : gfx::ImageSkia();
+  images_[for_state] = image;
 
   if (old_preferred_size != GetPreferredSize())
     PreferredSizeChanged();
@@ -250,11 +254,11 @@
 }
 
 void ToggleImageButton::SetImage(ButtonState image_state,
-                                 const gfx::ImageSkia* image) {
+                                 const gfx::ImageSkia& image) {
   if (toggled_) {
-    alternate_images_[image_state] = image ? *image : gfx::ImageSkia();
+    alternate_images_[image_state] = image;
   } else {
-    images_[image_state] = image ? *image : gfx::ImageSkia();
+    images_[image_state] = image;
     if (state() == image_state)
       SchedulePaint();
   }
diff --git a/ui/views/controls/button/image_button.h b/ui/views/controls/button/image_button.h
index 94f70ba8..eba2a835 100644
--- a/ui/views/controls/button/image_button.h
+++ b/ui/views/controls/button/image_button.h
@@ -44,7 +44,12 @@
   virtual const gfx::ImageSkia& GetImage(ButtonState state) const;
 
   // Set the image the button should use for the provided state.
-  virtual void SetImage(ButtonState state, const gfx::ImageSkia* image);
+  void SetImage(ButtonState state, const gfx::ImageSkia* image);
+
+  // As above, but takes a const ref. TODO(estade): all callers should be
+  // updated to use this version, and then the implementations can be
+  // consolidated.
+  virtual void SetImage(ButtonState state, const gfx::ImageSkia& image);
 
   // Set the background details.
   void SetBackground(SkColor color,
@@ -142,7 +147,7 @@
 
   // Overridden from ImageButton:
   const gfx::ImageSkia& GetImage(ButtonState state) const override;
-  void SetImage(ButtonState state, const gfx::ImageSkia* image) override;
+  void SetImage(ButtonState state, const gfx::ImageSkia& image) override;
 
   // Overridden from View:
   bool GetTooltipText(const gfx::Point& p,
diff --git a/ui/views/controls/message_box_view.cc b/ui/views/controls/message_box_view.cc
index a5cea55c..2a71f75 100644
--- a/ui/views/controls/message_box_view.cc
+++ b/ui/views/controls/message_box_view.cc
@@ -148,13 +148,18 @@
 }
 
 bool MessageBoxView::AcceleratorPressed(const ui::Accelerator& accelerator) {
-  // We only accepts Ctrl-C.
+  // We only accept Ctrl-C.
   DCHECK(accelerator.key_code() == 'C' && accelerator.IsCtrlDown());
 
   // We must not intercept Ctrl-C when we have a text box and it's focused.
   if (prompt_field_ && prompt_field_->HasFocus())
     return false;
 
+  // Don't intercept Ctrl-C if we only use a single message label supporting
+  // text selection.
+  if (message_labels_.size() == 1u && message_labels_[0]->selectable())
+    return false;
+
   ui::ScopedClipboardWriter scw(ui::CLIPBOARD_TYPE_COPY_PASTE);
   base::string16 text = message_labels_[0]->text();
   for (size_t i = 1; i < message_labels_.size(); ++i)
@@ -189,6 +194,10 @@
     message_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
     message_labels_.push_back(message_label);
   }
+  // Don't enable text selection if multiple labels are used, since text
+  // selection can't span multiple labels.
+  if (message_labels_.size() == 1u)
+    message_labels_[0]->SetSelectable(true);
 
   if (params.options & HAS_PROMPT_FIELD) {
     prompt_field_ = new Textfield;